calc22 --- 分号赋值链式修复、TOKEN_ASSIGN
1. 概述
本次迭代修复了 a=5;b=6;a+b 分号链式赋值失败的 Bug,并新增 TOKEN_ASSIGN 运算符 token,使表达式求值器内部支持赋值操作。
Bug 表现:
calc> a=5;b=6;a+b
error: undefined variable 'b'
修复后:
calc> a=5;b=6;a+b
a = 5
b = 6
5 + 6 = 11
result: 11
2. 变更清单
| 文件 | 操作 | 说明 |
|---|---|---|
parse.h |
编辑 | TokenType 新增 TOKEN_ASSIGN |
parse.c |
编辑 | switch 增加 case '=':;update_expect/token_name 同步更新 |
eval.c |
编辑 | parse_factor 中标识符后检测 TOKEN_ASSIGN,解析 RHS 并调用 sym_set |
main.c |
编辑 | is_assignment 中 = 使用 TOKEN_ASSIGN;parse_and_eval 和 repl 中简单 = 跳过 is_assignment 路径,由 eval_exprs 处理 |
3. Bug 根因分析
3.1 问题路径
输入 a=5;b=6;a+b 在 REPL 中的执行路径:
is_assignment("a=5;b=6;a+b")
→ 检测到第一个 '=',var_name="a",RHS="5;b=6;a+b"
eval_exprs("5;b=6;a+b")
→ 解析 "5" → OK
→ 遇到 ';' → 继续
→ 解析 "b=6" → '=' 不是合法 token (TOKEN_ERROR)
→ parse_factor 未识别为赋值,走变量查找
→ sym_get("b") 返回 1 → 打印 "undefined variable 'b'"
3.2 三个叠加问题
| # | 问题 | 位置 |
|---|---|---|
| 1 | = 不是合法 token,被解析为 TOKEN_ERROR |
parse.c |
| 2 | parse_factor 中标识符后遇 = 不会识别为赋值 |
eval.c |
| 3 | is_assignment 只处理输入中第一个 =,eval_exprs 内部的分号后赋值不受理 |
main.c + eval.c |
4. 修复方案
4.1 parse.h --- 新增 TOKEN_ASSIGN
c
TOKEN_ASSIGN, /**< = */
4.2 parse.c --- 识别 = 为合法 token
c
case '=': tok.type = TOKEN_ASSIGN; break;
4.3 eval.c --- parse_factor 中处理赋值
在 parse_factor 的 TOKEN_IDENTIFIER 分支中,检测 TOKEN_ASSIGN:
c
if (next.type == TOKEN_ASSIGN) {
parse_consume();
long double val = parse_expr();
if (eval_error) return 0.0;
sym_set(t.data.name, val);
if (print_steps) printf(" %s = %Lg\n", t.data.name, val);
return val;
}
4.4 main.c --- 简单 = 由 eval_exprs 处理
is_assignment 中 = 使用 TOKEN_ASSIGN:
c
if (*p == '=' && *(p+1) != '=') { *op = TOKEN_ASSIGN; return 1; }
parse_and_eval 和 repl 中,仅对复合赋值(+= -= 等)走 is_assignment 路径,简单 = 由 eval_exprs 统一处理。
5. 测试验证
bash
$ make test
============================================
calc --- 测试套件
============================================
124 passed, 0 failed, 124 total
============================================
$ ./build/calc "a=5;b=6;a+b"
11
$ printf 'a=5;b=6;a+b\nexit\n' | ./build/calc
calc> a = 5
b = 6
5 + 6 = 11
result: 11