我正在構建一個 LL(1) 決議器(遞回下降決議器),我需要決議句子a = 3,我有兩個程式來匹配該規則:parse_assignment和parse_binary_operator,
每個函式消費第一個token,然后需要看運算子( =)是否符合規則,所以我先呼叫parse_assignment哪個消費token“a”,然后消費“=”,再消費“3”。如果函式失敗(不匹配),我會嘗試匹配下一條規則。
但是如果我想決議句子a - 1怎么辦?我嘗試呼叫parse_assignment但隨后它消耗a并失敗,然后我嘗試呼叫parse_binary_operator但標記“a”已被消耗,因此該函式-1現在只有“ ”要決議。
所以我需要以某種方式將令牌回傳到流,以防函式不匹配,但我認為將令牌回傳到流不是一個好主意,我想有更穩定的技術可以做到這一點。
uj5u.com熱心網友回復:
"LL(1)" 中的 "(1)" 表示允許決議器查詢 (1) 未使用的令牌,以便決定采取哪個操作。這個標記通常被稱為“先行”標記,因為決議器可以提前查看它而無需實際消耗它。無論你在決議器和詞法分析器之間實作什么介面,都必須以某種方式實作這個特性;否則,您將恰好遇到您提到的問題。
此介面的確切性質將取決于您用于撰寫決議器的語言,因此很難給出具體的答案。但基本上,詞法分析器將有兩個基本方法:
peek,它回傳前瞻標記的標記型別。(令牌通常具有許多附加功能,所有這些都應該通過peek或其他方法以某種方式可用,這些方法也是先行令牌的視圖。這些包括令牌的語意值(如果有的話)以及一些指示令牌在源檔案中的位置。consume,丟棄前瞻標記并將其替換為下一個輸入標記。
還有其他可能的介面,它們本質上是等效的。例如,實作一個布爾便利函式是很常見的,比如“匹配一個 X 并在成功時使用令牌”,盡管如果您還需要回傳匹配令牌的語意值,這可能不那么方便。
前瞻標記是詞法分析器狀態的一部分,它還包括諸如當前正在決議的字串和該字串中的當前輸入位置等資訊。將這種狀態存盤在全域變數中曾經很常見(這是詞法分析器在 (f)lex 的幫助下構建的),但這使得撰寫具有兩個不同詞法分析器的程式變得更加困難。現代編程風格不鼓勵使用全域變數,這使得需要在決議器狀態(或物件)中包含詞法分析器的狀態(或物件),或者通過遞回決議呼叫顯式傳遞對詞法分析器狀態的參考。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/354808.html
