Spaces:
Sleeping
Sleeping
File size: 2,518 Bytes
bf9c466 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | /* 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)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}
|