我怎么计算antlr监听器退出函数中的元素数?

时间:2017-09-29 10:30:12

标签: antlr antlr4

我有这样的语法:

xor_expression
    : or_expression (XOR or_expression)*
    ;

如何计算此规则中发生的(XOR or_expression)*次重复次数。这需要从堆栈有效数量的参数中获取。例如,对于1 xor 1 xor 1 - 1 xor 1需要3,我需要2,等等。

这给了我全部的孩子,但没有关系。

public override void ExitXor_expression([NotNull] preprintParser.Xor_expressionContext context)
{
    Debug.WriteLine(context.ChildCount);
}

3 个答案:

答案 0 :(得分:0)

要计算规则中or_expression个孩子的数量,请使用标签:

xor_expression
    : expr+=or_expression (XOR expr+=or_expression)*
    ;

这将在Xor_expressionContext内产生一个字段

List<ParseTree> expr;

包含实际匹配的or_expression个实例。显然,expr.size()将提供所请求的计数。

答案 1 :(得分:0)

grammar Question;

/* Count xor. */

question
@init {System.out.println("Question last update 1950");}
    :   expr+ EOF
    ;

expr
    :   xor_expression
    ;

xor_expression
    : or_expression ( xors+='xor' or_expression )*
      {System.out.println($text + " : " + $ctx.or_expression().size() + " or_expression with " + $ctx.xors.size() + " XOR" );}
    ;

or_expression
    :   atom
    ;

atom
    :   ID
    |   NUMBER
    ;

ID     : [a-z]+ ;
NUMBER : [0-9]+ ;
WS     : [ \t\r\n]+ -> channel(HIDDEN) ;

输入文件t.text:

1 xor 1
1 xor 1 xor 1

使用ANTLr 4.6执行:

$ grun Question question -tokens -diagnostics t.text
[@0,0:0='1',<NUMBER>,1:0]
[@1,1:1=' ',<WS>,channel=1,1:1]
[@2,2:4='xor',<'xor'>,1:2]
[@3,5:5=' ',<WS>,channel=1,1:5]
[@4,6:6='1',<NUMBER>,1:6]
...
[@16,22:21='<EOF>',<EOF>,3:0]
Question last update 1950
1 xor 1 : 2 or_expression with 1 XOR
1 xor 1 xor 1 : 3 or_expression with 2 XOR

这些数字应该可以从听众那里获取。它们属于规则上下文。解析器提取:

public static class Xor_expressionContext extends ParserRuleContext {
    public Token s1;
    public List<Token> xors = new ArrayList<Token>();
    public List<Or_expressionContext> or_expression() {
        return getRuleContexts(Or_expressionContext.class);
    }

答案 2 :(得分:0)

我(1)稍微修改了你的语法,添加了一个访问者规则,称之为XOR

// file xor.g4
grammar: xor ;
prog : xor_expression+ EOF ;
xor_expression
    : or_expression (XOR or_expression)* NEWLINE          #XOR
    ;
or_expression : 'true' | 'false' ;
XOR : 'XOR' ;
WS  :   [ \t]+ -> skip ; // toss out whitespace
NEWLINE : '\r'? '\n' ;

接下来,antlr xor.g4 -visitor会自动生成xorBaseVisitor.java中的访问者群,其中包含方法visitXOR( xorParser.XORContext ctx )。 (2)我扩展了那个类并重新实现了这个方法,在那里我可以获得两种计数 - 令牌或&#34;真实部分&#34; (我不知道他们在CS中叫什么)

public Integer visitXOR( xorParser.XORContext ctx ) {
    List<xorParser.Or_expressionContext> mylist = ctx.or_expression();
    System.out.println("visitXOR - #or children = " + mylist.size());
    System.out.println("visitXOR - #getChildCount() = " + ctx.getChildCount());
    for( xorParser.Or_expressionContext x : mylist ) {
            System.out.println( "\t" + x.getText() );
    }
    return 0;
}

关键在于xorParser.java,它生成一个规则上下文类,其中包含一个返回or_expression列表的方法

public static class XORContext extends Xor_expressionContext {
    public List<Or_expressionContext> or_expression() {
        return getRuleContexts(Or_expressionContext.class);
    }
...

以下是一个示例运行

$ antlr4 -visitor -no-listener xor.g4  && javac -g XorTest.java *xor*java
Note: XorTest.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
$ java XorTest
true
true XOR false XOR true
^D
visitXOR - #or children = 1
visitXOR - #getChildCount() = 2
        true
visitXOR - #or children = 3
visitXOR - #getChildCount() = 6
        true
        false
        true
$

HTH