2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
17 #include "ao_lisp_read.h"
19 static const uint16_t lex_classes[128] = {
52 PRINTABLE|WHITE, /* */
54 PRINTABLE|STRINGC, /* " */
55 PRINTABLE|COMMENT, /* # */
59 PRINTABLE|QUOTEC, /* ' */
60 PRINTABLE|BRA, /* ( */
61 PRINTABLE|KET, /* ) */
63 PRINTABLE|SIGN, /* + */
65 PRINTABLE|SIGN, /* - */
68 PRINTABLE|DIGIT, /* 0 */
69 PRINTABLE|DIGIT, /* 1 */
70 PRINTABLE|DIGIT, /* 2 */
71 PRINTABLE|DIGIT, /* 3 */
72 PRINTABLE|DIGIT, /* 4 */
73 PRINTABLE|DIGIT, /* 5 */
74 PRINTABLE|DIGIT, /* 6 */
75 PRINTABLE|DIGIT, /* 7 */
76 PRINTABLE|DIGIT, /* 8 */
77 PRINTABLE|DIGIT, /* 9 */
79 PRINTABLE|COMMENT, /* ; */
112 PRINTABLE|BACKSLASH, /* \ */
144 PRINTABLE|VBAR, /* | */
146 PRINTABLE|TWIDDLE, /* ~ */
150 static int lex_unget_c;
211 if (c < '0' || '7' < c) {
215 v = (v << 3) + c - '0';
224 static uint16_t lex_class;
233 lex_class = ENDOFFILE;
237 lex_class = lex_classes[c];
238 if (lex_class & BACKSLASH) {
241 lex_class = ENDOFFILE;
243 lex_class = PRINTABLE;
246 } while (lex_class & IGNORE);
250 #define AO_LISP_TOKEN_MAX 32
252 static char token_string[AO_LISP_TOKEN_MAX];
253 static int token_int;
254 static int token_len;
256 static inline void add_token(int c) {
257 if (c && token_len < AO_LISP_TOKEN_MAX - 1)
258 token_string[token_len++] = c;
261 static inline void end_token(void) {
262 token_string[token_len] = '\0';
273 if (lex_class & ENDOFFILE)
276 if (lex_class & WHITE)
279 if (lex_class & COMMENT) {
280 while ((c = lexc()) != '\n') {
281 if (lex_class & ENDOFFILE)
287 if (lex_class & (BRA|KET|QUOTEC)) {
299 if (lex_class & TWIDDLE) {
303 if (lex_class & STRINGC) {
306 if (lex_class & (STRINGC|ENDOFFILE)) {
313 if (lex_class & PRINTABLE) {
323 if (!(lex_class & NUMBER)) {
326 if (token_len != 0 &&
333 if (lex_class & DIGIT) {
336 token_int = token_int * 10 + c - '0';
341 if (lex_class & (NOTNAME)) {
342 // if (lex_class & ENDOFFILE)
346 if (isnum && hasdigit) {
348 token_int = -token_int;
359 static int parse_token;
361 struct ao_lisp_cons *ao_lisp_read_cons;
362 struct ao_lisp_cons *ao_lisp_read_cons_tail;
363 struct ao_lisp_cons *ao_lisp_read_stack;
366 push_read_stack(int cons, int in_quote)
368 DBGI("push read stack %p %d\n", ao_lisp_read_cons, in_quote);
371 ao_lisp_read_stack = ao_lisp_cons_cons(ao_lisp_cons_poly(ao_lisp_read_cons),
372 ao_lisp_cons_cons(ao_lisp_int_poly(in_quote),
373 ao_lisp_read_stack));
374 if (!ao_lisp_read_stack)
377 ao_lisp_read_cons = NULL;
378 ao_lisp_read_cons_tail = NULL;
383 pop_read_stack(int cons)
387 ao_lisp_read_cons = ao_lisp_poly_cons(ao_lisp_read_stack->car);
388 ao_lisp_read_stack = ao_lisp_poly_cons(ao_lisp_read_stack->cdr);
389 in_quote = ao_lisp_poly_int(ao_lisp_read_stack->car);
390 ao_lisp_read_stack = ao_lisp_poly_cons(ao_lisp_read_stack->cdr);
391 for (ao_lisp_read_cons_tail = ao_lisp_read_cons;
392 ao_lisp_read_cons_tail && ao_lisp_read_cons_tail->cdr;
393 ao_lisp_read_cons_tail = ao_lisp_poly_cons(ao_lisp_read_cons_tail->cdr))
396 ao_lisp_read_cons = 0;
397 ao_lisp_read_cons_tail = 0;
398 ao_lisp_read_stack = 0;
401 DBGI("pop read stack %p %d\n", ao_lisp_read_cons, in_quote);
408 struct ao_lisp_atom *atom;
415 DBGI("token %d (%s)\n", parse_token, token_string);
419 ao_lisp_read_cons = ao_lisp_read_cons_tail = ao_lisp_read_stack = 0;
421 while (parse_token == OPEN) {
422 if (!push_read_stack(cons, in_quote))
427 DBGI("token %d (%s)\n", parse_token, token_string);
430 switch (parse_token) {
434 ao_lisp_error(AO_LISP_EOF, "unexpected end of file");
435 return _ao_lisp_atom_eof;
438 atom = ao_lisp_atom_intern(token_string);
440 v = ao_lisp_atom_poly(atom);
445 v = ao_lisp_int_poly(token_int);
448 string = ao_lisp_string_copy(token_string);
450 v = ao_lisp_string_poly(string);
455 if (!push_read_stack(cons, in_quote))
459 v = _ao_lisp_atom_quote;
466 v = ao_lisp_cons_poly(ao_lisp_read_cons);
468 in_quote = pop_read_stack(cons);
472 /* loop over QUOTE ends */
477 struct ao_lisp_cons *read = ao_lisp_cons_cons(v, NULL);
481 if (ao_lisp_read_cons_tail)
482 ao_lisp_read_cons_tail->cdr = ao_lisp_cons_poly(read);
484 ao_lisp_read_cons = read;
485 ao_lisp_read_cons_tail = read;
487 if (!in_quote || !ao_lisp_read_cons->cdr)
490 v = ao_lisp_cons_poly(ao_lisp_read_cons);
492 in_quote = pop_read_stack(cons);
496 DBGI("token %d (%s)\n", parse_token, token_string);