diff options
Diffstat (limited to 'src/lisp/ao_lisp_read.c')
-rw-r--r-- | src/lisp/ao_lisp_read.c | 113 |
1 files changed, 72 insertions, 41 deletions
diff --git a/src/lisp/ao_lisp_read.c b/src/lisp/ao_lisp_read.c index 508d16b4..bcd23ce1 100644 --- a/src/lisp/ao_lisp_read.c +++ b/src/lisp/ao_lisp_read.c @@ -142,7 +142,7 @@ static const uint16_t lex_classes[128] = { PRINTABLE, /* { */ PRINTABLE|VBAR, /* | */ PRINTABLE, /* } */ - PRINTABLE|TWIDDLE, /* ~ */ + PRINTABLE, /* ~ */ IGNORE, /* ^? */ }; @@ -168,16 +168,38 @@ lex_unget(int c) lex_unget_c = c; } +static uint16_t lex_class; + +static int +lexc(void) +{ + int c; + do { + c = lex_get(); + if (c == EOF) { + c = 0; + lex_class = ENDOFFILE; + } else { + c &= 0x7f; + lex_class = lex_classes[c]; + } + } while (lex_class & IGNORE); + return c; +} + static int -lex_quoted (void) +lex_quoted(void) { int c; int v; int count; c = lex_get(); - if (c == EOF) - return EOF; + if (c == EOF) { + lex_class = ENDOFFILE; + return 0; + } + lex_class = 0; c &= 0x7f; switch (c) { case 'n': @@ -220,32 +242,6 @@ lex_quoted (void) } } -static uint16_t lex_class; - -static int -lexc(void) -{ - int c; - do { - c = lex_get(); - if (c == EOF) { - lex_class = ENDOFFILE; - c = 0; - } else { - c &= 0x7f; - lex_class = lex_classes[c]; - if (lex_class & BACKSLASH) { - c = lex_quoted(); - if (c == EOF) - lex_class = ENDOFFILE; - else - lex_class = PRINTABLE; - } - } - } while (lex_class & IGNORE); - return c; -} - #define AO_LISP_TOKEN_MAX 32 static char token_string[AO_LISP_TOKEN_MAX]; @@ -299,25 +295,60 @@ _lex(void) return DOT; } } - if (lex_class & TWIDDLE) { - token_int = lexc(); - return NUM; - } if (lex_class & POUND) { - for (;;) { - c = lexc(); + c = lexc(); + switch (c) { + case 't': add_token(c); - switch (c) { - case 't': - return BOOL; - case 'f': - return BOOL; + end_token(); + return BOOL; + case 'f': + add_token(c); + end_token(); + return BOOL; + case '\\': + for (;;) { + int alphabetic; + c = lexc(); + alphabetic = (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')); + if (token_len == 0) { + add_token(c); + if (!alphabetic) + break; + } else { + if (alphabetic) + add_token(c); + else { + lex_unget(c); + break; + } + } + } + end_token(); + if (token_len == 1) + token_int = token_string[0]; + else if (!strcmp(token_string, "space")) + token_int = ' '; + else if (!strcmp(token_string, "newline")) + token_int = '\n'; + else if (!strcmp(token_string, "tab")) + token_int = '\t'; + else if (!strcmp(token_string, "return")) + token_int = '\r'; + else if (!strcmp(token_string, "formfeed")) + token_int = '\f'; + else { + ao_lisp_error(AO_LISP_INVALID, "invalid character token #\\%s", token_string); + continue; } + return NUM; } } if (lex_class & STRINGC) { for (;;) { c = lexc(); + if (lex_class & BACKSLASH) + c = lex_quoted(); if (lex_class & (STRINGC|ENDOFFILE)) { end_token(); return STRING; |