使用Menhir解析含变量的算术表达式时出现值异常求助
问题排查与修复
问题1:变量赋值后相互覆盖
原因分析
代码中变量名没有被正确传递到哈希表中:
- 词法分析器
lexer.mll里,匹配变量名的规则仅返回NAMEtoken,没有把匹配到的具体字符串(比如a、b)传递给语法分析器。 - 语法分析器
parser.mly中,%token NAME没有声明类型,导致var规则返回的$1是默认的unit类型,而非变量名字符串。 - 所有变量赋值操作都是往哈希表的同一个
unit键存储值,最后执行b=2时直接覆盖了a=1的结果,因此查询任何变量都会得到最后存入的2。
修复步骤
修改
parser.mly的token声明:
将%token NAME改为:%token <string> NAME声明NAME token携带字符串类型的值。
修改
lexer.mll的变量名匹配规则:
将|['a'-'z']+ {NAME}改为:|['a'-'z']+ as lxm { NAME lxm }把匹配到的变量名字符串传递给语法分析器。
问题2:a-b结果为0
原因分析
这个问题是问题1的连锁反应:因为a和b的实际取值都是哈希表中unit键对应的2,所以2-2=0。解决问题1后,该结果会自动修正为1-2=-1。
额外优化:运算符优先级调整
当前代码中%left SUB EQUAL将减法和赋值设为相同优先级,这会导致类似a=1-b的表达式被错误解析为(a=1)-b,不符合常规的表达式优先级逻辑。建议调整为:
%left SUB %right EQUAL
这样赋值操作优先级更低且为右结合,符合常规表达式的解析习惯。
其他小问题(非当前异常原因)
calc.ml中open Syntax但未提供syntax.ml代码,可以移除该行或补充对应的syntax文件。makefile的calc.cmo规则中重复编译了lexer.ml、parser.mli和parser.ml,可以简化为仅编译calc.ml,因为其他目标已经处理了这些文件的编译。
内容的提问来源于stack exchange,提问作者wang kai
相关产品推荐
相关产品推荐

