@@ -52,6 +52,14 @@ def eval : Expr → Nat
5252 | lit n => n
5353 | app op arg₁ arg₂ => op.interpret arg₁.eval arg₂.eval
5454
55+ def lits : Expr → List Nat
56+ | lit n => [n]
57+ | app _ arg₁ arg₂ => arg₁.lits ++ arg₂.lits
58+
59+ def apps : Expr → List Op
60+ | lit _ => []
61+ | app op arg₁ arg₂ => arg₁.apps ++ op :: arg₂.apps
62+
5563structure ParseState where
5664 ops : List Op := []
5765 args : List Nat := []
@@ -67,21 +75,25 @@ def pushArg (σ : ParseState) (arg : Nat) : ParseState :=
6775@[simp]
6876theorem pushArg_ops (σ : ParseState) : (σ.pushArg arg).ops = σ.ops := rfl
6977
70- def pushOp (σ : ParseState) (op : Op) : ParseState :=
78+ def pushOp? (σ : ParseState) (op : Op) : Option ParseState :=
7179 match σ.hold with
72- | [] => { σ with hold := [op] }
80+ | [] => some { σ with hold := [op] }
7381 | top :: hold =>
7482 match compare top.prio op.prio, top.leftAssoc with
75- | .lt, _ | .eq, false => { σ with hold := op :: top :: hold }
83+ | .lt, _ | .eq, false => some { σ with hold := op :: top :: hold }
7684 | .gt, _ | .eq, true =>
7785 match σ.output with
78- | arg₂ :: arg₁ :: out => { σ with hold := op :: hold, output := .app top arg₁ arg₂ :: out }
79- | _ => σ -- Trash value chosen to easily satisfy `pushOp_ops`.
86+ | arg₂ :: arg₁ :: out => some { σ with hold := op :: hold, output := .app top arg₁ arg₂ :: out }
87+ | _ => none
8088
8189@[simp]
82- theorem pushOp_ops (σ : ParseState) : (σ.pushOp op).ops = σ.ops := by
83- rw [pushOp]
84- repeat (split <;> try rfl)
90+ theorem pushOp?_ops {σ : ParseState} (h : σ.pushOp? op = some σ') : σ'.ops = σ.ops := by
91+ rw [pushOp?] at h
92+ repeat ' split at h
93+ all_goals
94+ first
95+ | injection h with h; rw [←h]
96+ | contradiction
8597
8698def finalize (σ : ParseState) : ParseState :=
8799 match _ : σ.hold, σ.output with
@@ -93,26 +105,38 @@ def finalize (σ : ParseState) : ParseState :=
93105end ParseState
94106
95107-- Parses an expression based on the "shunting yard algorithm".
96- def parse! (ops : List Op) (args : List Nat) : Expr :=
97- go { ops, args } |> .output[0 ]!
108+ def parse? (ops : List Op) (args : List Nat) : Option Expr :=
109+ go { ops, args } >>= (· .output[0 ]?)
98110where
99- go (σ : ParseState) : ParseState :=
111+ go (σ : ParseState) : Option ParseState :=
100112 match _ : σ.ops, σ.args with
101- | op :: ops, arg :: args => { σ with ops, args } |>.pushArg arg |>.pushOp op |> go
102- | [], [arg] => { σ with args := [] } |>.pushArg arg |>.finalize
103- | _, _ => panic! "Invalid parse state"
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
104119 termination_by σ.ops
105- decreasing_by simp_all +arith
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
124+
125+ theorem parse?.lits_eq_args (h : parse? ops args = some e) : e.lits = args := by
126+ sorry
127+
128+ theorem parse?.apps_eq_ops (h : parse? ops args = some e) : e.apps = ops := by
129+ sorry
106130
107131end Expr
108132
109- def doAlgebra (ops : List Op) (args : List Nat) : Nat :=
110- Expr.parse! ops args |>.eval
133+ def doAlgebra (ops : List Op) (args : List Nat) : Option Nat :=
134+ Expr.eval <$> Expr. parse? ops args
111135
112- example : doAlgebra [.add, .mul, .sub] [2 , 3 , 4 , 5 ] = 9 := by native_decide
113- example : doAlgebra [.pow, .mul, .add] [2 , 3 , 4 , 5 ] = 37 := by native_decide
114- example : doAlgebra [.add, .mul, .sub] [2 , 3 , 4 , 5 ] = 9 := by native_decide
115- example : doAlgebra [.div, .mul] [7 , 3 , 4 ] = 8 := by native_decide
136+ example : doAlgebra [.add, .mul, .sub] [2 , 3 , 4 , 5 ] = some 9 := by native_decide
137+ example : doAlgebra [.pow, .mul, .add] [2 , 3 , 4 , 5 ] = some 37 := by native_decide
138+ example : doAlgebra [.add, .mul, .sub] [2 , 3 , 4 , 5 ] = some 9 := by native_decide
139+ example : doAlgebra [.div, .mul] [7 , 3 , 4 ] = some 8 := by native_decide
116140
117141/-!
118142## Prompt
0 commit comments