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.
16 #include "ao_lisp_read.h"
18 static const uint16_t lex_classes[128] = {
51 PRINTABLE|WHITE, /* */
53 PRINTABLE|STRINGC, /* " */
54 PRINTABLE|COMMENT, /* # */
58 PRINTABLE|QUOTEC, /* ' */
59 PRINTABLE|BRA, /* ( */
60 PRINTABLE|KET, /* ) */
62 PRINTABLE|SIGN, /* + */
64 PRINTABLE|SIGN, /* - */
67 PRINTABLE|DIGIT, /* 0 */
68 PRINTABLE|DIGIT, /* 1 */
69 PRINTABLE|DIGIT, /* 2 */
70 PRINTABLE|DIGIT, /* 3 */
71 PRINTABLE|DIGIT, /* 4 */
72 PRINTABLE|DIGIT, /* 5 */
73 PRINTABLE|DIGIT, /* 6 */
74 PRINTABLE|DIGIT, /* 7 */
75 PRINTABLE|DIGIT, /* 8 */
76 PRINTABLE|DIGIT, /* 9 */
78 PRINTABLE|COMMENT, /* ; */
111 PRINTABLE|BACKSLASH, /* \ */
143 PRINTABLE|VBAR, /* | */
145 PRINTABLE|TWIDDLE, /* ~ */
149 static int lex_unget_c;
160 static uint8_t at_eol;
222 if (c < '0' || '7' < c) {
226 v = (v << 3) + c - '0';
235 static uint16_t lex_class;
244 lex_class = ENDOFFILE;
248 lex_class = lex_classes[c];
249 if (lex_class & BACKSLASH) {
252 lex_class = ENDOFFILE;
254 lex_class = PRINTABLE;
257 } while (lex_class & IGNORE);
261 #define AO_LISP_TOKEN_MAX 32
263 static char token_string[AO_LISP_TOKEN_MAX];
264 static int token_int;
265 static int token_len;
267 static inline void add_token(int c) {
268 if (c && token_len < AO_LISP_TOKEN_MAX - 1)
269 token_string[token_len++] = c;
272 static inline void end_token(void) {
273 token_string[token_len] = '\0';
284 if (lex_class & ENDOFFILE)
287 if (lex_class & WHITE)
290 if (lex_class & COMMENT) {
291 while ((c = lexc()) != '\n') {
292 if (lex_class & ENDOFFILE)
298 if (lex_class & (BRA|KET|QUOTEC)) {
310 if (lex_class & TWIDDLE) {
314 if (lex_class & STRINGC) {
317 if (lex_class & (STRINGC|ENDOFFILE)) {
324 if (lex_class & PRINTABLE) {
334 if (!(lex_class & NUMBER)) {
337 if (token_len != 0 &&
344 if (lex_class & DIGIT) {
347 token_int = token_int * 10 + c - '0';
352 if (lex_class & (NOTNAME)) {
353 // if (lex_class & ENDOFFILE)
357 if (isnum && hasdigit) {
359 token_int = -token_int;
370 static int parse_token;
371 static uint8_t been_here;
372 static struct ao_lisp_cons *read_cons;
373 static struct ao_lisp_cons *read_cons_tail;
374 static struct ao_lisp_cons *read_stack;
377 push_read_stack(int cons, int in_quote)
380 read_stack = ao_lisp_cons_cons(ao_lisp_cons_poly(read_cons),
381 ao_lisp_cons_cons(ao_lisp_int_poly(in_quote),
387 read_cons_tail = NULL;
392 pop_read_stack(int cons)
396 read_cons = ao_lisp_poly_cons(read_stack->car);
397 read_stack = ao_lisp_poly_cons(read_stack->cdr);
398 in_quote = ao_lisp_poly_int(read_stack->car);
399 read_stack = ao_lisp_poly_cons(read_stack->cdr);
400 for (read_cons_tail = read_cons;
401 read_cons_tail && read_cons_tail->cdr;
402 read_cons_tail = ao_lisp_poly_cons(read_cons_tail->cdr))
415 struct ao_lisp_atom *atom;
422 ao_lisp_root_add(&ao_lisp_cons_type, &read_cons);
423 ao_lisp_root_add(&ao_lisp_cons_type, &read_cons_tail);
424 ao_lisp_root_add(&ao_lisp_cons_type, &read_stack);
431 read_cons = read_cons_tail = read_stack = 0;
433 while (parse_token == OPEN) {
434 if (!push_read_stack(cons, in_quote))
441 switch (parse_token) {
447 atom = ao_lisp_atom_intern(token_string);
449 v = ao_lisp_atom_poly(atom);
454 v = ao_lisp_int_poly(token_int);
457 string = ao_lisp_string_copy(token_string);
459 v = ao_lisp_string_poly(string);
464 if (!push_read_stack(cons, in_quote))
468 v = _ao_lisp_atom_quote;
475 v = ao_lisp_cons_poly(read_cons);
477 in_quote = pop_read_stack(cons);
481 /* loop over QUOTE ends */
486 struct ao_lisp_cons *read = ao_lisp_cons_cons(v, NULL);
491 read_cons_tail->cdr = ao_lisp_cons_poly(read);
494 read_cons_tail = read;
496 if (!in_quote || !read_cons->cdr)
499 v = ao_lisp_cons_poly(read_cons);
501 in_quote = pop_read_stack(cons);