meriley meriley - 2 months ago 24
Java Question

ANTLR4 Validating user-defined types match

I was looking at the Antlr v4 Grammars. Specifically the Java example.

https://github.com/antlr/grammars-v4/blob/master/java/Java.g4

I noticed that the below input is valid using the provided grammar.

public class HelloWorld {
public static void main(String[] args) {
Float f = "hello world!";
}
}


Obviously we all know this is not a valid statement in Java. How in Antlr4 do you invalidate this, and throw an error? I suspect you do it in the BaseVisitor generated functions but I am struggling to find an example in the Antlr4 book or online.

Answer

Depending on the specific compiler, this is done in the contextual analysis/ typechecking - in the walkthrough of the parse tree. It is done by "decorating" the tree with types. This would put "string" as a type on the "hello world!" node, and "float" on the declaration node. The compiler would then be able to spot the mistake and give an error message.

Yes, it is done with the visitors provided with ANTLR. You can extend the BaseVisitor class to create your own visitor methods, in which you do the decoration and type checking. An example underneath from one of my own projects:

@Override
public Node visitEqCond(EqCondNode node){
    CondNode left = (CondNode) visit(node.left);
    CondNode right = (CondNode) visit(node.right);

    if(left.type.equals("num") && right.type.equals("num") && left.typeCorrect && right.typeCorrect){
        node.type = "bool";
    }
    else{
        node.typeCorrect = false;
        if(!left.type.equals("num")){
            err.TypeNotApplicableInOperationError(left.type, node.operator, node.lineNumber);
        }
        if(!right.type.equals("num")){
            err.TypeNotApplicableInOperationError(right.type, node.operator, node.lineNumber);
        }
    }
    return node;
}

Obviously this requires you to have created your own nodes with the "type" and "typeCorrect" attributes. Concretely, this method is quite simple. When you visit a specific expression, you set the type depending on which type you have there. For example, an expression would be the "hello world" part of the assignment in your example. When I visit the specific node (let's say it's called StringExpr) I set the "type" attribute to String, and I do the same for the assignment node, which I set to "Float". I can then see, that the assignment and expression does not correspond, and can throw an error.

Comments