aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/cc
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-05-21 20:40:13 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-05-21 20:40:13 -0700
commitc4e73787a6987a32f07594074bbaceb7cd29409d (patch)
tree4ce741ef66de7f3c51e2d60a788efff6b1822978 /sys/cmd/cc
parent7d2a1280cd4321d2a3b2fff0b2413085347a7b4d (diff)
feat: partial implementation of expression parsing
Diffstat (limited to 'sys/cmd/cc')
-rw-r--r--sys/cmd/cc/ast.c193
-rw-r--r--sys/cmd/cc/cc.h69
2 files changed, 225 insertions, 37 deletions
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