2012-02-11 126 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没由于MissingTokenException而不匹配。语法有什么问题,我需要改变以允许星星成为ITEM_TEXT的一部分?

回答

2

取而代之的是验证语义谓词,使用门语义谓词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

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: 
    '*' 
; 

或者,如果你不需要保持STAR作为一个明确的片段,和你想捕捉的所有字符的项目文本,而不是一个子集:

outline_item: OUTLINE_ITEM_MARKER ITEM_TEXT; 

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

OUTLINE_ITEM_MARKER: 
    '*'+ 
; 
+0

事实上,它简化了语法颇有几分......不过,你的语法不作之间的'*'在一行的开始,一个在别处区别:东西OP正在试图做的事。 – 2012-02-11 19:00:12

+0

@BartKiers请阅读提供的语法(或更好,但在ANTLRWorks测试)作出这样的假设了。 – ironchefpython 2012-02-11 20:00:27

+0

请注意,我没有说你的建议没有奏效。当然,它只适用于一些规则,但我非常怀疑OP是否仅仅这样做了:这可以在没有完备的递归下降解析器的帮助下完成。 OP的问题是如何区分两个相同的字符(*在这种情况下)放置在输入中的特定位置。这是你在词法分析规则中没有解决的问题。 – 2012-02-11 20:22:16