Рекурсивные группы в ANTLR4 - PullRequest
0 голосов
/ 01 мая 2018

Я новичок в ANTLR4, и мне тяжело с его грамматикой. Если у вас есть данные, структурированные по следующим правилам:

  • Сообщение представляет собой многострочный набор групп
  • Группа состоит из сегмента и, возможно, модификаторов
  • сегмент состоит из трех буквенно-цифровых символов
  • a [модификатор указывает необязательную группу, которая (группа) ограничена]
  • a {модификатор указывает группу повторений, которая (группа) ограничена}

Примером этого формата данных является:

MSH
MSA
[{ ERR }]
[{ NTE }]
[
    [
        PID
        [{NTE}]
    ]
    {
        ORC
        [
             {
                  [TQ1]
                  [{ TQ2 }]
             }
        ]
    //shortened for brevity
    }
]

Так что читается как:

  • Обязательный и единственный сегмент MSH
  • Обязательный и единственный сегмент MSA
  • Необязательная группа, состоящая из необязательной группы PID и необязательного повторяющегося NTE и повторяющейся группы ORC с необязательным повторяющимся необязательным TQ1 и необязательным повторяющимся TQ2
  • И так далее ...

Пока у меня есть:

message : group+ NEWLINE ;

group : ID+
      | (ID | '{'group'}'
      | (ID | '['group']'
      ;

OPTSTART : '[' ;
OPTEND : ']' ;
REPSTART : '{' ;
REPEND : '}' ;
ID : [a-zA-Z0-9]*
WS : [ \t\r\n]+ -> skip ;

Я просто застрял прямо сейчас. Мне удалось заставить дерево разбора проанализировать MSH и MSA, но я не совсем уверен, что я на правильном пути. Буду очень признателен за любые советы или подсказки.

1 Ответ

0 голосов
/ 01 мая 2018

Приведенное описание DSL:

  • Сообщение представляет собой многострочный набор групп
  • Группа состоит из сегмента и, возможно, модификаторов
  • сегмент состоит из трех буквенно-цифровых символов
  • a [модификатор указывает необязательную группу, которая (группа) ограничена]
  • a {модификатор указывает группу повторения, которая (группа) ограничена}

можно напрямую перевести на грамматику ANTLR:

// each group self-terminates, so no NL terminal required
// use EOF terminal to ensure that entire source is parsed
message : group+ EOF ;

// list each possible representation of a group
group   : LBRACK group RBRACK
        | LBRACE group RBRACE
        | SEGMENT 
        ;

// literal implementation of a segment
SEGMENT : Char Char Char ;

// define literals only once
LBRACK  : '[' ;
RBRACK  : ']' ;
LBRACE  : '{' ;
RBRACE  : '}' ;

// all whitespace is inconsequential
WS      : [ \t\r\n]  -> skip ;

fragment Char : [a-zA-Z0-9] ;
...