【发布时间】:2014-05-30 16:12:04
【问题描述】:
到目前为止,我已经搜索了整本“The Definitive ANTLR 4 Reference”一书以及许多网站来寻找我的问题的答案,但我仍然找不到关于该主题的任何内容。
我正在使用 ANTLR 4 创建 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
这样我可以在一个while循环中有多个语句。我的访客类如下所示:
public class EvalVisitor extends ExprBaseVisitor<Integer> {
/** "memory" for our calculator; variable/value pairs go here */
Map<String, Integer> memory;
public EvalVisitor() {
memory = new HashMap<String, Integer>();
}
/** ID '=' expr NEWLINE */
@Override
public Integer visitAssign(ExprParser.AssignContext ctx) {
String id = ctx.ID().getText(); // id is left-hand side of '='
int value = super.visit(ctx.expr()); // compute value of expression on right
memory.put(id, value); // store it in our memory
return value;
}
/** expr NEWLINE */
@Override
public Integer visitPrintExpr(ExprParser.PrintExprContext ctx) {
Integer value = super.visit(ctx.expr()); // evaluate the expr child
System.out.println(value); // print the result
return 0; // return dummy value
}
/** INT */
@Override
public Integer visitInt(ExprParser.IntContext ctx) {
return Integer.valueOf(ctx.INT().getText());
}
/** ID */
@Override
public Integer visitId(ExprParser.IdContext ctx) {
String id = ctx.ID().getText();
if ( memory.containsKey(id) ) return memory.get(id);
return 0;
}
/** expr op=('*'|'/') expr */
@Override
public Integer visitMulDiv(ExprParser.MulDivContext ctx) {
int left = super.visit(ctx.expr(0)); // get value of left subexpression
int right = super.visit(ctx.expr(1)); // get value of right subexpression
if ( ctx.op.getType() == ExprParser.MUL ) return left * right;
return left / right; // must be DIV
}
/** expr op=('+'|'-') expr */
@Override
public Integer visitAddSub(ExprParser.AddSubContext ctx) {
int left = super.visit(ctx.expr(0)); // get value of left subexpression
int right = super.visit(ctx.expr(1)); // get value of right subexpression
if ( ctx.op.getType() == ExprParser.ADD ) return left + right;
return left - right; // must be SUB
}
/** '(' expr ')' */
@Override
public Integer visitParens(ExprParser.ParensContext ctx) {
return super.visit(ctx.expr()); // return child expr's value
}
@Override
public boolean visitGreaterEqual(GreaterEqualContext ctx) {
int left = super.visit(ctx.expr(0));
int right = super.visit(ctx.expr(1));
if(ctx.op.getType() == ExprParser.GREATER) {
return left > right;
}
else {
return left < right;
}
}
@Override
public Integer visitWhileLoop(WhileLoopContext ctx) {
if(visit(ctx.getRuleContext())) {
}
return super.visitWhileLoop(ctx);
}
}
由于我刚刚开始使用 ANTLR 4,因此我从书中获取了大部分访问者类中的代码。我很难相信,除了 while 循环的语法之外,没有提及如何实现Terence Parr 写的书中简单的 While 循环的任何访问者/听众或操作。有人可以帮我为 While 循环编写访问者/侦听器 Java 代码吗?
【问题讨论】:
-
您好,这是来自“语言实现模式”的更多内容:amazon.com/…
-
@TheANTLRGuy 我有那本书,快速浏览了一下,看看我是否能找到如何实现 while 循环,遗憾的是,它没有。
-
您是否看过称为基于树的解释器的模式?第 230 页。我认为它并没有专门执行 while 循环,但它确实返回了 Colin,这要复杂得多。它清楚地显示了如何在树中移动虚拟程序计数器。