2010-10-30 64 views
1

我正在尝试制定一个解析器规则,该规则允许零个或多个第二个规则之前的标记以及每个连续标记 - 这些标记是关闭的一部分 - 在AST中是前一个标记的子标记,第二个规则也是最后一个标记的子标记。使AST节点成为递归规则的最低后裔

更容易的例子来解释......

expression11 : ((NOT | COMPLEMENT)^)* expression12; 

例如,在上述的解析器规则,如果我有表达!x(其中x是一个ID),我想,在我的AST ,x是第二个爆炸操作员的孩子,这是第一个孩子。

期望:

! 
    \ child 
    ! 
     \ child 
     x 

代替我的期望的行为,上面的行产生AST的量,第二砰操作者是第一个孩子,但,x是所述第一砰操作者的子级,第二个的兄弟姐妹。显然不是我想要的一个一元运算符。

遇到行为:

 ! 
child/ \ child 
    x -sib- ! 

如果我添加第三个运营商(如“!X”)的第三个变成第二个孩子,符合市场预期,且x仍然是一个孩子第一,第二个兄弟姐妹。

我想也许我可以通过周围用括号中的整个运营商的部分并添加另一个插入符号解决这个问题,比如

expression11 : (((NOT | COMPLEMENT)^)*)^ expression12; 
在努力迫使expression12是运营商的全封闭的孩子

,盼望这将被解释为“整个关闭的孩子意味着最后裔的孩子”,但事实并非如此,这样做并没有改变行为。

我的问题是“如何让解析器处理规则,使得expression12的结果成为最后代的'NOT'或'COMPLEMENT'节点的子节点而不是最高的祖先节点的子节点? “

我原以为这会很简单,但我无法从antlr.org上的Antlr资源中找出它,也不能恳求Google。它必须始终完成,还是有另一种方法来完全构建我忽略的规则?

以下是完整性规则。他们还没有完成,将被修改,但他们是完整的,并为测试工作,并与他们一切都很好 - 正如预期的那样,因为他们很简单。 12用于数组长度和方法调用,13用于新类和数组,14用于数组索引,15用于终端/括号。

expression12 : expression13 (DOT (LENGTH | (ID LPAREN (expression (COMMA expression)*)? RPAREN)))?; 
expression13 : expression14 | (NEW^ ((ID LPAREN RPAREN) | (INTTYPE LSQBRACK expression RSQBRACK))); 
expression14 : expression15 (LSQBRACK expression RSQBRACK)*; 
expression15 : (LPAREN expression RPAREN) | INTLIT | TRUE | FALSE | ID | THIS; 

谢谢任何​​能够提供帮助的人;你的时间非常感谢。

+0

我必须说你对规则名称的选择是相当混乱。除此之外,一个好的,详细的问题!+1 – 2010-10-30 08:44:36

+0

@Bart Kiers:这是我更大的表达规则的所有部分,每个表达式N规则是不同的优先级别,其中expression1是我的最低优先级运算符(逻辑OR),而expression15是最高优先级运算符。也许不像其他人那样做,但我没有这么长时间,而且还在学习。 – Loduwijk 2010-10-30 14:28:36

回答

2

如果您不希望操作员显示为兄弟姐妹,则不得使用Kleene星。尝试像(未经测试)

expression11 : (NOT | COMPLEMENT)^ expression11 
      | expression12; 
+0

使用您的答案后,我终于在antlr邮件列表中找到了答案(http://antlr.1301665.n2.nabble.com/A-little-trouble-with-parsing-unary-operators-td5067826.html# a5067826)。我认为它必须存在某个地方。无论如何,简单和伟大的作品;非常感谢你。 – Loduwijk 2010-10-30 14:35:50