commit 262eb4d3ef6079850ac72782a532154e30acaa18
parent d3b19ed080fb15073d1ed3199b1f346c7420c19f
Author: amin <dev@aminmesbah.com>
Date: Sat, 13 Mar 2021 01:59:04 +0000
Evaluate the expression
FossilOrigin-Name: df52d5b264272236a8ab56ac18be2393ce1c62dd9517f1d4d3604c6d17322b0c
Diffstat:
M | build.sh | | | 2 | +- |
M | calc.c | | | 83 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- |
2 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/build.sh b/build.sh
@@ -10,7 +10,7 @@ build_dir="."
cc=clang
source_files=("calc.c")
-cflags=("-std=c99" "-Wall" "-Wextra" "-Wshadow" "-Wsign-compare" "-Wswitch-enum" "-Wno-missing-braces")
+cflags=("-std=c99" "-Wall" "-Wextra" "-Wshadow" "-Wsign-compare" "-Wno-missing-braces")
debug_flags=("-g" "-Og" "-Werror")
# shellcheck disable=SC2207
ldflags=()
diff --git a/calc.c b/calc.c
@@ -390,6 +390,77 @@ Expr *parse_expr(void) {
return parse_expr_add();
}
+int32_t eval_expr(Expr *e) {
+ assert(e);
+
+ switch (e->kind) {
+ case EXPR_OPERAND:
+ return e->operand;
+ break;
+ case EXPR_UNARY: {
+ int32_t val = eval_expr(e->left);
+ switch (e->op) {
+ case TOKEN_OP_SUB:
+ return -val;
+ break;
+ case TOKEN_OP_BIN_NOT:
+ return ~val;
+ break;
+ default:
+ ERROR();
+ break;
+ }
+ } break;
+ case EXPR_BINARY: {
+ int32_t val1 = eval_expr(e->left);
+ int32_t val2 = eval_expr(e->right);
+
+ switch (e->op) {
+ case TOKEN_OP_ADD:
+ return val1 + val2;
+ break;
+ case TOKEN_OP_SUB:
+ return val1 - val2;
+ break;
+ case TOKEN_OP_BIN_OR:
+ return val1 | val2;
+ break;
+ case TOKEN_OP_BIN_XOR:
+ return val1 ^ val2;
+ break;
+ case TOKEN_OP_MUL:
+ return val1 * val2;
+ break;
+ case TOKEN_OP_DIV:
+ if (val2 == 0) {
+ ERROR();
+ }
+ return val1 / val2;
+ break;
+ case TOKEN_OP_MOD:
+ return val1 % val2;
+ break;
+ case TOKEN_OP_SHIFT_L:
+ return val1 << val2;
+ break;
+ case TOKEN_OP_SHIFT_R:
+ return val1 >> val2;
+ break;
+ case TOKEN_OP_BIN_AND:
+ return val1 & val2;
+ break;
+ default:
+ ERROR();
+ break;
+ }
+ } break;
+ case EXPR_NONE: // fallthrough
+ default:
+ ERROR();
+ break;
+ }
+}
+
// precedence climbing
// op_unary = "-" | "~".
// op_mul = "*" | "/" | "%" | "<<" | ">>" | "&".
@@ -400,18 +471,24 @@ Expr *parse_expr(void) {
// expr_add = expr_mul {op_add expr_mul}.
// expr = expr_add.
// number = "0" .. "9" {"0" .. "9"}.
-void parse_test(void) {
+Expr *parse_test(void) {
char *source = "12*34 + 45/56 + ~-25";
printf("parse_test: '%s'\n", source);
g_stream = source;
Expr *e = parse_expr();
print_expr(e);
+ printf("\n");
+ return e;
+}
+
+void eval_test(Expr *e) {
+ printf("Result: %i\n", eval_expr(e));
}
int main(void) {
buf_test();
lex_test();
- parse_test();
- printf("\n");
+ Expr *e = parse_test();
+ eval_test(e);
return 0;
}