我正在编写一个 lambda 演算解释器来娱乐和练习。我让 iostreams 通过添加一个ctype
将标点符号定义为空格的方面来正确标记标识符:
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 上似乎很少有 lambda 演算代码。到目前为止,我发现的大部分内容都充满了 unicode λ
字符。所以我想尝试添加 Unicode 支持。
但ctype<wchar_t>
工作方式与ctype<char>
. 没有主表;有四种方法do_is
x2 do_scan_is
、 和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
在这里是无关紧要的,但我想的更广泛。)我是否首先滥用了方面?以上是否正确?实现更少的逻辑会更好吗?