在這裏提到的所有程式都實作在我幫 lean 寫的一個解析器擴充程式庫 https://git.sr.ht/~dannypsnl/parsec-extra 中
右結合的 infix
partial def infixR (opList : List (Parsec (α → α → α))) (tm : Parsec α)
: Parsec α := go #[]
where
go (ls : Array (α × (α → α → α))) : Parsec α := do
let lhs ← tm
for findOp in opList do
match ← tryP findOp with
| .some f => return ← go (ls.push (lhs, f))
| .none => continue
let rhs := lhs
return ls.foldr (fun (lhs, bin) rhs => bin lhs rhs) rhs
prefix op tm
def «prefix» (opList : List $ Parsec (α → α)) (tm : Parsec α)
: Parsec α := do
let mut op := .none
for findOp in opList do
op ← tryP findOp
if op.isSome then break
match op with
| .none => tm
| .some f => return f (← tm)
postfix op tm
def «postfix» (opList : List $ Parsec (α → α)) (tm : Parsec α)
: Parsec α := do
let e ← tm
let mut op := .none
for findOp in opList do
op ← tryP findOp
if op.isSome then break
match op with
| .none => return e
| .some f => return f e