2012-02-11 5 views
1

Я использую ANTLRv3 разобрать вход, который выглядит следующим образом:ANTLR генерируется анализатор производит MissingTokenException

* 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 Didn 't соответствует из-за MissingTokenException. Что не так с грамматикой, что мне нужно изменить, чтобы звезды стали частью ITEM_TEXT?

ответ

2

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

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

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

What is a 'semantic predicate' in ANTLR?

0

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

outline_item: OUTLINE_ITEM_MARKER ITEM_TEXT; 

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

OUTLINE_ITEM_MARKER: 
    STAR+ 
; 

fragment STAR: 
    '*' 
; 

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

outline_item: OUTLINE_ITEM_MARKER ITEM_TEXT; 

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

OUTLINE_ITEM_MARKER: 
    '*'+ 
; 
+0

Действительно, это упрощает грамматику совсем немного ... Однако ваша грамматика не делает различия между '*' в начале строки, а другая в другом: что-то пытается сделать OP. –

+0

@BartKiers Перед тем, как принять это предположение, прочитайте предоставленную грамматику (или еще лучше проверьте ее в ANTLRWorks). – ironchefpython

+0

Обратите внимание, что я не сказал, что ваше предложение не работает. Конечно, он работает с несколькими правилами, но я очень сомневаюсь, что OP делает только это: это можно сделать без помощи полномасштабного рекурсивного анализатора спуска. Вопрос OP состоит в том, как сделать различие между двумя одинаковыми символами (* в этом случае), когда они помещаются в определенное место на входе. Это то, что вы не адресуете в правилах lexer. –

 Смежные вопросы

  • Нет связанных вопросов^_^