Bisher habe ich das ganze "The Definitive ANTLR 4 Reference" Buch sowie viele Websites für eine Antwort auf meine Frage gesucht und ich kann immer noch nichts finden auf der Thema.Besucher/Listener-Code für eine While-Schleife in ANTLR 4
Ich benutze ANTLR 4, um eine Untergruppe der C-Sprache zu erstellen, die einige grundlegende Funktionen ausführt. Worüber ich keine Ahnung habe, ist die Implementierung einer einfachen while-Schleife in meiner Visitor-Klasse. Bisher habe ich das in meiner Grammatik:
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
So könnte ich mehrere Anweisungen innerhalb einer While-Schleife haben. Meine Besucher Klasse sieht wie folgt aus:
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);
}
}
Der meiste Code in der Besucher Klasse i aus dem Buch nahm, weil ich gerade bin angefangen mit ANTLR 4. Ich finde es schwer zu glauben, dass, abgesehen Von der Grammatik für die While-Schleife wird nicht erwähnt, wie man Besucher/Listener oder Aktionen für eine einfache While-Schleife in dem von Terence Parr geschriebenen Buch implementiert. Kann mir jemand helfen, einen Besucher-/Listener-Java-Code für eine While-Schleife zu schreiben?
Hallo, das ist mehr Inhalt von "Language Implementation Patterns": http: //www.amazon/Language-Implementation-Patterns-Domain-Specific-Programmierung/dp/193435645X/ref = pd_bxgy_b_img_y –
@TheANTLRGuy Ich habe dieses Buch und schaute es mir kurz an, um zu sehen, ob ich finden konnte, wie man eine While-Schleife implementiert und Leider tut es das nicht. – Greg
Haben Sie sich das Muster namens Baum-basierter Interpreter angesehen? Seite 230. Es macht nicht speziell while-Schleifen, die ich denke, aber es bringt Colin zurück, die viel komplizierter ist. Es zeigt deutlich, wie man einen virtuellen Programmzähler durch einen Baum bewegt. –