Грамматика для продолжения маркера (т.е. идентификатора) на следующей строке путем экранирования (игнорирования) символа продолжения и новой строки ('\n')

Операторы языка управления IBM i (CL) заканчиваются символом \n (новая строка) и используют +\n или -\n для продолжения длинного оператора на следующей строке (- продолжается с позиции 1 следующей строки, + продолжается с 1-го непустого символа в строке). следующую строку). Я использовал пример ANTLR4 RC1 "Fun with Python Newlines" в книге, который является близким совпадением, и он работает нормально, при условии, что символ продолжения + или - не разделяет текст токена. Например, это действительно в CL:

    chg+                                                   
    var +                                                
    &x (&-                                             
    x++                                                    
       1) /* "Change variable" statement resulting in: chgvar &X (&X+1) */

-or-

    chgvar &y (&a || 'some +
    stuff') /* result: chgvar &y (&a || 'some stuff') */

Вот грамматика для простой тестовой установки, поддерживающей только ID и - в качестве перевода строки:

ПРИМЕЧАНИЕ. На основе lexmagic/SimplePy.g4.

    grammar CL;
    pgm       :   stat+ EOF ;
    stat      :   ID NEWLINE ;
    ID        :   [a-zA-Z_] [a-zA-Z_0-9]* ;
    NEWLINE   :   '\r'? '\n' ;
    WS        :   [ \t]+ -> skip ;
    LINE_ESC  :   '-' '\r'? '\n' -> skip ;

Вот как его запустить (после того, как все экспорты и псевдонимы необходимы в терминале):

    antlr4 CL.g4
    javac *.java
    grun CL pgm -tree
    abc- (Return once)
    def (Return, CTRL-D)
    line 2:0 extraneous input 'def' expecting NEWLINE
    (pgm (stat abc def \n) <EOF>)

ANTLR4 видит ID как два токена abc, def вместо abcdef, и я понимаю, почему (когда лексер видит -\n, он выдает токен ID для abc, отбрасывает -\n и запускает def как новый токен.). Парсер видит abc def\n вместо abcdef\n.

Вопрос в том, есть ли способ заставить синтаксический анализатор видеть abc-\ndef\n как один токен вместо двух?

С другой стороны, если исходный код = abc -\ndef\n, то он должен законно выдавать 2 токена из-за пробела между abc и -\n.


person user1997980    schedule 21.01.2013    source источник
comment
Чтобы было проще отличить код от описания, следует использовать форматирование кода Stack Overflow. Вы можете использовать обратные кавычки (`) для встроенного кода и 4 пробела в начале строки для блоков кода. Это значительно облегчит понимание того, что вы пытаетесь сказать. Я начал с редактирования (возможно, ожидает утверждения), но, поскольку я не очень хорошо знаю код, вам нужно будет его закончить.   -  person Nick    schedule 22.01.2013


Ответы (1)


Я склоняюсь к использованию пользовательской реализации CharStream, чтобы скрыть символы продолжения от лексера, что работает как стандартные потоки, за исключением:

  • Реализация IntStream.LA(i) требует чтобы пропустить символы продолжения, когда это необходимо как для положительного, так и для отрицательного i.
  • Реализация IntStream.consume требует чтобы пропустить скрытую область, когда это необходимо, т. е. после использования обычной реализации consume, если следующие два символа -\n или +\n, то немедленно переместите индекс за пропущенные символы.
  • Реализация IntStream.seek требует чтобы убедиться, что индекс остается на видимом символе (дополнительную информацию см. в Javadocs).
  • Реализация CharStream.getText должен возвращать текст из указанного интервала с удаленными из результата невидимыми символами продолжения.

  • Реализация IntStream.mark, IntStream.release, IntStream.index, IntStream.size и IntStream.getSourceName не требует ничего особенного.

Возможно, вам потребуется выполнить дополнительные действия, чтобы убедиться, что номера строк и столбцов, связанных с вашими токенами, правильные, поскольку лексер не увидит каждый входной символ.

person Sam Harwell    schedule 22.01.2013
comment
Спасибо за ваш подробный ответ, и ваша стратегия имеет смысл. Тем не менее, я не программист на Java, но я попробую (как только я смогу понять, с чего начать, хе-хе). - person user1997980; 23.01.2013