diff options
| author | Toby Goodwin <toby@paccrat.org> | 2018-03-19 20:55:56 +0000 |
|---|---|---|
| committer | Toby Goodwin <toby@paccrat.org> | 2018-03-19 20:55:56 +0000 |
| commit | 7a643120366f1ea24eac5ccb759d4df616e7789b (patch) | |
| tree | 17faf7ba3be5e185b8262cfcbafbe23a9f64260a /tree.c | |
| parent | 2dd0aa249c9bac4e5c616d1f386dc4271fdbab46 (diff) | |
implement desugaring version (again, lost due to git problem)
Diffstat (limited to 'tree.c')
| -rw-r--r-- | tree.c | 47 |
1 files changed, 40 insertions, 7 deletions
@@ -2,9 +2,47 @@ #include "rc.h" +/* convert if followed by ifnot to else */ +static Node *desugar_ifnot(Node *n) { + if (n->type == nBody && n->u[1].p && n->u[1].p->type == nIfnot) { + /* (body (if c x) (if-not y)) => (body (if c (else x y))) */ + if (n->u[0].p->type == nIf) { + Node *yes = n->u[0].p; + Node *no = n->u[1].p; + Node *els = nalloc(offsetof(Node, u[2])); + els->type = nElse; + els->u[1].p = no->u[0].p; + els->u[0].p = yes->u[1].p; + yes->u[1].p = els; + n->u[1].p = NULL; + } else goto fail; + } else if (n->type == nBody && + n->u[1].p && n->u[1].p->type == nBody && + n->u[1].p->u[0].p && + n->u[1].p->u[0].p->type == nIfnot) { + /* (body (if c x) (body (if-not y) z)) => + (body (if c (else x y)) z) */ + if (n->u[0].p->type == nIf) { + Node *yes = n->u[0].p; + Node *no = n->u[1].p->u[0].p; + Node *els = nalloc(offsetof(Node, u[2])); + els->type = nElse; + els->u[1].p = no->u[0].p; + els->u[0].p = yes->u[1].p; + yes->u[1].p = els; + n->u[1].p = n->u[1].p->u[1].p; + } else goto fail; + } + + return n; +fail: + rc_error("`if not' must follow `if'"); + return NULL; +} + /* make a new node, pass it back to yyparse. Used to generate the parsetree. */ -extern Node *mk(int /*nodetype*/ t,...) { +extern Node *mk(enum nodetype t,...) { va_list ap; Node *n; va_start(ap, t); @@ -60,13 +98,8 @@ extern Node *mk(int /*nodetype*/ t,...) { break; } n->type = t; - if (t == nBody && n->u[1].p && n->u[1].p->type == nIfnot) { - if (n->u[0].p->type == nIf) { - fprint(2, "here i am!\n"); - } else - rc_error("`if not' must follow `if'"); - } + n = desugar_ifnot(n); va_end(ap); return n; } |