【问题标题】:Antlr single child tree using rewrite rulesAntlr 使用重写规则的单子树
【发布时间】:2011-07-20 16:41:05
【问题描述】:

我有这个公式:

否定表达式 : NEGATION^* 原子 ;

原子
: 'a'..'z' | 'A'..'Z';

使用上面的语法规则,如果我输入公式 ¬¬a,我会得到这个树结构:

¬ 是根节点, ¬ 被遗弃的孩子;正确的孩子

但是,我想要的是: ¬ 作为根节点, 第二个¬是上述节点的唯一孩子 a 是第二个的唯一孩子 ¬

基本上,我看到所有的 NEGATION 符号都只有一个孩子,这可能吗?我知道我们可能可以使用“重写规则”来重构树,但我不知道该怎么做。

感谢任何帮助或建议!谢谢!

【问题讨论】:

  • ¬ 是根节点,第二个 ¬ 是上述节点的唯一子节点,"a" 是第二个节点的唯一子节点 ¬

标签: antlr binary-tree


【解决方案1】:

重写规则可以遵循解析器规则的每个备选方案。

rule :
   alt1 -> rewriteRule1
 | alt2 -> rewriteRule2
 ...
 | altN -> rewriteRuleN;

您会发现,即使您的解析器语法正常工作,您也可能需要对其进行重构以生成正确的树。为了解决您的具体问题,我建议如下:

negationExpr :
   NEGATION negationExpr 
     -> ^(NEGATION negationExpr)
 | atom 
     -> atom;

这将为每个否定运算符在树中添加一个级别。 ^ 将为紧跟在括号后面的令牌创建一个根,并将下一个 negationExpr 规则的结果添加为子。

【讨论】:

  • 嗨 Adam12,您的解决方案效果很好。感谢您的帮助,不胜感激!
【解决方案2】:

Adam12 的建议是一个优雅的解决方案。我只是对您的(JiandongC)代码 sn-p 有一点意见,以及构建 AST 的另一种可能方式。

请注意,..(范围运算符)在解析器规则中无效!您需要将 atom 设为词法分析器规则,或者执行以下操作:

atom 
  :  LETTER
  ; 

LETTER 
  :  'a'..'z' | 'A'..'Z'
  ;

至于 AST 的创建,您也可以简单地忽略偶数个 NEGATION 令牌,因为 - - 将是正数。

negationExpr 
  :  (NEGATION NEGATION)* ( NEGATION atom -> ^(NEGATION atom)
                          | atom          -> atom
                          )
  ;

如果NEGATION 令牌的数量是奇数,则上面的规则只是构造^(NEGATION atom),否则atom 将被创建为单个节点(根)。

【讨论】:

  • 嗨 Bart Klert,当我发布问题时,我在 atom grammer 中有“..”只是为了让它看起来更容易。我已经有了你建议的。但指出这一点做得很好。
  • @JiandongC,是的,我是这么认为的,但想确定一下:)。阅读您的帖子的人可能会认为它是有效的,并“按原样”尝试。
  • 感谢您关于导入偶数 NEGATION 令牌的建议,这是一个很好的建议,我会考虑的!
  • @JiandongC,没问题。有一些事情要说保持 AST 作为原始来源,然后通过删除 - - 并用 0 替换像 ^(* 0 ^(+ 1 ^(2 / 3))) 这样的树来优化(副本)AST,因为 0 * ...无论如何总是为零,等等。你决定什么时候应该做这些事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多