2013-05-13 108 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