## ~emersion/arithm-parser

714eea8347cf4736d28b904caeb8134ab522b46f — Simon Ser 1 year, 6 months ago
```Fix associativity of sums and products

See https://eli.thegreenplace.net/2009/03/14/some-problems-of-recursive-descent-parsers
```
```2 files changed, 43 insertions(+), 34 deletions(-)

M calc.c
M test.sh
```
`M calc.c => calc.c +42 -34`
```@@ 118,25 118,29 @@ struct ast_node *expect_product(struct parser *parser) {
return NULL;
}

-	char chr = parser_peek_char(parser);
-	switch (chr) {
-	case '*':
-	case '/':
+	while (1) {
+		char chr = parser_peek_char(parser);
+		switch (chr) {
+		case '*':
+		case '/':

-		struct ast_node *right = expect_product(parser);
-		if (right == NULL) {
-			return NULL;
-		}
+			struct ast_node *right = expect_power(parser);
+			if (right == NULL) {
+				return NULL;
+			}

-		struct ast_binop *binop = calloc(1, sizeof(*binop));
-		binop->node.type = AST_BINOP;
-		binop->op = chr;
-		binop->left = n;
-		binop->right = right;
-		return &binop->node;
-	default:
-		return n;
+			struct ast_binop *binop = calloc(1, sizeof(*binop));
+			binop->node.type = AST_BINOP;
+			binop->op = chr;
+			binop->left = n;
+			binop->right = right;
+
+			n = &binop->node;
+			break;
+		default:
+			return n;
+		}
}
}

@@ 146,25 150,29 @@ struct ast_node *expect_sum(struct parser *parser) {
return NULL;
}

-	char chr = parser_peek_char(parser);
-	switch (chr) {
-	case '+':
-	case '-':
+	while (1) {
+		char chr = parser_peek_char(parser);
+		switch (chr) {
+		case '+':
+		case '-':

-		struct ast_node *right = expect_sum(parser);
-		if (right == NULL) {
-			return NULL;
-		}
+			struct ast_node *right = expect_product(parser);
+			if (right == NULL) {
+				return NULL;
+			}

-		struct ast_binop *binop = calloc(1, sizeof(*binop));
-		binop->node.type = AST_BINOP;
-		binop->op = chr;
-		binop->left = n;
-		binop->right = right;
-		return &binop->node;
-	default:
-		return n;
+			struct ast_binop *binop = calloc(1, sizeof(*binop));
+			binop->node.type = AST_BINOP;
+			binop->op = chr;
+			binop->left = n;
+			binop->right = right;
+
+			n = &binop->node;
+			break;
+		default:
+			return n;
+		}
}
}

```
`M test.sh => test.sh +1 -0`
```@@ 18,6 18,7 @@ expect() {
expect "1" 1
expect "1+1" 2
expect "1+2+3" 6
+expect "5-1-2" 2
expect "2*3" 6
expect "1+2*3" 7
expect "2*3+1" 7

```