/* * Copyright (c) Camden Dixie O'Brien * SPDX-License-Identifier: AGPL-3.0-only */ #include "reader.h" #include #include 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; } static int parse_whitespace(const char *input, int len) { for (int i = 0; i < len; ++i) { if (!isspace(input[i])) return i; } return len; } static int parse_number( memory_pool_t *pool, const char *input, int len, expression_t **out) { int value = 0, used = 0; while (used < len && isdigit(input[used])) { value *= 10; value += input[used] - '0'; ++used; } if (0 == used) return 0; expression_t *number = allocate_expression(pool); number->is_number = true; number->number = value; *out = number; return used; } static int parse_factor( memory_pool_t *pool, const char *input, int len, expression_t **out) { if (len > 1 && input[0] == '(') { int result, used = 1; result = parse_whitespace(input + used, len - used); used += result; result = parse_expression(pool, input + used, len - used, out); if (0 == result) return 0; used += result; result = parse_whitespace(input + used, len - used); used += result; 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_factor(pool, input, len, &expr); if (0 >= result) return 0; used += result; while (len > used) { const expression_t *term0 = expr; result = parse_whitespace(input + used, len - used); used += result; operator_t operator; if ('*' == input[used]) operator= OPERATOR_MULTIPLY; else if ('/' == input[used]) operator= OPERATOR_DIVIDE; else break; ++used; result = parse_whitespace(input + used, len - used); used += result; expression_t *term1; result = parse_factor(pool, input + used, len - used, &term1); if (0 >= result) return 0; used += result; expr = allocate_expression(pool); expr->is_number = false; expr->application.operator= operator; expr->application.operands[0] = term0; expr->application.operands[1] = term1; } *out = expr; return used; } int parse_expression( memory_pool_t *pool, const char *input, int len, expression_t **out) { int result, used = 0; result = parse_whitespace(input + used, len - used); used += result; expression_t *expr; result = parse_term(pool, input + used, len - used, &expr); if (0 >= result) return 0; used += result; while (len > used) { const expression_t *term0 = expr; result = parse_whitespace(input + used, len - used); used += result; operator_t operator; if ('+' == input[used]) operator= OPERATOR_ADD; else if ('-' == input[used]) operator= OPERATOR_SUBTRACT; else break; ++used; result = parse_whitespace(input + used, len - used); used += result; expression_t *term1; result = parse_term(pool, input + used, len - used, &term1); if (0 >= result) return 0; used += result; expr = allocate_expression(pool); expr->is_number = false; expr->application.operator= operator; expr->application.operands[0] = term0; expr->application.operands[1] = term1; } *out = expr; return used; }