2015-11-06 108 views
3

我正在開發一個翻譯器,用於將PC上的簡單腳本翻譯成某些字節碼以在微控制器上執行它(字節碼)。如何從ParseResults獲取抽象語法樹

我使用lex和re2c開發了C++中的翻譯器,但是我正在考慮切換到pyparsing。

爲了將我的腳本語句翻譯成字節碼中的少量操作,我需要獲取該語句的抽象語法樹。

I.E.這個腳本:

X = 1 - 2; 

應轉換爲這個二進制數:

register1 <- 1 
register2 <- 2 
register3 <- register1 - register2 
x <- register3 

我有了這個Python代碼:

integer = Combine(number) 
ident = Word(alphas,alphanums) 

expr = Forward() 
atom = (integer | 
     (lpar + expr.suppress() + rpar) 
     ) 
expr << (atom + (addop | multop) + atom) 

statement = ident + assign + expr 


L = statement..parseString(line) 

是否有訪問AST的葉子的例子在L?或者類似的東西...提前

感謝

回答

2

您當前的解析器將只是給你解析令牌的平面列表,因爲這是在pyparsing默認。這樣做的目的是,無論您如何構建解析器,無論是在較小的部分中,然後將它們放在一起,還是僅在一個巨大的語句中,您從解析中獲得的令牌都是結構化(或不結構化)相同。爲了獲得與AST相似的東西,你需要使用pyparsing的Group類來定義你想要的結構(我也推薦使用結果名稱)。因此,例如,如果你改變聲明:

statement = Group(ident("lhs") + '=' + Group(expr)("rhs")) 

那麼你的輸出將是更具可預測性 - 每一個解析的語句將有3個頂級元素 - 目標標識符(尋址爲result.lhs)中,「= '運算符和源表達式(可作爲result.rhs尋址)。源表達式可能有更多的結構,但總的來說,每個語句中總是會有最頂層的3個。

爲了保證您的RHS表達式的括號組被保留評估您的expr的時候,再使用組:

atom = (integer | Group(lpar + expr + rpar)) 

您可以瀏覽解析結果的層次結構,如果你是走的列表嵌套列表。我也鼓勵你看看SimpleBool example on the pyparsing wiki。在這個例子中,各種解析的表達式被渲染成類的實例,然後可以使用訪問者或迭代器來處理,然後每個類可以實現自己的特殊邏輯來發送字節碼。想象一下,你已經編寫了一個典型的解析器來生成一個AST,然後通過AST來創建CodeGenerator對象,這些對象被劃分到AssignmentCodeGenerator或IfCodeGenerator或PrintCodeGenerator類中,然後走這個結構來創建你的字節碼。相反,您可以在pyparsing中定義賦值,if-then-else或print語句表達式,使pyparsing直接創建類,然後遍歷類來創建字節碼。最後,你的代碼被整齊地組織成不同的語句類型,並且每種類型都封裝了它應該輸出的字節碼的類型。

+0

非常感謝! SimpleBool是我需要查看的很好的代碼示例。 infixNotation是定義表達式的絕佳解決方案。 另外我不是Python的主人,所以操作員的操作符對我來說很有洞察力 – Mtr