diff options
Diffstat (limited to 'src/prc1/parse.c')
| -rw-r--r-- | src/prc1/parse.c | 101 |
1 files changed, 49 insertions, 52 deletions
diff --git a/src/prc1/parse.c b/src/prc1/parse.c index 1c3aba2..db4bdcc 100644 --- a/src/prc1/parse.c +++ b/src/prc1/parse.c @@ -4,6 +4,7 @@ #include "fn.h" #include "lex.h" #include "lit.h" +#include "sym.h" #include "prv.h" #include "type.h" #include <stddef.h> @@ -45,6 +46,29 @@ static const char *expected(const struct step *s) return s->id ? s->id : tmap[s->type]; } +static int unexpected(const struct tk *tk) +{ + 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; +} + static int iter(const struct lex *l, struct prv *p) { struct pos *pos = p->pos; @@ -52,41 +76,28 @@ static int iter(const struct lex *l, struct prv *p) const struct tk *tk = p->tk; if (!pos) - return p->entry(l, p); + { + if (lex_eof(l, p->stk)) + return 0; + + return p->entry(l, p) ? -1 : 1; + } pos = &p->pos[p->i]; + /* no rules have matched the current token */ if (!(s = pos->step)) { - if (lex_eof(l, tk)) - return 0; - else if (p->n > 1) + if (p->n > 1) return pop(l, p) ? -1 : 1; + else if (lex_eof(l, tk)) + return 0; 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; - } + return unexpected(tk); } else if (lex_eof(l, tk)) { + /* pop all remaining rules */ if (p->stk == p->tk) return pop(l, p) ? -1 : 1; else if (s->type) @@ -101,41 +112,26 @@ static int iter(const struct lex *l, struct prv *p) } } + /* rule has been completely parsed, execute */ 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) + return pos->seq->fn(l, p) ? -1 : 1; + /* skip if: */ + else if ( + /* rule type does not match */ + s->type != tk->type + /* ID does not match */ || (s->type == ID && s->id && strcmp(s->id, tk->s)) - || (s->type == ID && kw(tk->s) && s->chain)) + /* rule does not expect a keyword */ + || (s->type == ID && !s->id && kw(tk->s))) { + /* move to next rule on no match */ pos->step = (++pos->seq)->steps; p->tk = p->stk; } + /* move to next step */ 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++; + pos->step++; if (!lex_eof(l, p->tk)) p->tk++; @@ -146,6 +142,7 @@ static int iter(const struct lex *l, struct prv *p) static void free_prv(struct prv *p) { + sym_free(p->s); free(p->tdc); free(p->pos); } |
