Как управлять обработкой ошибок и синхронизацией в Antlr 4/С#

Я использую Antlr 4 с целью С#. Вот часть моей грамматики:

/*
 * Parser Rules
 */
text : term+  EOF;
term : a1 a2 a3;
a1: ....
...
...

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

Как синхронизировать ввод со следующим действительным термином? и Как получить игнорируемый текст?


person Angie    schedule 31.08.2013    source источник


Ответы (2)


Для этого вам нужно будет создать собственную реализацию IAntlrErrorStrategy, а затем установить свойство Parser.ErrorHandler в экземпляр вашей стратегии обработки ошибок. Документация для Java-версий ANTLRErrorStrategy интерфейс и реализация по умолчанию DefaultErrorStrategy могут предоставить полезную информацию. для реализации стратегии ошибок, но я должен предупредить вас, что создание пользовательской стратегии ошибок — это расширенная функция с ограниченной документацией. Ожидается, что разработчик уже является экспертом в реализации алгоритма синтаксического анализа Adaptive LL(*) в ANTLR 4 (мы говорим о понимании на уровне исследователя).

person Sam Harwell    schedule 31.08.2013
comment
Спасибо, мистер Харвелл (это второй раз, когда вы отвечаете мне на два похожих вопроса. Так что большое вам спасибо, но в обоих случаях вы дали мне очень общий ответ, я до сих пор не могу найти решение.) Если я просто хотел получить игнорируемый текст при возникновении ошибки. Как я мог найти его? - person Angie; 01.09.2013
comment
Здесь нет простого решения, которое не было бы очень общим. Каждый раз, когда мне нужно было что-то особенное в отношении обработки ошибок, я создавал свое собственное решение, специфичное для конкретного языка, который я анализировал, и разрабатываемого приложения. - person Sam Harwell; 01.09.2013
comment
В документации DefaultErrorStrategy есть кое-что о recover говорит, что метод восстановления будет потреблять токены до ресинхронизации, можем ли мы собирать использованные токены? (Я пытаюсь расширить DefaultErrorStrategy). - person Angie; 01.09.2013
comment
Спасибо, мистер Харвелл, я нашел полезную информацию, я поместил ее в ответ и надеюсь, что вы посоветуете мне, есть ли лучшее решение. - person Angie; 02.09.2013

На первый вопрос (Как синхронизировать ввод со следующим действительным термином?) я нашел полезную информацию, которая привела меня к приемлемому решению.

Antlr генерирует следующий субкод для предыдущей грамматики:

public TextContext text() {
    TextContext _localctx = new TextContext(_ctx, State);
    EnterRule(_localctx, 0, RULE_text);
    int _la;
    try {
        EnterOuterAlt(_localctx, 1);
        State = 49;
        _errHandler.Sync(this);
        _la = _input.La(1);
        do {
            State = 48; term();
            State = 51;
            _errHandler.Sync(this);
            _la = _input.La(1);
        } while ( _la==KEYWORD );
        State = 53; Match(EOF);
    }
    catch (RecognitionException re) {
        _localctx.exception = re;
        _errHandler.ReportError(this, re);
        _errHandler.Recover(this, re);
    }
    finally {
        ExitRule();
    }
    return _localctx;
}

Вызов '_errHandler.Sync(this);' заставляет синтаксический анализатор продвигаться по входному потоку, пытаясь найти следующий допустимый ход (в результате компонента «term+»). Чтобы остановить синхронизацию синтаксического анализатора в других подправилах, примите правило «term», я расширил класс DefaultErrorStrategy следующим образом:

public class MyErrorStrategy : Antlr4.Runtime.DefaultErrorStrategy
{
    public EventErrorStrategy() : base()
    { }

    public override void Sync(Antlr4.Runtime.Parser recognizer)
    {
        if(recognizer.Context is Dict.TextAnalyzer.DictionaryParser.TextContext)
            base.Sync(recognizer);
    }
}

затем предоставил его парсеру:

parser.ErrorHandler = new MyErrorStrategy();
person Angie    schedule 02.09.2013