@@ -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
6161namespace 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+
83176end Examples
84177
85178end Parser
0 commit comments