ANTLR - базовая грамматика, включая неожиданные символы? - PullRequest
0 голосов
/ 05 февраля 2010

У меня есть действительно простая грамматика ANTLR, которую я пытаюсь заставить работать, но в настоящий момент терпит неудачу. Буду очень признателен за некоторые указания на это ...

root    :   (keyword|ignore)*;
keyword :    KEYWORD;
ignore  :    IGNORE;

KEYWORD : ABBRV|WORD;   

fragment WORD : ALPHA+;
fragment ALPHA : 'a'..'z'|'A'..'Z';
fragment ABBRV : WORD?('.'WORD);

IGNORE  : .{ Skip(); };

Со следующим тестовым вводом:

"some ASP.NET and .NET stuff. that work."

Мне нужно дерево, которое представляет собой просто список узлов ключевых слов,

"some", "ASP.NET", "and", ".NET", "stuff", "that", "work"

На данный момент я получаю

"some", "ASP.NET", "and", ".NET", "stuff. that",

(по какой-то причине в последнем ключевом слове появляется ".", И в нем пропущено слово "работа"

Если я изменю предложение ABBRV на

fragment ABBRV : ('.'WORD);

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

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

Ответы [ 2 ]

0 голосов
/ 26 февраля 2010

Я решил попытаться решить вашу проблему с помощью грамматики ANTLR3. Вот что я придумал, с некоторыми прикрепленными строками:

  • Ваша спецификация не содержит много правил, и в результате моя грамматика не очень тщательна.
  • Подумайте о добавлении в KEYW, чтобы найти больше токенов.
  • У меня сейчас нет ANTLR, совместимого с C #. Используйте 'skip ()', чтобы сделать его совместимым.

    grammar TestSplitter;
    
    start: (KEYW DELIM!?)* ;
    KEYW: ('a'..'z'|'A'..'Z'|'.')+ ;
    DELIM: '.'? ' '+ ;
    
0 голосов
/ 05 февраля 2010

Есть пара вещей, во-первых, ваше правило игнорирования парсера никогда не сработает и даже не должно появляться в этой грамматике (также не включаться в корневое правило). Конечно, поскольку вы выполняли отладку и имели правило игнорирования, тестирование намного проще (путем удаления skip (); в правиле лексера IGNORE).

Теперь объясним тестовые данные, поскольку ни один из токенов лексера не совпадает только с WORD '.' окончание ваших тестовых данных игнорируется из-за периода сразу после текста. Если вы поместите пробел между «работой» и точкой, то появится последнее слово, а точка не появится, это то, что вы хотите. Лексер не знает, что делать с «работой». когда это закончится. Если вы добавите другое слово в конце (поставьте пробел между точкой и новым словом), тогда «работа». передается из правил лексера как один токен IGNORE. Я бы подумал, что слово будет пропущено и период должен быть только в токене IGNORE.

...