2009-07-23 72 views
8

G'day!如何在ANTLR中構造一個乾淨的,像Python一樣的語法?

如何構造一個簡單的ANTLR語法來處理多行表達式而不需要分號或反斜線?

我試圖寫一個簡單的DSL的表達式:

# sh style comments 
ThisValue = 1 
ThatValue = ThisValue * 2 
ThisOtherValue = (1 + 2 + ThisValue * ThatValue) 
YetAnotherValue = MAX(ThisOtherValue, ThatValue) 

總之,我希望我的應用程序提供了一些初步命名值的腳本,然後拉出最後的結果。然而,我越來越掛在語法上。我想支持像多行表達式如下:

# Note: no backslashes required to continue expression, as we're in brackets 
# Note: no semicolon required at end of expression, either 
ThisValueWithAReallyLongName = (ThisOtherValueWithASimilarlyLongName 
           +AnotherValueWithAGratuitouslyLongName) 

我開始了與ANTLR語法是這樣的:

exprlist 
    : (assignment_statement | empty_line)* EOF! 
    ; 
assignment_statement 
    : assignment NL!? 
    ; 
empty_line 
    : NL; 
assignment 
    : ID '=' expr 
    ; 

// ... and so on 

這看似簡單,但我已經與煩惱換行:

warning(200): StackOverflowQuestion.g:11:20: Decision can match input such as "NL" using multiple alternatives: 1, 2 
As a result, alternative(s) 2 were disabled for that input 

圖形,在org.antlr.works.IDE:

Decision Can Match NL Using Multiple Alternatives http://img.skitch.com/20090723-ghpss46833si9f9ebk48x28b82.png

我已經戒了周圍的語法,但總是與違反預期的行爲的結束:

  • 在文件到底是不是需要一個換行符
  • 空行是可以接受的
  • 從英鎊符號開始的一行中的所有內容都將作爲註釋被丟棄
  • 賦值以行尾而非分號結尾
  • 如果包含在括號中,表達式可以跨越多行ets

我可以找到具有許多這些特徵的示例ANTLR語法。我發現,當我削減他們的表現力,以限制他們的需求時,我最終打破了一些東西。其他人太簡單了,當我添加表現力的時候我會打破他們。

這個語法應該採用哪個角度?你能指出任何既不平凡又不完整的圖靈完整語言的例子嗎?

回答

6

我將讓你的標記生成器做繁重,而不是你的新行規則混合到你的語法:

  • 計數括號,括號和大括號,而同時也有未關閉的組不會產生NL令牌。這會給你免費的線路延續,而不會讓你的語法變得更聰明。

  • 無論最後一行是否以'\n'字符結尾,都始終在文件末尾生成一個NL令牌,那麼您不必擔心沒有NL的語句的特例。陳述總是以NL結尾。

第二點會讓你簡化你的語法是這樣的:

exprlist 
    : (assignment_statement | empty_line)* EOF! 
    ; 
assignment_statement 
    : assignment NL 
    ; 
empty_line 
    : NL 
    ; 
assignment 
    : ID '=' expr 
    ; 
+0

現在我需要弄清楚如何讓tokenizer完成那個繁重的工作。回到文檔,我想。 :) – 2009-07-23 11:45:50

0

這個怎麼樣?

exprlist 
    : (expr)? (NL+ expr)* NL!? EOF! 
    ; 
expr 
    : assignment | ... 
    ; 
assignment 
    : ID '=' expr 
    ; 
0

我假設你選擇讓NL可選的,因爲在你輸入代碼的最後聲明中並沒有以新行結束。

雖然它很有意義,但是對於解析器而言,生活會變得更加困難。應該珍視分隔符令牌(如NL),因爲它們可以消除歧義並減少衝突的可能性。

在你的情況下,解析器不知道它是否應該解析「賦值NL」或「賦值empty_line」。有很多方法可以解決這個問題,但其中大多數只是爲了一個不明智的設計選擇而設立的樂隊助手。

我的建議是一個無辜的黑客:使NL成爲強制性的,並始終將NL附加到輸入流的末尾!

這看起來可能有點令人討厭,但實際上它會爲您節省很多未來的麻煩。

相關問題