0

I'm in the process of creating a programming language using ANTLR4 to create a simlpe calculator. I am pretty much stuck on this error, I've been looking around, but can't seem to fix it, any suggestions/help?

I've been looking through my java file, but can't understand why it gives me that error.

$ 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

Here's the part where I implement my grammar methods to my 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*/

The following errors are:

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);
}
TheKingZ
  • 13
  • 4
  • you have exception type and certain place in code where it occurs. What the issue then? – tym32167 Oct 07 '20 at 13:33
  • Does this answer your question? [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – OH GOD SPIDERS Oct 07 '20 at 13:34
  • So apparently `ctx.p` is `null`. That will depend on your grammar and the test input, neither of which you include in your question. – rici Oct 07 '20 at 15:31

1 Answers1

0

The exception message says:

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) 
...

It means a NullPointerException has occurred in the visit() method of AbstractParseTreeVisitor. It was caused by a call from the context of visitWhileLoop(), which was itself called from the context of visitWhileLoop(). It looks like a recursive call, but the line numbers for the errors make it seem like there are two separate methods. The code you posted only seemed to have one method called visitWhileLoop(), so I'm not sure what's going on there.

public Double visitWhileLoop(implParser.WhileLoopContext ctx){
    while(visit(ctx.c).equals(1.0)){
        visit(ctx.p);
    }
    return null;
}

There are two calls to visit() from visitWhileLoop(). I would guess that one or other of them is passing in a null to visit(). In other words, the value of ctx.c or ctx.p is null.

You could run this in an IDE's debugger with a breakpoint on the visitWhileLoop() method to find out more information about what's happening.

ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66