about summary refs log tree commit diff
path: root/lr.c
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2015-10-23 15:02:51 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2015-10-23 15:02:51 +0200
commitaaf0aede377ebf96a5acfd8f12aa0b5e48445b3e (patch)
treeee3b981aad365f4324d22ed3e2e32accb7e49dba /lr.c
parent7444f77df97dcf98be62e13ff2e3fbe7aae77de1 (diff)
downloadlr-aaf0aede377ebf96a5acfd8f12aa0b5e48445b3e.tar.gz
lr-aaf0aede377ebf96a5acfd8f12aa0b5e48445b3e.tar.xz
lr-aaf0aede377ebf96a5acfd8f12aa0b5e48445b3e.zip
generic expr chaining
Diffstat (limited to 'lr.c')
-rw-r--r--lr.c52
1 files changed, 25 insertions, 27 deletions
diff --git a/lr.c b/lr.c
index 7a953f5..4bd1832 100644
--- a/lr.c
+++ b/lr.c
@@ -258,8 +258,10 @@ parse_inner()
 			return e;
 		parse_error("missing )");
 		return 0;
-	} else
+	} else {
+		parse_error("unknown expression");
 		return 0;
+	}
 }
 
 struct expr *
@@ -429,26 +431,34 @@ parse_cmp()
 }
 
 struct expr *
+chain(struct expr *e1, enum op op, struct expr *e2)
+{
+	struct expr *i, *j, *e;
+	for (j = 0, i = e1; i->op == op; j = i, i = i->b.expr)
+		;
+	if (!j) {
+		e = mkexpr(op);
+		e->a.expr = e1;
+		e->b.expr = e2;
+		return e;
+	} else {
+		e = mkexpr(op);
+		e->a.expr = i;
+		e->b.expr = e2;
+		j->b.expr = e;
+		return e1;
+	}
+}
+
+struct expr *
 parse_and()
 {
 	struct expr *e1 = parse_cmp();
 	struct expr *r = e1;
-	struct expr *l = 0, *a = 0;
 
 	while (token("&&")) {
 		struct expr *e2 = parse_cmp();
-		if (!l) {
-			l = mkexpr(EXPR_AND);
-			l->a.expr = e1;
-			l->b.expr = e2;
-			r = l;
-		} else {
-			a = mkexpr(EXPR_AND);
-			a->a.expr = l->b.expr;
-			a->b.expr = e2;
-			l->b.expr = a;
-			l = a;
-		}
+		r = chain(r, EXPR_AND, e2);
 	}
 	
 	return r;
@@ -460,22 +470,10 @@ parse_or()
 {
 	struct expr *e1 = parse_and();
 	struct expr *r = e1;
-	struct expr *l = 0, *o = 0;
 
 	while (token("||")) {
 		struct expr *e2 = parse_and();
-		if (!l) {
-			l = mkexpr(EXPR_OR);
-			l->a.expr = e1;
-			l->b.expr = e2;
-			r = l;
-		} else {
-			o = mkexpr(EXPR_OR);
-			o->a.expr = l->b.expr;
-			o->b.expr = e2;
-			l->b.expr = o;
-			l = o;
-		}
+		r = chain(r, EXPR_OR, e2);
 	}
 	
 	return r;