Tree-sitter中token.immediate对命名Extra Token失效问题求助
解决Tree-sitter命名Extra下token.immediate()失效的问题
当你把空格从匿名Extra改成命名Extra(如$.s)后,token.immediate()确实会失效——这个方法只对不生成语法树节点的内联正则Extra生效。针对你这个单个a对应(a)、连续无空格aa对应(b)的场景,可以通过优先级控制+原子token定义来解决:
具体实现方案
直接调整语法规则的优先级,让连续无空格的aa匹配优先于单个a,同时用token()将连续序列标记为不可分割的原子单元,避免Extra插入干扰。示例代码如下:
module.exports = grammar({ name: 'your_lang', extras: ($) => [$.s], // 命名空格Extra,会出现在输出树中 rules: { source_file: ($) => repeat(choice($.b, $.a)), // 用prec.highest赋予最高优先级,确保无空格aa被优先匹配 b: ($) => prec.highest(token(seq('a', 'a'))), a: ($) => 'a', s: ($) => /\s+/, } });
原理说明
- 优先级控制:通过
prec.highest让b规则的匹配优先级远高于a,当解析器遇到连续的aa时,会优先匹配b,而非拆成两个a。 - 原子token:
token(seq('a', 'a'))将两个a标记为一个整体原子,解析器不会在这个序列内部插入任何Extra(包括你的命名空格$.s),完美实现"连续无空格"的匹配要求。 - 命名Extra保留:
$.s作为命名Extra仍然会被解析到语法树中,满足你后续注释高亮等需求。
如果需要更精细的优先级调整,也可以通过precedences字段显式声明规则优先级,效果和prec.highest一致:
module.exports = grammar({ name: 'your_lang', extras: ($) => [$.s], rules: { source_file: ($) => repeat(choice($.b, $.a)), b: ($) => token(seq('a', 'a')), a: ($) => 'a', s: ($) => /\s+/, }, precedences: ($) => [ [$.b, $.a] // 声明b的优先级高于a ] });
内容的提问来源于stack exchange,提问作者uben
相关产品推荐
相关产品推荐

