求助:解决Tree-sitter语法中的未解析冲突问题
解决Tree-sitter标识符组语法的未解析冲突
需求与示例
目标语法规则:
- 独立的
identifier作为组(group)的名称与起始标记 - 格式为
identifier = identifier的行作为当前组的公式(formula)条目
示例代码:
identifier identifier = identifier identifier = identifier identifier identifier = identifier identifier = identifier
期望生成的语法树:
document group name formula formula group name formula formula
冲突错误信息
Tree-sitter抛出如下未解析冲突:
Unresolved conflict for symbol sequence: identifier _nl_eof • identifier … Possible interpretations: 1: (group identifier _nl_eof • group_repeat1) 2: (group identifier _nl_eof) • identifier … Possible resolutions: 1: Specify a left or right associativity in `group` 2: Add a conflict for these rules: `group`
问题根源
冲突源于解析器无法判断换行后的identifier属于哪种情况:
- 是前一个组的后续内容(尽管需求中组内除名称外只能是带
=的公式,但原始规则未明确约束组内内容的格式) - 是新组的名称标记
解决方案
方案1:明确组规则的左关联性(推荐)
通过prec.left()指定组规则的左结合性,强制解析器将每个独立的identifier视为新组的开始,同时明确组内公式必须以换行符开头,与组名区分开。
修正后的完整语法规则示例:
module.exports = grammar({ name: 'your_custom_lang', rules: { document: $ => repeat($.group), // 指定左结合,明确组的边界 group: $ => prec.left(seq( $.name, // 公式必须紧跟换行符,避免与新组名混淆 repeat(seq($._nl, $.formula)) )), name: $ => $.identifier, formula: $ => seq($.identifier, '=', $.identifier), identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/, _nl: $ => /\n+/, _ws: $ => /\s+/, }, // 忽略空白字符(除换行外) extras: $ => [$._ws], });
方案2:添加冲突声明
如果左关联性不适用场景,可以显式为group规则添加冲突标记,告知Tree-sitter允许该歧义并选择正确的解析路径:
group: $ => conflict(seq( $.name, repeat(seq($._nl, $.formula)) )),
关键细节补充
- 必须确保公式规则强制包含
=符号,避免解析器将裸identifier误判为公式 - 通过
seq($._nl, $.formula)明确公式与组名的分隔方式,消除边界歧义
内容的提问来源于stack exchange,提问作者redexp
相关产品推荐
相关产品推荐

