0

我正在使用以下简单的语法来了解 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 中为 input 运行语法时1+2,我在控制台中收到以下错误:

[16:54:08] 解释...... [16:54:08] 在 2:0
NoViableAltException(''@[1:1: Tokens : (ID | INT | PLUS | ADDNUM);])

谁能帮我理解我哪里出错了。

4

1 回答 1

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

ANTLR 规则

何时使用解析器、词法分析器或片段规则没有严格的规则,但它们通常用于:

词法分析器规则

词法分析器规则通常是语言的最小部分(字符串、数字、标识符、注释等)。尝试从输入创建词法分析器规则1+2会导致问题,因为:

  • 如果您想从该标记中提取有意义的内容(例如,对其进行评估),则需要拆分该标记的内容,因为在从中创建 1 个标记后,整个表达式中的文本将“粘合”在一起;
  • 当中间有空格时,您会遇到问题:1 +   2.

表达式1+2是三个标记:INTPLUS另一个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令牌:因此永远不能在您的解析器规则中使用它!

解析器规则

解析器规则将标记粘合在一起:它们确保语言是语法有效的(也称为解析)。需要强调的是,解析器规则可以使用其他解析器规则或词法分析器规则,但不能使用片段规则。


另请参阅:ANTLR:有一个简单的例子吗?

于 2012-02-13T22:11:22.110 回答