我使用以下简单语法来理解ANTLR。
grammar Example;
options {
language=Java;
}
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
INT : '0'..'9'+
;
PLUS : '+';
ADDNUM :
INT PLUS INT;
prog : ADDNUM;
当我尝试在ANTLRWorks中为输入1+2
运行语法时,我在控制台中收到以下错误:
[16:54:08]解释... [16:54:08]问题匹配令牌2:0
NoViableAltException(''@ [1:1:Tokens:(ID | INT | PLUS | ADDNUM);])
任何人都可以帮助我了解我的错误。
答案 0 :(得分:1)
您可能没有将prog
指示为ANTLRWorks中的起始规则。如果你这样做,一切都会好起来的。
但你真的不应该像ADDNUM
那样创建一个与表达式匹配的词法分析器规则:这应该是一个解析器规则:
grammar Example;
prog : addExpr EOF;
addExpr : INT PLUS INT;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
INT : '0'..'9'+;
PLUS : '+';
使用解析器,词法分析器或片段规则时没有严格的规则,但这是他们通常使用的:
词法分析器规则通常是语言的最小部分(字符串,数字,标识符,注释等)。尝试从1+2
之类的输入创建词法分析器规则会导致问题,因为:
1 + 2
。表达式1+2
是三个令牌:INT
,PLUS
和另一个INT
。
当您不希望使用此规则时,会使用片段规则,因为“真实”令牌。例如,采用以下词法分析器规则:
ID : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*
FLOAT : '0'..'9'+ '.' '0'..'9'+;
INT : '0'..'9'+;
在上述规则中,您使用了'0'..'9'
四次,因此您可以将其放在单独的规则中
ID : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | DIGIT)*
FLOAT : DIGIT+ '.' DIGIT+;
INT : DIGIT+;
DIGIT : '0'..'9';
但您不想创建DIGIT
令牌:您只希望其他词法分析器规则使用DIGIT
。在这种情况下,您可以创建fragment
规则:
ID : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | DIGIT)*
FLOAT : DIGIT+ '.' DIGIT+;
INT : DIGIT+;
fragment DIGIT : '0'..'9';
这将确保永远不会有DIGIT
令牌:并且因此永远不会在您的解析器规则中使用它!
解析器规则将令牌粘合在一起:它们确保语言为syntactic valid (a.k.a. parsing)。要强调,解析器规则可以使用其他解析器规则或词法分析器规则,但不是片段规则。