Java ANTLR 4中while循环的访问者/侦听器代码

Java ANTLR 4中while循环的访问者/侦听器代码,java,antlr,antlr4,Java,Antlr,Antlr4,到目前为止,我已经搜索了整本“权威的ANTLR 4参考书”以及许多网站来寻找我问题的答案,但我仍然找不到任何关于这个主题的内容 我正在使用Antlr4创建一个C语言的子集,该子集具有一些基本功能。我不知道的是如何在我的访问者类中实现一个简单的while循环。到目前为止,我的语法中有以下内容: grammar Expr; prog: stat+ ; stat: expr NEWLINE # printExpr | ID '=' expr NEW

到目前为止,我已经搜索了整本“权威的ANTLR 4参考书”以及许多网站来寻找我问题的答案,但我仍然找不到任何关于这个主题的内容

我正在使用Antlr4创建一个C语言的子集,该子集具有一些基本功能。我不知道的是如何在我的访问者类中实现一个简单的while循环。到目前为止,我的语法中有以下内容:

grammar Expr;

prog:   stat+ ;

stat:   expr NEWLINE                # printExpr
    |   ID '=' expr NEWLINE         # assign
    |   loop NEWLINE                # whileLoop
    |   relational NEWLINE          # relat
    |   NEWLINE                     # blank 
    ;

expr:   expr op=('*'|'/') expr      # MulDiv
    |   expr op=('+'|'-') expr      # AddSub
    |   INT                         # int
    |   ID                          # id
    |   '(' expr ')'                # parens
    ;

relational:     expr op=(GREATER|LESS) expr     # GreaterEqual
          ;

loop:   'while' '('relational')' NEWLINE? '{'stat*'}'   #while
    ;

GREATER : '>' ;
LESS : '<' ;
MUL :   '*' ; // assigns token name to '*' used above in grammar
DIV :   '/' ;
ADD :   '+' ;
SUB :   '-' ;
ID  :   [a-zA-Z]+ ;      // match identifiers
INT :   [0-9]+ ;         // match integers
NEWLINE:'\r'? '\n' ;     // return newlines to parser (is end-statement signal)
WS  :   [ \t]+ -> skip ; // toss out whitespace
语法表达式;
prog:stat+;
统计:expr新行#printExpr
|ID“=”表达式换行符#分配
|循环换行符#whileLoop
|关系换行符#relat
|换行符#空白
;
expr:expr op=(“*”|“/”)expr#MulDiv
|expr op=(“+”|“-”)expr#AddSub
|INT#INT
|ID#ID
|“(‘expr’)”帕伦斯
;
关系型:expr op=(较大|较小)expr#较大相等
;
循环:“while”“('relational')”换行符{'stat*'}'
;
更大:“>”;
减:"对,;
}
否则{
返回左<右;
}
}
@凌驾
public Integer visitWhileLoop(WhileLoopContext ctx){
如果(访问(ctx.getRuleContext()){
}
返回超级访问权限(ctx);
}
}

visitor类中的大部分代码都是从这本书中获取的,因为我刚刚开始使用ANTLR 4。我发现很难相信,除了while循环的语法之外,Terence Parr所写的书中没有提到如何实现简单while循环的任何访问者/听众或操作。有人能帮我写一个访问者/监听器Java代码来进行一段时间的循环吗

我发现很难相信,除了while循环的语法之外,Terence Parr所写的书中没有提到如何实现简单while循环的任何访问者/听众或操作

这是因为ANTLR引用是关于ANTLR的,它是关于解析的,而不是关于解析后的阶段

你不能这样做:

您已经声明访问者返回
Integer
s,所以每个规则都应该返回这个值。创建一个自定义包装器
Value
,用于封装语言的值(数字、字符串、布尔值),或者在关系表达式为false时仅返回
0

@Override
public Integer visitGreaterEqual(ExprParser.GreaterEqualContext ctx) {
    int left = this.visit(ctx.expr(0));
    int right = this.visit(ctx.expr(1));

    if (ctx.op.getType() == ExprParser.GREATER) {
        return left > right ? 1 : 0; // 0 is false (all other values are true)
    }
    else {
        return left < right ? 1 : 0;
    }
}
请注意,嵌套
while
语句时,上面的代码将失败,因为内部while将返回
0
,导致外部while停止循环。在这种情况下,最好创建一个自定义的
Value
类,并引入某种不会导致循环停止的
Value.VOID
实例

运行以下主要方法:

public static void main(String[] args) throws Exception {

    String expression = "n = 1\n" +
            "while (n < 10) {\n" +
            "  n\n" +
            "  n = n + 1\n" +
            "}\n";
    ExprLexer lexer = new ExprLexer(new ANTLRInputStream(expression));
    ExprParser parser = new ExprParser(new CommonTokenStream(lexer));
    new EvalVisitor().visit(parser.prog());
}
publicstaticvoidmain(字符串[]args)引发异常{
字符串表达式=“n=1\n”+
“而(n<10){\n”+
“n\n”+
“n=n+1\n”+
“}\n”;
ExprLexer lexer=新的ExprLexer(新的antlInputStream(表达式));
ExprParser parser=newexprparser(newcommontokenstream(lexer));
新建EvalVisitor().visit(parser.prog());
}
将打印:

1 2 3 4 5 6 7 8 9 1. 2. 3. 4. 5. 6. 7. 8. 9
还可以看看这个演示语言,它使用ANTLR4和
if
while
语句,以及一个自定义的
对象:

嗨,这是“语言实现模式”中的更多内容:@theantlrgy我有这本书,并快速查看了一下,看看是否可以找到如何实现while循环和,遗憾的是,事实并非如此。您看过称为基于树的解释器的模式吗?第230页。我认为它并没有专门做while循环,但它确实让Colin返回,这要复杂得多。它清楚地显示了如何通过树移动虚拟程序计数器。非常感谢Bart。你的解决方案非常有效!不过有一个问题——我正试图了解访问者方法中所做的工作,这些工作都是由访问者方法完成的。以if语句的实现为例:您所做的是收集列表中的所有条件及其代码块。然后检查哪些条件为真,这样就可以访问对应于该特定条件的语句块-这就是合并条件+语句块的原因,以便轻松找到应该运行的块。我说得对吗?
@Override
public Integer visitWhile(ExprParser.WhileContext ctx) {

    // Evaluate the relational expression and continue the while
    // loop as long as it is true (does not equal zero).
    while (this.visit(ctx.relational()) != 0) {

        // Evaluate all statements inside the while loop.
        for (ExprParser.StatContext stat : ctx.stat()) {
            this.visit(stat);
        }
    }

    // 0 now also is false, so maybe return null instead which would be
    // some sort of VOID value (or make a proper Value class).
    return 0;
}
public static void main(String[] args) throws Exception {

    String expression = "n = 1\n" +
            "while (n < 10) {\n" +
            "  n\n" +
            "  n = n + 1\n" +
            "}\n";
    ExprLexer lexer = new ExprLexer(new ANTLRInputStream(expression));
    ExprParser parser = new ExprParser(new CommonTokenStream(lexer));
    new EvalVisitor().visit(parser.prog());
}
1 2 3 4 5 6 7 8 9