編譯器設計-解析類型算法
Compiler Design - Types of Parsingspa
語法分析器遵循由上下文無關語法定義的產生式規則。生成規則的實現方式(派生)將解析分爲兩種類型:自上而下解析和自下而上解析。設計
自頂向下分析Top-down Parsing 3d
當解析器開始從開始符號構造解析樹,而後嘗試將開始符號轉換爲輸入時,稱爲自頂向下解析。 指針
遞歸降低解析:它是自頂向下解析的一種常見形式。它被稱爲遞歸,由於它使用遞歸過程來處理輸入。遞歸降低解析受到回溯的影響。 blog
回溯:這意味着,若是產品的一個派生失敗,語法分析器將使用同一產品的不一樣規則從新啓動進程。這種技術能夠屢次處理輸入字符串以肯定正確的生產。 遞歸
自下而上分析Bottom-up Parsing 進程
顧名思義,自底向上的解析從輸入符號開始,並嘗試構建解析樹直至開始符號。ip
Example:字符串
Input string : a + b * c
Production rules:
S → E
E → E + T
E → E * T
E → T
T → id
Let us start bottom-up parsing
a + b * c
讀取輸入並檢查是否有任何生產與輸入匹配:
a + b * c
T + b * c
E + b * c
E + T * c
E * c
E * T
E
S
在上一章中,咱們瞭解到自頂向下解析技術解析輸入,並開始從根節點逐漸向下移動到葉節點構建解析樹。
遞歸降低分析Recursive Descent Parsing
遞歸降低是一種自頂向下的解析技術,它從頂部構造解析樹,從左到右讀取輸入。它對每一個終端和非終端實體使用過程。這種解析技術遞歸地解析輸入以生成解析樹,這可能須要也可能不須要回溯。但與之相關聯的語法(若是沒有保留因子)不能避免回溯。一種不須要任何回溯的遞歸降低解析稱爲預測解析。
這種解析技術被認爲是遞歸的,由於它使用的上下文無關語法本質上是遞歸的。
回溯Back-tracking
自上而下的解析器從根節點(開始符號)開始,並根據生產規則匹配輸入字符串以替換它們(若是匹配)。要理解這一點,請以CFG爲例:
S → rXd | rZd
X → oa | ea
Z → ai
對於輸入字符串:read,自上而下的解析器,其行爲以下:
它將從生產規則中的S開始,並將其收益率與輸入的最左邊的字母(即「r」)匹配。S(S→rXd)的產生與之相匹配。因此自上而下的解析器前進到下一個輸入字母(即「e」)。解析器嘗試展開非終端「X」,並從左側檢查其結果(X→oa)。它與下一個輸入符號不匹配。因此自上而下的解析器回溯以得到X的下一個產生式規則(X→ea)。
如今解析器按順序匹配全部輸入字母。接受字符串。
預測分析器 Predictive parser
Predictive parser是一種遞歸降低解析器,它可以預測將使用哪一個產品來替換輸入字符串。預測解析器不受回溯的影響。
爲了完成它的任務,預測解析器使用一個前瞻指針,它指向下一個輸入符號。爲了使解析器無需回溯,預測解析器對語法施加一些約束,只接受一類稱爲LL(k)語法的語法。
預測性分析使用堆棧和分析表來分析輸入並生成分析樹。堆棧和輸入都包含一個結束符號$,表示堆棧爲空而且輸入被消耗。解析器引用解析表來決定輸入和堆棧元素的組合。
在遞歸降低解析中,對於單個輸入實例,解析器可能有多個產品可供選擇,而在預測解析器中,每一個步驟最多有一個產品可供選擇。可能存在沒有與輸入字符串匹配的產品的實例,從而致使分析過程失敗。
LL分析器LL Parser
LL語法分析器接受LL語法。LL文法是上下文無關文法的一個子集,但有必定的限制,要獲得簡化的版本,才能實現容易。LL語法能夠經過遞歸降低和表驅動兩種算法來實現。
LL解析器表示爲LL(k)。第一個L in LL(k)從左到右解析輸入,第二個L in LL(k)表示最左邊的派生,k自己表示look ahead的數量。通常k=1,因此LL(k)也能夠寫成LL(1)。
LL解析算法 LL Parser Algorithm
對於解析器的解釋,咱們可使用肯定性的LL(1),由於表的大小隨着k的值呈指數增加。其次,若是給定的語法不是LL(1),那麼對於任何給定的k,一般都不是LL(k)。
下面給出了LL(1)解析的算法:
Input:
string ω
parsing table M for grammar G
Output:
If ω is in L(G) then left-most derivation of ω,
error otherwise.
Initial State : $S on stack (with S being start symbol)
ω$ in the input buffer
SET ip to point the first symbol of ω$.
repeat
let X be the top stack symbol and a the symbol pointed by ip.
if X∈ Vt or $
if X = a
POP X and advance ip.
else
error()
endif
else /* X is non-terminal */
if M[X,a] = X → Y1, Y2,... Yk
POP X
PUSH Yk, Yk-1,... Y1 /* Y1 on top */
Output the production X → Y1, Y2,... Yk
else
error()
endif
endif
until X = $ /* empty stack */
若是A→α|β是G的兩個不一樣乘積,則語法G是LL(1):
對於無終端,α和β都導出以a開頭的字符串。
α和β中至多有一個能夠導出空字符串。
若是β→t,則α不導出以跟隨(a)中的終端開始的任何字符串。