Skip to content

Commit fba32ac

Browse files
committed
Port Parser arithmetic parser
1 parent ff81008 commit fba32ac

File tree

1 file changed

+99
-6
lines changed

1 file changed

+99
-6
lines changed

LeanEffectsContainer/Parser.lean

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def run
3939
(p : Prog (Parser :: effs) α) : List Char → Prog effs (List Char × α) :=
4040
Prog.foldP
4141
(P := fun _ => List Char → Prog effs (List Char × α))
42-
(var0 := fun x => fun rest => pure (rest, x))
42+
(var0 := fun x => fun rest => if rest.isEmpty then pure (rest, x) else NonDet.fail)
4343
(varS := id)
4444
(op := fun ⟨c, k⟩ =>
4545
match c with
@@ -54,9 +54,9 @@ def run
5454
| .inr s => fun st => Prog.scp ⟨s, fun p => ProgN.varS (k p st)⟩)
5555
p
5656

57-
def parse (s : String) (p : Prog (Parser :: effs) α) : Prog effs (String × α) := do
58-
let (rest, res) ← run p (s.toList)
59-
pure (String.ofList rest, res)
57+
def parse (s : String) (p : Prog (Parser :: effs) α) : Prog effs α := do
58+
let (_, res) ← run p (s.toList)
59+
pure res
6060

6161
namespace Examples
6262

@@ -68,18 +68,111 @@ def digit
6868
let natToChar n := Char.ofNat (n + '0'.toNat)
6969
List.range 10 |>.foldl (fun r d => r ?? char (natToChar d)) NonDet.fail
7070

71+
mutual
72+
73+
partial def many
74+
{α : Type}
75+
[NonDet ∈ effs]
76+
(p : Prog effs α) : Prog effs (List α) :=
77+
pure [] ?? many1 p
78+
79+
partial def many1
80+
{α : Type}
81+
[NonDet ∈ effs]
82+
(p : Prog effs α) : Prog effs (List α) := do
83+
let a ← p
84+
let as ← many p
85+
pure (a :: as)
86+
end
87+
7188
#guard
72-
(digit
89+
(many digit
7390
|> parse "123"
7491
|> NonDet.runFirst
75-
|> Prog.run) = some ("23", '1')
92+
|> Prog.run) = some ['1', '2', '3']
93+
94+
#guard
95+
(many digit
96+
|> parse ""
97+
|> NonDet.runFirst
98+
|> Prog.run) = some []
99+
100+
#guard
101+
(many1 digit
102+
|> parse "123"
103+
|> NonDet.runFirst
104+
|> Prog.run) = some ['1', '2', '3']
105+
106+
#guard
107+
(many1 digit
108+
|> parse ""
109+
|> NonDet.runFirst
110+
|> Prog.run) = none
76111

77112
#guard
78113
(digit
79114
|> parse "a123"
80115
|> NonDet.runFirst
81116
|> Prog.run) = none
82117

118+
section Arithmetic
119+
120+
mutual
121+
122+
partial def expr
123+
[NonDet ∈ effs]
124+
[Parser ∈ effs]
125+
: Prog effs Nat := do
126+
let i ← term
127+
let plus := do
128+
let _ ← NonDet.once <| char '+'
129+
let j ← expr
130+
pure (i + j)
131+
plus ?? pure i
132+
133+
partial def term
134+
[NonDet ∈ effs]
135+
[Parser ∈ effs]
136+
: Prog effs Nat :=
137+
let times := do
138+
let i ← factor
139+
let _ ← char '*'
140+
let j ← term
141+
pure (i * j)
142+
times ?? factor
143+
144+
partial def factor
145+
[NonDet ∈ effs]
146+
[Parser ∈ effs]
147+
: Prog effs Nat :=
148+
let num := do
149+
let ds ← many1 digit
150+
pure (String.ofList ds |> String.toNat!)
151+
let bracketed := do
152+
let _ ← char '('
153+
let i ← expr
154+
let _ ← char ')'
155+
pure i
156+
num ?? bracketed
157+
158+
end
159+
160+
def exScoped :=
161+
parse "1" expr
162+
|> NonDet.runFirst
163+
|> Prog.run
164+
165+
#guard exScoped = some 1
166+
167+
def exFactor :=
168+
parse "(2+8)*5" expr
169+
|> NonDet.runFirst
170+
|> Prog.run
171+
172+
#guard exFactor = some 50
173+
174+
end Arithmetic
175+
83176
end Examples
84177

85178
end Parser

0 commit comments

Comments
 (0)