在树保姆语法中,如何匹配标识符中保留关键字以外的字符串?
In a tree-sitter grammar, how do I match strings except for reserved keywords in identifiers?
这可能与我不了解 Keyword Extraction 功能有关,从文档看来,这似乎是为了避免关键字和以下表达式之间不存在 space 的问题。但是假设我有一个相当标准的变量名、函数名等标识符正则表达式:
/\w*[A-Za-z]\w*/
如何防止它匹配 IF
或 ELSE
之类的保留关键字?所以这个表达式会产生一个错误:
int IF = 5;
虽然这不会:
int x = 5;
有 a pull request pending since 2019 to add an EXCLUDE feature,但截至撰写本文时尚未实施(2021 年 4 月 - 如果过了一段时间而您正在阅读本文,请重新检查!)。并且由于 treesitter 也不支持其正则表达式中的负面回溯,因此必须在语义级别进行处理。您可以做的一件事是使此检查更容易,即枚举所有保留字,然后将它们添加为标识符正则表达式的替代项:
keyword: $ => choice('IF', 'THEN', 'ELSE'),
name: $ => /\w*[A-Za-z]\w*/,
identifier: $ => choice($.keyword, $.name)
根据 treesitter 的 match rules 规则 4,在表达式 int IF = 5;
中,IF
标记将匹配 (identifier keyword)
而不是 (identifier name)
,因为它是一个更具体的匹配。这意味着您可以轻松查询非法 (identifier keyword)
节点,并在您的语言服务器中或从您使用 treesitter 语法的任何地方向用户显示错误。
请注意,此方法 运行 存在在您的 (identifier keyword)
匹配项与使用这些关键字的实际语言结构之间产生许多冲突的风险。如果是这样,您将不得不在语义级别处理整个事情:扫描所有标识符以检查它们是否是保留字。
这可能与我不了解 Keyword Extraction 功能有关,从文档看来,这似乎是为了避免关键字和以下表达式之间不存在 space 的问题。但是假设我有一个相当标准的变量名、函数名等标识符正则表达式:
/\w*[A-Za-z]\w*/
如何防止它匹配 IF
或 ELSE
之类的保留关键字?所以这个表达式会产生一个错误:
int IF = 5;
虽然这不会:
int x = 5;
有 a pull request pending since 2019 to add an EXCLUDE feature,但截至撰写本文时尚未实施(2021 年 4 月 - 如果过了一段时间而您正在阅读本文,请重新检查!)。并且由于 treesitter 也不支持其正则表达式中的负面回溯,因此必须在语义级别进行处理。您可以做的一件事是使此检查更容易,即枚举所有保留字,然后将它们添加为标识符正则表达式的替代项:
keyword: $ => choice('IF', 'THEN', 'ELSE'),
name: $ => /\w*[A-Za-z]\w*/,
identifier: $ => choice($.keyword, $.name)
根据 treesitter 的 match rules 规则 4,在表达式 int IF = 5;
中,IF
标记将匹配 (identifier keyword)
而不是 (identifier name)
,因为它是一个更具体的匹配。这意味着您可以轻松查询非法 (identifier keyword)
节点,并在您的语言服务器中或从您使用 treesitter 语法的任何地方向用户显示错误。
请注意,此方法 运行 存在在您的 (identifier keyword)
匹配项与使用这些关键字的实际语言结构之间产生许多冲突的风险。如果是这样,您将不得不在语义级别处理整个事情:扫描所有标识符以检查它们是否是保留字。