我的任务是实现一个访问者,该访问者会将以下将算术表达式求值的语法转换为AST:
grammar SmallC;
program : exp
;
exp : lexp ((op = '>' | op = '<' |op = '>=' | op = '<=' | op = '!=' | op = '==') lexp)?
;
lexp : term ((op = '+'|op = '-') term)*
;
term: factor((op = '%'| op = '\*'| op = '/') factor)*
;
factor : Number
;
Number : [0-9]+
;
当前,ANTLR为表达式“ 3 * 6”创建以下树:
程序-> exp-> lexp->项->(factor * factor)-> Number->(3 * 6)
我想要的是这样的:
程序->乘法(3,6)
我尝试通过实现可遍历树并输出某些数据结构的访问者函数来开始使用此函数,但是它失败了。这是我的课程:
主Java
import org.antlr.v4.runtime.*;
public class Main {
public static void main(String[] args) {
ANTLRInputStream input = new ANTLRInputStream("3*6");
SmallCLexer lexer = new SmallCLexer(null);
lexer.setInputStream(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
tokens.fill();
SmallCParser parser = new SmallCParser(null);
parser.setBuildParseTree(true);
parser.setTokenStream(tokens);
ParserRuleContext tree = parser.program();
MyVisitor visitor = new MyVisitor();
visitor.visit(tree);
}
}
MyVisitor.java
import org.antlr.v4.runtime.*;
public class MyVisitor extends SmallCBaseVisitor<SmallCNode> {
@Override public SmallCNode visitExp(SmallCParser.ExpContext ctx) {
if ( ctx.lexp().size() == 2) {
SmallCLexp lhs = (SmallCLexp) ctx.lexp(0).accept(this);
SmallCLexp rhs = (SmallCLexp) ctx.lexp(1).accept(this);
String op = ctx.op.getText();
return new SmallCExp(lhs,rhs,op);
} else {
visitLexp(ctx.lexp(0));
}
}
@Override public SmallCNode visitLexp(SmallCParser.LexpContext ctx) {
if ( ctx.term().size() == 2) {
SmallCTerm lhs = (SmallCTerm) ctx.term(0).accept(this);
SmallCTerm rhs = (SmallCTerm) ctx.term(1).accept(this);
String op = ctx.op.getText();
return new SmallCLexp(lhs,rhs,op);
} else {
visitTerm(ctx.term(0));
}
}
@Override public SmallCNode visitTerm(SmallCParser.TermContext ctx) {
if (ctx.factor().size() == 2) {
SmallCFactor lhs = (SmallCFactor) ctx.factor(0).accept(this);
SmallCFactor rhs = (SmallCFactor) ctx.factor(1).accept(this);
String op = ctx.op.getText();
return new SmallCTerm(lhs,rhs,op);
} else {
visitFactor(ctx.factor(0));
}
}
@Override public SmallCNode visitFactor(SmallCParser.FactorContext ctx) {
String fc = ctx.getText();
return new SmallCFactor(fc);
}
这是我的节点类:
public class SmallCNode {
}
public class SmallCExp extends SmallCNode{
SmallCLexp lhs;
SmallCLexp rhs;
String op;
public SmallCExp(SmallCLexp lhs, SmallCLexp rhs, String op) {
super();
this.lhs = lhs;
this.rhs = rhs;
this.op = op;
}
}
public class SmallCLexp extends SmallCNode {
SmallCTerm lhs;
SmallCTerm rhs;
String op;
public SmallCLexp(SmallCTerm lhs, SmallCTerm rhs, String op) {
super();
this.lhs = lhs;
this.rhs = rhs;
this.op = op;
}
}
public class SmallCTerm extends SmallCNode{
SmallCFactor lhs;
SmallCFactor rhs;
String op;
public SmallCTerm(SmallCFactor lhs, SmallCFactor rhs, String op) {
super();
this.lhs = lhs;
this.rhs = rhs;
this.op = op;
}
}
public class SmallCFactor extends SmallCNode {
String factor;
public SmallCFactor(String factor) {
super();
this.factor = factor;
}
}
当我运行Main.java时,出现以下错误:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
This method must return a result of type SmallCNode
at MyVisitor.visitExp(MyVisitor.java:8)
at MyVisitor.visitExp(MyVisitor.java:1)
at SmallCParser$ExpContext.accept(SmallCParser.java:151)
at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:70)
at SmallCBaseVisitor.visitProgram(SmallCBaseVisitor.java:20)
at SmallCParser$ProgramContext.accept(SmallCParser.java:103)
at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:42)
at Main.main(Main.java:20)
现在,我对这件事很陌生,我意识到可能很多我想念的东西。我不知道如何从这里继续,如果能得到我所缺少的东西的清单,我将不胜感激:)
最佳答案
您代码中的许多else
块都不返回SmallCNode
,而必须返回。
它不应该是:
@Override public SmallCNode visitTerm(SmallCParser.TermContext ctx) {
if (ctx.factor().size() == 2) {
SmallCFactor lhs = (SmallCFactor) ctx.factor(0).accept(this);
SmallCFactor rhs = (SmallCFactor) ctx.factor(1).accept(this);
String op = ctx.op.getText();
return new SmallCTerm(lhs,rhs,op);
} else {
visitFactor(ctx.factor(0));
}
但:
@Override public SmallCNode visitTerm(SmallCParser.TermContext ctx) {
if (ctx.factor().size() == 2) {
SmallCFactor lhs = (SmallCFactor) ctx.factor(0).accept(this);
SmallCFactor rhs = (SmallCFactor) ctx.factor(1).accept(this);
String op = ctx.op.getText();
return new SmallCTerm(lhs,rhs,op);
} else {
return visitFactor(ctx.factor(0));
}