Estoy escribiendo un intérprete de cálculo lambda para la diversión y la práctica. Llegué a iostreams identificadores correctamente no simbólica mediante la adición de una faceta ctype
que define puntuacion como espacio en blanco: (! classic_table()
probablemente sería más limpio pero que no funciona en OS X)reemplazando ctype <wchar_t>
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;
}
}
};
Y luego intercambiar los faceta en cuando me golpeó un identificador:
locale token_loc(in.getloc(), new token_ctype);
…
locale const &oldloc = in.imbue(token_loc);
in.unget() >> token;
in.imbue(oldloc);
No parece ser sorprendentemente poco código cálculo lambda en la web. La mayoría de lo que he encontrado hasta ahora está lleno de caracteres λ
unicode. Así que pensé en intentar agregar soporte Unicode.
Pero ctype<wchar_t>
funciona de forma completamente diferente a ctype<char>
. No hay una tabla maestra; hay cuatro métodos do_is
x2, do_scan_is
y do_scan_not
. Así que hice esto:
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);
}
};
(Disculpas por el formato plana; la vista previa convierte las pestañas de manera diferente.)
El código es la forma menos elegante. Mejor expresar la noción de que solo la puntuación es espacio en blanco adicional, pero eso hubiera estado bien en el original si hubiera tenido classic_table
.
¿Hay una manera más simple de hacer esto? ¿Realmente necesito todas esas sobrecargas? (Las pruebas mostraron do_scan_not
es extraño aquí, pero estoy pensando más ampliamente.) ¿Estoy abusando de las facetas en primer lugar? ¿Es lo anterior incluso correcto? ¿Sería mejor estilo implementar menos lógica?
En términos de código de ejemplo, es posible que desee ver Scheme o LISP, ya que ambos idiomas están basados en cálculo lambda. Debería haber algún código LISP o Scheme con el que pueda jugar. –
Todos los lenguajes funcionales estándar son agradables, pero esperaba encontrar algunas fuentes abreviadas de la forma '(\ foo bar. Foo foo \ baz ... ... ad nauseam. Me gustaría jugar con lambda binario cálculo (http://en.wikipedia.org/wiki/Binary_lambda_calculus, http://homepages.cwi.nl/~tromp/cl/cl.html) en lugar de perder tiempo escribiendo código esotérico. Pero esta pregunta es sobre iostreams y disparidad de elegancia entre personajes anchos y estrechos. – Potatoswatter
¿Estás abusando de facetas para construir un analizador de tokenización? Espero también que sea frágil y lento. Por otra parte, es probablemente la forma más directa de aprender el entradas y salidas de iostreams. ¡Gracias por mostrarnos! – sehe