C 語言 抽象語法樹AST
抽象語法樹簡介
(一)簡介
抽象語法樹(abstract syntax code,AST)是原始碼的抽象語法結構的樹狀表示,樹上的每個節點都表示原始碼中的一種結構,這所以說是抽象的,是因為抽象語法樹並不會表示出真實語法出現的每一個細節,比如說,巢狀括號被隱含在樹的結構中,並沒有以節點的形式呈現。抽象語法樹並不依賴於源語言的語法,也就是說語法分析階段所採用的上下文無文文法,因為在寫文法時,經常會對文法進行等價的轉換(消除左遞迴,回溯,二義性等),這樣會給文法分析引入一些多餘的成分,對後續階段造成不利影響,甚至會使合個階段變得混亂。因些,很多編譯器經常要獨立地構造語法分析樹,為前端,後端建立一個清晰的介面。
抽象語法樹在很多領域有廣泛的應用,比如瀏覽器,智慧編輯器,編譯器。
(二)抽象語法樹例項
(1)四則運算表示式
表示式: 1+3*(4-1)+2
抽象語法樹為:
(2)xml
程式碼2.1:
- <letter>
- <address>
- <city>ShiChuang</city>
- </address>
- <people>
- <id>12478</id>
- <name>Nosic</name>
- </people>
- <
/letter>
抽象語法樹
(3)程式1
程式碼2.2
- while b != 0
- {
- if a > b
- a = a-b
- else
- b = b-a
- }
- return a
抽象語法樹
(4)程式2
程式碼2.3
- sum=0
- for i in range(0,100)
- sum=sum+i
- end
抽象語法樹
(三)為什麼需要抽象語法樹
當在源程式語法分析工作時,是在相應程式設計語言的語法規則指導下進行的。語法規則描述了該語言的各種語法成分的組成結構,通常可以用所謂的前後文無關文法或與之等價的
例如,四則運算表示式的文法為:
文法1.1
- E->T|EAT
- T->F|TMF
- F->(E)|i
- A->+|-
- M->*|/
改為LL(1)後為:
文法1.2
- E->TE'
- E'->ATE'|e_symbol
- T->FT'
- T'->MFT'|e_symbol
- F->(E)|i
- A->+|-
- M->*|/
例如,當在開發語言時,可能在開始的時候,選擇LL(1)文法來描述語言的語法規則,編譯器前端生成LL(1)語法樹,編譯器後端對LL(1)語法樹進行處理,生成位元組碼或者是彙編程式碼。但是隨著工程的開發,在語言中加入了更多的特性,用LL(1)文法描述時,感覺限制很大,並且編寫文法時很吃力,所以這個時候決定採用LR(1)文法來描述語言的語法規則,把編譯器前端改生成LR(1)語法樹,但在這個時候,你會發現很糟糕,因為以前編譯器後端是對LL(1)語樹進行處理,不得不同時也修改後端的程式碼。
抽象語法樹的第一個特點為:不依賴於具體的文法。無論是LL(1)文法,還是LR(1),或者還是其它的方法,都要求在語法分析時候,構造出相同的語法樹,這樣可以給編譯器後端提供了清晰,統一的介面。即使是前端採用了不同的文法,都只需要改變前端程式碼,而不用連累到後端。即減少了工作量,也提高的編譯器的可維護性。
抽象語法樹的第二個特點為:不依賴於語言的細節。在編譯器家族中,大名鼎鼎的gcc算得上是一個老大哥了,它可以編譯多種語言,例如c,c++,java,ADA,Object C, FORTRAN, PASCAL, COBOL等等。在前端gcc對不同的語言進行詞法,語法分析和語義分析後,產生抽象語法樹形成中間程式碼作為輸出,供後端處理。要做到這一點,就必須在構造語法樹時,不依賴於語言的細節,例如在不同的語言中,類似於if-condition-then這樣的語句有不同的表示方法
在c中為:
- if(condition)
- {
- do_something();
- }
在fortran中為:
- If condition then
- do_somthing()
- end if
在構造if-condition-then語句的抽象語法樹時,只需要用兩個分支節點來表於,一個為condition,一個為if_body。如下圖:
在源程式中出現的括號,或者是關鍵字,都會被丟掉。