Как сообщить об ошибках от ANTLR 4 Visitor?

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

Сообщается, что нет необходимости чрезмерно усложнять лексический анализатор грамматики и правила синтаксического анализатора с помощью семантического анализа, потому что гораздо лучше предоставлять содержательные сообщения об ошибках от Посетителя.

Поэтому я пытаюсь проверить согласованность типов, правильность даты и т. Д. В Посетителе. И меня удивляет то, что нет никакого способа (по крайней мере, я его не вижу) сообщить об ошибке от Посетителя, кроме как выбросить исключения. И если я выдаю исключение, я не смогу продолжить проверку выражения и сразу обнаружить все ошибки. Вдобавок мне нужно каким-то образом отлавливать все типы исключений синтаксического анализа (как мне их узнать?). В общем, выброс исключения не кажется правильным решением.

Не могли бы вы дать мне направление, как планируется сообщать об ошибках в семантике выражений во время обхода посетителя?


person Sasha    schedule 03.09.2015    source источник


Ответы (1)


Поскольку вы определяете посетителя, вы можете создать и передать ему объект, которому он будет сообщать об ошибках.

Простой пример:

public interface IErrorReporter
{
    void ReportError(ParserRuleContext context, string error);
}
public class ValidationVisitor : YourLanguageBaseVisitor<Whatever>
{
    private readonly IErrorReporter _errorReporter;

    public ValidationVisitor(IErrorReporter errorReporter)
    {
        _errorReporter = errorReporter;
    }

    public override Whatever VisitSomeNode(YourLanguageParser.SomeNodeContext context)
    {
        if (context.GetText() != "expected")
            _errorReporter.ReportError(context, "Invalid text");

        return Visit(context.someSubNode());
    }
}

Затем подтвердите следующим образом:

var parseTree = DoTheParsingStuff();

// Implement that one, store the errors in a list
var errorReporter = new SimpleErrorReporter();  

new ValidationVisitor(errorReporter).Visit(parseTree);

if (errorReporter.Errors.Count > 0)
{
    // Display errors
}

ParserRuleContext может быть полезен для определения места возникновения ошибки (строка / столбец и т. Д.), Но в противном случае вы можете реализовать все, что соответствует вашим потребностям в сообщении об ошибках.


Дополнительное примечание: если вы планируете иметь много посетителей, тогда создайте AST и тогда проверка на основе этого может быть полезной в долгосрочной перспективе. Вам нужно решить, стоит ли оно того.

person Lucas Trzesniewski    schedule 03.09.2015
comment
Спасибо за ответ. Это вариант. Вы знаете, правильный ли это способ сделать это или просто обходной путь? Как я вижу, у Lexer и Parser есть общий механизм errorListeners для сообщения об ошибках. Я был удивлен, что посетитель этого не сделал. - person Sasha; 03.09.2015
comment
Это упрощенная версия того, что я делаю, и она очень хорошо работает. Не существует стандартного способа, поскольку вы можете делать все, что хотите, в посетителях / слушателях. Лексерам / парсерам нужен механизм сообщения об ошибках, но посетителям и слушателям он в общем случае не нужен. - person Lucas Trzesniewski; 03.09.2015
comment
Также стоит отметить, что Lexer и Parser сообщают только о синтаксических ошибках. Слушатель и посетитель могут проверить, является ли синтаксически правильный ввод семантически допустимым, проверив текущий контекст, предыдущие значения и т. Д. - например, код страны состоит из двух букв, но является ли XX допустимым кодом страны? Это страна, с которой мы ведем бизнес? так далее - person Panagiotis Kanavos; 11.09.2015