2016-12-13 7 views
0

Я пытаюсь реализовать парсер для языка игрушек.Как правильно реализовать посетителя ANTLR4

Я уже написал грамматику, но когда я пытаюсь создать AST из КНТ, я столкнулся с проблемой.

Я определяю класс, который наследует от MyParserVisitor<ASTNode>, где ASTNode - это фиктивный класс, из которого наследуется каждый класс в классе.

Теперь, два из правил моей грамматики следующим образом:

program: 
    funcDecl* expr 
; 
expr: 
    constant          # constExpr 
| identifier         # idExpr 
; 

где funcDecl, constant и identifier терминальные правила.

Когда я пытаюсь реализовать посетителя для program, всякий раз, когда я вызываю функцию visit, я должен привести результат к правильному типу. Например:

@Override 
public Program visitProgram(fopplParser.ProgramContext ctx){ 
    // Rule: funcDecl* expr 
    List<FuncDecl> funcs = new LinkedList<FuncDecl>(); 
    for(fopplParser.FuncDeclContext f : ctx.funcDecl()) 
     funcs.add((FuncDecl) visit(f)); 

    Expr expr = (Expr)visit(ctx.expr()); 
    return new Program(funcs, expr); 
} 

Можно ли каким-либо образом опустить все эти отливки? Мне кажется, что я делаю что-то неправильно здесь.

В случае FuncDecl, я мог бы изменить эту строку в funcs.add(visitFuncDecl(f)); и осуществлять visitFuncDecl со следующей подписью pubic FuncDecl visitFuncDecl(fopplParser.FuncDeclContext ctx); , но я не могу сделать это с выражением, так как не существует visitExpr функция, но две функции , а именно visitConstExpr и visitIdExpr.

Кроме того, если у меня есть правило такое, что idList: identifier* в этом случае я не могу вернуть List<Identifier>. Должен ли я создать класс, который является ничем иным, как оберткой для List<Identifier>, или мне нужно сделать мой наследователь наследуемым классом от MyParserVisitor<Object>?

ответ

1

Я думаю, что вы вводите в заблуждение значение класса посетителей ANTLR и ваше намерение ходить по дереву разбора. Класс посетителей ANTLR предназначен для оценок. Его можно параметризовать, чтобы вернуть данный класс в результате посещения узлов (например, математическое значение при оценке выражения). Для ходьбы дерево разбора использует вместо этого прослушиватель дерева разбора. Затем вы можете переопределить функции enterXXX и exitXXX и построить свою таблицу символов или что угодно.