AI开发C语言应用按步走,表达式计算器calc的第二十二步,分号赋值链式修复、TOKEN_ASSIGN

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
相关推荐
张张123y44 分钟前
DSH 插件调试避坑:client.js 设置面板、热重载与高频报错排查表
开发语言·javascript·人工智能·开源·ecmascript·后端开发·ai agent
Navigator_Z2 小时前
LeetCode //C - 1317. Convert Integer to the Sum of Two No-Zero Integers
c语言·算法·leetcode
冻柠檬飞冰走茶4 小时前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
FRing034 小时前
vue2干货总结7(自定义指令、插槽、单页应用程序、路由的使用(VueRouter))
开发语言·前端·vue.js·vue2
雪落漂泊4 小时前
C++算法 二分查找篇(上)
开发语言·c++·算法
波力海苔夹心脆6755 小时前
C# WPF 资源字典详解:ResourceDictionary、MergedDictionaries 与自定义控件案例
开发语言·c#·wpf·入门教程·resource·资源字典
不会算法的笨小孩5 小时前
异常的使用以及会出现的问题
开发语言·c++·c++11·异常
Hhy_11078 小时前
《C++深度解构06》手撕 string —— 从底层内存管理到深浅拷贝彻底吃透
c语言·开发语言·c++·学习·visual studio
starzy19908 小时前
深入理解Scala函数定义:从方法到函数的类型跨越
开发语言·scala
starzy19908 小时前
深入理解Scala递归函数:从栈溢出到尾调用优化
开发语言·scala