2012-04-23 96 views
0

可以說我有這樣我.Y語法的一部分:YACC(野牛)AST簡化

stmt : expr { $$ = $1; } 
     | stmt expr { $$ = insert_stmt_list($1, $2); } 

在那裏我可以有給出了一個表達的陳述,或者我可以有幾種表達導致一份聲明清單。 關於後者,我通過insert_stmt ...函數來存儲它,但是第一次將它發送到棧頂。

我的問題是:我如何處理$$ = $ 1? 我的意思是,insert_stmt_list將所有內容放在一個結構中,我知道它在那裏,我可以打印它們的值等等,但是$$ = S1到底在哪裏?如何閱讀? :-)

謝謝!

回答

1

回覆:怎麼看?

您有一個左遞歸語法,首先必須識別expr。這減少到stmt和0123'產生的語義值通過$$ = $1;成爲stmt1的語義值。

這僅僅意味着「從右側(恰好是唯一一個)取第一個符號的語義值並將其作爲左側的語義值傳播」。

然後,如果另一expr看出,解析繼續與其他生產:

stmt : ... 
    | stmt expr { $$ = insert_stmt_list($1, $2); } 

這裏,$1stmt來在右手側是這是在分配給$$語義值之前的減產產生了stmt

您已經設計了該系統,因此expr的功能如同stmt。此外,expr產生的值適合作爲insert_stmt_list的參數:表達式是列表。

所以:

  1. 如果輸入只有一個表達式E,然後出現了stmt就是這樣表達。

  2. 如果你有兩個表達式E1和E2,然後emeges的stmt的結果是:

    insert_stmt_list(E1, E2) 
    
  3. 如果你有三個表達式,那麼整個stmt是這些調用的結果:

    insert_stmt_list(insert_stmt_list(E1, E2), E3) 
    

等等。這是否有意義取決於這個「插入」操作的語義。

+0

最大的問題是,如果我期待一個陳述,如何處理表達呢?我能夠處理這個使用泛型結構,我有一個標誌{is_STATEMENT,is_EXPRESSION,...}和一個指向各自結構的指針。所有這些都是因爲C不允許知道指針的類型。 – Nitrate 2012-04-24 18:48:15

+0

你可以看看Lisp的抽象語法。評價的基本句法單位是表達式。如果您希望對幾個表達式進行單一表達式預期的副作用評估,則可以使用類似'progn'的操作符:'(progn expr1 expr2 ... exprn)'。這不是一個多餘的節點。 – Kaz 2012-04-24 19:33:09

0

這是更地道寫是這樣的:

stmt : expr { $$ = make_new_stmt_list($1); } 
     | stmt expr { $$ = insert_stmt_list($1, $2); } 

這種或那種方式,你需要換你表達數據結構在一份聲明中列表數據結構。

+1

解決方案的問題在於,當您爲ast(抽象語法樹)目的創建語句列表時,應該放棄無意義的節點。這就是爲什麼我得出這樣的結論:將價值放在堆棧頂端$$ = $ 1是要走的路,但隨後一切都變得模糊:-) – Nitrate 2012-04-23 19:31:04

+0

表達式列表和單個表達式之間的區別不是然而,一定毫無意義。這是在抽象語法中找到的那種東西。你*有這樣的方式其實沒有抽象;你的代碼從字面上理解語法。即'stmt:expr'聲明,在語法上,一個語句是一個表達式,所以你已經將它轉換爲'$$ = $ 1'。一個更抽象的觀點是,這個左遞歸生產只是一個構建序列的「夾具」(可能只有一個元素)。 – Kaz 2012-04-23 23:04:03