2013-05-13 109 views
2

我有与EBNF语法的问题ANTLRWorks:EBNF文法(ANTLR)

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 

回答

2

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

此外,看起来UPPER_CASE,LOWER_CASEDIGITS不应该自己创建令牌,因此它们应该被标记为fragment规则。在下面的例子中,我将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。由于此文本可能与CLASSNAMEOBJECTNAME相匹配,词法分析器最终将为其指定语法中出现的第一条规则的类型。换句话说,如果CLASSNAME出现在语法OBJECTNAME之前,输入X3总是CLASSNAME令牌,将永远OBJECTNAME令牌。如果CLASSNAME之前出现的语法OBJECTNAME,输入X3始终OBJECTNAME从未CLASSNAME(其实,在这种情况下,就不会有标记是一个CLASSNAME)。

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

    accessor : PUBLIC | PROTECTED | PRIVATE; 
    

编辑2(约区分CLASSNAME和注释OBJECTNAME):

要区分CLASSNAMEOBJECTNAME,您可以创建与其匹配的词法分析规则IDENTIFIER

IDENTIFIER : UPPER_LOWER_CASE (DIGIT | UPPER_LOWER_CASE)*; 

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

classname : IDENTIFIER; 
objectname : IDENTIFIER; 

显然,这让是一个classname,这是不是在你的语言有效。在可能的情况下,我总是倾向于放松解析器规则,稍后再进一步验证,以便提供更好的错误消息。例如,如果允许匹配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

+0

感谢响应。你能回答我的新问题吗?我编辑了第一篇文章。 – Hladeo 2013-05-13 17:13:40

+0

那么有没有可能区分CLASSNAME和OBJECTNAME?我写了一个简单的Java类生成器,我可以输入:'create ClassName + name:String,-age:int;'其中变量,年龄,字符串和int是OBJECTNAME。 – Hladeo 2013-05-13 17:55:07

+0

@Hladeo请参阅编辑2在我的答案:) – 2013-05-13 18:08:30