2016-03-28 1 views
0

Я смотрел Antmr v4 Grammars. В частности, пример Java.ANTLR4 Подтверждение пользовательских типов соответствует

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

Я заметил, что ниже входной действуют с помощью прилагаемой грамматики.

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

Очевидно, что все мы знаем, что это не допустимый оператор на Java. Как в Antlr4 вы аннулируете это и бросаете ошибку? Я подозреваю, что вы делаете это в сгенерированных BaseVisitor функциях, но я изо всех сил пытаюсь найти пример в книге Antlr4 или в Интернете.

+0

Парсеры (результат генераторов парсера) просто этого не делают. Они обрабатывают только синтаксический анализ, и его недостаточно для анализа реальной программы. См. Мое эссе «Жизнь после парсинга» (через мою биографию или вы можете просто поиграть в нее). –

ответ

1

В зависимости от конкретного компилятора это делается в контексте анализа/проверки типов - в пошаговом руководстве дерева синтаксического анализа. Это делается путем «украшения» дерева типами. Это поместило бы «string» как тип в «hello world!». узел и «float» на узле объявления. Затем компилятор сможет обнаружить ошибку и дать сообщение об ошибке.

Да, это делается с посетителями, предоставляемыми ANTLR. Вы можете расширить класс BaseVisitor, чтобы создать свои собственные методы посетителей, в которых вы выполняете оформление и проверку типов. Пример под одной из моих собственных проектов:

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

Очевидно, что это требует, чтобы вы создали свои собственные узлы с «типа» и «typeCorrect» атрибуты. Конкретно, этот метод довольно прост. Когда вы посещаете определенное выражение, вы устанавливаете тип в зависимости от того, какой тип у вас там. Например, выражение должно быть частью назначения в вашем примере "hello world". Когда я посещаю конкретный узел (скажем, он называется StringExpr), я устанавливаю атрибут «type» для String, и я делаю то же самое для узла назначения, который я установил в «Float». Затем я вижу, что присваивание и выражение не соответствуют и могут вызывать ошибку.

0

Вы можете сделать это с использованием семантических предикатов. Взгляните на эту статью: What is a 'semantic predicate' in ANTLR?

+0

На практике вы не можете этого сделать. Во-первых, информация, необходимая для семантики, может пока недоступна (что, если эта информация является справочной ссылкой?). Во-вторых, проверки совместимости типов для реальных языков очень сложны; они, как правило, не привязаны к предикатам, которые вы можете реализовать, когда проверки выполняются во время разбора парсинга. (Вы можете показать мне интерфейс для производственного языка, реализованного таким образом.) –