當前位置:首頁 » 編程軟體 » 編譯原理抽象語法樹的構建

編譯原理抽象語法樹的構建

發布時間: 2023-04-02 13:27:21

『壹』 如何用python寫一個解釋器

大學里計算機科學最吸引我的地方就是編譯器。最神奇的是,編譯器是如何讀出我寫的那些爛代碼,並且還能生成那麼復雜的程序。當我終於選了一門編譯方面的課程時,我發現這個過程比我想的要簡單得多。
在本系列的文章中,我會試著通過為一種基本命令語言IMP寫一個解釋器,來展示這種簡易性。因為IMP是一個簡單廣為人知的語言,所以打算用 Python寫這個解釋器。Python代碼看起來很像偽代碼,所以即使你不認識 Python,你也能理解它。解析可以通過一套從頭開始實現的解析器組合完成(在本系列的下一篇文章中會有解釋)。除了sys(用於I/O)、re(用於解析正則表達式)以及unittest(用於確保一切工作正常)庫,沒有使用其他額外的庫。
IMP 語言
在開始寫之前,我們先來討論一下將要解釋的語言。IMP是擁有下面結構的最小命令語言:
賦值語句(所有變數都是全局的,而且只能存儲整數):

Python

1

x := 1

條件語句:

Python

1
2
3
4
5

if x = 1 then
y := 2
else
y := 3
end

while循環:

Python

1
2
3

while x < 10 do
x := x + 1
end

復合語句(分號分隔):

Python

1
2

x := 1;
y := 2

OK,所以它只是一門工具語言,但你可以很容易就把它擴展成比Lua或python更有用的語言。我希望能把這份教程能保持盡量簡單。
下面這個例子是計算階乘的程序:

Python

1
2
3
4
5
6

n := 5;
p := 1;
while n > 0 do
p := p * n;
n := n - 1
end

IMP沒有讀取輸入的方式,所以初始狀態必須是在程序最開始寫一系列的賦值語句。也沒有列印結果的方式,所以解釋器必須在程序的結尾列印所有變數的值。
解釋器的結構
解釋器的核心是「中間表示」(Intermediate representation,IR)。這就是如何在內存中表示IMP程序。因為IMP是一個很簡單的語言,中間表示將直接對應於語言的語法;每一種表達和語句都有對應的類。在一種更復雜的語言中,你不僅需要一個「語法表示」,還需要一個更容易分析或運行的「語義表示」。
解釋器將會執行三個階段:
源碼中的字元分割成標記符(token)
將標記符組織成一棵抽象語法樹(AST)。抽象語法樹就是中間表示。
評估這棵抽象語法樹,並在最後列印這棵樹的狀態
將字元串分割成標記符的過程叫做「詞法分析」,通過一個詞法分析器完成。關鍵字是很短,易於理解的字元串,包含程序中最基本的部分,如數字、標識符、關鍵字和操作符。詞法分析器會除去空格和注釋,因為它們都會被解釋器忽略。

將標記符組織成抽象語法樹(AST)的過程稱為「解析過程」。解析器將程序的結構提取成一張我們可以評估的表格。

實際執行這個解析過的抽象語法樹的過程稱為評估。這實際上是這個解析器中最簡單的部分了。
本文會把重點放在詞法分析器上。我們將編寫一個通用的詞彙庫,然後用它來為IMP創建一個詞法分析器。下一篇文章將會重點打造一個語法分析器和評估計算器。
詞彙庫
詞法分析器的操作相當簡單。它是基於正則表達式的,所以如果你不熟悉它們,你可能需要讀一些資料。簡單來說,正則表達式就是一種能描述其他字元串的特殊的格式化的字元串。你可以使用它們去匹配電話號碼或是郵箱地址,或者是像我們遇到在這種情況,不同類型的標記符。
詞法分析器的輸入可能只是一個字元串。簡單起見,我們將整個輸入文件都讀到內存中。輸出是一個標記符列表。每個標記符包括一個值(它代表的字元串)和一個標記(表示它是一個什麼類型的標記符)。語法分析器會使用這兩個數據來決定如何構建一棵抽象語法樹。
由於不論何種語言的詞法分析器,其操作都大同小異,我們將創建一個通用的詞法分析器,包括一個正則表達式列表和對應的標簽(tag)。對每一個表達式,它都會檢查是否和當前位置的輸入文本匹配。如果匹配,匹配文本就會作為一個標記符被提取出來,並且被加上該正則表達式的標簽。如果該正則表達式沒有標簽,那麼這段文本將會被丟棄。這樣免得我們被諸如注釋和空格之類的垃圾字元干擾。如果沒有匹配的正則表達式,程序就要報錯並終止。這個過程會不斷循環直到沒有字元可匹配。
下面是一段來自詞彙庫的代碼:

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

import sys
import re

def lex(characters, token_exprs):
pos = 0
tokens = []
while pos < len(characters):
match = None
for token_expr in token_exprs:
pattern, tag = token_expr
regex = re.compile(pattern)
match = regex.match(characters, pos)
if match:
text = match.group(0)
if tag:
token = (text, tag)
tokens.append(token)
break
if not match:
sys.stderr.write('Illegal character: %sn' % characters[pos])
sys.exit(1)
else:
pos = match.end(0)
return tokens

注意,我們遍歷正則表達式的順序很重要。lex會遍歷所有的表達式,然後接受第一個匹配成功的表達式。這也就意味著,當使用詞法分析器時,我們應當首先考慮最具體的表達式(像那些匹配運算元(matching operator)和關鍵詞),其次才是比較一般的表達式(像標識符和數字)。
詞法分析器
給定上面的lex函數,為IMP定義一個詞法分析器就非常簡單了。首先我們要做的就是為標記符定義一系列的標簽。IMP只需要三個標簽。RESERVED表示一個保留字或操作符。INT表示一個文字整數。ID代表標識符。

Python

1
2
3
4
5

import lexer

RESERVED = 'RESERVED'
INT = 'INT'
ID = 'ID'

接下來定義詞法分析器將會用到的標記符表達式。前兩個表達式匹配空格和注釋。它們沒有標簽,所以 lex 會丟棄它們匹配到的所有字元。

Python

1
2
3

token_exprs = [
(r'[ nt]+', None),
(r'#[^n]*', None),

然後,只剩下所有的操作符和保留字了。記住,每個正則表達式前面的「r」表示這個字元串是「raw」;Python不會處理任何轉義字元。這使我們可以在字元串中包含進反斜線,正則表達式正是利用這一點來轉義操作符比如「+」和「*」。

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

(r':=', RESERVED),
(r'(', RESERVED),
(r')', RESERVED),
(r';', RESERVED),
(r'+', RESERVED),
(r'-', RESERVED),
(r'*', RESERVED),
(r'/', RESERVED),
(r'<=', RESERVED),
(r'<', RESERVED),
(r'>=', RESERVED),
(r'>', RESERVED),
(r'=', RESERVED),
(r'!=', RESERVED),
(r'and', RESERVED),
(r'or', RESERVED),
(r'not', RESERVED),
(r'if', RESERVED),
(r'then', RESERVED),
(r'else', RESERVED),
(r'while', RESERVED),
(r'do', RESERVED),
(r'end', RESERVED),

最後,輪到整數和標識符的表達式。要注意的是,標識符的正則表達式會匹配上面的所有的保留字,所以它一定要留到最後。

Python

1
2
3

(r'[0-9]+', INT),
(r'[A-Za-z][A-Za-z0-9_]*', ID),
]

既然正則表達式已經定義好了,我們還需要創建一個實際的lexer函數。

Python

1
2

def imp_lex(characters):
return lexer.lex(characters, token_exprs)

如果你對這部分感興趣,這里有一些驅動代碼可以測試輸出:

Python

1
2
3
4
5
6
7
8
9
10
11

import sys
from imp_lexer import *

if __name__ == '__main__':
filename = sys.argv[1]
file = open(filename)
characters = file.read()
file.close()
tokens = imp_lex(characters)
for token in tokens:
print token

繼續……

『貳』 編譯原理簡單嗎

編譯原理主要是講了編譯器的實現。
那什麼是編譯器呢?
編譯器就是將 源程序→編譯器 →目標機器代碼的程序
本文將用一段最簡單的代碼進行說明

1 + 2 + 3

第一步. 詞法分析
當代碼從文件中被讀入到編輯器時,將會進行詞法分析
示例中的代碼最終會轉換為(下面為偽代碼)

1 ADD 2 ADD 3

第二步. 語法分析
這一步編譯器將會把詞法分析的結果轉換成AST(abstract syntax tree, 抽象語法樹)
所有的操作數將會作為子節點,所有的操作符將會作為父節點。(不知道的同學可以看一下樹的生成)

1 + 2 + 3 對應的樹
3. 生成目標代碼
對上面的樹進行後序遍歷,將會得到下面的偽代碼

((1 2 +) 3 +)

生成的匯編偽代碼為

START:

MOV VALUE, 0//初始化結果為0

ADD VALUE, 1

ADD VALUE, 2//(1 2 +)的匯編偽代碼

ADD VALUE, 3

RET VALUE

END

最終匯編代碼會被編譯成機器代碼,在計算機上執行。
下面為一般情況下的編譯流程
1. 詞法分析(生成代碼對應的token序列,使用正則表達式)
2. 語法分析(生成AST)
3. 語義分析(對代碼的語法進行檢查)
4. 代碼生成(生成可執行的代碼)

『叄』 Ocaml語言編程 AST文件(抽象語法樹)定義了 stmt可以是stmt也可以是stmt List 為什麼還會報錯

您好,這樣的:
抽象語法樹的結構不依賴於源語言的文法,也就是語法分析階段所採用的上下文無關文法。因為在Parser工程中,經常會對文法進行等價的轉換(消除左遞歸、回溯、二義性等),這樣會給文法引入一些多餘的成分,對後續階段造成不利影響,甚至會使各階段變得混亂。因此,很多編譯器(包括GJC)經常要獨立地構造語法分析樹,為前、後端建立一個清晰的介面。

『肆』 編譯原理筆記9:語法分析樹、語法樹、二義性的消除

語法分析樹和語法樹不是一種東西 。習慣上,我們把前者叫做「具體語法樹」,其能夠體現推導的過程;後者叫做「抽象語法樹」,其不體現過程,只關心最後的結果。

語法分析樹是語言推導過程的圖形化表示方法。這種表示方法反映了語言的實質以及語言的推導過程。

定義:對於 CFG G 的句型,分析樹被定義為具有下述性質的一棵樹:

推導,有最左推導和最右推導,這兩種推導方式在推導過程中的分析樹可能不同,但因最終得到的句子是相同的,所以最終的分析樹是一樣的。

分析樹能反映句型的推導過程,也能反映句型的結構。然而實際上,我們往往不關心推導的過程,而只關心推導的結果。因此,我們要對 分析樹 進行改造,得到 語法樹 。語法樹中全是終結符,沒有非終結符。而且語法樹中沒有括弧

定義:

說白了,語法樹這玩意,就一句話: 葉子全是操作數,內部全是操作符 ,樹里沒有非終結符也不能有括弧。

語法樹要表達的東西,是操作符(運算)作用於操作數(運算對象)

舉倆例子吧:

【例】: -(id+id) 的語法樹:

【例】:-id+id 的語法樹:

顯然,我們從上面這兩個語法樹中,直接就能觀察出來它們的運算順序。

【例】:句型 if C then s1 else s2

二義性問題:一個句子可能對應多於一棵語法樹。

【例】: 設文法 G: E → E+E | E*E | (E) | -E | id

則,句子 id+id*id、id+id+id 可能的分析樹有:

在該例中,雖然 id+id+id 的 「+」 的結合性無論左右都不會影響結果。但萬一,萬一「+」的含義變成了「減法」,那麼左結合和右結合就會引起很大的問題了。

我們在這里講的「二義性」的「義」並非語義——我們現在在學習的內容是「語法分析器」,尚未到需要研究語言背後含義的階段。

我們現在講的「二義性」指的是一個句子對應多種分析樹。

二義性的體現,是文法對同一句子有不止一棵分析樹。這種問題由【句子產生過程中的某些推導有多於一種選擇】引起。懸空 else 問題就可以很好地體現這種【超過一種選擇】帶來的二義性問題,示例如下。

看下面這么個例子。。

(其實,我感覺這個其實比較像是「說話大喘氣」帶來的理解歧義問題。。。)上面的產生式中並沒體現出來該咋算分一塊,所以兩種完全不同的句子結構都是合法的。

二義性問題是有救的,大概有以下這三種辦法:

這些辦法的核心,其實都是將優先順序和結合性說明白。

核心:把優先順序和結合性說明白

既然要說明白,那就不能讓一個非終結符可以直接在當次推導中能推出會帶來優先順序和結合性歧義的東西。(對分析樹的一個內部節點,不會有出現在其下面的分支是相同的非終結符的情況。如果有得選,那就有得歧義了。沒得選才能確定地一路走到黑)

改寫為非二義文法的二義文法大概有下面這幾個特點:

改寫的關鍵步驟:

【例】改寫下面的二義文法為非二義文法。圖右側是要達成的優先順序和結合性

改寫的核心其實就兩句話:

所以能夠得到非終結符與運算的對應關系(因為不同的運算有不同的優先順序,我們想要引入多個優先順序就要引入多個新的非終結符。這樣每個非終結符就可以負責一個優先順序的運算符號,也就是說新的非終結符是與運算有關系的了。因此這里搞出來了「對應關系」四個字)如下:

優先順序由低到高分別是 +、 、-,而距離開始符號越近,優先順序越低。因此在這里的排序也可以+ -順序。每個符號對應一層的非終結符。根據所需要的結合性,則可確定是左遞歸還是右遞歸,以確定新的產生式長什麼樣子

【例】:規定優先順序和結合性,寫出改寫的非二義文法

我們已經掌握了一種叫做【改寫】的工具,能讓我們消除二義性。接下來我們就要用這個工具來嘗試搞搞懸空 else 問題!

懸空 else 問題出現的原因是 then 數量多於 else,讓 else 有多個可以結合的 then。在二義文法中,由於選哪兩個 then、else 配對都可以,故會引起出現二義的情況。在這里,我們規定 else 右結合,即與左邊最靠近的 then 結合。

為改寫此文法,可以將 S 分為完全匹配(MS)和不完全匹配(UMS)兩類。在 MS 中體現 then、else 個數相等即匹配且右結合;在UMS 中 then、else 不匹配,體現 else 右結合。

【例】:用改寫後的文法寫一個條件語句

經過檢查,無法再根據文法寫出其他分析樹,故已經消除了二義性

雖然二義文法會導致二義性,但是其並非一無是處。其有兩個顯著的優點:

在 Yacc 中,我們可以直接指定優先順序、結合性而無需自己重寫文法。

left 表示左結合,right 表示右結合。越往下的算符優先順序越高。

嗯就這么簡單。。。

我們其實可以把語言本身定義成沒有優先順序和結合性的。。然後所有的優先、結合都交由括弧進行控制,哪個先算就加括弧。把一個過程的結束用明確的標志標記出來。

比如在 Ada 中:

在 Pascal 中,給表達式加括弧:

『伍』 抽象語法樹的簡介

在計算機科學中,抽象語法樹(abstract syntax tree或者縮寫為AST),或者語法樹(syntax tree),是源代碼的抽象語法結構的樹狀表現形式,這里特指編程語言的源代碼。樹上的每個節點都表示源代碼中的一種結構。之所以說語法是「抽象」的,是因為這里的語法並不會表示出真實語法中出現的每個細節。比如,嵌套括弧被隱含在樹的結構中,並沒有以節點的形式呈現;而類似於if-condition-then這樣的條件跳轉語句,可以使用帶有兩個分支的節點來表示。
和抽象語法樹相對的是具體語法樹(concrete syntaxtree),通常稱作分析樹(parse tree)。一般的,在源代碼的翻譯和編譯過程中,語法分析器創建出分析樹。一旦AST被創建出來,在後續的處理過程中,比如語義分析階段,會添加一些信息。

『陸』 Java 虛擬機一樣的速度甚至出現AOT編譯方式嗎

不論是物理機還是虛擬機,大部分的程序代碼從開始編譯到最終轉化成物理機的目標代碼或虛擬機能執行的指令集之前,都會按照如下圖所示的各個步驟進行:

『柒』 編譯原理問題,高手進。

回答下列問題:(30分)
(6分)對於下面程序段
program test (input, output)
var i, j: integer;
procere CAL(x, y: integer);
begin
y:=y*y; x:=x-y; y:=y-x
end;
begin
i:=2; j:=3; CAL(i, j)
writeln(j)
end.
若參數傳遞的方法分別為(1)傳值、(2)傳地址,(3)傳名,請寫出程序執行的輸出結果。
答: (1) 3 (2) 16 (3) 16 (每個值2分)

(6分)計算文法G(M)的每個非終結符的FIRST和FOLLOW集合,並判斷該文法是否是LL(1)的,請說明理由。
G(M):
M → TB
T → Ba |
B → Db | eT |
D → d |

解答:
計算文法的FIRST和FOLLOW集合:(4分)
FIRST(M) = { a,b,e,d, } FIRST(T) = { a,b,e,d, }
FIRST(B) = {b,e,d, } FIRST(D) = {d,}
FOLLOW (M) = {#} FOLLOW (T) = { a,b,e,d,#}
FOLLOW (B) = {a,# } FOLLOW (D) = { b}

檢查文法的所有產生式,我們可以得到:
1. 該文法不含左遞歸,
2. 該文法中每一個非終結符M,T,B,D的各個產生式的候選首符集兩兩不相交。
3. 該文法的非終結符T、B和D,它們都有候選式,而且
FIRST(T)∩FOLLOW(T)={ a,b,e,d }≠
所以該文法不是LL(1)文法。(2分)

(4分)考慮下面的屬性文法
產 生 式 語 義 規 則
S→ABC

A→a
B→b
C→c B.u := S.u
A.u := B.v + C.v
S.v := A.v
A.v :=3*A.u
B.v := B.u
C.v := 1
畫出字元串abc的語法樹;
對於該語法樹,假設S.u的初始值為5,屬性計算完成後,S.v的值為多少。
答:(1) (2分)

(2) S.v的值為18 (2分)

(4分)運行時的DISPLAY表的內容是什麼?它的作用是什麼?
答:DISPLAY表是嵌套層次顯示表。每當進入一個過程後,在建立它的活動記錄區的同時建立一張嵌套層次顯示表diaplay.假定現在進入的過程層次為i,則它的diaplay表含有i+1個單元,自頂向下每個單元依次存放著現行層、直接外層、…、直至最外層(主程序,0層)等每層過程的最新活動記錄的起始地址。通過DISPLAY表可以訪問其外層過程的變數。

(5分)對下列四元式序列生成目標代碼:
A:=B*C
D:=E+A
G:=B+C
H:=G*D
其中,H在基本塊出口之後是活躍變數, R0和R1是可用寄存器。
答: 目標代碼序列
LD R0 B
MUL R0 C
LD R1 E
ADD R1 R0
LD R0 B
ADD R0 C
MUL R0 R1
ST R0 H

(5分)寫出表達式a+b*(c-d)對應的逆波蘭式、三元式序列和抽象語法樹。
答:
逆波蘭式:(abcd-*+) (1分)
三元式序列: (2分)
OP ARG1 ARG2
(1) - c d
(2) * b (1)
(3) + a (2)
抽象語法樹:(2分)

(8分)構造一個DFA,它接受={a,b}上所有包含ab的字元串。
答:
(2分)構造相應的正規式:(a|b)*ab(a|b)*

(3分)
a a

a b
b b

(3分)確定化:
I
{0,1,2} {1,2,3} {1,2}
{1,2,3} {1,2,3} {1,2,4,5,6}
{1,2} {1,2,3} {1,2}
{1,2,4,5,6} {1,2,3,5,6} {1,2,5,6}
{1,2,3,5,6} {1,2,3,5,6} {1,2,4,5,6}
{1,2,5,6} {1,2,3,5,6} {1,2,5,6}
b b
b a
a a a a

a b b
b

最小化:
{0,1,2} {3,4,5}
{0, 2},1, {3,4,5}

(6分)寫一個文法使其語言為L(G)={anbncm| m,n≥1,n為奇數,m為偶數}。
答:
文法G(S):

(8分)對於文法G(S):

1. 寫出句型b(Ma)b的最右推導並畫出語法樹。
2. 寫出上述句型的短語,直接短語和句柄。
答:
1. (4分)

2. (4分)
短語: Ma), (Ma), b(Ma)b
直接短語: Ma)
句柄: Ma)

(12分)對文法G(S):
S → a | ^ | (T)
T → T,S | S
(1) 構造各非終結符的FIRSTVT和LASTVT集合;
(2) 構造算符優先表;
(3) 是算符優先文法嗎?
(4) 構造優先函數。
答:
(1) (4分)

(2) (4分)
a ^ ( ) ,
a > >
^ > >
( < < < = <
) > >
, < < < > >

(3) 是算符優先文法,因為任何兩個終結符之間至多隻有一種優先關系。 (1分)

(4) 優先函數(3分)
a ^ ( ) ,
F 4 4 2 4 4
G 5 5 5 2 3

(8分)設某語言的do-while語句的語法形式為
S do S(1) While E
其語義解釋為:

針對自下而上的語法分析器,按如下要求構造該語句的翻譯模式,將該語句翻譯成四元式:
(1) 寫出適合語法制導翻譯的產生式;
(2) 寫出每個產生式對應的語義動作。
答:(1). 適合語法制導翻譯的文法(4分)
G(S):
R do
UR S(1) While
SU E
(2). (4分)
R do
{ R.QUAD:=NXQ }

UR S(1) While
{ U.QUAD:=R.QUAD;
BACKPATCH(S.CHAIN, NXQ) }

SU E
{ BACKPATCH(E.TC, U.QUAD);
S.CHAIN:=E.FC }

答案二:
(1) S do M1 S(1) While M2 E
M ε (4分)
(2) M ε { M.QUAD := NXQ } (4分)
S do M1 S(1) While M2 E
{
BACKPATCH(S(1).CHAIN, M2.QUAD);
BACKPATCH(E.TC, M1.QUAD);
S.CHAIN:=E. FC
}

(10分)將語句
while C>0 do if A B=0 then C:=C+D else C:=C*D
翻譯成四元式。
答:
100 (j>, C, 0, 102)
101 (j, -, -, 112)
102 (jnz, A, -, 106)
103 (j, -, -, 104)
104 (j=, B, 0, 106)
105 (j, -, -, 109)
106 (+, C, D, T1)
107 (:=, T1, -, C)
108 (j, -, -, 100)
109 (*, C, D, T2)
110 (:=, T2, -, C)
111 (j, -, -, 100)
112

(10分)設有基本塊如下:
T1:=3
T2:=A*B
T3:=9+T1
M:=A*B
T4:=C-D
L:=T3*T4
T2:=C+D
N:=T2
畫出DAG圖;
設L,M,N 是出基本塊後的活躍變數,請給出優化後的四元式序列。
答:

1. (6分)
L

*
T2,M T4 T2,N

* - +

T1 T3
3 A B 12 C D

2. (4分)
M:=A*B
S1:=C-D
L:=12*S1
N:=C+D

(8分)文法G(S)及其LR分析表如下,請給出串baba#的分析過程。
(1) S → DbB (2) D → d (3) D → ε
(4) B → a (5) B → Bba (6) B → ε
LR分析表
ACTION GOTO
b D a # S B D
0 r3 s3 1 2
1 acc
2 s4
3 r2
4 r6 S5 r6 6
5 r4 r4
6 s7 r1
7 S8
8 r5 r5
解答:
步驟 狀態 符號 輸入串
0 0 # baba#
1 02 #D baba#
2 024 #Db aba#
3 0245 #Dba ba#
4 0246 #DbB ba#
5 02467 #DbBb a#
6 024678 #DbBba #
7 0246 #DbB #
8 01 #S # acc
哈哈,估計認識!!

『捌』 簡述利用推導構造語法樹的過程

語法樹,是針對上下文無關文法,用來表示一個句型的生成過程的一種描述手段。
對於給定的句型,依據文法構造它的語法樹,是語法分析的任務。
編譯原理課程中重點學習的各種語法分析方法,都是解決語法樹的構造的具體分析方法。
在學習並掌握各種語法分析方法之前,一般只能依據直覺印象,通過猜測、拼湊等手段,去試著推演,湊出符合要求的句型的語法樹。所以這個階段練慣用的題目一般也不很復雜,通過多多練習也能找到一些技巧(其實主要是後面將要學習的自頂向下語法分析中的一些原則)。
對於給定的文法,有一些句型可能能構建出兩棵甚至多棵結構不同的語法樹,結果不一定是唯一的。這樣的文法就是所謂的二義性文法。
對於非二義性文法而言,任意一個句型的語法樹都是唯一的。

『玖』 符號表和抽象語法樹是什麼關系兩者在編譯器設計中是否必需

一般的編譯器可能包含下面這些模塊:

1, 詞法分析器:
輸入: 源代碼
輸出: token
2, 語法分析器:
輸入: token
輸出: AST
在這個過程中, 可以識別出不符合語法規則的語句, 就可以報syntax錯誤, 如果有syntax錯誤, 編譯結束
3, 語義分析器:
輸入: AST
輸出: 無
在這個過程中, 根據語言的語義規則來識別語義錯誤, 要識別語義錯誤 就必須編譯AST, 因為是樹的遍歷, 假如你先遍歷到了int a 這個節點, 接著又遍歷到了一個表達式a = 4這個節點, 你需要檢查變數a有沒有聲明啊, 變數a和4的類型批不匹配呢? 這時你如果沒有保存變數a的信息, 那麼你怎麼檢查? 所以就需要符號表來保存這些信息了.
4, 代碼優化:
最簡單的就是常量折疊優化了, 比如: a = 1 + 2 這個語句可以直接換成: a = 3了, 也就是說在編譯階段就把一些必要的運算先計算完成, 在程序運行的時候就不需要計算這些了, 就提高了程序的運行效率. 這部分是最復雜的了, 還有各種各樣各樣的優化
5, 代碼生成:
輸入: AST
輸出: 可以是虛擬機代碼, 可以是本地匯編代碼

熱點內容
格物致知編程 發布:2025-07-16 18:07:54 瀏覽:947
戴爾伺服器系統設置如何設置 發布:2025-07-16 18:02:09 瀏覽:958
為什麼換安卓這么難 發布:2025-07-16 17:14:44 瀏覽:421
轉動密碼鎖怎麼開 發布:2025-07-16 17:14:37 瀏覽:611
伺服器和網關ip 發布:2025-07-16 17:09:35 瀏覽:930
如何用net映射伺服器盤符 發布:2025-07-16 17:08:50 瀏覽:13
小飛機android 發布:2025-07-16 16:51:00 瀏覽:236
python獲取api 發布:2025-07-16 16:35:28 瀏覽:740
安卓應用耗電優化是什麼 發布:2025-07-16 16:29:39 瀏覽:502
惠普電腦都有什麼配置的 發布:2025-07-16 15:51:49 瀏覽:520