Piszę interpretator rachunku lambda dla zabawy i ćwiczeń. Mam iostreams prawidłowo tokenize identyfikatorów dodając ctype
aspekt, który określa jako białe znaki interpunkcyjne (! classic_table()
prawdopodobnie być czystsze, ale to nie działa na OS X)przesłonięcie 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;
}
}
};
A potem zamienić aspekt, gdy uderzyłem w identyfikator:
locale token_loc(in.getloc(), new token_ctype);
…
locale const &oldloc = in.imbue(token_loc);
in.unget() >> token;
in.imbue(oldloc);
Wygląda na zaskakująco mały kod różniczkowy lambda w Internecie. Większość z tego, co dotąd odkryłem, jest pełna znaków Unicode λ
. Pomyślałem, że spróbuję dodać obsługę Unicode.
Ale ctype<wchar_t>
działa zupełnie inaczej niż ctype<char>
. Nie ma tabeli głównej; istnieją cztery metody: do_is
x2, do_scan_is
i do_scan_not
. Tak więc sam sposób:
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);
}
};
(Przeproszenia do formatowania płaskimi podgląd przekształca zaczepy inaczej).
Kod jest o wiele mniej eleganckie. Lepiej wyrażam pogląd, że tylko interpunkcja jest dodatkowym odstępem, ale w oryginale byłoby to w porządku, gdybym miał classic_table
.
Czy jest to prostszy sposób? Czy naprawdę potrzebuję wszystkich tych przeciążeń? (Testowanie pokazało, że jest tu obca, ale myślę szerzej.) Czy w pierwszej kolejności nadużywam aspektów? Czy powyższe jest poprawne? Czy lepszym stylem byłoby wprowadzanie mniejszej logiki?
Pod względem przykładowego kodu, możesz chcieć spojrzeć na Schemat lub LISP, ponieważ oba te języki są oparte na rachunku lambda. Powinien istnieć jakiś kod LISP lub Scheme, w które możesz grać. –
Wszystkie standardowe języki funkcyjne są ładne, ale miałem nadzieję, że znajdę kilka ciętych i wysuszonych źródeł w formie '(\ foo bar. Foo foo \ baz. ...' ad nauseam. Chciałbym grać z binarną lambda calculus (http://en.wikipedia.org/wiki/Binary_lambda_calculus, http://homepages.cwi.nl/~tromp/cl/cl.html) zamiast spędzać czas na pisaniu kodu ezoterycznego. Ale to pytanie dotyczy iostreams i rozbieżność elegancji pomiędzy szerokimi i wąskimi postaciami: – Potatoswatter
Jesteś kimś, co nadużywasz faset do budowy tokenizującego parsera, w pełni oczekuję, że będzie on jednocześnie kruchy i powolny, to znowu jest najbardziej bezpośredni sposób na nauczenie się podsumowanie iostreams Dziękujemy za zgłoszenie – sehe