ANTLR4: плохая производительность при вызове getInterpreter().adaptivePredict

Парр и Уважаемое сообщество,

Сначала я хотел бы поблагодарить вас за потрясающий Antlr4 (и за antlr в целом :-)). Я использую Antlr 3 последние 6 месяцев (я уже был очень доволен), но еще больше я доволен antlr4. Я заметил очень существенные улучшения в простоте грамматики и времени генерации, используя java в качестве целевого языка. К сожалению, у меня есть некоторые опасения по поводу производительности во время выполнения, которых у меня не было с antlr3.

Вот отрывок из моей грамматики:

declare_specs
:
DECLARE? declare_spec+
|
DECLARE
;

declare_spec
:
constant_declaration
| variable_declaration
| exception_declaration
| procedure_body
| function_body
;

Вот сгенерированный код (я добавил System.out.println для трассировки):

    public final Declare_specsContext declare_specs() throws RecognitionException {
            System.out.println("TIME: " + timestamp() + " - declare_specs - 1");
        Declare_specsContext _localctx = new Declare_specsContext(_ctx, getState());
        System.out.println("TIME: " + timestamp() + " - declare_specs - 2");
        enterRule(_localctx, 118, RULE_declare_specs);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 3");
        int _la;
        try {
            int _alt;
        System.out.println("TIME: " + timestamp() + " - declare_specs - 4");
        setState(826);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 5");
        switch ( getInterpreter().adaptivePredict(_input,69,_ctx) ) {
            case 1:
        System.out.println("TIME: " + timestamp() + " - declare_specs - 6");
                enterOuterAlt(_localctx, 1);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 7");
                {

                        if (f_trace >= f_trace_low) {
                            System.out.println("TIME: " + timestamp() + " - DECLARE_SPECS - FIRST ALT");
                        };

                setState(817);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 8");
                _la = _input.LA(1);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 9");
                if (_la==DECLARE) {
                    {
                    setState(816); match(DECLARE);
                    }
                }

        System.out.println("TIME: " + timestamp() + " - declare_specs - 10");
                setState(820); 
        System.out.println("TIME: " + timestamp() + " - declare_specs - 11");
                _errHandler.sync(this);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 12");
                _alt = getInterpreter().adaptivePredict(_input,68,_ctx);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 13");
                do {
                    switch (_alt) {
                    case 1:
                        {
                        {
        System.out.println("TIME: " + timestamp() + " - declare_specs - 14");
                        setState(819);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 15");
                        declare_spec();
        System.out.println("TIME: " + timestamp() + " - declare_specs - 16");
                        }
                        }
                        break;
                    default:
                        throw new NoViableAltException(this);
                    }
        System.out.println("TIME: " + timestamp() + " - declare_specs - 17");
                    setState(822);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 18");
                    _errHandler.sync(this);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 19");
                    _alt = getInterpreter().adaptivePredict(_input,68,_ctx);
        System.out.println("TIME: " + timestamp() + " - declare_specs - 20");
                } while ( _alt!=2 && _alt!=-1 );
                }
                break;

            case 2:
                enterOuterAlt(_localctx, 2);
                {

                        if (f_trace >= f_trace_low) {
                            System.out.println("TIME: " + timestamp() + " - DECLARE_SPECS - SECOND ALT");
                        };

                setState(825); match(DECLARE);
                }
                break;
            }
        }
        catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        }
        finally {
            exitRule();
        }
        return _localctx;
    }

Вот следы:

................
TIME: 2013-02-06 09:47:10.417 - declare_specs - 12
TIME: 2013-02-06 09:47:11.023 - declare_specs - 13
.................
TIME: 2013-02-06 09:51:38.915 - DECLARE_SPEC - AFTER
.................
TIME: 2013-02-06 09:51:38.916 - declare_specs - 19
TIME: 2013-02-06 09:52:31.435 - declare_specs - 20
...................
TIME: 2013-02-06 09:52:31.435 - DECLARE_SPEC - INIT

Я теряю 60 дюймов при вызове _alt = getInterpreter().adaptivePredict(_input,68,_ctx); второй раз, но меньше 1' при вызове _alt = getInterpreter().adaptivePredict(_input,68,_ctx); в первый раз. Что изменилось, так это параметры _input и _ctx.

Проблема кроется, скорее всего, в моей грамматике, но я в тупике ;-). 1. Можете ли вы сказать мне, где я могу искать решение. 2. Что же все-таки происходит в AdaptivePredict ;-)

Спасибо за помощь!

С уважением, Вольфганг Хаммер


person wolfgang hämmer    schedule 06.02.2013    source источник
comment
Извините, дорогой мистер Парр и уважаемое сообщество   -  person wolfgang hämmer    schedule 06.02.2013


Ответы (1)


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

parser.addErrorListener(new DiagnosticErrorListener());
parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
person Sam Harwell    schedule 06.02.2013
comment
Привет Helotes, спасибо за ответ! У меня есть три вида ошибок: 1. reportAttemptingFullContext d=nnn, input='xxx' 2. reportContextSensitivity d=nnn, input='xxx' 3. reportAmbiguityd=nnn: ambigAlts={1, n, ...} , input='xxx' Я заглянул в код: d — это решение в DFA, и ввод очевиден. Как я могу перейти от d (решение) к ошибочному правилу в моей грамматике? Это вообще возможно? Код в классе ParserATNSimulator довольно сложен. Спасибо за помощь! С уважением, Вольфганг Хаммер - person wolfgang hämmer; 06.02.2013