Сгенерированный ANTLR парсер создает MissingTokenException - PullRequest
1 голос
/ 11 февраля 2012

Я использую ANTLRv3 для разбора ввода, которое выглядит так:

* this is an outline item at level 1
** item at level 2
*** item at level 3
* another item at level 1
* an item with *bold* text

Звезды в начале линии отмечают начало элемента контура. Звезды также могут быть частью текста предмета (например, *bold*).

Это грамматика для разбора элементов контура без поддержки звезд в тексте элемента:

outline_item: OUTLINE_ITEM_MARKER ITEM_TEXT;
OUTLINE_ITEM_MARKER: STAR_IN_COLUMN_ZERO STAR* (' '|'\t');
ITEM_TEXT: ('a'..'z'|'A'..'Z'|'0'..'9'|'\r'|'\n'|' '|'\t')+;
fragment STAR_IN_COLUMN_ZERO: {getCharPositionInLine()==0}? '*';
fragment STAR: {getCharPositionInLine()>0}? '*';

Для ввода *** foo bar ANTLR создает следующее дерево разбора:

without_star_in_item_text

Пока это работает, как и ожидалось. Теперь я пытаюсь добавить звездочку к возможным символам для текста элемента, поэтому я изменил правило лексера для ITEM_TEXT на следующее:

ITEM_TEXT: ('a'..'z'|'A'..'Z'|'0'..'9'|'\r'|'\n'|' '|'\t'|STAR)+;

Теперь для того же ввода создается следующее дерево разбора:

with_star_in_item_text

Это вывод в ANTLRWorks:

input.txt line 1:0 rule STAR failed predicate: {getCharPositionInLine()>0}?
input.txt line 1:1 missing OUTLINE_ITEM_MARKER at '** foo bar'

Кажется, что OUTLINE_ITEM_MARKER не совпадает из-за MissingTokenException. Что не так с грамматикой, что мне нужно изменить, чтобы звёзды были частью ITEM_TEXT?

Ответы [ 2 ]

2 голосов
/ 11 февраля 2012

Вместо проверяющего семантического предиката , используйте стробированный семантический предикат 1 в ваших fragment с.

Следующая грамматика:

grammar Test;

outline_items
 : outline_item+ EOF
 ;

outline_item
 : OUTLINE_ITEM_MARKER ITEM_TEXT
 ;

OUTLINE_ITEM_MARKER 
 : STAR_IN_COLUMN_ZERO STAR* (' '|'\t')
 ;

ITEM_TEXT
 : ('a'..'z'|'A'..'Z'|'0'..'9'|'\r'|'\n'|' '|'\t'|STAR)+
 ;

fragment STAR_IN_COLUMN_ZERO
 : {getCharPositionInLine()==0}?=> '*'
 ;

fragment STAR
 : {getCharPositionInLine()>0}?=> '*'
 ;

Ваш ввод:

* this is an outline item at level 1
** item at level 2
*** item at level 3
* another item at level 1
* an item with *bold* text

будет проанализирован следующим образом:

enter image description here

1 Что такое «семантический предикат» в ANTLR?

0 голосов
/ 11 февраля 2012

Вы пытались сделать вашу грамматику проще?

outline_item: OUTLINE_ITEM_MARKER ITEM_TEXT;

ITEM_TEXT:
    (' '|'\t') (' '|'\t'|'a'..'z'|'A'..'Z'|'0'..'9'| STAR)+
;

OUTLINE_ITEM_MARKER:
    STAR+ 
;

fragment STAR:   
    '*'
;

Или если вам не нужно сохранять STAR в качестве явного фрагмента, и вы хотите захватить все символы в тексте элемента, а не подмножество:

outline_item: OUTLINE_ITEM_MARKER ITEM_TEXT;

ITEM_TEXT:
    (' '|'\t') (~('\n'|'\r'))+
;

OUTLINE_ITEM_MARKER:
    '*'+ 
;
...