2

我在 ANTLRWorks 中遇到了 EBNF 语法问题:

line 37:    
upper_lower_case
: LOWER_CASE 
| UPPER_CASE
;

line 42:
CLASSNAME 
:   UPPER_CASE (DIGITS | upper_lower_case )*
;

line 51:
UPPER_CASE 
:   'A'..'Z'
;

line 55:
LOWER_CASE 
:   'a'..'z'
;

line 60:
DIGITS  :   '0'..'9'
;

我希望 CLASSNAME 始终以大写字母开头,并且它可以由数字、大写或小写字母组成。

错误日志:

[13:11:59] warning(200): classgenerator.g:43:42: 
Decision can match input such as "'0'..'9'" using multiple alternatives: 1, 2

As a result, alternative(s) 2 were disabled for that input
[13:11:59] warning(200): classgenerator.g:43:42: 
Decision can match input such as "<EOT>" using multiple alternatives: 2, 3

As a result, alternative(s) 3 were disabled for that input
[13:11:59] error(201): classgenerator.g:43:42: The following alternatives can never be 
matched: 3

[13:11:59] error(208): classgenerator.g:60:1: The following token definitions can never 
be matched because prior tokens match the same input: UPPER_CASE,DIGITS

谁能帮我解决这个问题?提前致谢。

问候, Hladeo

编辑:

所以如果片段关键字不引用标记,我应该使用它吗?这样使用fragment关键字会不会出错?

tokens {
PUBLIC    = '+';
PRIVATE   = '-';
PROTECTED = '=';
}

fragment ACCESSOR
: PUBLIC
| PRIVATE
| PROTECTED
;

和另一个问题。

OBJECTNAME  
:   UPPER_LOWER_CASE (UPPER_LOWER_CASE | DIGIT)*
;

OBJECTNAME 应该至少包含一个字母(大写或小写无关紧要)和可选的另一个字母或数字 - 这部分代码有什么问题?例如,当我尝试输入时variable- 没关系,但是当我以大写字母开头时Variable出现错误:

line 1:15 mismatched input 'Variable' expecting OBJECTNAME
4

1 回答 1

2

您的词法分析器规则CLASSNAME当前引用解析器规则upper_lower_case(词法分析器规则以大写字母开头;解析器规则以小写字母开头)。词法分析器规则只能引用词法分析器规则。

此外,似乎UPPER_CASELOWER_CASEDIGITS不应自己创建标记,因此应将它们标记为fragment规则。在下面的示例中,我更改DIGITSDIGIT因为它只匹配一位数字。

CLASSNAME : UPPER_CASE (DIGIT | UPPER_LOWER_CASE)*;

fragment UPPER_LOWER_CASE : LOWER_CASE | UPPER_CASE;
fragment UPPER_CASE : 'A'..'Z';
fragment LOWER_CASE : 'a'..'z';
fragment DIGIT : '0'..'9';

编辑 1(对于问题中的编辑):

  • 输入中的一段文本只能有一种标记类型。例如,考虑输入文本X3。由于此文本可以匹配 aCLASSNAME或 an OBJECTNAME,因此词法分析器最终会为其分配出现在语法中的第一条规则的类型。换句话说,如果CLASSNAME出现OBJECTNAME在语法中,输入X3永远是一个CLASSNAME标记,永远不会是一个OBJECTNAME标记。如果OBJECTNAME出现CLASSNAME在语法中,则输入X3始终是 anOBJECTNAME并且永远不会是 a CLASSNAME(实际上,在这种情况下,任何标记都不会是 a CLASSNAME)。

  • 您的ACCESSOR规则看起来应该是解析器规则,如下所示:

    accessor : PUBLIC | PROTECTED | PRIVATE;
    

编辑 2(关于区分CLASSNAMEand的评论OBJECTNAME):

要区分CLASSNAMEOBJECTNAME,您可以创建一个IDENTIFIER匹配其中任何一个的词法分析器规则。

IDENTIFIER : UPPER_LOWER_CASE (DIGIT | UPPER_LOWER_CASE)*;

然后,您可以创建解析器规则来处理区别:

classname : IDENTIFIER;
objectname : IDENTIFIER;

显然,这允许x3成为 a classname,这在您的语言中无效。如果可能的话,我总是喜欢稍微放宽解析器规则并稍后执行进一步验证,以便提供更好的错误消息。例如,如果您允许x3match classname,那么在解析输入并拥有 AST (ANTLR 3) 或解析树 (ANTLR 4) 后,您可以查找 的所有实例classname并确保匹配IDENTIFIER以所需的大写字母开头信。

解析器的自动错误报告产生的示例错误消息:

第 1:15 行不匹配的输入“变量”期望 CLASSNAME

单独验证产生的示例错误消息:

第 1:15 行类名variable必须以大写字母开头

于 2013-05-13T13:25:16.607 回答