我在 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
谁能帮我解决这个问题吗? 提前致谢。
问候, 赫拉德奥
编辑:
那么如果它不引用标记,我应该使用fragment关键字吗?这样使用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
最佳答案
您的词法分析器规则 CLASSNAME
当前引用解析器规则 upper_lower_case
(词法分析器规则以大写字母开头;解析器规则以小写字母开头)。词法分析器规则只能引用词法分析器规则。
此外,UPPER_CASE
、LOWER_CASE
和 DIGITS
似乎不应自行创建标记,因此应将它们标记为 片段
规则。在下面的示例中,我将 DIGITS
更改为 DIGIT
,因为它只匹配一位数字。
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
。由于此文本可能与CLASSNAME
或OBJECTNAME
匹配,因此词法分析器最终将为其分配语法中出现的第一个规则的类型。换句话说,如果语法中CLASSNAME
出现在OBJECTNAME
之前,则输入X3
将始终为CLASSNAME
token ,并且永远不会是OBJECTNAME
token 。如果在语法中OBJECTNAME
出现在CLASSNAME
之前,则输入X3
将始终为OBJECTNAME
并且永远不会成为CLASSNAME
(事实上,在这种情况下,没有 token 永远不会成为CLASSNAME
)。您的
ACCESSOR
规则看起来应该是一个解析器规则,如下所示:accessor : PUBLIC | PROTECTED | PRIVATE;
编辑2(关于区分CLASSNAME
和OBJECTNAME
的注释):
要区分 CLASSNAME
和 OBJECTNAME
,您可以创建与其中任何一个匹配的词法分析器规则 IDENTIFIER
。
IDENTIFIER : UPPER_LOWER_CASE (DIGIT | UPPER_LOWER_CASE)*;
然后您可以创建一个解析器规则来处理区别:
classname : IDENTIFIER;
objectname : IDENTIFIER;
显然,这允许 x3
成为 classname
,这在您的语言中无效。如果可能的话,我总是喜欢稍微放松解析器规则,并稍后执行进一步的验证,这样我可以提供更好的错误消息。例如,如果您允许 x3
匹配 classname
,那么在解析输入并拥有 AST (ANTLR 3) 或解析树 (ANTLR 4) 后,您可以查看对于 classname
的所有实例,并确保匹配的 IDENTIFIER
以所需的大写字母开头。
解析器自动错误报告生成的错误消息示例:
line 1:15 mismatched input 'variable' expecting CLASSNAME
单独验证生成的错误消息示例:
line 1:15 class name
variable
must start with an upper case letter
关于antlr - EBNF 语法(ANTLR),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16520805/