我正在尝试制作一个解析器规则,该规则在第二个规则之前允许零个或多个令牌,并且每个连续令牌 - 属于闭包的那些 - 在AST中是一个子节点上一个标记,第二个规则也是最后一个符号的子项。
通过示例更容易解释......
expression11 : ((NOT | COMPLEMENT)^)* expression12;
例如,给定上面的解析器规则,如果我有表达式!! x(其中x是一个ID),我希望在我的AST中,x是第二个bang运算符的子节点,即子节点第一个。
所需:
!
\ child
!
\ child
x
而不是我想要的行为,上面的行产生一个AST,第二个bang操作符是第一个的子节点,但x是第一个bang操作符的子节点,第二个操作符的兄弟节点。显然不是我想要的一元操作员。
遇到的行为:
!
child / \ child
x -sib- !
如果我添加第三个运算符(如“!!! x”),第三个运算符将成为第二个运算符的子项,正如预期的那样,x仍然是第一个运算符的子项,第二个运算符的第二个。
我想也许我可以通过用括号括起整个运算符部分并添加另一个插入符来解决这个问题,例如
expression11 : (((NOT | COMPLEMENT)^)*)^ expression12;
努力迫使表达式12成为整个操作员关闭的孩子,希望这会被解释为“整个关闭的孩子意味着最后裔的孩子”,但这不是这种情况并没有改变行为。
我的问题是“如何让解析器处理规则,使得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 :(得分:2)
如果您不希望运算符显示为兄弟姐妹,则不得使用Kleene星。尝试类似(未经测试的)
expression11 : (NOT | COMPLEMENT)^ expression11
| expression12;