Do tej pory przeszukałem całą książkę "The definitive ANTLR 4 Reference", jak również wiele stron, aby znaleźć odpowiedź na moje pytanie i nadal nie mogę znaleźć niczego na temat.Kod użytkownika/odbiornika pętli while w ANTLR 4
Używam ANTLR 4 do tworzenia podzbioru języka C, który wykonuje niektóre podstawowe funkcje. Nie mam pojęcia, jak zaimplementować prostą pętlę while w mojej klasie Visitor. Do tej pory mam to w mojej gramatyce:
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
W ten sposób mógłbym mieć wiele instrukcji wewnątrz pętli while. Moja klasa Visitor wygląda następująco:
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);
}
}
Większość kodu w klasie zwiedzających wziąłem z książki, bo jestem dopiero zaczyna używając ANTLR 4. Trudno mi uwierzyć, że na bok z gramatyki pętli while, nie ma żadnej wzmianki o tym, jak zaimplementować użytkowników/słuchaczy lub akcje dla prostej pętli While w książce napisanej przez Terence'a Parra. Czy ktoś może mi pomóc w pisaniu kodu Java dla odwiedzających/słuchaczy dla pętli While?
Witam, to jest więcej treści z "Wzorców implementacji języka": http: //www.amazon .pl/Language-Implementation-Patterns-Domain-specific-Programming/dp/193435645X/ref = pd_bxgy_b_img_y –
@ TheANTLRGuy Mam tę książkę i rzuciłem okiem na nią, aby sprawdzić, czy mogę znaleźć sposób na wykonanie pętli while i Niestety, tak nie jest. – Greg
Czy spojrzałeś na wzorzec zwany interpreter drzewa? Strona 230. nie robi tego specjalnie podczas pętli, ale to sprawia, że powrót Colina jest znacznie bardziej skomplikowany. Wyraźnie pokazuje, jak przenieść licznik wirtualnego programu przez drzewo. –