原創|使用教程|編輯:鄭恭琳|2018-01-04 13:18:51.000|閱讀 785 次
概述:這篇文章的目標是教你何時使用哪種解析算法,以及哪些解析算法可能需要刷新。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
在閱讀之前,請務必首先查看第1部分、第2部分、第3部分、第4部分和第5部分!
從理論上講,解析是一個已解決的問題,但是這種問題還是會一再地被解決。也就是說,有很多不同的算法,每個算法都有強大的優點和缺點,而且學者們還在不斷進步。
在本節中,我們不會教導如何實現每一個解析算法,但是我們將解釋它們的特征。目標是您可以選擇更多的知道哪些分析工具使用或哪些算法更好地學習和實現您的自定義分析器。
我們先從全局概述所有解析器的功能和策略。
有兩種解析策略:自頂向下解析(top-down parsing)和自底向上解析(bottom-up parsing)。這兩個術語都是根據解析器生成的分析樹來定義的。簡單的解釋:
讓我們看一個例子,從一個分析樹開始。
同樣的樹會由一個自頂向下和一個自底向上的解析器以不同的順序生成。在下面的圖片中,數字表示創建節點的順序。
傳統上,自頂向下的解析器更容易構建,但自下而上的解析器更強大。現在,情況更加平衡,主要是因為自上而下的解析策略的進步。
推導的概念與策略密切相關。派生指出了規則中的非終結符元素出現在右側的順序,用于獲取左側的非終結符號。使用BNF術語,它指示如何使用__expression__中出現的元素來獲得< symbol >。這兩種可能性是最左邊的推導和最右邊的推導。第一個表示規則從左到右應用,而第二個表示相反。
一個簡單的例子:想象一下,你正在試圖解析符號結果,在語法中定義了這樣的結果。
expr_one = .. // stuff expr_two = .. // stuff result = expr_one 'operator' expr_two
您可以先將符號規則應用于符號expr_one,然后執行expr_two,反之亦然。在最左邊的派生的情況下,你選擇第一個選項,而為了最右邊的派生,你選擇第二個。
理解推導是深度優先還是遞歸應用是很重要的。也就是說,它被應用到開始表達式,然后再被應用到所獲得的中間結果。因此,在這個例子中,如果在應用expr_one對應的規則之后,有一個新的非終結符;那個先變了 非終結符expr_two僅在它成為第一個非終結符并且不遵循原始規則中的順序時才應用。
派生與兩種策略相關聯,因為對于自下而上的解析,您可以應用最右邊的派生,而對于自頂向下的解析,您可以選擇最左派生。請注意,這對最終的解析樹沒有影響;它只是影響中間元素和使用的算法。
用自上而下和自下而上的策略構建的解析器有一些我們應該談論的內容。
術語“前瞻”和“回溯”在解析方面的含義與其在大型計算機科學領域中的含義不同。Lookahead表示在當前的元素之后的元素的數量,這些元素被考慮來決定采取哪個當前的行動。
一個簡單的例子:解析器可能會檢查下一個標記以決定現在應用哪個規則。當適當的規則匹配時,當前token被消耗,但下一個仍然在隊列中。
回溯是一種算法的技術。它包括通過嘗試部分解決方案找到復雜問題的解決方案,然后不斷檢查最有前途的解決方案。如果當前正在測試的那個失敗,則解析器回溯(即,它回到最后被成功解析的位置)并且嘗試另一個。
它們與LL、LR和LALR分析算法特別相關,因為只需要一個預讀標記的語言的解析器更容易構建并且更快地運行。在算法名稱之后的括號(即LL(1),LR(k))之間指示由這些算法使用的前瞻tokens。符號(*)表示該算法可以檢查無限的超前tokens,盡管這可能會影響算法的性能。
圖表解析器是可以自下而上(即CYK)或自上而下(即Earley)的一系列解析器。圖表解析器基本上試圖通過使用動態編程來避免回溯,這可能是昂貴的。或動態優化是在較小的子問題中解決較大問題的一般方法。
圖表解析器使用的常見動態編程算法是(Viterbi algorithm)。該算法的目標是在給定已知事件序列的情況下找到最有可能的隱藏狀態。基本上,考慮到我們所知道的tokens,我們試圖找出最可能的規則。
名稱圖表解析器來自這樣一個事實,即部分結果存儲在名為圖表的結構中(通常,圖表是表格)。存儲部分結果的特定技術稱為memoization。其他算法也使用Memoization,與圖表解析器無關,如packrat。
在討論解析算法之前,我們想談談在解析算法中使用自動機。是一個抽象機器族群,其中有著名的圖靈機(Turing machine)。
當談到解析器時,您可能會聽到(確定性)下推自動機(PDA)這個術語,當您閱讀詞法分析器時,您會聽到術語(確定性)有限自動機(DFA)。PDA比DFA更強大,更復雜(雖然比圖靈機簡單)。
由于它們定義了抽象機器,通常它們與實際算法沒有直接關系。相反,他們正式描述算法必須能夠處理的復雜程度。如果有人說解決問題X需要一個DFA,他意味著你需要一個和DFA一樣強大的算法。
但是,由于DFA是狀態機,在詞法分析器的情況下,區分通常是沒有意義的。這是因為狀態機實現相對簡單(即有現成的庫),所以大多數情況下,DFA是通過狀態機實現的。這就是為什么我們要簡要地談論DFA以及為什么他們經常用于詞法分析器。
DFA是一個(有限的)狀態機,這個概念我們假設你很熟悉。基本上,狀態機有許多可能的狀態和每個狀態的轉換函數。這些轉換功能控制機器如何從一個狀態移動到另一個狀態以響應事件。當用于練習時,機器每次輸入一個輸入字符,直到達到接受狀態(即它可以建立一個標記)。
他們用于幾個原因:
在線算法是一個不需要整個輸入工作的算法。在詞法分析器的情況下,這意味著只要算法看到其中的字符,就可以識別它。另一種選擇是它需要整個輸入來識別每個token。
除了這些屬性之外,將一組正則表達式轉換為DFA相當容易,這使得可以以許多開發人員熟悉的簡單方式輸入規則。然后,您可以自動將其轉換為可以高效處理的狀態機。
請繼續關注第7部分!
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn