Clang中包含了很是多的關於抽象語法樹(AST)的訪問和操做的類和接口。咱們程序開發人員能夠直接經過繼承其中的某些類,重寫其中的關鍵成員方法,從而造成咱們本身的對抽象語法樹的操做。編程
那麼,首先咱們簡要介紹幾個概念:設計模式
抽象語法樹(AST):抽象語法樹是源代碼的抽象語法結構的樹狀表現形式。樹上的每一個節點都表示源代碼中的一種結構。之因此說語法是「抽象」的,是由於這裏的語法並不會表示出真實語法中出現的每一個細節。通常的,在源代碼的翻譯和編譯過程當中,語法分析以後會建立出抽象語法樹。一旦AST被建立出來,在後續的處理過程當中,好比語義分析階段,會添加不少語義信息幫助進行後續的語義翻譯工做。AST其實就是一個程序的靜態模型,它抽象出了一個程序在靜態時結構狀態,咱們能夠經過對AST的分析從而瞭解一個程序的相關靜態信息。數據結構
Source to Source轉換:我所理解的源到源的轉換能夠簡單的當作是從一種源代碼的形式轉換到另外一種源代碼的形式。這其中,形式的定義很寬泛,包括了最簡單的源代碼風格、變量函數的命名到不一樣的編程語言。這些的轉換均可以成爲source to source transformation。編程語言
那麼,若是要進行源到源的轉換,最直接的思路和方式就是經過得到一個程序代碼片斷的抽象語法樹(AST),而後經過修改AST的若干子樹或若干結點,而後將AST轉換成源代碼,從而完成源到源的轉換。函數
既然,咱們已經明白了咱們的目標和途徑,那麼接下來就介紹一下Clang中的基於AST的操做以及它們的設計模式。spa
Clang中的AST部分操做和表示的設計和實現比較相似於設計模式中的訪問者模式。翻譯
Stmt是表示程序語言語法成分的最原始的抽象基類接口,而咱們的其餘各類語法類型則是繼承Stmt,如IfStmt,NullStmt,DeclStmt等等。
它們至關因而訪問者模式中的Element和ConcreteElement。元素類和抽象元素類。
RecursiveASTVisitor相似於訪問者模式中的訪問者。
咱們在實現本身的操做AST的方法時須要繼承自RecursiveASTVisitor類,並重寫其中的多個方法,通常爲bool VisitXXX(Stmt* stmt)方法。
每個VisitXXX方法都是訪問某個具體對應類型的Stmt結點並對它進行操做的函數。 因此RecursiveASTVisitor和咱們寫的Visitor類就至關於抽象訪問者類和訪問者類。
ASTConsumer類的主要功能是提供一種自頂向下的對抽象語法樹進行訪問的入口。
由於AST中包含了各類各樣的Stmt,因此也能夠認爲ASTConsumer相似於提供了訪問這個包含多種類型Stmt的容器的入口。
所以咱們能夠將它對應到訪問者模式中的ObjectStructure和Client。在這其中有多種方法來遍歷當前程序生成的抽象語法樹AST,從而得到各類各樣類型的AST Node。
所以,咱們須要本身實現一個繼承自ASTConsumer得類,並重寫其中的遍歷AST的方法,如:HandleTopLevelDecl,HandleTranslationUnit等等。
有人說,訪問者模式比較適用於對已有功能的重構,或者說對一個項目已經完成,它的元素類型、數據結構已經定的差很少,而對數據的操做還有可能後序會改變。這樣,可使用訪問者模式對原有的代碼進行重構一遍。設計