语法不起作用(NoViableAltException)

时间:2012-05-24 06:42:31

标签: antlr antlr3

我是ANTLR的新手,我正试着玩它。这是我能想到的最简单的语法,当我解析变量“id123”时它仍然无效(NoViableAltException),但它适用于“abc1”,“ab”,“c1d2f3”。

我正在使用ANTLR 3.1.3和ANTLRWorks 1.4。

options 
{
    language = 'CSharp2';
    output = AST;
}

assign  :   variable '=' value;
value   :   (variable|constant);
variable:   LETTER (LETTER|DIGIT)*;
constant:   (STRING|INTEGER);

DIGIT   :   '0'..'9';
NATURAL :   (DIGIT)+;   
INTEGER :   ('-')? NATURAL; 
REAL    :   (INTEGER '.' NATURAL);

LETTER  :   ('a'..'z'|'A'..'Z');

CR      :   '\r'        { $channel = HIDDEN; }; 
LF      :   '\n'        { $channel = HIDDEN; }; 
CRLF    :   CR LF       { $channel = HIDDEN; }; 
SPACE   :   (' '|'\t')  { $channel = HIDDEN; };

STRING  :   '"' (~'"')* '"';

1 个答案:

答案 0 :(得分:2)

ANTLR的词法分析器试图尽可能地匹配。每当两个(或更多)规则匹配相同数量的字符时,首先定义的规则将“赢”。因此,只要词法分析器偶然发现一个数字,就会创建一个DIGIT标记,因为它是在NATURAL之前定义的:

DIGIT   :   '0'..'9';
NATURAL :   (DIGIT)+;   

但是对于输入"id123",词法分析器产生了以下3个标记:

LETTER          'i'
LETTER          'd'
NATURAL         '123'

因为词法分析器贪婪地匹配,因此创建了NATURAL,并且三个DIGIT令牌。

你应该做的是制作词法{ER}规则{/ 1}}:

variable

另请注意,我制作了几个词法规则assign : VARIABLE '=' value; value : (VARIABLE | constant); constant : (STRING | INTEGER | REAL); VARIABLE : LETTER (LETTER|DIGIT)*; INTEGER : ('-')? NATURAL; REAL : (INTEGER '.' NATURAL); SPACE : (' ' | '\t' | '\r' | '\n') { $channel = HIDDEN; }; STRING : '"' (~'"')* '"'; fragment NATURAL : (DIGIT)+; fragment DIGIT : '0'..'9'; fragment LETTER : ('a'..'z' | 'A'..'Z'); 。这意味着词法分析器永远不会生成fragmentNATURALDIGIT令牌。这些LETTER规则只能由其他词法规则使用。换句话说,你的词法分析器只生成fragmentVARIABLEINTEGERREAL标记*(因此这些是你可以在解析器规则中使用的唯一标记) !)。

*和STRING令牌,当然......