~emersion/arithm-parser

714eea8347cf4736d28b904caeb8134ab522b46f — Simon Ser 1 year, 6 months ago ba9a903
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 '/':
		parser_read_char(parser);
	while (1) {
		char chr = parser_peek_char(parser);
		switch (chr) {
		case '*':
		case '/':
			parser_read_char(parser);

		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 '-':
		parser_read_char(parser);
	while (1) {
		char chr = parser_peek_char(parser);
		switch (chr) {
		case '+':
		case '-':
			parser_read_char(parser);

		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