В ANTLR, как разобрать вложенную функцию с помощью Java - PullRequest
2 голосов
/ 11 октября 2019

Я новичок в ANTLR, у меня есть список функций, которые в основном имеют вложенные типы.

Ниже приведены примеры для функций:

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

Если вход имеет:

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

Таким образом, используя ANTLR с Java-программой, как определить и проверить правильность имен функций и правильности числа параметров и типов данных, что должно быть рекурсивным, поскольку функция будет находиться в глубоко вложенном формате. ?

проверить класс теста:

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;
}

}

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); это утверждение не является аргументом печати, этотолько печать ------>.

1 Ответ

2 голосов
/ 15 октября 2019

Эту задачу можно выполнить, выполнив два основных шага:

1 ) Разобрать заданные входные данные и построить Абстрактное синтаксическое дерево (AST).

2 ) Обходите дерево и проверяйте каждую функцию, каждый аргумент, один за другим, используя шаблоны Listener или Visitor.

К счастью, ANTLR предоставляет инструменты для реализации обоих шагов.
Вот простая грамматика, которую я написал на основе вашего примера. Это делает рекурсивный анализ и строит AST. Возможно, вы захотите расширить его функциональность в соответствии с вашими потребностями.

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 '('(function | argument (',' argument)*)')';

argument: (NAME | function);

Важное замечание: синтаксический анализатор несделайте различие между действительными (с вашей точки зрения) и недействительными функциями, аргументами, количеством аргументов и т. д. Таким образом, функция типа Function.whatever(InvalidArg) также является действительной конструкция с точки зрения парсера . Чтобы дополнительно проверить входные данные и проверить, соответствует ли оно вашим требованиям (которые представляют собой предопределенный список функций и их аргументов), вы должны пройти по дереву, используя Listener или Visitor (я думаю, что Visitor идеально подходит здесь).

Чтобы лучше понять, что это такое, я бы порекомендовал прочитать это и это . Но если вы хотите углубиться в предмет, вы должны обязательно взглянуть на " Книга драконов ", в которой подробно рассматривается тема.

...