如何在Tree-sitter语法中解析带可选模块前缀的类型标识符?
ASN.1类型标识符的Tree-sitter语法解析问题
我需要解析ITU-T建议X.680至X.683中定义的ASN.1类型标识符,该标识符支持两种合法形式:带模块前缀的MyModule.MyType,以及不带前缀的MyType,且模块名与类型标识符的语法完全一致。
我当前编写的Tree-sitter语法如下:
DefinedType: $ => prec.right(seq( optional(seq($.modulereference, '.')), alias($.uppercased_identifier, 'typereference'), optional($.ActualParameterList), )),
但解析XSD.String时,Tree-sitter会将XSD识别为typereference,遇到句点时直接报错。我尝试过使用prec.right()、prec.left()以及conflicts配置,都无法让解析器选择最长的匹配项。想请教这种可选前缀的解析在Tree-sitter中是否可行,以及正确的实现方式是什么?
解决方案
这种可选前缀的解析是可行的,问题出在原语法用optional包裹前缀的方式,会让Tree-sitter优先匹配更短的不带前缀结构。调整语法定义的方式即可解决:
- 显式区分两种匹配分支:将
DefinedType定义为包含两个分支的choice,分别对应带模块前缀和不带前缀的情况。 - 给带前缀分支设置更高优先级:确保解析器优先尝试匹配更长的带前缀结构,失败后再退回到不带前缀的情况。
调整后的语法代码:
DefinedType: $ => prec(1, choice( // 带模块前缀的分支,优先级更高 seq( $.modulereference, '.', alias($.uppercased_identifier, 'typereference'), optional($.ActualParameterList) ), // 不带前缀的分支 seq( alias($.uppercased_identifier, 'typereference'), optional($.ActualParameterList) ) ))
关键说明
- 原语法中的
optional会让解析器先尝试跳过前缀部分,直接匹配typereference,导致更长的带前缀匹配被忽略。 - 显式的
choice结构配合优先级设置,能强制解析器先检查是否存在带前缀的完整结构,再处理不带前缀的情况。 - 需确保
modulereference的语法定义与typereference的基础规则完全一致(比如都是符合ASN.1规范的大写标识符),这样解析器才能正确识别前缀部分。
内容的提问来源于stack exchange,提问作者Jonathan Wilbur
相关产品推荐
相关产品推荐

