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

Menhir配置多解析器时跨文件引用%public规则报错问题

错误原因

你的配置存在以下几个问题,直接导致构建失败:

  • 低级笔误:test_parser.mly里规则绑定的列表变量是el,语义动作里错写成e,触发未定义变量报错。
  • dune配置逻辑错误:merge_into参数的作用是把多个mly文件合并为单个解析器模块,不会生成独立的Parser模块,和你要两个独立解析器的需求完全相悖;同时你新增的menhir stanza和原有stanza都包含parser模块,导致构建规则冲突。
  • 规则引用逻辑错误:Menhir的%public修饰符只是允许规则被其他文件导入,不会自动跨文件生效,你没有在test_parser.mly里显式引入parser.mly的内容,自然找不到expr规则。
  • 声明缺失:规则里用了COMMAtoken,但你既没有在任何mly文件里定义这个token,也没在lexer里加逗号对应的分词规则。
  • 架构隐患:你当前只有一个lexer,如果强行拆成两个独立mly,两个mly生成的token类型是互相独立的,会出现lexer返回的token和解析器期望类型不匹配的错误,额外增加很多兼容成本。
修复方案

你当前场景是同一套词法规则下两个解析入口,优先用单mly多入口的实现方式,这是Menhir官方推荐的多入口写法,零额外兼容成本:

  1. 直接修改parser.mly,补充COMMAtoken定义,新增test入口,修正变量名:
%token <int> INT
%token PLUS
%token EOL
%token COMMA

%left PLUS

%start <int> main
%start <int> test

%%

main:
| e = expr EOL
    { e }

test:
| el = separated_nonempty_list(COMMA, expr) EOL
    { List.fold_left (+) 0 el }

%public expr:
| i = INT { i }
| e1 = expr PLUS e2 = expr { e1 + e2 }
  1. 修改lexer.mll,在分词规则里补充逗号的匹配逻辑:
| ',' { COMMA }
  1. 还原bin/dune配置,删掉之前错误添加的test_parser相关menhir配置和merge_into参数,最终核心配置如下:
(ocamllex
 (modules lexer))

(menhir
 (modules parser)
 (flags --table)
)

(executable
 (name main)
 (public_name program)
 (libraries menhirLib)
)

(rule
 (targets parser_messages.ml)
 (deps parser.messages parser.mly)
 (action  (with-stdout-to %{targets} (run menhir --compile-errors %{deps}))))
  1. 重新生成错误信息文件后构建即可:
menhir --list-errors bin/parser.mly > bin/parser.messages
dune build

构建完成后直接调用Parser.main和Parser.test两个独立入口即可,所有规则自动复用,没有类型冲突。

如果你确实有强需求必须拆成两个独立mly文件(比如两个解析器用完全独立的词法规则、需要独立发布),需要抽离公共token和规则到单独的共享mly文件,再让两个解析器mly通过%include引入共享内容,同时注意要么给每个解析器配独立lexer,要么手动统一两个解析器的token类型,避免类型不匹配问题,这种方式配置成本高,非必要不选。


内容的提问来源于stack exchange,提问作者Lhooq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 13:03:20