在JavaScript的Peggy语法中集成Lexer Token的问题
解决Peggy语法中使用Moo Token的栈溢出与语法错误问题
核心问题分析
- 栈溢出原因:规则名与Moo定义的token类型重名,导致Peggy递归调用规则而非匹配token,引发无限循环。例如
identifier = $identifier中,规则identifier和token类型identifier同名,Peggy会不断调用规则本身,最终栈溢出。 - 语法错误原因:Peggy动作代码块中返回对象时未使用
return关键字,直接写{ type: ... }会被解析为代码块而非返回值,导致语法错误。
修正方案
步骤1:调整Peggy语法文件
修改grammar.peggy,避免规则名与token类型重名,并正确使用动作代码返回结果:
start = sentence sentence = action:$action _ object:$object { return { action: { type: "action", value: action }, object: { type: "object", value: object } }; } _ "whitespace" = [ \t\n\r]*
步骤2:优化Moo Lexer(可选)
为避免匹配到包含目标词汇的长单词,给正则添加单词边界\b,确保只匹配完整的动作或对象词汇:
let lexer = moo.compile({ object: { match: new RegExp(`\\b(${objects.join('|')})\\b`), type: 'object', }, identifier: { match: /[a-z]+/, type: moo.keywords({ action: actions, }), }, and: { match: new RegExp(`\\b(${andOperator.join('|')})\\b`), }, or: { match: new RegExp(`\\b(${orOperator.join('|')})\\b`), }, whitespace: {match: /\s+/, lineBreaks: true}, });
步骤3:重新生成并测试
- 用Peggy CLI重新生成解析器:
peggy grammar.peggy -o parser.js
- 运行测试脚本:
node test.js
此时输入take book会输出结构化的解析结果:
{ action: { type: 'action', value: 'take' }, object: { type: 'object', value: 'book' } }
关键知识点说明
- 在Peggy中,使用
$<token类型>语法直接匹配Moo生成的对应类型token,无需定义同名规则。 - 动作代码块中返回值必须显式使用
return,否则对象字面量会被解析为代码块结构,导致语法错误。 - Moo的
keywords会将匹配到的关键词标记为指定token类型,因此actions数组中的词汇会被识别为action类型token,而非普通identifier。
内容的提问来源于stack exchange,提问作者Suppenterrine
相关产品推荐
相关产品推荐

