ANTLR соответствия символов, когда другие символы требуются в первую очередь? - PullRequest
1 голос
/ 10 января 2012

См. Грамматику ниже.Когда я пытаюсь выполнить синтаксический анализ:

String s = "UNH+message refere+APERAK:D:97A:UN\n";

, я получаю следующую ошибку:

line 1:34 mismatched character '\n' expecting 'H'
line 2:0 missing RDEL at '<EOF>'

Что не имеет смысла для меня, так как кажется, что он ищет UNH перед тем, как встретить \n, который не будет следовать правилу 'file'.

    grammar Aperak;

    options {
      language = Java;
    }

    @header { package test.fixed.aperak; }
    @lexer::header { package test.fixed.aperak; }

    file returns [String result]: 'UNH' unh01 unh02 RDEL { $result = $unh01.text + " -- " + $unh02.text; };

    unh01 : FDEL optField;
    unh02 : FDEL unh02x1 unh02x2 unh02x3 unh02x4 (unh02x5)?;
    unh02x1 : optField;
    unh02x2 : SDEL optField;
    unh02x3 : SDEL optField;
    unh02x4 : SDEL optField;
    unh02x5 : SDEL optField;

    optField : AN*;

    RDEL : '\n';
    SDEL : ':';
    FDEL : '+';

    AN : 'a'..'z' | 'A'..'Z' | '0'..'9' | ' ';

Ответы [ 2 ]

1 голос
/ 10 января 2012

Ваш лексер действительно выглядит так:

UNH  : 'UNH';
RDEL : '\n';
SDEL : ':';
FDEL : '+';
AN   : 'a'..'z' | 'A'..'Z' | '0'..'9' | ' ';

Литерал 'UNH' в вашем правиле file становится правилом лексера, помещенным над всеми другими правилами лексера.

Когда лексер теперь натыкается на "UN", за которым следует что-то отличное от "H", он выдает ошибку, потому что лексеру некуда возвращаться. Если ваше правило AN соответствует более чем одному символу, лексер может следовать этому правилу, но, поскольку оно соответствует только одному символу, лексер не будет возвращаться с "UN".

Как уже было предложено, dasblinkenlight является правильным: AN должен соответствовать 1 или более символов, а optField может соответствовать необязательному AN. Однако другая часть его (или ее) ответа не совсем верна: отсюда мой ответ.

1 голос
/ 10 января 2012

Я думаю, что ANTLR действительно путают с двумя перекрывающимися правилами, которые охватывают вход UNH:

  • Один токен UNH или
  • Последовательность из трех токеноввведите AN, с текстами "U", "N" и "H"

Я думаю, вам следует изменить правила optField и AN, чтобы переместить * влексер, вот так:

optField : AN?;

AN : ('a'..'z' | 'A'..'Z' | '0'..'9' | ' ')+;
...