ashok
ashok

Reputation: 1268

In ANTLR how to parse the nested function using java

I am new to ANTLR, I have a list of functions which are mostly of nested types.

Below are the examples for functions:

1. Function.add(Integer a,Integer b)
2. Function.concat(String a,String b)
3. Function.mul(Integer a,Integer b)

If the input is having:

Function.concat(Function.substring(String,Integer,Integer),String)

So by using ANTLR with Java program, how to define and validate whether the function names are correct and parameter count and datatypes are correct, which has to be recursive as the Function will be in deeply nested format?

validate test class:

public class FunctionValidate {

public static void main(String[] args) {

    FunctionValidate fun = new FunctionValidate();
    fun.test("FUNCTION.concat(1,2)");  

}

private String test(String source) {
    CodePointCharStream input = CharStreams.fromString(source);
    return compile(input);
}

private String compile(CharStream source) {
    MyFunctionsLexer lexer = new MyFunctionsLexer(source);
    CommonTokenStream tokenStream = new CommonTokenStream(lexer);
    MyFunctionsParser parser = new MyFunctionsParser(tokenStream);
    FunctionContext tree = parser.function();
    ArgumentContext tree1= parser.argument();
    FunctionValidateVisitorImpl visitor = new FunctionValidateVisitorImpl();
    visitor.visitFunction(tree);
    visitor.visitArgument(tree1);
    return null;
}

}

Visitor impl:

    public class FunctionValidateVisitorImpl extends MyFunctionsParserBaseVisitor<String> {

    @Override
    public String visitFunction(MyFunctionsParser.FunctionContext ctx) {
        String function = ctx.getText();
        System.out.println("------>"+function);
        return null;
    }


    @Override
    public String visitArgument(MyFunctionsParser.ArgumentContext ctx){
        String param = ctx.getText();
        System.out.println("------>"+param);
        return null;
    }


}

System.out.println("------>"+param); this statement is not printing argument it is only printing ------>.

Upvotes: 1

Views: 1457

Answers (1)

Pavel Smirnov
Pavel Smirnov

Reputation: 4799

This task can be accomplished by implementing two main steps:

1) Parse given input and build an Abstract Syntax Tree (AST).

2) Traverse the tree and validate each function, each argument, one after another, using a Listener or a Visitor patterns.

Fortunately, ANTLR provides tools for implementing both steps.
Here's a simple grammar I wrote based on your example. It does recursive parsing and builds the AST. You may want to extend its functionality to meet your needs.

Lexer:

lexer grammar MyFunctionsLexer;

FUNCTION: 'FUNCTION';

NAME: [A-Z]+;

DOT: '.';

COMMA: ',';

L_BRACKET: '(';

R_BRACKET: ')';

WS : [ \t\r\n]+ -> skip;

Parser:

parser grammar MyFunctionsParser;

options {
    tokenVocab=MyFunctionsLexer;
}

function : FUNCTION '.' NAME '('(argument (',' argument)*)')';

argument: (NAME | function);

Important thing to notice here: the parser does not make distinction between a valid (from your point of view) and invalid functions, arguments, number of arguments, etc. So the function like Function.whatever(InvalidArg) is also a valid construction from parser's point of view. To further validate the input and test whether it meets your requirements (which is a predefined list of functions and their arguments), you have to traverse the tree using a Listener or a Visitor (I think Visitor fits here perfectly).

To get a better understanding of what it is I'd recommend reading this and this. But if you want to get deeper into the subject, you should definitely look at "The Dragons Book", which covers the topic exhaustively.

Upvotes: 2

Related Questions