В зависимости от конкретного компилятора это делается в контексте анализа/проверки типов - в пошаговом руководстве дерева синтаксического анализа. Это делается путем «украшения» дерева типами. Это поместило бы «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». Затем я вижу, что присваивание и выражение не соответствуют и могут вызывать ошибку.
Парсеры (результат генераторов парсера) просто этого не делают. Они обрабатывают только синтаксический анализ, и его недостаточно для анализа реальной программы. См. Мое эссе «Жизнь после парсинга» (через мою биографию или вы можете просто поиграть в нее). –