2008-10-17 54 views
2

我已閱讀GOLD主頁(http://www.devincook.com/goldparser/)文檔,常見問題和維基百科,以瞭解GOLD可能有哪些實際應用。我正在思考如何使用編程語言(很容易)爲我的系統提供服務,比如SAP上的ABAP或Axapta上的X ++ - 但即使使用GOLD,對我來說這看起來並不可行,至少不容易。黃金分析系統 - 什麼可用於編程?

由GOLD生成的解析結果的最終用法轉義了我 - 你如何處理解析的結果?

編輯:一個實際的例子(描述)會很好。

回答

9

解析實際上包含兩個階段。第一個是「lexing」,它將原始字符串轉換爲程序可以更容易理解的東西(通常稱爲令牌)。

簡單的例子,法將轉換:

如果(A + B> 2)然後

在於:

 
IF_TOKEN LEFT_PAREN IDENTIFIER(a) PLUS_SIGN IDENTIFIER(b) GREATER_THAN NUMBER(2) RIGHT_PAREN THEN_TOKEN 

解析需要令牌的該流,並試圖使但更有意義。在這種情況下,它會嘗試將這些標記與IF_STATEMENT匹配。爲了解析,中頻_STATEMENT很可能是這樣的:

 IF (BOOLEAN_EXPRESSION) THEN

凡詞法階段的結果是一個令牌流,解析階段的結果是解析樹。

因此,解析器可以在上述轉變中:

 
    if_statement 
     | 
     v 
    boolean_expression.operator = GREATER_THAN 
     |   | 
     |   v 
     V  numeric_constant.string="2" 
    expression.operator = PLUS_SIGN 
    |  | 
    |  v 
    v identifier.string = "b" 
    identifier.string = "a" 

這裏你可以看到,我們有一個IF_STATEMENT。一個IF_STATEMENT有一個參數,它是一個BOOLEAN_EXPRESSION。這是以某種方式向解析器解釋的。當解析器轉換令牌流時,它會「知道」IF是什麼樣的,並且知道BOOLEAN_EXPRESSION是什麼樣的,所以它可以在看到代碼時做出正確的分配。

例如,如果你剛纔:

如果(A + B),然後

解析器可以知道,它不是一個布爾表達式(因爲+是算術,而不是一個布爾運算符)和解析可能會在此處引發錯誤。

接下來,我們看到一個BOOLEAN_EXPRESSION有3個組件,運算符(GREATER_THAN)和兩邊,左邊和右邊。

在左側指向另一個表達式「a + b」,而在右側指向NUMERIC_CONSTANT,在這種情況下是字符串「2」。同樣,解析器「知道」這是一個NUMERIC常量,因爲我們告訴它關於數字的字符串。如果不是數字,它將是一個標識符(如「a」和「b」)。

注意,如果我們有這樣的事情:

如果(A + B> 「XYZ」),那麼

那 「解析」(右邊左邊表情,字符串常量)就好了。我們不知道這是否是一個有效的表達式。我們不知道「a」或「b」是否引用字符串或數字。所以,這是解析器無法爲我們決定的事情,不能將其標記爲錯誤,因爲它根本不知道。當我們評估(執行或嘗試編譯代碼)IF語句時會發生這種情況。

如果我們這樣做:

如果[A> B),然後

解析器可以很容易地看到,語法錯誤是一個問題,而且會引發錯誤。那串令牌看起來並不像它知道的任何東西。

所以,問題是,當你得到一個完整的分析樹,你有一些保證,首先削減「代碼看起來不錯」。現在執行期間,其他錯誤可能會出現。

要評估分析樹,您只需走樹。在編譯或評估部分中,您將有一些與解析樹的主要節點關聯的代碼。假設我們有一位翻譯。

public void execute_if_statment(ParseTreeNode node) { 
    // We already know we have a IF_STATEMENT node 
    Value value = evaluate_expression(node.getBooleanExpression()); 
    if (value.getBooleanResult() == true) { 
     // we do the "then" part of the code 
    } 
} 

public Value evaluate_expression(ParseTreeNode node) { 
    Value result = null; 
    if (node.isConstant()) { 
     result = evaluate_constant(node); 
     return result; 
    } 
    if (node.isIdentifier()) { 
     result = lookupIdentifier(node); 
     return result; 
    } 
    Value leftSide = evaluate_expression(node.getLeftSide()); 
    Value rightSide = evaluate_expression(node.getRightSide()); 
    if (node.getOperator() == '+') { 
     if (!leftSide.isNumber() || !rightSide.isNumber()) { 
      throw new RuntimeError("Must have numbers for adding"); 
     } 
     int l = leftSide.getIntValue(); 
     int r = rightSide.getIntValue(); 
     int sum = l + r; 
     return new Value(sum); 
    } 
    if (node.getOperator() == '>') { 
     if (leftSide.getType() != rightSide.getType()) { 
      throw new RuntimeError("You can only compare values of the same type"); 
     } 
     if (leftSide.isNumber()) { 
      int l = leftSide.getIntValue(); 
      int r = rightSide.getIntValue(); 
      boolean greater = l > r; 
      return new Value(greater); 
     } else { 
      // do string compare instead 
     } 
    } 
} 

所以,你可以看到我們在這裏有一個遞歸評估器。您會看到我們如何檢查運行時類型並執行基本評估。

會發生什麼是execute_if_statement將評估它的主要表達式。即使我們只想在解析中使用BOOLEAN_EXPRESION,所有表達式對於我們的目的來說都是相同的。所以,execute_if_statement調用evaluate_expression。

在我們的系統中,所有表達式都有一個操作符和一個左側和右側。表達式的每一邊也是一個表達式,所以你可以看到我們如何立即嘗試和評估這些表達以獲得它們的真實價值。有一點需要注意的是,如果表達式由一個CONSTANT組成,那麼我們只需返回常量值,如果它是一個標識符,我們將它作爲一個變量來查看(這將是一個很好的地方扔「我找不到變量「a」消息),否則我們回到左側/右側的事情。

我希望你能看到一個簡單的求值程序如何工作,一旦你有一個來自解析器的令牌流。請注意,在評估過程中,語言的主要元素已經到位,否則我們會遇到語法錯誤,從未到達這個階段。我們可以簡單地期望「知道」,例如,當我們有一個PLUS算子時,我們將有2個表達式,左邊和右邊。或者當我們執行一個IF語句時,我們已經有一個布爾表達式來評估。解析是對我們來說很重要的。

開始使用新的語言可能是一個挑戰,但是一旦你開始使用,其他的就會變得非常簡單,而且它幾乎是「魔術」的,它最終都會有效。

請注意,不要格式化,但下劃線會讓事情變得糟糕 - 我希望它仍然很清楚。

1

GOLD可用於任何類型的應用程序,您必須應用上下文無關文法輸入。

闡述:

從本質上講,CFGS適用於所有編程語言。所以如果你想爲你的公司開發一種腳本語言,你需要編寫一個解析器 - 或者得到一個解析程序。或者,如果您希望爲公司的非程序員輸入半自然語言,則可以使用解析器讀取該輸入並吐出更多「機器可讀」數據。從本質上講,上下文無關語法允許您描述比正則表達式更多的輸入。 GOLD系統顯然使解析問題比lex/yacc(UNIX解析標準程序)容易一些。

+0

請您詳細說明一下。 – 2008-10-17 14:02:23

2

我會推薦antlr.org獲取信息以及我將用於任何解析器使用的「免費」工具。