Разбить одно слово на несколько токенов на основе позиции ANTLR4

Я пишу синтаксический анализатор для RPG 2. RPG 2 основана на позициях, и для этого я использую предикаты. Однако есть одно место, где я застрял.

Одно утверждение в RPG похоже на

  26 C  N20      'PICK'    CHAINORDOFIL              09

Здесь CHAIN ​​занимает позицию с 27 по 32, а ORDOFIL — с 33 по 41.

Мои правила для соответствия цепочке и следующему идентификатору похожи на

CALCULATION_OPERATIONS_CHAIN : CHAIN_T  {(getCharPositionInLine()>=27) &&(getCharPositionInLine()<=32)}? ->type(CHAIN_T);

CALCULATION_FACTOR2_1:  IDENT_T  {(getCharPositionInLine()>=33) && (getCharPositionInLine()<=42)}?   ->type(IDENT_T);

Но моя проблема в том, что "CHAINORDOFIL" соответствует второму правилу (как IDENT_T).

Что я могу сделать, чтобы сопоставить CHAIN ​​в первом правиле и ORDOFIL во втором?

Любое предложение? заранее спасибо


person Ravishankar    schedule 25.07.2017    source источник
comment
Я считаю, что использование полноценного синтаксического анализатора для такой простой задачи является излишним. Поскольку ввод основан на позиции, он, безусловно, также основан на строке. Итак, все, что вам нужно, это прочитать ввод построчно, а затем скопировать подстроки с известных позиций. Гораздо проще, чем писать грамматику.   -  person Mike Lischke    schedule 26.07.2017
comment
Привет Майк, спасибо за ваш ответ. На самом деле я пишу полный парсер для RPG 2. Это небольшой сценарий, с которым я не могу справиться в своем полноценном парсере.   -  person Ravishankar    schedule 26.07.2017
comment
Проблема в том, что синтаксический анализатор связан вводом символов, а не позициями. Он пытается интерпретировать ввод символов, а ваши предикаты - это просто хаки вокруг этого. И, как вы можете видеть, они работают только в том случае, если лексер может выполнять свою работу на основе символов. Как только это не удается, все ваши предикаты бесполезны. Вместо этого я рекомендую лексировать всю строку как один токен, и на вашем семантическом шаге, когда вы проходите по дереву синтаксического анализа, вы можете разделить этот токен на подэлементы с известными позициями.   -  person Mike Lischke    schedule 26.07.2017


Ответы (1)


Я смог решить эту проблему с помощью Modes.

Как только я сопоставляю ЦЕПЬ, я переключаюсь в режим и обрабатываю там идентификатор (ORDOFIL).

Правила звучат так

CALCULATION_OPERATIONS_CHAIN : CHAIN_T  {(getCharPositionInLine()>=27) && (getCharPositionInLine()<=32)}? ->type(CHAIN_T),pushMode(CHAIN);

mode CHAIN;
CHAIN_WHITESPACE_T : ' ' ->skip;
CHAIN_FACTOR2_1: IDENT_T {(getCharPositionInLine()>=33) && (getCharPositionInLine()<=42)}?  ->type(IDENT_T);
CHAIN_ENDLINE : NEWLINE -> type(EOL),popMode,popMode ;
person Ravishankar    schedule 26.07.2017