Почему определенные токены не распознаются?

(используя antlr-4.1-complete.jar)

Я новичок в ANTLR4 и создал простую грамматику, чтобы проверить, чему я научился. Я обнаружил, что результаты сбивают с толку, и я чувствую, что должна быть какая-то основная концепция, которую мне (на протяжении всего моего чтения) удалось не понять.

Вот грамматика, которую я определил:

grammar Gm;

// parser RULES
gmModel
    : obj+
    EOF
    ;

obj : objItem nameItem begin pairs end ;

objItem : OBJDECL ;
nameItem : OBJNAME ;
begin : OPEN ;
end : CLOSE ;
pairs : Pair+ ;

// LEXER RULES
OBJDECL : 'object' ;
OBJNAME : 'anotherobj' | 'testobj';
OPEN : '{' ;
CLOSE : '}' ;

fragment Var : ID_START (ID_CONT)+ ; // variable names start with an alpha
fragment Val : .*? ';' ; // values can be anything; capture everything up to the semicolon

Pair : Var Val ;

// fragments
fragment ID_START : [a-zA-Z] ;
fragment ID_CONT : [-_a-zA-Z0-9] ;

WS : [ \t]+ -> skip ;

И вот файл, который я использую в качестве входных данных. Каждый объект имеет некоторое количество групп имя-значение. В большинстве случаев это пара - есть только одно значение (разделенное пробелом/табуляцией), но иногда за именем следуют два значения, поэтому оно фиксируется точкой с запятой.

object testobj {
    testvar testval;
    v_B 1234.9876;
}

object anotherobj {
    name o611;
    phases "CN";
    v_A 2401.7771;
    groupid OBJTEST;
    timeslice 1 hour;
}

Хотя я определяю

OBJDECL : 'object' ;

как правило Lexer, он не распознается как токен (TestRig в основном показывает несколько фрагментов текста). Я даже поставил его первым, потому что я читал, что первые определенные токены имеют приоритет. Я также читал, что используется максимально длинный токен, и, возможно, именно это здесь и происходит, но в этом случае я не понимаю, как определить полезные токены, которые могут соответствовать строкам непредсказуемой длины.

Любая помощь, которую вы могли бы предложить, будет очень признательна!

Кроме того, последний комментарий после дополнительной обработки: если я сделаю следующие два изменения, токенизация будет правильной, ЗА ИСКЛЮЧЕНИЕМ того, что каждая пара состоит только из точки с запятой (куда делось содержимое?)

pairs : Pair+ ;
->
pairs : pair+ ;

и

Pair : Var Val ;
->
pair : ID_START (ID_CONT)+ .*? ';' ;

(другими словами, создайте пару правил парсера и замените фрагменты Var/Val определением на месте)

Исходя из моего ограниченного понимания, я думаю, что это изменение «улучшает» ситуацию, потому что я эффективно удаляю максимально длинный токен, который можно было сопоставить раньше (Pair +), но я все еще не понимаю, почему имя/значение (я) теперь полностью отсутствуют и я также (очевидно!) до сих пор не понимаю рекомендуемый способ создания токенов, чтобы убедиться, что они не слишком жадные.

Почему сейчас поднимается только точка с запятой? Непонимание этого — одна из причин, по которой я чувствую, что мне все еще не хватает чего-то основного. (Но на случай, если вы не можете сказать по моим частым правкам, я много думал об этом и прочитал много других ранее опубликованных вопросов и ответов, чтобы не задавать глупый вопрос, но я действительно в тупике. )

Спасибо за любое руководство!


person J Smith    schedule 29.07.2013    source источник


Ответы (1)


person    schedule
comment
Большое спасибо, Рэмг!! Я не включил это в свой первоначальный пост, но я пробовал поэкспериментировать и с лексическими модусами, но у меня это не сработало. Читая ваш пост, я вижу, что ошибся, когда я поставил -> pushMode(READPAIR) после скобки OPEN и попытался использовать popMode в фигурной скобке CLOSE (это казалось наиболее похожим на примеры XML, с которыми я столкнулся); ваш пример мне очень помог. Спасибо еще раз. - person J Smith; 29.07.2013