calc

Simple math expression parser.
git clone git://git.amin.space/calc.git
Log | Files | Refs | LICENSE

commit 3c99feab11f34771533a26f7ed325eb0905a19df
parent 262eb4d3ef6079850ac72782a532154e30acaa18
Author: amin <dev@aminmesbah.com>
Date:   Tue,  4 May 2021 19:04:08 +0000

Add explicit grouping of sub expressions

FossilOrigin-Name: c3a40f0302c0b53419907eb98ec5922ad242771ec73c8630a14dc18ebd8b0edf
Diffstat:
Mcalc.c | 29+++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/calc.c b/calc.c @@ -84,6 +84,8 @@ void buf_test(void) { X(TOKEN_OP_SHIFT_R, ">>") \ X(TOKEN_OP_BIN_AND, "&") \ X(TOKEN_OP_BIN_NOT, "~") \ + X(TOKEN_PAREN_L, "(") \ + X(TOKEN_PAREN_R, ")") \ X(TOKEN_INT, "") \ \ X(_TOKEN_KIND_COUNT, "") @@ -195,6 +197,8 @@ char *lex_next_token(Token *out_t) { case '%': out_t->kind = TOKEN_OP_MOD; cursor++; break; case '&': out_t->kind = TOKEN_OP_BIN_AND; cursor++; break; case '~': out_t->kind = TOKEN_OP_BIN_NOT; cursor++; break; + case '(': out_t->kind = TOKEN_PAREN_L; cursor++; break; + case ')': out_t->kind = TOKEN_PAREN_R; cursor++; break; case '\0': out_t->kind = TOKEN_NONE; break; @@ -223,14 +227,14 @@ Token token_consume(void) { return t; } -Token token_consume_kind(enum TokenKind kind) { +bool token_consume_kind(enum TokenKind kind) { Token t = token_peek(); if (token_is_kind(t, kind)) { token_consume(); + return true; } else { - t = (Token){0}; + return false; } - return t; } Token token_require_kind(enum TokenKind kind) { @@ -358,12 +362,24 @@ Expr *parse_expr_operand(void) { return e; } +Expr *parse_expr(void); + +Expr *parse_expr_grouping(void) { + if (token_consume_kind(TOKEN_PAREN_L)) { + Expr *e = parse_expr(); + token_require_kind(TOKEN_PAREN_R); + return e; + } else { + return parse_expr_operand(); + } +} + Expr *parse_expr_unary(void) { if (is_unary_op(token_peek().kind)) { enum TokenKind op = token_consume().kind; return expr_unary(op, parse_expr_unary()); } else { - return parse_expr_operand(); + return parse_expr_grouping(); } } @@ -465,14 +481,15 @@ int32_t eval_expr(Expr *e) { // op_unary = "-" | "~". // op_mul = "*" | "/" | "%" | "<<" | ">>" | "&". // op_add = "+" | "-" | "|" | "^". -// exp_operand = number. +// expr_operand = number. +// expr_grouping = "(" expr ")" // expr_unary = ([op_unary] exp_unary) | exp_base. // expr_mul = expr_unary {op_mul expr_unary}. // expr_add = expr_mul {op_add expr_mul}. // expr = expr_add. // number = "0" .. "9" {"0" .. "9"}. Expr *parse_test(void) { - char *source = "12*34 + 45/56 + ~-25"; + char *source = "12*34 + 45/56 + ~-25 + ((4+6) / (6+4))"; printf("parse_test: '%s'\n", source); g_stream = source; Expr *e = parse_expr();