2013-03-03 68 views
1

這是一個更普遍的問題,因爲我不知道如何開始。基本上,我必須使用Yacc來解釋/翻譯一種稱爲CALC的組合語言,它可以對變量執行算術運算,然後將其打印出來。我已經有了解釋工作,但是我的項目的第二部分是編寫一個C++文件,其中包含原始文件中的所有說明,並進行了翻譯。如何使用Yacc將語言翻譯成C++?

我的問題是,我該怎麼做?我是否在代碼中寫入文件以符合我的語法規則,還是在主內部執行?我一直試圖在語法規則代碼內部做到這一點,但是我發現數據正在被寫入文件反向(也就是說,如果我聲明瞭四個變量,那麼程序會打印出原來聲明的最後一個變量先編程,等等)。

+0

這真的不清楚。如果你已經解決了Yacc部分,你爲什麼問Yacc? – 2013-03-03 20:24:49

+0

它仍然與Yacc有關。我已經解釋了這種語言,但是我必須使用Yacc編寫一個與給定程序完全相同的C++文件。 – user1174511 2013-03-03 20:27:33

+1

@ user1174511如果你已經實現瞭解釋,那麼你已經有了某種形式的包含代碼的抽象數據結構(例如AST或ASG)。你可以走這個結構並將其「序列化」到C++。 – 2013-03-03 20:35:12

回答

2

好,Yacc的確實做了自下而上的解析。

您大致有兩種選擇:

  1. 可以輸出結果你現在的樣子,當輸入導致的降低和執行附加代碼,但隨後你將需要重新排序的東西所有的時間。

  2. 您可以在規則中構建abstract syntax tree,然後按順序遍歷它。這是通常的做法。

0

我會在兩個階段做到這一點:使用yacc創建解析樹,然後走樹輸出需要輸出的任何東西。

0

數據被寫入到文件向後

特定位聽起來像是你選擇了一個不同的結構比你想要的。 Yacc允許左右遞歸,這使您可以(例如)按照您看到每個項目(左遞歸)的順序解析列表,或者按照相反的順序解析列表。這裏是正確的遞歸的例子,你可能現在正在做的:

list : ITEM 
    | ITEM list 

注意,當此子文法看到一個項目的投入,它不知道使用這兩個作品上,僅僅基於 - - 他們都以ITEM開始。所以,解析器向前看一個標記。如果下一個標記不是ITEM,那麼它知道使用第一個生產。但如果下一個標記是ITEM,那麼它必須處理第二個生產。但是該產品中有非終結符list,這意味着解析器實際上並沒有減少,但將第一個ITEM推到堆棧上並尋找另一個list

這樣做的結果是,如果你給這個subgrammar一個ITEM標記的列表,它會繼續將它們推到堆棧上,直到它最終看到一個ITEM沒有被另一個ITEM跟隨。在這一點上,最終的物品將通過第一生產被降低(從而變成list,和所有其他項目將通過一個由第二生產被減小一個。在向左遞歸。

list : ITEM   /* matches first ITEM in list */ 
    | list ITEM /* matches all other ITEMs in list */ 

這次,當解析器看到一個ITEM時,list製作中只有一個製作以ITEM開頭,所以它會立即減少第一個製作,將該ITEM轉換爲list。現在,如果輸入流中有另一項ITEM,它將嘗試匹配一個list,後跟一個ITEM,並且與第二個生產完全匹配。

這些是解析簡單列表的常見習慣用法。請注意,如果您的列表是「零個或多個」而不是「一個或多個」,那麼您只需使用空白製作而不是包含單個ITEM的製作。使用左遞歸(你通常想要的),擁有一個與第一個項目相匹配的單獨生產爲你提供了一個方便的地方,例如,初始化一個將要保存所有可能遵循的ITEM的數組。