Parsing 将规则添加到TreeSetter LR1语法会更改优先级
我试图在TreeSetter语法中获得正确的运算符优先级。Treesitter是一个LR1解析器生成器 我有一个简单的艺术语法,部分如下:Parsing 将规则添加到TreeSetter LR1语法会更改优先级,parsing,lr1,treesitter,Parsing,Lr1,Treesitter,我试图在TreeSetter语法中获得正确的运算符优先级。Treesitter是一个LR1解析器生成器 我有一个简单的艺术语法,部分如下: multiply_expression: $ => prec.left(2, seq( $._expression, '*', $._expression, )), addition_expression: $ => prec.left(1, seq( $._expression, '+', $.
multiply_expression: $ => prec.left(2, seq(
$._expression,
'*',
$._expression,
)),
addition_expression: $ => prec.left(1, seq(
$._expression,
'+',
$._expression,
)),
这是正确的<代码>乘法表达式的优先级确实高于加法表达式
但是,当我添加中间规则时,优先级会发生变化:
_partial_multi: $ => seq(
$._expression,
'*',
),
multiply_expression: $ => prec.left(2, seq(
$._partial_multi,
$._expression,
)),
我将$.expression“*”
移动到它自己的规则。对我来说,这似乎是一个等价的语法,我希望不会有任何变化。但是,随着此更改,优先级不再正确<代码>加法表达式保持不变,其优先级似乎高于乘法表达式
为什么引入额外步骤会改变优先级?这个问题有名字吗,或者在哪里可以找到更多的信息?在编写语法或解决优先级问题时,是否有需要遵循的规则或思考的方法?以下是您的完整语法,以确保再现性:
module.exports = grammar({
name: 'github_example',
conflicts: $ => [],
rules: {
source_file: $ => $._expression,
_expression: $ => choice(
$.number,
$.multiply_expression,
$.addition_expression
),
number: $ => /\d+/,
_partial_multi: $ => seq(
$._expression,
'*',
),
multiply_expression: $ => prec.left(2, seq(
$._partial_multi,
$._expression,
)),
addition_expression: $ => prec.left(1, seq(
$._expression,
'+',
$._expression,
)),
}
});
您可以通过向\u partial\u multi
规则添加优先级并从multiply\u表达式中删除左关联优先级来解决此问题:
_partial_multi: $ => prec(2, seq(
$._expression,
'*',
)),
multiply_expression: $ => seq(
$._partial_multi,
$._expression,
),
这里所做的是将乘法作为优先级为2的右联想运算符。这就是在语法中定义左或右关联性的方法,这些语法不会将其公开为原语。您可以通过如下方式将乘法设置为左关联:
_partial_multi: $ => prec(2, seq(
'*',
$._expression,
)),
multiply_expression: $ => seq(
$._expression,
$._partial_multi,
),
实际上,您偶然发现了一件非常有趣的事情,即您不需要显式的语言构造来定义语法中的优先级和关联性!它们只是“语法糖”,使语法更容易读写。有关如何通过分解规则指定优先级和关联性的详细信息,请参见。您可以看到,纯粹通过语法结构来指定优先级和关联性是令人困惑的,除非您仔细考虑,否则几乎会从您期望的内容中反向读取!正如您还发现的,混合使用这两种方法(通过语言结构和语法结构指定优先级和关联性)可能会导致混淆行为。最好坚持使用其中一种方法。我不知道TreeSetter如何重新排序和解决冲突的细节,但在我看来,您似乎还没有告诉解析器生成器如何解决涉及\u partial\u multi
的冲突。你应该给那个作品分配一个优先权。而且,像往常一样,如果你在问题中加入了一个,你会更容易得到帮助。摘录不容易测试。说完这些,我模糊地试图填写一个测试文件,并应用了我在第一条评论中提出的建议。它似乎起作用了。正如您所报告的那样,原始测试(基于您的摘录)只是解析错误;不会发出歧义警告。(对于bison,它使用不同的优先级配置方式,会为您的语法发布冲突报告。)