Spaces:
Sleeping
Sleeping
| /* tasks/expr/source.c | |
| * Recursive-descent expression evaluator in C. | |
| * Agents must migrate this to Rust. | |
| * | |
| * Key invariants: | |
| * - Division by zero returns an error (Rust: Result::Err / Option::None) | |
| * - Integer arithmetic, no floating point | |
| * - Operator precedence handled by the AST structure (agents build the tree) | |
| */ | |
| typedef enum { OP_ADD, OP_SUB, OP_MUL, OP_DIV } Op; | |
| typedef struct Expr { | |
| enum { EXPR_LIT, EXPR_BINOP } tag; | |
| union { | |
| long long lit; | |
| struct { Op op; struct Expr *left; struct Expr *right; } binop; | |
| }; | |
| } Expr; | |
| /* Returns 1 on success, 0 on division-by-zero */ | |
| int eval_bin_op(Op op, long long a, long long b, long long *out) { | |
| switch (op) { | |
| case OP_ADD: *out = a + b; return 1; | |
| case OP_SUB: *out = a - b; return 1; | |
| case OP_MUL: *out = a * b; return 1; | |
| case OP_DIV: | |
| if (b == 0) return 0; /* division by zero — signal error */ | |
| *out = a / b; /* truncates toward zero */ | |
| return 1; | |
| default: return 0; | |
| } | |
| } | |
| /* Recursively evaluate. Returns 1 on success, 0 on any error. */ | |
| int eval_expr(const Expr *expr, long long *out) { | |
| if (expr->tag == EXPR_LIT) { | |
| *out = expr->lit; | |
| return 1; | |
| } | |
| long long left_val, right_val; | |
| if (!eval_expr(expr->binop.left, &left_val)) return 0; | |
| if (!eval_expr(expr->binop.right, &right_val)) return 0; | |
| return eval_bin_op(expr->binop.op, left_val, right_val, out); | |
| } | |
| /* Helpers to build expression trees */ | |
| Expr *make_lit(long long n) { | |
| Expr *e = malloc(sizeof(Expr)); | |
| e->tag = EXPR_LIT; e->lit = n; | |
| return e; | |
| } | |
| Expr *make_binop(Op op, Expr *left, Expr *right) { | |
| Expr *e = malloc(sizeof(Expr)); | |
| e->tag = EXPR_BINOP; | |
| e->binop.op = op; | |
| e->binop.left = left; | |
| e->binop.right = right; | |
| return e; | |
| } | |
| void free_expr(Expr *e) { | |
| if (!e) return; | |
| if (e->tag == EXPR_BINOP) { | |
| free_expr(e->binop.left); | |
| free_expr(e->binop.right); | |
| } | |
| free(e); | |
| } | |
| int main(void) { | |
| /* (3 + 4) * 2 */ | |
| Expr *e = make_binop(OP_MUL, make_binop(OP_ADD, make_lit(3), make_lit(4)), make_lit(2)); | |
| long long result; | |
| if (eval_expr(e, &result)) | |
| printf("(3+4)*2 = %lld\n", result); | |
| free_expr(e); | |
| /* 10 / 0 — should fail */ | |
| Expr *div0 = make_binop(OP_DIV, make_lit(10), make_lit(0)); | |
| if (!eval_expr(div0, &result)) | |
| printf("10/0 = error (division by zero)\n"); | |
| free_expr(div0); | |
| return 0; | |
| } | |