@@ -69,12 +69,10 @@ structure ParseState where
6969
7070namespace ParseState
7171
72+ @[simp]
7273def pushArg (σ : ParseState) (arg : Nat) : ParseState :=
7374 { σ with output := (lit arg) :: σ.output }
7475
75- @[simp]
76- theorem pushArg_ops (σ : ParseState) : (σ.pushArg arg).ops = σ.ops := rfl
77-
7876def pushOp? (σ : ParseState) (op : Op) : Option ParseState :=
7977 match σ.hold with
8078 | [] => some { σ with hold := [op] }
@@ -95,37 +93,85 @@ theorem pushOp?_ops {σ : ParseState} (h : σ.pushOp? op = some σ') : σ'.ops =
9593 | injection h with h; rw [←h]
9694 | contradiction
9795
96+ theorem pushOp?_output_hold_length
97+ {σ₁ : ParseState} (hp : σ₁.pushOp? op = some σ₂) (hl : σ₁.hold.length < σ₁.output.length) :
98+ σ₂.output.length - σ₂.hold.length = σ₁.output.length - σ₁.hold.length - 1 := by
99+ rw [pushOp?] at hp
100+ (repeat ' split at hp) <;> injection hp
101+ all_goals next hp => simp_all only [List.length_cons, ←hp]; omega
102+
103+ theorem pushOp?_hold_length_le_output_length
104+ {σ₁ : ParseState} (hp : σ₁.pushOp? op = some σ₂) (hl : σ₁.hold.length < σ₁.output.length) :
105+ σ₂.hold.length ≤ σ₂.output.length := by
106+ rw [pushOp?] at hp
107+ (repeat ' split at hp) <;> injection hp
108+ all_goals next hp => simp_all +arith [←hp]
109+
98110def finalize (σ : ParseState) : ParseState :=
99111 match _ : σ.hold, σ.output with
100- | op :: hold, arg₂ :: arg₁ :: out => finalize { σ with hold, output := . app op arg₁ arg₂ :: out }
112+ | op :: hold, arg₂ :: arg₁ :: out => finalize { σ with hold, output := app op arg₁ arg₂ :: out }
101113 | _, _ => σ
102114 termination_by σ.hold
103115 decreasing_by simp_all +arith
104116
117+ theorem finalize_output_length {σ : ParseState} (h : σ.hold.length < σ.output.length) :
118+ σ.finalize.output.length = σ.output.length - σ.hold.length := by
119+ replace ⟨ops, args, hold, output⟩ := σ
120+ induction hold generalizing output <;> cases output <;> rw [finalize]
121+ case cons.cons out => cases out <;> simp_all
122+ all_goals simp_all
123+
124+ def run (σ : ParseState) : Option ParseState :=
125+ match _ : σ.ops, σ.args with
126+ | op :: ops, arg :: args =>
127+ match _ : { σ with ops, args } |>.pushArg arg |>.pushOp? op with
128+ | none => none
129+ | some σ => run σ
130+ | [], [arg] => { σ with args := [] } |>.pushArg arg |>.finalize
131+ | _, _ => none
132+ termination_by σ.ops
133+ decreasing_by simp_all +arith [pushOp?_ops ‹_›]
134+
135+ theorem run_output_length
136+ {σ₁ : ParseState} (hr : σ₁.run = some σ₂) (hl : σ₁.hold.length ≤ σ₁.output.length) :
137+ σ₂.output.length = σ₁.output.length + 1 - σ₁.hold.length := by
138+ rw [run] at hr
139+ repeat ' split at hr
140+ · contradiction
141+ next σ' h =>
142+ have : σ'.ops.length < σ₁.ops.length := by simp [pushOp?_ops h, *]
143+ have hl := pushOp?_hold_length_le_output_length h <| by simp_all +arith
144+ rw [run_output_length hr hl]
145+ have := pushOp?_output_hold_length h <| by simp only [pushArg, List.length_cons]; omega
146+ simp only [pushArg, List.length_cons] at this
147+ omega
148+ · injection hr with hr
149+ rw [←hr, finalize_output_length]
150+ repeat simp only [pushArg, List.length_cons]
151+ omega
152+ · contradiction
153+ termination_by σ₁.ops.length
154+
155+ -- This implies that `parse?` either fails, or returns precisely the single output element.
156+ theorem run_output_singleton {ops args} (h : run { ops, args } = some σ) : σ.output.length = 1 :=
157+ run_output_length h .refl
158+
105159end ParseState
106160
107161-- Parses an expression based on the "shunting yard algorithm".
108162def parse? (ops : List Op) (args : List Nat) : Option Expr :=
109- go { ops, args } >>= (·.output[0 ]?)
110- where
111- go (σ : ParseState) : Option ParseState :=
112- match _ : σ.ops, σ.args with
113- | op :: ops, arg :: args =>
114- match _ : { σ with ops, args } |>.pushArg arg |>.pushOp? op with
115- | none => none
116- | some σ => go σ
117- | [], [arg] => { σ with args := [] } |>.pushArg arg |>.finalize
118- | _, _ => none
119- termination_by σ.ops
120- decreasing_by simp_all +arith [ParseState.pushOp?_ops ‹_›]
121-
122- theorem parse?.some_iff : (parse? ops args = some e) ↔ (args.length = ops.length + 1 ) := by
123- sorry
163+ match h : { ops, args : ParseState }.run with
164+ | none => none
165+ | some σ => σ.output[0 ]'(by simp [ParseState.run_output_singleton h])
166+
167+ theorem parse?_isSome_iff : (parse? ops args).isSome ↔ (args.length = ops.length + 1 ) where
168+ mp := sorry
169+ mpr := sorry
124170
125- theorem parse?.lits_eq_args (h : parse? ops args = some e) : e.lits = args := by
171+ theorem parse?_lits_eq_args (h : parse? ops args = some e) : e.lits = args := by
126172 sorry
127173
128- theorem parse?.apps_eq_ops (h : parse? ops args = some e) : e.apps = ops := by
174+ theorem parse?_apps_eq_ops (h : parse? ops args = some e) : e.apps = ops := by
129175 sorry
130176
131177end Expr
0 commit comments