问题描述
我正在使用ANTLR4创建编程语言来创建Simlpe计算器。 我一直在寻找这个错误,我一直在寻找,但是似乎无法解决它,有什么建议/帮助吗?
我一直在浏览我的java文件,但是不明白为什么它会给我这个错误。
$ make test
Exception in thread "main" java.lang.NullPointerException
at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
at Interpreter.visitWhileLoop(main.java:79)
at Interpreter.visitWhileLoop(main.java:47)
at implParser$WhileLoopContext.accept(implParser.java:377)
at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
at Interpreter.visitStart(main.java:52)
at Interpreter.visitStart(main.java:47)
at implParser$startContext.accept(implParser.java:123)
at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
at main.main(main.java:38)
make: *** [Makefile:18: test] Error 1
这是我对main.java实现语法方法的部分:
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
import org.antlr.v4.runtime.CharStreams;
import java.io.IOException;
public class main {
public static void main(String[] args) throws IOException{
// we expect exactly one argument: the name of the input file
if (args.length!=1) {
System.err.println("\n");
System.err.println("Simple calculator\n");
System.err.println("=================\n\n");
System.err.println("Please give as input argument a filename\n");
System.exit(-1);
}
String filename=args[0];
// open the input file
CharStream input = CharStreams.fromFileName(filename);
//new ANTLRFileStream (filename); // depricated
// create a lexer/scanner
implLexer lex = new implLexer(input);
// get the stream of tokens from the scanner
CommonTokenStream tokens = new CommonTokenStream(lex);
// create a parser
implParser parser = new implParser(tokens);
// and parse anything from the grammar for "start"
ParseTree parseTree = parser.start();
// Construct an interpreter and run it on the parse tree
Interpreter interpreter = new Interpreter();
interpreter.visit(parseTree);
}
}
// We write an interpreter that implements interface
// "implVisitor<T>" that is automatically generated by ANTLR
// This is parameterized over a return type "<T>" which is in our case
// simply a Double.
class Interpreter extends AbstractParseTreeVisitor<Double> implements implVisitor<Double> {
static Environment env=new Environment();
public Double visitStart(implParser.StartContext ctx){
for(implParser.CommandContext c:ctx.cs) visit(c);
return null;
};
public Double visitSingleCommand(implParser.SingleCommandContext ctx){
return visit(ctx.c);
}
public Double visitMultipleCommands(implParser.MultipleCommandsContext ctx){
for(implParser.CommandContext c:ctx.cs) visit(c);
return null;
}
public Double visitAssignment(implParser.AssignmentContext ctx){
Double v=visit(ctx.e);
env.setvariable(ctx.x.getText(),v);
return null;
}
public Double visitOutput(implParser.OutputContext ctx){
Double v=visit(ctx.e);
System.out.println(v);
return null;
}
public Double visitWhileLoop(implParser.WhileLoopContext ctx){
while(visit(ctx.c).equals(1.0)){
visit(ctx.p);
}
return null;
}
public Double visitIfStatement(implParser.IfStatementContext ctx){
while(visit(ctx.c1).equals(1.0)){
visit(ctx.p1);
}
return null;
}
/*public Double visitSubstraction(implParser.SubstractionContext ctx) {
return visit(ctx.e1);
}
public Double visitDivison(implParser.DivisonContext ctx) {
return visit(ctx.e1);
}*/
public Double visitMUL(implParser.MULContext ctx) {
Double left = this.visit(ctx.expr(0));
Double right = this.visit(ctx.expr(1));
switch (ctx.op.getType()) {
case implParser.MULT:
return left * right;
case implParser.DIV:
return left / right;
case implParser.MOD:
return left % right;
default:
throw new RuntimeException("unkNown operator: " + implParser.tokenNames[ctx.op.getType()]);
}
}
public Double visitOP(implParser.OPContext ctx) {
Double left = this.visit(ctx.expr(0));
Double right = this.visit(ctx.expr(1));
switch (ctx.op.getType()) {
case implParser.PLUS:
//return left && right;
return left + right;
case implParser.MINUS:
return left - right;
default:
throw new RuntimeException("unkNown operator: " + implParser.tokenNames[ctx.op.getType()]);
}
}
public Double visitParenthesis(implParser.ParenthesisContext ctx){
return visit(ctx.e);
};
public Double visitvariable(implParser.VariableContext ctx){
return env.getvariable(ctx.x.getText());
};
/*public Double visitAddition(implParser.AdditionContext ctx){
return visit(ctx.e1)+visit(ctx.e2);
};
public Double visitMultiplication(implParser.MultiplicationContext ctx){
return visit(ctx.e1)*visit(ctx.e2);
};
*/
public Double visitConstant(implParser.ConstantContext ctx){
return Double.parseDouble(ctx.c.getText());
};
public Double visitUnequal(implParser.UnequalContext ctx){
Double v1=visit(ctx.e1);
Double v2=visit(ctx.e2);
if (v1.equals(v2)) return 0.0;
else return 1.0;
}
public Double visitEqual(implParser.EqualContext ctx){
Double v1=visit(ctx.e1);
Double v2=visit(ctx.e2);
if (v1.equals(v2)) return 0.0;
else return 1.0;
}
public Double visitLess(implParser.LessContext ctx){
Double v1=visit(ctx.e1);
Double v2=visit(ctx.e2);
if (v1.equals(v2)) return 0.0;
else return 1.0;
}
public Double visitLessOrEqual(implParser.LessOrEqualContext ctx){
Double v1=visit(ctx.e1);
Double v2=visit(ctx.e2);
if (v1.equals(v2)) return 0.0;
else return 1.0;
}
public Double visitGreater(implParser.GreaterContext ctx){
Double v1=visit(ctx.e1);
Double v2=visit(ctx.e2);
if (v1.equals(v2)) return 0.0;
else return 1.0;
}
public Double visitGreaterOrEqual(implParser.GreaterOrEqualContext ctx){
Double v1=visit(ctx.e1);
Double v2=visit(ctx.e2);
if (v1.equals(v2)) return 0.0;
else return 1.0;
}
public Double visitAND(implParser.ANDContext ctx){
Double v1=visit(ctx.e1);
Double v2=visit(ctx.e2);
if (v1.equals(v2)) return 0.0;
else return 1.0;
}
public Double visitOR(implParser.ORContext ctx){
Double v1=visit(ctx.e1);
Double v2=visit(ctx.e2);
if (v1.equals(v2)) return 0.0;
else return 1.0;
}
public Double visitNum(implParser.NumContext ctx){
return null;
}
}
/*
class Expr{};
class var extends Expr{}; //Subclass
class Const extends Expr{}; //Subclass
class Multiplication extends Expr{}; //Subclass*/
以下错误是:
public Double visitStart(implParser.StartContext ctx){
[52]for(implParser.CommandContext c:ctx.cs) visit(c);
return null;
};
public Double visitWhileLoop(implParser.WhileLoopContext ctx){
while(visit(ctx.c).equals(1.0)){
[79] visit(ctx.p);
}
解决方法
异常消息显示:
Exception in thread "main" java.lang.NullPointerException
at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:18)
at Interpreter.visitWhileLoop(main.java:79)
at Interpreter.visitWhileLoop(main.java:47)
at implParser$WhileLoopContext.accept(implParser.java:377)
...
这意味着AbstractParseTreeVisitor的visit()
方法中发生了NullPointerException。它是由visitWhileLoop()
上下文中的调用引起的,该调用本身是从visitWhileLoop()
上下文中调用的。它看起来像递归调用,但是错误的行号使它看起来好像有两个单独的方法。您发布的代码似乎只有一种叫做visitWhileLoop()
的方法,所以我不确定那里发生了什么。
public Double visitWhileLoop(implParser.WhileLoopContext ctx){
while(visit(ctx.c).equals(1.0)){
visit(ctx.p);
}
return null;
}
有两次从visit()
到visitWhileLoop()
的呼叫。我猜想其中一个或多个正在将null
传递给visit()
。换句话说,ctx.c
或ctx.p
的值为null
。
您可以在IDE的调试器中使用visitWhileLoop()
方法的断点来运行此程序,以查找有关正在发生的事情的更多信息。