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 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- sys/cmd/cc/cc.h | 69 ++++++++++---------- 2 files changed, 225 insertions(+), 37 deletions(-) (limited to 'sys/cmd/cc') 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 diff --git a/sys/cmd/cc/cc.h b/sys/cmd/cc/cc.h index 7c9d679..1412302 100644 --- a/sys/cmd/cc/cc.h +++ b/sys/cmd/cc/cc.h @@ -326,7 +326,7 @@ enum /* unary postfix ops */ Xpostinc, Xpostdec, Xindex, Xcall, Xsel, Xcmpndlit, /* binary ops */ - Xoror, Xandand, Xor, Xxor, Xand, Xeql, Xgt, Xlt, Xgteq, Xlteq, Xlsft, Xrsft, + Xoror, Xandand, Xor, Xxor, Xand, Xneq, Xeql, Xgt, Xlt, Xgteq, Xlteq, Xlsft, Xrsft, Xadd, Xsub, Xmul, Xdiv, Xmod, /* primary */ Xparen, Xident, Xlit, @@ -346,6 +346,40 @@ enum Ncall = iota(3), }; +/* expressions */ +struct Expr +{ + struct Node; + uint64 type; + union { + struct { + Expr *l; + Expr *r; + } asn; + struct { + Expr *c; + Expr *t; + Expr *e; + } cond; + union { + Expr *pre; + Expr *post; + } unary; + struct { + uint64 to; + Expr *x; + } cast; + struct { + Expr *l; + Expr *r; + } binary; + struct { + Expr *x[2]; + } comma; + }; +}; + + /* statements */ struct Stmt { @@ -381,39 +415,6 @@ struct Stmt }; }; -/* expressions */ -struct Expr -{ - struct Node; - uint64 type; - union { - struct { - Expr *l; - Expr *r; - } asn; - struct { - Expr *c; - Expr *t; - Expr *e; - } cond; - union { - Expr *pre; - Expr *post; - } unary; - struct { - uint64 to; - Expr *x; - } cast; - struct { - Expr *l; - Expr *r; - } binary; - struct { - Expr *x[2]; - } comma; - }; -}; - /* declarations */ struct Ptr -- cgit v1.2.1