From e0070bfb1ec08559b7097234a47fb2e5202d4d0a Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Thu, 24 Oct 2024 20:46:05 +0100 Subject: [PATCH] Add paren support to reader --- lib/reader.c | 31 +++++++++++++++++++++++-------- tests/reader_tests.c | 26 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lib/reader.c b/lib/reader.c index 201abc6..6bdd650 100644 --- a/lib/reader.c +++ b/lib/reader.c @@ -3,11 +3,12 @@ #include #include +static int parse_expression( + memory_pool_t *pool, const char *input, int len, expression_t **out); + static int parse_number( memory_pool_t *pool, const char *input, int len, expression_t **out) { - (void)pool; - int value = 0, used = 0; while (used < len && isdigit(input[used])) { value *= 10; @@ -24,13 +25,27 @@ static int parse_number( return used; } +static int parse_factor( + memory_pool_t *pool, const char *input, int len, expression_t **out) +{ + if (len > 1 && input[0] == '(') { + const int result = parse_expression(pool, input + 1, len - 1, out); + if (0 == result) + return 0; + const int used = result + 1; + return len >= used && input[used] == ')' ? used + 1 : 0; + } else { + return parse_number(pool, input, len, out); + } +} + static int parse_term( memory_pool_t *pool, const char *input, int len, expression_t **out) { int result, used = 0; expression_t *expr; - result = parse_number(pool, input, len, &expr); + result = parse_factor(pool, input, len, &expr); if (0 >= result) return 0; used += result; @@ -40,15 +55,15 @@ static int parse_term( operator_t operator; if ('*' == input[used]) - operator = OPERATOR_MULTIPLY; + operator= OPERATOR_MULTIPLY; else if ('/' == input[used]) - operator = OPERATOR_DIVIDE; + operator= OPERATOR_DIVIDE; else break; ++used; expression_t *term1; - result = parse_number(pool, input + used, len - used, &term1); + result = parse_factor(pool, input + used, len - used, &term1); if (0 >= result) return 0; used += result; @@ -80,9 +95,9 @@ static int parse_expression( operator_t operator; if ('+' == input[used]) - operator = OPERATOR_ADD; + operator= OPERATOR_ADD; else if ('-' == input[used]) - operator = OPERATOR_SUBTRACT; + operator= OPERATOR_SUBTRACT; else break; ++used; diff --git a/tests/reader_tests.c b/tests/reader_tests.c index 6b984c3..6e7e4e6 100644 --- a/tests/reader_tests.c +++ b/tests/reader_tests.c @@ -141,6 +141,31 @@ input_1_plus_2_times_3_is_parsed_as_a_right_nested_application(void) ASSERT_EQUAL(3, operand1->application.operands[1]->number); } +static void paren_1_plus_2_times_3_close_paren_parses_as_left_nested(void) +{ + init_memory_pool(&pool); + const expression_t *result = read_expression(&pool, "(1+2)*3", 7); + ASSERT_NOT_NULL(result); + ASSERT_FALSE(result->is_number); + ASSERT_EQUAL(OPERATOR_MULTIPLY, result->application.operator); + + const expression_t *operand0 = result->application.operands[0]; + ASSERT_NOT_NULL(operand0); + ASSERT_FALSE(operand0->is_number); + ASSERT_EQUAL(OPERATOR_ADD, operand0->application.operator); + ASSERT_NOT_NULL(operand0->application.operands[0]); + ASSERT_TRUE(operand0->application.operands[0]->is_number); + ASSERT_EQUAL(1, operand0->application.operands[0]->number); + ASSERT_NOT_NULL(operand0->application.operands[1]); + ASSERT_TRUE(operand0->application.operands[1]->is_number); + ASSERT_EQUAL(2, operand0->application.operands[1]->number); + + const expression_t *operand1 = result->application.operands[1]; + ASSERT_NOT_NULL(operand1); + ASSERT_TRUE(operand1->is_number); + ASSERT_EQUAL(3, operand1->number); +} + int main(void) { TESTING_BEGIN(); @@ -154,5 +179,6 @@ int main(void) RUN_TEST(input_1_plus_2_plus_3_is_parsed_as_a_left_nested_application); RUN_TEST(input_1_times_2_times_3_is_parsed_as_a_left_nested_application); RUN_TEST(input_1_plus_2_times_3_is_parsed_as_a_right_nested_application); + RUN_TEST(paren_1_plus_2_times_3_close_paren_parses_as_left_nested); TESTING_END(); }