Я пишу интерпретатор лямбда-исчисления для забавы и практики. Я заставил iostreams правильно маркировать идентификаторы путем добавления a 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 );
В сети, кажется, существует удивительно мало кода лямбда-исчисления. Большая часть того, что я нашел до сих пор, полна 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
является посторонним здесь, но я думаю более широко.) Я злоупотребляю фасетами во-первых? Вышеупомянутое даже корректно? Это был бы лучший стиль для реализации меньшего количества логики?
ИМХО, код, который вы разместили, в порядке. Вы можете реализовать некоторые методы, используя другие, если хотите более простой код (возможно, в ущерб эффективности), но то, как вы это сделали, в порядке.
Несоответствие основано на том факте, что люди не хотят иметь несколько мегабайтных таблиц в своих программах UNICODE.