2013-02-21 96 views
2

我正在嘗試使用ANTLR將LALR語法轉換爲LL,並且遇到了一些問題。到目前爲止,我認爲將表達式轉換爲自上而下的方法對我來說是直接的。問題是當我將Range(1..10)和(1.0..10.0)包含在浮點數中時。在範圍和語法錯誤中使用浮點數?

我試圖使用在這裏找到的答案,它甚至不能正確運行我的代碼,更不用說解決浮點範圍,即(float..float)。 Float literal and range parameter in ANTLR

附加是我的語法的一個樣本,只關注這個問題。

grammar Test; 

options { 
    language = Java; 
    output = AST; 
} 

parse: 'in' rangeExpression ';' 
    ; 

rangeExpression : expression ('..' expression)? 
       ; 

expression : addingExpression (('=='|'!='|'<='|'<'|'>='|'>') addingExpression)* 
      ; 

addingExpression : multiplyingExpression (('+'|'-') multiplyingExpression)* 
       ; 

multiplyingExpression : unaryExpression 
         (('*'|'/'|'div') unaryExpression)* 
         ; 

unaryExpression: ('+'|'-')* primitiveElement; 

primitiveElement : literalExpression 
       | id ('.' id)? 
       | '(' expression ')' 
       ; 

literalExpression : NUMBER 
        | BOOLEAN_LITERAL 
        | 'infinity' 
        ;    

id : IDENTIFIER 
    ; 

// L E X I C A L R U L E S  
Range 
: '..' 
; 

NUMBER 
    : (DIGITS Range) => DIGITS   {$type=DIGITS;} 
    | (FloatLiteral) => FloatLiteral {$type=FloatLiteral;} 
    | DIGITS       {$type=DIGITS;} 
    ; 


// fragments 
fragment FloatLiteral : Float; 
fragment Float 
: DIGITS (options {greedy = true; } : '.' DIGIT* EXPONENT?) 
| '.' DIGITS EXPONENT? 
| DIGITS EXPONENT 
; 

BOOLEAN_LITERAL : 'false' 
       | 'true' 
       ; 

IDENTIFIER : LETTER (LETTER | DIGIT)*; 

WS : (' ' 
     | '\t' 
     | '\r' 
     | '\n' 
     ) {$channel=HIDDEN;} 
    ; 
fragment LETTER : ('a'..'z' | 'A'..'Z' | '_') ; 
fragment DIGITS: DIGIT+; 
fragment DIGIT : '0'..'9'; 
fragment EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; 

任何理由爲什麼它不即使考慮:

in 10; 

in 10.0; 

提前感謝!

回答

2

下面的東西是不正確的:

  • 你永遠匹配您的literalExpression規則的NUMBER你改變令牌的類型中的每個替代
  • ,爲此的NUMBER令牌FloatLiteral將永遠不能被創造

像這樣的事情應該兩個11..221.1..2.2工作:

... 

literalExpression : INT 
        | BOOLEAN_LITERAL 
        | FLOAT 
        | 'infinity' 
        ;    

id : IDENTIFIER 
    ; 

// L E X I C A L R U L E S  
Range 
: '..' 
; 

INT 
    : (DIGITS Range)=> DIGITS 
    | DIGITS (('.' DIGITS EXPONENT? | EXPONENT) {$type=FLOAT;})? 
    ; 

BOOLEAN_LITERAL : 'false' 
       | 'true' 
       ; 

IDENTIFIER : LETTER (LETTER | DIGIT)*; 

WS : (' ' 
     | '\t' 
     | '\r' 
     | '\n' 
     ) {$channel=HIDDEN;} 
    ; 
fragment LETTER : ('a'..'z' | 'A'..'Z' | '_') ; 
fragment DIGITS: DIGIT+; 
fragment DIGIT : '0'..'9'; 
fragment EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; 
fragment FLOAT : ; 
+0

感謝您的快速解決!但是我相信如果我沒有弄錯,這沒有解決(在10..10;),即數字範圍 – 2013-02-21 18:09:20

+0

@AndyM,啊,是的,你說得對。檢查我的編輯版本。 – 2013-02-21 18:19:19

+0

我不確定爲什麼我一旦放入EXPONENT就會得到這個:required(...)+ loop與字符'e'中的任何內容都不匹配......感謝您的幫助! – 2013-02-21 18:37:40

1

要將有關處理(1.0 .. 10.0)問題:

注意解析器規則primitiveElement定義選擇,因爲'(' expression ')',但排除expression永遠無法達到規則rangeExpression

考慮重新定義expressionrangeExpression像這樣:

expression : rangeExpression 
      ; 

rangeExpression : compExpression ('..' compExpression)? 
       ; 

compExpression : addingExpression (('=='|'!='|'<='|'<'|'>='|'>') addingExpression)* 
       ; 

這確保了expression規則坐在上面的各種形式表達,並預期在括號將工作。

+0

我現在擁有它的方式實際上捕捉(10.0),但永遠不會捕捉(10.0..20.0)。一旦我切換到你的代碼,ANTLR v3抱怨規則'('表達')將永遠達不到。 – 2013-02-21 18:24:17

+0

@AndyM'(10。0)'被原始語法捕獲,因爲括號不包含範圍 - 範圍是它不會在圓括號中接受的唯一表達式。 ANTLR v3.5中沒有任何警告,我的答案中顯示了更改。確保'primitiveElement'仍然有替代''('表達')''。這是你得到的唯一警告嗎? – user1201210 2013-02-21 18:42:05

+0

一旦我做了@Bart更改,它就起作用了!感謝您注意到這個錯誤 – 2013-02-21 19:04:05