Remove read_expression and use parse_expression directly

This commit is contained in:
Camden Dixie O'Brien 2024-10-24 22:28:12 +01:00
parent b44bd100ca
commit f591809d1f
4 changed files with 57 additions and 61 deletions

View File

@ -16,13 +16,15 @@ static bool step_repl(void)
const int len = read_line(getchar, buffer, BUFFER_SIZE); const int len = read_line(getchar, buffer, BUFFER_SIZE);
if (len < 0) if (len < 0)
return false; return false;
const expression_t *e = read_expression(&pool, buffer, len);
if (NULL == e) { expression_t *expression;
const int used = parse_expression(&pool, buffer, len, &expression);
if (used != len) {
puts("Invalid expression\n"); puts("Invalid expression\n");
return true; return true;
} }
const int result = evaluate(e); const int result = evaluate(expression);
printf("%d\n", result); printf("%d\n", result);
return true; return true;

View File

@ -5,7 +5,7 @@
int read_line(int (*get_byte)(void), char *buffer, int buffer_size); int read_line(int (*get_byte)(void), char *buffer, int buffer_size);
const expression_t * int parse_expression(
read_expression(memory_pool_t *pool, const char *input, int len); memory_pool_t *pool, const char *input, int len, expression_t **out);
#endif #endif

View File

@ -1,11 +1,20 @@
#include "reader.h" #include "reader.h"
#include <ctype.h> #include <ctype.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
static int parse_expression( int read_line(int (*get_byte)(void), char *buffer, int buffer_size)
memory_pool_t *pool, const char *input, int len, expression_t **out); {
for (int len = 0; len < buffer_size; ++len) {
const int byte = get_byte();
if (EOF == byte)
return -1;
if ('\n' == byte)
return len;
buffer[len] = (char)byte;
}
return buffer_size;
}
static int parse_whitespace(const char *input, int len) static int parse_whitespace(const char *input, int len)
{ {
@ -104,7 +113,7 @@ static int parse_term(
return used; return used;
} }
static int parse_expression( int parse_expression(
memory_pool_t *pool, const char *input, int len, expression_t **out) memory_pool_t *pool, const char *input, int len, expression_t **out)
{ {
int result, used = 0; int result, used = 0;
@ -152,27 +161,3 @@ static int parse_expression(
*out = expr; *out = expr;
return used; return used;
} }
int read_line(int (*get_byte)(void), char *buffer, int buffer_size)
{
for (int len = 0; len < buffer_size; ++len) {
const int byte = get_byte();
if (EOF == byte)
return -1;
if ('\n' == byte)
return len;
buffer[len] = (char)byte;
}
return buffer_size;
}
const expression_t *
read_expression(memory_pool_t *pool, const char *input, int len)
{
expression_t *expression;
const int used = parse_expression(pool, input, len, &expression);
if (used == len)
return expression;
else
return NULL;
}

View File

@ -19,7 +19,8 @@ static int test_get_byte(void)
static void input_1234_is_read_as_number_with_expected_value(void) static void input_1234_is_read_as_number_with_expected_value(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1234", 4); expression_t *result;
parse_expression(&pool, "1234", 4, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_TRUE(result->is_number); ASSERT_TRUE(result->is_number);
ASSERT_EQUAL(1234, result->number); ASSERT_EQUAL(1234, result->number);
@ -28,7 +29,8 @@ static void input_1234_is_read_as_number_with_expected_value(void)
static void input_4321_is_read_as_number_with_expected_value(void) static void input_4321_is_read_as_number_with_expected_value(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "4321", 4); expression_t *result;
parse_expression(&pool, "4321", 4, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_TRUE(result->is_number); ASSERT_TRUE(result->is_number);
ASSERT_EQUAL(4321, result->number); ASSERT_EQUAL(4321, result->number);
@ -37,7 +39,8 @@ static void input_4321_is_read_as_number_with_expected_value(void)
static void input_1234_with_len_3_is_read_as_123(void) static void input_1234_with_len_3_is_read_as_123(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1234", 3); expression_t *result;
parse_expression(&pool, "1234", 3, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_TRUE(result->is_number); ASSERT_TRUE(result->is_number);
ASSERT_EQUAL(123, result->number); ASSERT_EQUAL(123, result->number);
@ -46,7 +49,8 @@ static void input_1234_with_len_3_is_read_as_123(void)
static void input_1_plus_2_with_no_spaces_is_read_as_an_add_application(void) static void input_1_plus_2_with_no_spaces_is_read_as_an_add_application(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1+2", 3); expression_t *result;
parse_expression(&pool, "1+2", 3, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_ADD, result->application.operator); ASSERT_EQUAL(OPERATOR_ADD, result->application.operator);
@ -55,7 +59,8 @@ static void input_1_plus_2_with_no_spaces_is_read_as_an_add_application(void)
static void operands_of_15_plus_54_are_read_as_numbers(void) static void operands_of_15_plus_54_are_read_as_numbers(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "15+54", 5); expression_t *result;
parse_expression(&pool, "15+54", 5, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_NOT_NULL(result->application.operands[0]); ASSERT_NOT_NULL(result->application.operands[0]);
@ -70,7 +75,8 @@ static void
input_6_minus_2_with_no_spaces_is_read_as_a_subtract_application(void) input_6_minus_2_with_no_spaces_is_read_as_a_subtract_application(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "6-2", 3); expression_t *result;
parse_expression(&pool, "6-2", 3, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_SUBTRACT, result->application.operator); ASSERT_EQUAL(OPERATOR_SUBTRACT, result->application.operator);
@ -80,7 +86,8 @@ static void
input_1_plus_2_plus_3_is_parsed_as_a_left_nested_application(void) input_1_plus_2_plus_3_is_parsed_as_a_left_nested_application(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1+2+3", 5); expression_t *result;
parse_expression(&pool, "1+2+3", 5, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_ADD, result->application.operator); ASSERT_EQUAL(OPERATOR_ADD, result->application.operator);
@ -106,7 +113,8 @@ static void
input_1_times_2_times_3_is_parsed_as_a_left_nested_application(void) input_1_times_2_times_3_is_parsed_as_a_left_nested_application(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1*2*3", 5); expression_t *result;
parse_expression(&pool, "1*2*3", 5, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_MULTIPLY, result->application.operator); ASSERT_EQUAL(OPERATOR_MULTIPLY, result->application.operator);
@ -132,7 +140,8 @@ static void
input_1_plus_2_times_3_is_parsed_as_a_right_nested_application(void) input_1_plus_2_times_3_is_parsed_as_a_right_nested_application(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1+2*3", 5); expression_t *result;
parse_expression(&pool, "1+2*3", 5, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_ADD, result->application.operator); ASSERT_EQUAL(OPERATOR_ADD, result->application.operator);
@ -157,7 +166,8 @@ input_1_plus_2_times_3_is_parsed_as_a_right_nested_application(void)
static void paren_1_plus_2_times_3_close_paren_parses_as_left_nested(void) static void paren_1_plus_2_times_3_close_paren_parses_as_left_nested(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "(1+2)*3", 7); expression_t *result;
parse_expression(&pool, "(1+2)*3", 7, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_MULTIPLY, result->application.operator); ASSERT_EQUAL(OPERATOR_MULTIPLY, result->application.operator);
@ -179,24 +189,19 @@ static void paren_1_plus_2_times_3_close_paren_parses_as_left_nested(void)
ASSERT_EQUAL(3, operand1->number); ASSERT_EQUAL(3, operand1->number);
} }
static void garbage_input_yeilds_null(void) static void garbage_input_yeilds_error(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "arwizxhu", 8); expression_t *result;
ASSERT_NULL(result); const int used = parse_expression(&pool, "arwizxhu", 8, &result);
} ASSERT_EQUAL(0, used);
static void valid_expression_followed_by_garbage_yeilds_null(void)
{
init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "5+2jvkre", 8);
ASSERT_NULL(result);
} }
static void sum_with_single_spaces_around_plus_is_parsed_successfully(void) static void sum_with_single_spaces_around_plus_is_parsed_successfully(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1 + 2", 5); expression_t *result;
parse_expression(&pool, "1 + 2", 5, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_ADD, result->application.operator); ASSERT_EQUAL(OPERATOR_ADD, result->application.operator);
@ -205,7 +210,8 @@ static void sum_with_single_spaces_around_plus_is_parsed_successfully(void)
static void sum_with_multiple_spaces_around_plus_is_parsed_successfully(void) static void sum_with_multiple_spaces_around_plus_is_parsed_successfully(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1 + 2", 7); expression_t *result;
parse_expression(&pool, "1 + 2", 7, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_ADD, result->application.operator); ASSERT_EQUAL(OPERATOR_ADD, result->application.operator);
@ -214,7 +220,8 @@ static void sum_with_multiple_spaces_around_plus_is_parsed_successfully(void)
static void product_with_spaces_around_times_is_parsed_successfully(void) static void product_with_spaces_around_times_is_parsed_successfully(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "1 * 2", 6); expression_t *result;
parse_expression(&pool, "1 * 2", 6, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_FALSE(result->is_number); ASSERT_FALSE(result->is_number);
ASSERT_EQUAL(OPERATOR_MULTIPLY, result->application.operator); ASSERT_EQUAL(OPERATOR_MULTIPLY, result->application.operator);
@ -223,7 +230,8 @@ static void product_with_spaces_around_times_is_parsed_successfully(void)
static void spaces_inside_parens_are_ignored(void) static void spaces_inside_parens_are_ignored(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "( 14 )", 6); expression_t *result;
parse_expression(&pool, "( 14 )", 6, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_TRUE(result->is_number); ASSERT_TRUE(result->is_number);
ASSERT_EQUAL(14, result->number); ASSERT_EQUAL(14, result->number);
@ -232,7 +240,8 @@ static void spaces_inside_parens_are_ignored(void)
static void leading_spaces_are_ignored(void) static void leading_spaces_are_ignored(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, " 14", 5); expression_t *result;
parse_expression(&pool, " 14", 5, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_TRUE(result->is_number); ASSERT_TRUE(result->is_number);
ASSERT_EQUAL(14, result->number); ASSERT_EQUAL(14, result->number);
@ -241,7 +250,8 @@ static void leading_spaces_are_ignored(void)
static void trailing_spaces_are_ignored(void) static void trailing_spaces_are_ignored(void)
{ {
init_memory_pool(&pool); init_memory_pool(&pool);
const expression_t *result = read_expression(&pool, "14 ", 5); expression_t *result;
parse_expression(&pool, "14 ", 5, &result);
ASSERT_NOT_NULL(result); ASSERT_NOT_NULL(result);
ASSERT_TRUE(result->is_number); ASSERT_TRUE(result->is_number);
ASSERT_EQUAL(14, result->number); ASSERT_EQUAL(14, result->number);
@ -296,8 +306,7 @@ int main(void)
RUN_TEST(input_1_times_2_times_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(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); RUN_TEST(paren_1_plus_2_times_3_close_paren_parses_as_left_nested);
RUN_TEST(garbage_input_yeilds_null); RUN_TEST(garbage_input_yeilds_error);
RUN_TEST(valid_expression_followed_by_garbage_yeilds_null);
RUN_TEST(sum_with_single_spaces_around_plus_is_parsed_successfully); RUN_TEST(sum_with_single_spaces_around_plus_is_parsed_successfully);
RUN_TEST(sum_with_multiple_spaces_around_plus_is_parsed_successfully); RUN_TEST(sum_with_multiple_spaces_around_plus_is_parsed_successfully);
RUN_TEST(product_with_spaces_around_times_is_parsed_successfully); RUN_TEST(product_with_spaces_around_times_is_parsed_successfully);