(используя 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 +), но я все еще не понимаю, почему имя/значение (я) теперь полностью отсутствуют и я также (очевидно!) до сих пор не понимаю рекомендуемый способ создания токенов, чтобы убедиться, что они не слишком жадные.
Почему сейчас поднимается только точка с запятой? Непонимание этого — одна из причин, по которой я чувствую, что мне все еще не хватает чего-то основного. (Но на случай, если вы не можете сказать по моим частым правкам, я много думал об этом и прочитал много других ранее опубликованных вопросов и ответов, чтобы не задавать глупый вопрос, но я действительно в тупике. )
Спасибо за любое руководство!