即使其他匹配似乎可能,Treesitter 也会产生错误节点

问题描述

我正在尝试使用标识符和文字来解析语言。

b
b""

这里的 b一个标识符,而 b""一个文字(也可能是例如 b"foo")。

我有以下简化语法:

module.exports = grammar({
    name: 'foo',rules: {
        file: $ => repeat(choice(
            $.ident,$.literal,)),ident: _ => /[a-z]/,literal: _ => seq('b',/\"[a-z]*\"/),},});

这会产生以下匹配状态:

(file [0,0] - [2,0]
  (ERROR [0,0] - [0,1])
  (literal [1,0] - [1,3]))
foo.bar 0 ms    (ERROR [0,1])

即,我能够解析像 b"" 这样的构造,但是 ident 的匹配器进入错误分支并且无法恢复。

我已经尝试过 token 没有成功。这里缺少什么?

解决方法

正如@maxbrunsfeld 在 GH 讨论中指出的那样,token 确实是这个玩具示例的答案。

通过以下更改,这个玩具示例确实有效:

-         literal: _ => seq('b',/\"[a-z]*\"/),+         literal: _ => token(seq('b',/\"[a-z]*\"/)),
(file [0,0] - [2,0]
  (ident [0,0] - [0,1])
  (literal [1,0] - [1,3]))

如果 literal 的引用部分的匹配器变得更复杂,这会像预期的那样遇到非终端的常见问题,但这是 token 的一个特性,而不是我发布的示例,例如,

        ident: _ => /[a-z]/,literal: $ => token(seq('b',$.ident)),// WRONG.
Error processing rule literal
Details:
  Grammar error: Unexpected rule Symbol(Symbol { kind: NonTerminal,index: 1 })