You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TreeSitter优先级未生效:谓词逻辑语法解析冲突求助

TreeSitter谓词逻辑语法优先级冲突解决

在实现简单谓词逻辑的TreeSitter语法时,需要让否定运算符~的绑定优先级高于合取/\与析取\/,但按现有方式设置优先级后,执行tree-sitter generate时出现解析冲突错误。

原语法代码

module.exports = grammar({
    name: 'Predicate_Calculus',

    rules: {
      // TODO: add the actual grammar rules
      source_file: $ => repeat($._expression),
      _expression: $ => choice($.identifier,
                               $._unary_expression,
                               $._binary_expression,
                               seq('(', $._expression, ')')),
      _binary_expression: $ => choice(
        $.and,
        $.or
      ),
      _unary_expression: $ => prec(2, choice(
        $.not
      )),
      not: $ => seq('~', $._expression),
      and: $ => prec.left(seq($._expression, "/\\", $._expression)),
      or: $ => prec.left(seq($._expression, "\\/", $._expression)),
      identifier: $ => /[a-z_]+/

    }
  });

报错信息

╰─➤ tree-sitter generate
Unresolved conflict for symbol sequence:

  '~'  _expression  •  '/\'  …

Possible interpretations:

  1:  '~'  (and  _expression  •  '/\'  _expression)  (precedence: 0, associativity: Left)
  2:  (not  '~'  _expression)  •  '/\'  …

Possible resolutions:

  1:  Specify a higher precedence in `and` than in the other rules.
  2:  Specify a higher precedence in `not` than in the other rules.
  3:  Specify a left or right associativity in `not`
  4:  Add a conflict for these rules: `not`, `and`

问题原因

你之前给_unary_expression添加prec(2)的方式不生效,因为TreeSitter的优先级设置需要直接作用在具体产生式规则上,而不是包裹规则的choice容器。当前not规则本身没有优先级标记,导致解析器无法识别它和二元运算符的优先级关系。

修复方案

将优先级直接绑定到not规则上,同时明确二元运算符的优先级数值低于not,并给单目否定运算符设置右结合性(符合逻辑运算的常规习惯):

module.exports = grammar({
    name: 'Predicate_Calculus',

    rules: {
      source_file: $ => repeat($._expression),
      _expression: $ => choice(
        $.identifier,
        $.not,
        $.and,
        $.or,
        seq('(', $._expression, ')')
      ),
      // 移除多余的_unary_expression和_binary_expression中间层,简化结构
      not: $ => prec.right(2, seq('~', $._expression)),
      and: $ => prec.left(1, seq($._expression, "/\\", $._expression)),
      or: $ => prec.left(1, seq($._expression, "\\/", $._expression)),
      identifier: $ => /[a-z_]+/
    }
  });

关键修改点

  1. 直接给not规则加优先级:用prec.right(2)修饰not的产生式,2代表优先级高于二元运算符的1,right确保嵌套否定(如~~a)被解析为~(~a),符合逻辑运算习惯。
  2. 明确二元运算符优先级:给and和or设置prec.left(1),数值低于not的2,明确优先级层级。
  3. 简化语法结构:移除_unary_expression和_binary_expression中间规则,直接在_expression中列出所有表达式类型,让优先级关系更清晰。

修改后执行tree-sitter generate即可解决冲突,解析~a /\ b时会正确优先绑定~a,再和b进行合取运算。

内容的提问来源于stack exchange,提问作者asm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:45:36