因為有些運算子優先級相同,所以我們還需要再修改上面的函數來正確的支援這個概念;而且上面的程式為了避免複雜化,只解析一次 operator 加上 tm
就退出了,會導致實際上 1 + 2 * 3 * 4
這種算式的 * 4
部分沒有被解析。要解決這個問題,我們需要貪婪解析右半邊 op tm
的部分。綜上所述我們得到的程式碼是
def infixL (opList : List (Parsec (α → α → α))) (tm : Parsec α) : Parsec α := do let l ← tm let rs ← many do for findOp in opList do match ← tryP findOp with | .some f => return (f, ← tm) | .none => continue fail "cannot match any operator" return rs.foldl (fun lhs (bin, rhs) => (bin lhs rhs)) l
首先我們有一串 operator 而非一個,其次在右邊能被解析成 op tm
時都進行解析,最後用 foldl
把結果轉換成壓縮後的 α