#include "parse.h" #include "fn.h" #include "errloc.h" #include "lex.h" #include "lit.h" #include "prv.h" #include #include #include void ast_free(struct ast *ast) { for (struct lit *l = ast->lits, *next; l; l = next) { next = l->next; lit_free(l); free(l); } for (size_t i = 0; i < ast->nfns; i++) fn_free(&ast->fns[i]); free(ast->fns); } static const char *expected(const struct step *s) { static const char *tmap[] = { [ID] = "identifier", [LIT] = "literal", [NUM] = "number" }; return s->id ? s->id : tmap[s->type]; } static int iter(const struct lex *l, struct prv *p) { struct pos *pos = p->pos; const struct step *s; const struct tk *tk = p->tk; if (!pos) return lex_eof(l, tk) ? 0 : fn(l, p); pos = &p->pos[p->i]; if (!(s = pos->step)) { if (lex_eof(l, tk)) return 0; else if (p->n > 1) return pop(l, p) ? -1 : 1; else { switch (tk->type) { case LIT: errloc(tk, "unexpected literal \"%s\"", tk->s); break; case NUM: errloc(tk, "unexpected number %s", tk->s); break; case ID: errloc(tk, "unexpected %s %s", kw(tk->s) ? "keyword" : "identifier", tk->s); break; case ANY: case UNDEF: errloc(tk, "%s: unreachable", __func__); break; } return -1; } } else if (lex_eof(l, tk)) { if (p->stk == p->tk) return pop(l, p) ? -1 : 1; else if (s->type) { tk--; if (lex_eof(l, p->stk)) { errloc(tk, "expected %s", expected(pos->step)); return -1; } } } if (!s->type) return pos->seq->fn(l, p); else if ((s->type == ID || s->type == ANY) && !s->id && kw(tk->s) && !s->chain) { if (tk != p->stk || !p->n) { errloc(tk, "unexpected keyword %s", tk->s); return -1; } else if (pop(l, p)) return -1; pos = &p->pos[p->i]; } else if ((s->type != tk->type && s->type != ANY) || (s->type == ID && s->id && strcmp(s->id, tk->s)) || (s->type == ID && kw(tk->s) && s->chain)) { pos->step = (++pos->seq)->steps; p->tk = p->stk; } else { const struct tk *next = tk + 1; if (!s->chain) pos->step++; else if (!lex_eof(l, next)) { if (s->chain && kw(next->s)) pos->step++; } else pos->step++; p->tk++; } return 1; } static void free_prv(struct prv *p) { free(p->levels); free(p->pos); } int parse(const struct lex *l, struct ast *ast) { int ret; struct prv prv = {0}; prv.ast = ast; if (!(prv.tk = l->tokens)) return 0; while ((ret = iter(l, &prv)) > 0) ; free_prv(&prv); return ret; }