你的問題是關於構建AST節點的問題,但是你的解釋的主體是關於符號表的。這些想法是不一樣的! AST代表程序的結構。符號表代表關於哪些名稱在哪裏可見以及它們具有哪些類型的推論。
在您的符號表焦點之後,當您「輸入」一個塊並在「退出」時彈出它的概念在概念上是正確的,因爲它抽象地實現了每個塊的新範圍。
我不認爲你可以讓YACC做你說的話,因爲我不確定你可以在語法規則中的任何點附加語義動作。我相信你只能對整個規則附加行動,而且只有當規則被認可時(「減少」),行動纔會運行。所以,如果你真的想這樣做,你會想要彎曲語法來創建插入語義操作的機會。您可以通過重寫你的規則做到這一點(以下你的風格,我不認爲這實際上是有效的YACC語法):
compound_statement : block_start statement_list block_end ;
block_start = '{' pushScope() ;
block_end = '}' popScope();
我加入行動阻止開始和結束對稱的,但你可以多一點嗯,簡約(壞笑):
compound_statement : block_start statement_list '}' popScope() ;
block_start = '{' pushScope() ;
真正的祕密在這裏被創造的減少/語義動作執行的機會,你輸入塊後,通過添加子規則的原始規則。我經常用空的規則做這件事:
compound_statement : '{' compound_statement_sub_rule block_start statement_list '}' popScope() ;
compound_statement_sub_rule = pushScope() ;
已經顯示瞭如何做到這一點,我不認爲你想要這樣做。你正在做的是在解析過程中糾纏語義。如果沿着這條路走下去,你會發現自己用複雜的動作來修飾其餘的語法,以創建/查找標識符。通常使用語義操作來簡單地構建語法樹,然後在解析完成後,通過遍歷語法樹來實現符號表結構/標識符查找。
我會去辦公時間,問你想的問題,無論你認爲他們是否愚蠢。它會很好的回報。
-1手動製作這樣的空規則毫無意義,因爲如果你願意,yacc會爲你做所有重要的事情。另外,語法指導翻譯(Aho的書)的要點是避免創建一個分析樹並在單獨的遍中遍歷它的開銷,所以如果這真的是Aho的類,那麼你可能不想那麼做。 。 – 2011-04-13 17:21:29
@Chris Dodd:那你是說yacc會爲你插入虛擬規則和語義動作?好。我見過的大多數LALR解析器生成器都沒有(它很少見,額外的工具看起來沒有必要)。關於「語法指導翻譯」,你是對的,如果這就是他們所做的事情,他們必須把所有的東西編織在一起。一個合理的人將解釋OP的問題陳述「我們正在考慮下面的代碼來生成我們的AST」,因爲它表示他們沒有進行語法指導翻譯。 「Aho的書」也不完全是關於語法指導的翻譯。 – 2011-04-13 17:38:17