标记解析器失败

时间:2012-11-29 19:10:21

标签: antlr antlr3 parser-generator

对于我正在尝试解析的标记语言,我决定尝试使用ANTLR进行解析器生成。我是新手,我搞砸了。

我的语法是

grammar Test;
DIGIT   :   ('0'..'9');
LETTER  :   ('A'..'Z');
SLASH   :   '/'; 
restriction
    :   ('E' ap)
    |   ('L' ap)
    |   'N';
ap  :   LETTER LETTER LETTER;
car :   LETTER LETTER;
fnum    :   DIGIT DIGIT DIGIT DIGIT? LETTER?;
flt :   car fnum?;
message :   'A' (SLASH flt)? (SLASH restriction)?;

当我给它一个输入字符串A/KK543/EPOS时,它正是我想要的。但是当我给它A/KL543/EPOS时,它失败了(MismatchedTokenException(9!=5))。这似乎是某种冲突;它想在第一个L上生成restriction,所以看起来我在语言定义中做错了,但我无法正确地找出它。

1 个答案:

答案 0 :(得分:3)

对于输入"A/KK543/EPOS",将创建以下标记:

'A'        'A'
SLASH      '/'
LETTER     'K'
LETTER     'K'
DIGIT      '5'
DIGIT      '4'
DIGIT      '3'
SLASH      '/'
'E'        'E'
LETTER     'P'
LETTER     'O'
LETTER     'S'

但是对于输入"A/KL543/EPOS",会创建以下内容:

'A'        'A'
SLASH      '/'
LETTER     'K'
'L'        'L'
DIGIT      '5'
DIGIT      '4'
DIGIT      '3'
SLASH      '/'
'E'        'E'
LETTER     'P'
LETTER     'O'
LETTER     'S'

正如您所看到的,字符'L'标记为LETTER。对于解析器规则中的文字标记'A''E''L''N',ANTLR(自动)创建单独的词法规则,这些规则放在所有其他词法规则之前。这会使你的词法分析器在幕后看起来像这样:

A      : 'A';
E      : 'E';
L      : 'L';
N      : 'N';
DIGIT  : '0'..'9';
LETTER : 'A'..'Z';
SLASH  : '/'; 

因此,任何单个'A''E''L''N'都不会成为LETTER令牌。这就是ANTLR的工作原理。如果您希望将它们作为字母匹配,则您需要创建解析器规则letter并让 it 匹配这些令牌。像这样:

message
 : A (SLASH flt)? (SLASH restriction)?
 ;

flt
 : car fnum?
 ;

fnum
 : DIGIT DIGIT DIGIT DIGIT? letter?
 ;

restriction
 : E ap
 | L ap
 | N
 ;

ap
 : letter letter letter
 ;

car
 : letter letter
 ;

letter
 : A
 | E
 | L
 | N
 | LETTER
 ;

A      : 'A';
E      : 'E';
L      : 'L';
N      : 'N';
DIGIT  : '0'..'9';
LETTER : 'A'..'Z';
SLASH  : '/'; 

将解析输入"A/KL543/EPOS",如下所示:

enter image description here