You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Menhir解析含变量的算术表达式时出现值异常求助

问题排查与修复

问题1:变量赋值后相互覆盖

原因分析

代码中变量名没有被正确传递到哈希表中:

  • 词法分析器lexer.mll里,匹配变量名的规则仅返回NAME token,没有把匹配到的具体字符串(比如a、b)传递给语法分析器。
  • 语法分析器parser.mly中,%token NAME没有声明类型,导致var规则返回的$1是默认的unit类型,而非变量名字符串。
  • 所有变量赋值操作都是往哈希表的同一个unit键存储值,最后执行b=2时直接覆盖了a=1的结果,因此查询任何变量都会得到最后存入的2。

修复步骤

  1. 修改parser.mly的token声明:
    将%token NAME改为:

    %token <string> NAME
    

    声明NAME token携带字符串类型的值。

  2. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 23:35:33