对于我正在尝试解析的标记语言,我决定尝试使用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
,所以看起来我在语言定义中做错了,但我无法正确地找出它。
答案 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"
,如下所示: