《編譯器設計》第二章第5節的疑惑?
01-11
《編譯器設計》第二章第5節說的為了避免過度回滾而使用的最長適配詞法分析器的偽代碼到底好在哪?誰看過嗎,看了一晚上還是沒看懂Failed數組和全局計數器InputPos到底有什麼作用或者說好處在哪?
下圖分別是使用Failed數組優化後和沒使用Failed數組、全局計數器InputPos的情況。InitializeScanner必須在NextWord之前調用。目的:為了進行避免過渡回滾。例:對於正則表達式ab|(ab)*c,前面這個式子的*號應該是克林星號。
它要讀取完abababab然後回滾才能識別最長前綴ab,然後第二次讀取ababab又得回滾才能識別ab,然後第三次讀取abab又得回滾才能識別ab,最後一次讀取ab不用回滾。使用優化後的讀取器就能避免這種問題(也就是使用Failed數組和全局計數器InputPos)。任何建議回答都好,謝謝。==================分割線======================================首先謝謝知乎網友李元奇耐心詳細的回復,下面是對知乎網友李元奇的回復的疑問,貼出來不是對原答案的否定,只是因為我還存在較多疑問,希望被大家看到,可以幫我解答一下。評論如下:============================================================= 謝謝這麼詳細耐心的回答。下面的困惑點都是建立在上一個困惑點成立或者不成立的情況下,困惑如下:
1.在分割線下面的第五段出現的」一共讀取了4+3+2+1次「,請問這個讀取是指每次讀取一對ab嗎?所以第一次讀取4次,第二次讀取3次,第三次讀取2次,第四次讀取一次。2.書中說InitializeScanner必須在NextWord之前調用,那麼每次做的標記不都會被InitializeScanner衝掉嗎?除非對於某個輸入字元串,只是第一次識別的時候調用,後面的識別過程就不再是這樣調用了。3.假設疑問2不成立,確實是像後面"除非"所說。那麼根據後面的那個while循環,標記的應該是Failed數組state和InputPos分別為(Se,8),(S3,8),(S4,7),(S3,6),(S4,5),(S3,4),因為s2是屬於Sa,所以會退出循環,也就是不會繼續標記,這個時候就進行了後面的return TokenType[state],讀取結束,按照1所說的那種計算,這次讀取了4次。然後進行第二次讀取,那麼InputPos等於3(因為沒有進行InitializeScanner,所以保存的是上一次的值)state等於s0,進入第一個while循環,InputPos+1,不會觸發if Failed(因為這時候Failed[s0][4],是false,壓根沒有被第二個while更新,因為時候Failed數組的第一維度和第二維度的搭配不再和第一次遍歷讀取一樣了),然後就是push和得到下一個state,再次循環重複,後面的沒有受到第一次標記Failed數組的任何好處,這也就是我最大的困惑。
我也是去年聖誕節才開始學編譯原理的, @藍色 當時給我推薦的這本書,看了前端部分又把龍書的前端看了遍。
我也沒搞明白這段代碼的好處在哪裡。似乎Failed[][]的好處只有在詞法分析器對同一個字元串再一次進行分析的時候才能發揮出作用。對同一個字元串分析兩遍?搞毛啊?
推薦閱讀:
※請教,像C/Go這種靜態語言,編譯可執行文件的過程,是否是先生成彙編然後由彙編生成機器碼?
※為什麼不能把so文件靜態鏈接到可執行文件中?
※關於這段C代碼為什麼會輸出這種結果?
※開發一個 C++ 編譯器的難度有多大,難點又在哪裡?
※量子計算機的出現能否加快cpp的編譯時間?