3

我们如何区分 ANTLR 语法中的变量名和标识符?

VAR: ('A'..'Z')+ DIGIT*  ;
IDENT  :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-')*;

这段语法(在 ANTLR 中)不起作用,因为编译器会抱怨某些输入可能永远无法达到 IDENT。对于编译器作者来说,这似乎是一个经典的头脑风暴,The lexer hack

对于 ANTLR 用户,您能告诉我您的巧妙解决方法吗?谢谢

4

1 回答 1

1

泽尔写道:

这段语法(在 ANTLR 中)不起作用,因为编译器会抱怨某些输入可能永远无法达到 IDENT。

不,这是不正确的。以下语法:

grammar T;

parse
  :  .* EOF
  ;

VAR   : ('A'..'Z')+ DIGIT*  ;
IDENT : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-')*;

fragment DIGIT : '0'..'9';

不会产生任何错误或警告。词法分析器只创建两种类型的标记:

  1. 如果某事物以一个或多个大写 ascii 字母开头,后跟零个或多个数字,VAR则创建 a;
  2. 如果某些内容以小写 ascii 字母或下划线开头,后跟('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-')*IDENT则创建 a。

请注意,因此 anIDENT永远不能以大写 ascii 字母开头:那将始终变为VAR.

因此,如果您有一个如下所示的解析器规则:

foo
  :  IDENT
  ;

并且整个输入是"BAR",那么就会出现解析器错误,因为词法分析器不会产生一个INDENT标记,而是一个VAR标记,即使解析器“要求”一个IDENT.

您必须了解,无论解析器向词法分析器提出什么要求,词法分析器都独立于解析器运行。

于 2011-12-02T15:58:09.450 回答