From c4e73787a6987a32f07594074bbaceb7cd29409d Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Thu, 21 May 2020 20:40:13 -0700 Subject: feat: partial implementation of expression parsing --- sys/cmd/cc/ast.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 3 deletions(-) (limited to 'sys/cmd/cc/ast.c') diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c index f5c0ba2..2d741ea 100644 --- a/sys/cmd/cc/ast.c +++ b/sys/cmd/cc/ast.c @@ -152,13 +152,200 @@ nomatch(Token t, vlong kind) // ----------------------------------------------------------------------- // forward declarations -static Decl *decl(Parser *p, Lexer *lx); -static Expr *expr(Parser *p, Lexer *lx); -static error blkstmt(Parser *p, Lexer *lx, Stmt **s); +static Decl *decl(Parser *, Lexer *); +static Expr *expr(Parser *, Lexer *); +static error blkstmt(Parser *, Lexer *, Stmt **); +#define MAKEX(x, state) alloc((x)), (x)->kind = X##state // ----------------------------------------------------------------------- // expressions +static +Expr* +primary(Parser *p, Lexer *lx) +{ + +} + +static +Expr* +unary(Parser *p, Lexer *lx) +{ + Expr *x; + Token t; + + t = peek(p, 0); + switch (t.kind) { + case Aneg: MAKEX(x, neg); goto Prefix; + case Aand: MAKEX(x, ref); goto Prefix; + case Anot: MAKEX(x, not); goto Prefix; + case Astar: MAKEX(x, star); goto Prefix; + case Aadd: MAKEX(x, plus); goto Prefix; + case Asub: MAKEX(x, minus); goto Prefix; + case Ainc: MAKEX(x, preinc); goto Prefix; + case Adec: MAKEX(x, predec); goto Prefix; + Prefix: + x->pos.beg = t.pos; + x->unary.pre = unary(p, lx); + x->pos.end = x->unary.pre->pos.end; + return x; + + case Alparen: + panicf("cast not implemented"); + case Akeywd: + panicf("sizeof/align of not implemented"); + default: + return primary(p, lx); + } +} + +/* static data for binary operators */ +#define OPERATORS \ + OPERATOR(Astar, 10, Xmul) \ + OPERATOR(Adiv, 10, Xdiv) \ + OPERATOR(Amod, 10, Xmod) \ + OPERATOR(Aadd, 9, Xadd) \ + OPERATOR(Asub, 9, Xsub) \ + OPERATOR(Alsft, 8, Xlsft) \ + OPERATOR(Arsft, 8, Xrsft) \ + OPERATOR(Agteq, 7, Xgteq) \ + OPERATOR(Alteq, 7, Xlteq) \ + OPERATOR(Alt, 7, Xlt) \ + OPERATOR(Agt, 7, Xgt) \ + OPERATOR(Aeq, 6, Xeql) \ + OPERATOR(Aneq, 6, Xneq) \ + OPERATOR(Aand, 5, Xand) \ + OPERATOR(Axor, 4, Xxor) \ + OPERATOR(Aor, 3, Xor) \ + OPERATOR(Aandand, 2, Xandand) \ + OPERATOR(Aoror, 1, Xoror) + +static int prectab[] = +{ +#define OPERATOR(a, b, c) [a] = b, + OPERATORS +#undef OPERATOR +}; + +static int optab[] = +{ +#define OPERATOR(a, b, c) [a] = c, + OPERATORS +#undef OPERATOR +}; +#undef OPERATORS + +static +Expr* +binary(Parser *p, Lexer *lx, int prec) +{ + Token t; + int k, np; + Expr *l, *r, *x; + + l = unary(p, lx); + for (;;) { + t = peek(p, 0); + k = t.kind; + np = prectab[t.kind]; + if (np < prec) + return x; + + alloc(x); + x->pos.beg = l->pos.beg; + x->kind = optab[k]; + x->binary.l = l; + x->binary.r = r = binary(p, lx, np + 1); + x->pos.end = r->pos.end; + + l = x; + } + return l; +Bad: + errorat(t.pos, "failed to parse expression"); + return nil; +} + +static +Expr* +ternary(Parser *p, Lexer *lx) +{ + Pos b; + Token t; + Expr *x, *y; + + x = binary(p, lx, 1); + t = peek(p, 0); + b = t.pos; + + switch (t.kind) { + case Aqmark: + t = advance(p, lx); + y = x; + MAKEX(x, ternary); + x->pos.beg = b; + x->kind = Xternary; + x->cond.c = y; + x->cond.t = expr(p, lx); + if (nomatch(t, Acolon)) { + errorat(t.pos, "ternary expression missing ':'"); + goto Bad; + } + t = advance(p, lx); + x->cond.e = expr(p, lx); + x->pos.end = lx->pos; + break; + + case Aasn: MAKEX(y, asn); goto Assign; + case Aorasn: MAKEX(y, orasn); goto Assign; + case Axorasn: MAKEX(y, xorasn); goto Assign; + case Aandasn: MAKEX(y, andasn); goto Assign; + case Asubasn: MAKEX(y, subasn); goto Assign; + case Amulasn: MAKEX(y, mulasn); goto Assign; + case Adivasn: MAKEX(y, divasn); goto Assign; + case Amodasn: MAKEX(y, modasn); goto Assign; + case Alsftasn: MAKEX(y, lsftasn); goto Assign; + case Arsftasn: MAKEX(y, rsftasn); goto Assign; + Assign: + y->asn.l = x; + y->asn.r = ternary(p, lx); + x = y; + x->pos.beg = b; + x->pos.end = lx->pos; + break; + default: + ; + } + + return x; +Bad: + errorat(lx->pos, "failing expression parse"); + return nil; +} + +static +Expr* +expr(Parser *p, Lexer *lx) +{ + Pos b; + Token t; + Expr *x, *y; + + x = ternary(p, lx); + while (t = peek(p, 0), t.kind == Acomma) { + advance(p, lx); + y = x; + MAKEX(x, comma); + x->pos.beg = y->pos.beg; + x->comma.x[0] = y; + x->comma.x[1] = ternary(p, lx); + x->pos.end = lx->pos; + y = nil; + } + + return x; +} + // ----------------------------------------------------------------------- // statements -- cgit v1.2.1