From 7a643120366f1ea24eac5ccb759d4df616e7789b Mon Sep 17 00:00:00 2001 From: Toby Goodwin Date: Mon, 19 Mar 2018 20:55:56 +0000 Subject: implement desugaring version (again, lost due to git problem) --- tree.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) (limited to 'tree.c') diff --git a/tree.c b/tree.c index 6a79bbc..d167a7c 100644 --- a/tree.c +++ b/tree.c @@ -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; } -- cgit v1.2.3