2011-09-07 64 views
1

我想解析一個小的表達式語言(我沒有從供應商定義語言)並且一切都很好,直到我嘗試使用not操作符,這是用這種語言代替。ANTLR語法不能正確處理我的「不」操作符

我的語法由這兩個環節(又名無恥剪切和粘貼)的嚴重影響:

http://www.codeproject.com/KB/recipes/sota_expression_evaluator.aspxhttp://www.alittlemadness.com/2006/06/05/antlr-by-example-part-1-the-language

語言包括可以用與,或,不是運營商所使用的三種表達類型和括號改變優先級。表達式是:當我嘗試使用不操作我得到NoViableAltException

Skill("somename") > 1 | (LoggedIn("somename") & SkillExists("othername")) 

然而,:

Skill("name") > some_number (can also be <, >=, <=, =, !=) 
SkillExists("name") 
LoggedIn("name") (this one can also have [email protected]) 

此輸入工作正常。我無法弄清楚爲什麼。我將我的語法與codeproject.com鏈接上的ECalc.g進行了比較,他們似乎相匹配,但我不能看到一些細微差別。失敗:

Skill("somename") < 10 ~ SkillExists("othername") 

我的語法:

grammar UserAttribute; 

options { 
output=AST; 
ASTLabelType=CommonTree; 
} 

tokens { 
SKILL = 'Skill' ; 
SKILL_EXISTS = 'SkillExists' ; 
LOGGED_IN = 'LoggedIn'; 
GT = '>'; 
LT = '<'; 
LTE = '<='; 
GTE = '>='; 
EQUALS = '='; 
NOT_EQUALS = '!='; 
AND = '&'; 
OR = '|' ; 
NOT = '~'; 
LPAREN = '('; 
RPAREN = ')'; 
QUOTE = '"'; 
AT = '@';  
} 

/*------------------------------------------------------------------ 
* PARSER RULES 
*------------------------------------------------------------------*/ 
expression : orexpression EOF!; 
orexpression : andexpression (OR^ andexpression)*; 
andexpression : notexpression (AND^ notexpression)*; 
notexpression : primaryexpression | NOT^ primaryexpression; 
primaryexpression : term | LPAREN! orexpression RPAREN!; 
term : skill_exists | skill | logged_in; 
skill_exists : SKILL_EXISTS LPAREN QUOTE NAME QUOTE RPAREN; 
logged_in : LOGGED_IN LPAREN QUOTE NAME (AT NAME)? QUOTE RPAREN; 
skill: SKILL LPAREN QUOTE NAME QUOTE RPAREN ((GT | LT| LTE | GTE | EQUALS | NOT_EQUALS)? NUMBER*)?; 

/*------------------------------------------------------------------ 
* LEXER RULES 
*------------------------------------------------------------------*/ 
NAME : ('a'..'z' | 'A'..'Z' | '_')+; 
NUMBER : ('0'..'9')+ ; 
WHITESPACE : ('\t' | ' ' | '\r' | '\n'| '\u000C')+ { $channel = HIDDEN; } ; 
+0

但是應該如何'技能( 「somename」)<10〜SkillExists(「中文別名「)'被解析?我假設'Skill(「somename」)<10'是一個'skill'表達式,'〜SkillExists(「othername」)'是一個'notexpression'。但是沒有規則匹配一個'技能',後跟一個'notexpression',對吧? –

+0

這兩個技巧(「somename」)<10和SkillExists(「othername」)都是主要表達式,notexpression讓NOT令牌在任何主要表達式之前出現。這是否回答你的問題? 我是一個ANTLR新手,所以有可能我的語法是如此根本上有缺陷,它是超出希望。雖然我很確定我明白了,但我覺得我非常接近。 – Michael

+0

不,你不知道爲什麼'Skill(「somename」)<10〜SkillExists(「othername」)'失敗了,這對我來說並不奇怪:它應該失敗。我試圖在我的答案的第一句話中解釋這一點。 –

回答

2

我有2個備註:

既然你解析表達式單(expression : orexpression EOF!;),輸入"Skill("somename") < 10 ~ SkillExists("othername")"不僅在你的語法中無效,但在任何表達式解析器(我知道)方面它是無效的。 A notexpression只需要「右側」表達式,因此~ SkillExists("othername")是單個表達式,而Skill("somename") < 10也是單個表達式。但是在這兩個單一表達式之間,沒有ORAND運算符。這與評估表達式true false而不是true | falsetrue and false相同。

總之,你的語法不允許:

Skill("somename") < 10 ~ SkillExists("othername") 

但允許:

Skill("somename") < 10 & SkillExists("othername") 

這似乎合乎邏輯的我。

我不太明白您的skill規則(這是不明確的,順便說一句):

skill 
: SKILL LPAREN QUOTE NAME QUOTE RPAREN 
    ((GT | LT| LTE | GTE | EQUALS | NOT_EQUALS)? NUMBER*)? 
; 

這意味着,運營商是可選的,可以有在零個或多個數字結束。這意味着下面的輸入都是有效的:

  • Skill("foo") = 10 20
  • Skill("foo") 10 20 30
  • Skill("foo") <

也許你的意思是:

skill 
: SKILL LPAREN QUOTE NAME QUOTE RPAREN 
    ((GT | LT| LTE | GTE | EQUALS | NOT_EQUALS)^ NUMBER)? 
; 

呢? (所述?變爲^*被移除)

如果我只改變該規則和解析輸入:創建

Skill("somename") < 10 & SkillExists("othername") 

以下AST:

enter image description here

(正如你所看到的,AST需要更好的形成:即你需要在你的skill_exists,中有一些重寫規則0和skill規則)


編輯

,如果你想連續表達式之間已經暗示AND記號,做這樣的事情:

grammar UserAttribute; 

... 
tokens { 
... 
I_AND;  // <- added a token without any text (imaginary token) 
AND = '&'; 
... 
} 

andexpression 
    : (notexpression -> notexpression) (AND? notexpression -> ^(I_AND $andexpression notexpression))* 
    ; 

... 

正如你所看到的,因爲AND現在是可選的,它不能在重寫規則中使用,但您必須使用虛構標記I_AND

如果你現在解析輸入:

Skill("somename") < 10 ~ SkillExists("othername") 

你會得到以下AST:

enter image description here

+0

好的,你給了我很多信息,到目前爲止這一切都很有意義!謝謝!我知道有些供應商不是運營商,但卻無法指責它,你說得很清楚。他們的表達語言允許「true〜false」,而在任何其他語言方面,您都會寫這個「true &&!false」。所以我的語法實際上需要支持「true〜false」,而沒有其他操作符。 (在一個側面說明中,這讓我想知道如何解釋這個,它是一個暗示「和」...嗯)。 – Michael

+0

另外,?在技​​能規則中是重構失敗的遺留物。你是對的,我不需要那個,謝謝你指出來! (和數字後面的*一樣,我確實有技能,技能存在,並在幾天前作爲一個規則登錄,但將它們重構爲自己的規則,並且在重構後沒有充分檢查我的規則) – Michael

+0

我從來沒有聽說過重寫規則(總新手在這裏),但我在他們的鹿角維基上找到了一個wiki頁面...現在閱讀它們 – Michael