私は楽しみと練習のためにラムダ計算インタープリターを書いています。ctype
句読点を空白として定義するファセットを追加することにより、iostreamsが識別子を適切にトークン化するようにしました。
struct token_ctype : ctype<char> {
mask t[ table_size ];
token_ctype()
: ctype<char>( t ) {
for ( size_t tx = 0; tx < table_size; ++ tx ) {
t[tx] = isalnum( tx )? alnum : space;
}
}
};
(classic_table()
おそらくもっときれいでしょうが、それはOS Xでは機能しません!)
そして、識別子をヒットしたときにファセットを交換します。
locale token_loc( in.getloc(), new token_ctype );
…
locale const &oldloc = in.imbue( token_loc );
in.unget() >> token;
in.imbue( oldloc );
Web上には驚くほどラムダ計算コードがほとんどないようです。私がこれまでに見つけたもののほとんどは、Unicode λ
文字でいっぱいです。そこで、Unicodeサポートを追加してみようと思いました。
ただし、ctype<wchar_t>
とはまったく異なる動作をしctype<char>
ます。マスターテーブルはありません。do_is
x2 、、、do_scan_is
およびの4つのメソッドがありdo_scan_not
ます。だから私はこれをしました:
struct token_ctype : ctype< wchar_t > {
typedef ctype<wchar_t> base;
bool do_is( mask m, char_type c ) const {
return base::do_is(m,c)
|| (m&space) && ( base::do_is(punct,c) || c == L'λ' );
}
const char_type* do_is
(const char_type* lo, const char_type* hi, mask* vec) const {
base::do_is(lo,hi,vec);
for ( mask *vp = vec; lo != hi; ++ vp, ++ lo ) {
if ( *vp & punct || *lo == L'λ' ) *vp |= space;
}
return hi;
}
const char_type *do_scan_is
(mask m, const char_type* lo, const char_type* hi) const {
if ( m & space ) m |= punct;
hi = do_scan_is(m,lo,hi);
if ( m & space ) hi = find( lo, hi, L'λ' );
return hi;
}
const char_type *do_scan_not
(mask m, const char_type* lo, const char_type* hi) const {
if ( m & space ) {
m |= punct;
while ( * ( lo = base::do_scan_not(m,lo,hi) ) == L'λ' && lo != hi )
++ lo;
return lo;
}
return base::do_scan_not(m,lo,hi);
}
};
(フラットフォーマットについてお詫びします。プレビューではタブの変換が異なります。)
コードはあまりエレガントではありません。句読点だけが追加の空白であるという概念をより適切に表現しますが、私が持っていれば、それは元の形式では問題ありませんでしたclassic_table
。
これを行うためのより簡単な方法はありますか?私は本当にそれらすべての過負荷が必要ですか?(ここで示されたテストdo_scan_not
は無関係ですが、私はもっと広く考えています。)そもそも私はファセットを悪用していますか?上記も正しいですか?より少ないロジックを実装する方が良いスタイルでしょうか?