aboutsummaryrefslogtreecommitdiff
path: root/testlabel.lua
diff options
context:
space:
mode:
authorSergio Queiroz <sqmedeiros@gmail.com>2016-11-10 16:26:11 -0300
committerSergio Queiroz <sqmedeiros@gmail.com>2016-11-10 16:26:11 -0300
commitfd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea (patch)
tree875ab38000e52376583bc13741b18701c6294f80 /testlabel.lua
parentd84dd6b3659f94b09e67eb90a10e71eb05c5630e (diff)
downloadlpeglabel-fd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea.tar.gz
lpeglabel-fd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea.tar.bz2
lpeglabel-fd28f9d9e54f33bf7ae3a5e12dc71478f9c91aea.zip
Removing labeled choice, updating testlabel, and disabling an optmization related to Throw
Diffstat (limited to 'testlabel.lua')
-rw-r--r--testlabel.lua453
1 files changed, 309 insertions, 144 deletions
diff --git a/testlabel.lua b/testlabel.lua
index 25036b2..cb92657 100644
--- a/testlabel.lua
+++ b/testlabel.lua
@@ -11,6 +11,15 @@ local function checkeqlab (x, ...)
11 end 11 end
12end 12end
13 13
14local function checkeq (x, y, p)
15if p then print(x,y) end
16 if type(x) ~= "table" then assert(x == y)
17 else
18 for k,v in pairs(x) do checkeq(v, y[k], p) end
19 for k,v in pairs(y) do checkeq(v, x[k], p) end
20 end
21end
22
14-- throws a label 23-- throws a label
15p = m.T(1) 24p = m.T(1)
16s = "abc" 25s = "abc"
@@ -32,48 +41,97 @@ local g = m.P{
32r, l, serror = g:match(s) 41r, l, serror = g:match(s)
33assert(r == nil and l == 1 and serror == "abc") 42assert(r == nil and l == 1 and serror == "abc")
34 43
35--[==[ TODO: labeled choice does not work anymore 44
36-- throws a label that is not caught by labeled choice 45-- throws a label that is not caught by the recovery operator
37p = m.Lc(m.T(2), m.P"a", 1, 3) 46p = m.Rec(m.T(2), m.P"a", 1, 3)
38r, l, serror = p:match(s) 47r, l, serror = p:match(s)
39assert(r == nil and l == 2 and serror == "abc") 48assert(r == nil and l == 2 and serror == "abc")
40 49
41-- modifies previous pattern 50-- wraps the previous pattern with a recovery that catches label "2"
42-- adds another labeled choice to catch label "2" 51p = m.Rec(p, m.P"a", 2)
43p = m.Lc(p, m.P"a", 2)
44assert(p:match(s) == 2) 52assert(p:match(s) == 2)
45 53
46-- throws a label that is caught by labeled choice 54-- throws a label that is caught by recovery
47p = m.Lc(m.T(25), m.P"a", 25) 55p = m.Rec(m.T(25), m.P"a", 25)
48assert(p:match(s) == 2) 56assert(p:match(s) == 2)
49 57
50-- "fail" is label "0" 58-- "fail" is label "0"
51-- throws the "fail" label that is not caught by the labeled choice 59-- throws the "fail" label after the recovery
52s = "bola" 60s = "bola"
53r, l, serror = p:match("bola") 61r, l, serror = p:match("bola")
54assert(r == nil and l == 0 and serror == "bola") 62assert(r == nil and l == 0 and serror == "bola")
55 63
56-- labeled choice does not catch "fail" by default 64-- Recovery does not catch "fail" by default
57p = m.Lc(m.P"b", m.P"a", 1) 65p = m.Rec(m.P"b", m.P"a", 1)
58 66
59r, l, serror = p:match("abc") 67r, l, serror = p:match("abc")
60assert(r == nil and l == 0 and serror == "abc") 68assert(r == nil and l == 0 and serror == "abc")
61 69
62assert(p:match("bola") == 2) 70assert(p:match("bola") == 2)
63 71
64-- labeled choice can catch "fail" 72
65p = m.Lc(m.P"b", m.P"a", 0) 73-- recovery operator catches "1" or "3"
74p = m.Rec((m.P"a" + m.T(1)) * m.T(3), (m.P"a" + m.P"b"), 1, 3)
75assert(p:match("aac") == 3)
76assert(p:match("abc") == 3)
77r, l, serror = p:match("acc")
78assert(r == nil and l == 0 and serror == "cc")
79
80--throws 1, recovery pattern matches 'b', throw 3, and rec pat mathces 'a'
81assert(p:match("bac") == 3)
82
83r, l, serror = p:match("cab")
84assert(r == nil and l == 0 and serror == "cab")
85
86
87-- associativity
88-- (p1 / %1) //{1} (p2 / %2) //{2} p3
89-- left-associativity
90-- ("a" //{1} "b") //{2} "c"
91p = m.Rec(m.Rec(m.P"a" + m.T(1), m.P"b" + m.T(2), 1), m.P"c", 2)
66assert(p:match("abc") == 2) 92assert(p:match("abc") == 2)
67assert(p:match("bola") == 2) 93assert(p:match("bac") == 2)
94assert(p:match("cab") == 2)
95r, l, serror = p:match("dab")
96assert(r == nil and l == 0 and serror == "dab")
68 97
69-- "fail" is label "0" 98
70-- labeled choice catches "fail" or "3" 99-- righ-associativity
71p = m.Lc(m.P"a" * m.T(3), (m.P"a" + m.P"b"), 0, 3) 100-- "a" //{1} ("b" //{2} "c")
101p = m.Rec(m.P"a" + m.T(1), m.Rec(m.P"b" + m.T(2), m.P"c", 2), 1)
72assert(p:match("abc") == 2) 102assert(p:match("abc") == 2)
73assert(p:match("bac") == 2) 103assert(p:match("bac") == 2)
104assert(p:match("cab") == 2)
105r, l, serror = p:match("dab")
106assert(r == nil and l == 0 and serror == "dab")
107
108
109-- associativity -> in this case the error thrown by p1 is only
110-- recovered when we have a left-associative operator
111-- (p1 / %2) //{1} (p2 / %2) //{2} p3
112-- left-associativity
113-- ("a" //{1} "b") //{2} "c"
114p = m.Rec(m.Rec(m.P"a" + m.T(2), m.P"b" + m.T(2), 1), m.P"c", 2)
115assert(p:match("abc") == 2)
116r, l, serror = p:match("bac")
117assert(r == nil and l == 0 and serror == "bac")
118assert(p:match("cab") == 2)
119r, l, serror = p:match("dab")
120assert(r == nil and l == 0 and serror == "dab")
121
74 122
123-- righ-associativity
124-- "a" //{1} ("b" //{2} "c")
125p = m.Rec(m.P"a" + m.T(2), m.Rec(m.P"b" + m.T(2), m.P"c", 2), 1)
126assert(p:match("abc") == 2)
127r, l, serror = p:match("bac")
128assert(r == nil and l == 2 and serror == "bac")
75r, l, serror = p:match("cab") 129r, l, serror = p:match("cab")
76assert(r == nil and l == 0 and serror == "cab") 130assert(r == nil and l == 2 and serror == "cab")
131r, l, serror = p:match("dab")
132assert(r == nil and l == 2 and serror == "dab")
133
134
77 135
78-- tests related to predicates 136-- tests related to predicates
79p = #m.T(1) + m.P"a" 137p = #m.T(1) + m.P"a"
@@ -84,74 +142,66 @@ p = ##m.T(1) + m.P"a"
84r, l, serror = p:match("abc") 142r, l, serror = p:match("abc")
85assert(r == nil and l == 1 and serror == "abc") 143assert(r == nil and l == 1 and serror == "abc")
86 144
87p = #m.T(0) * m.P"a"
88assert(p:match("abc") == fail)
89
90p = #m.T(0) + m.P"a"
91assert(p:match("abc") == 2)
92
93p = -m.T(1) * m.P"a" 145p = -m.T(1) * m.P"a"
94r, l, serror = p:match("abc") 146r, l, serror = p:match("abc")
95assert(r == nil and l == 1 and serror == "abc") 147assert(r == nil and l == 1 and serror == "abc")
96 148
149p = -m.T(1) * m.P"a"
150r, l, serror = p:match("bbc")
151assert(r == nil and l == 1 and serror == "bbc")
152
97p = -(-m.T(1)) * m.P"a" 153p = -(-m.T(1)) * m.P"a"
98r, l, serror = p:match("abc") 154r, l, serror = p:match("abc")
99assert(r == nil and l == 1 and serror == "abc") 155assert(r == nil and l == 1 and serror == "abc")
100 156
101p = -m.T(0) * m.P"a" 157p = m.Rec(-m.T(22), m.P"a", 22)
102assert(p:match("abc") == 2) 158r, l, serror = p:match("abc")
159assert(r == nil and l == 0 and serror == "bc")
103 160
104p = -m.T(0) + m.P"a" 161assert(p:match("bbc") == 1)
105assert(p:match("abc") == 1)
106 162
107p = -(-m.T(0)) + m.P"a" 163p = m.Rec(#m.T(22), m.P"a", 22)
108assert(p:match("abc") == 2) 164assert(p:match("abc") == 1)
109 165
110p = m.Lc(-m.T(22), m.P"a", 22) 166p = #m.Rec(m.T(22), m.P"a", 22)
111assert(p:match("abc") == 2) 167assert(p:match("abc") == 1)
112 168
113p = m.Lc(-m.T(0), m.P"a", 0) 169p = m.Rec(m.T(22), #m.P"a", 22)
114assert(p:match("abc") == 1) 170assert(p:match("abc") == 1)
115 171
116p = m.Lc(#m.T(22), m.P"a", 22) 172p = m.Rec(#m.T(22), m.P"a", 22)
117assert(p:match("abc") == 2) 173r, l, serror = p:match("bbc")
174assert(r == nil and l == 0 and serror == "bbc")
118 175
119p = m.Lc(#m.T(0), m.P"a", 0)
120assert(p:match("abc") == 2)
121 176
122-- tests related to repetition 177-- tests related to repetition
123p = m.T(1)^0 178p = m.T(1)^0
124r, l, serror = p:match("ab") 179r, l, serror = p:match("ab")
125assert(r == nil and l == 1 and serror == "ab") 180assert(r == nil and l == 1 and serror == "ab")
126 181
127p = m.T(0)^0
128assert(p:match("ab") == 1)
129
130p = (m.P"a" + m.T(1))^0 182p = (m.P"a" + m.T(1))^0
131r, l, serror = p:match("aa") 183r, l, serror = p:match("aa")
132assert(r == nil and l == 1 and serror == "") 184assert(r == nil and l == 1 and serror == "")
133 185
134p = (m.P"a" + m.T(0))^0
135assert(p:match("aa") == 3)
136 186
137-- Bug reported by Matthew Allen 187-- Bug reported by Matthew Allen
138-- some optmizations performed by LPeg should not be 188-- some optmizations performed by LPeg should not be
139-- applied in case of labeled choices 189-- applied in case of labeled choices
140p = m.Lc(m.P"A", m.P(true), 1) + m.P("B") 190p = m.Rec(m.P"A", m.P(true), 1) + m.P("B")
141assert(p:match("B") == 2) 191assert(p:match("B") == 2)
142 192
143p = m.Lc(m.P"A", m.P(false), 1) + m.P("B") 193p = m.Rec(m.P"A", m.P(false), 1) + m.P("B")
144assert(p:match("B") == 2) 194assert(p:match("B") == 2)
145 195
146 196
147--[[ 197--[[
148S -> A /{1} 'a' 198S -> A //{1} 'a'
149A -> B 199A -> B
150B -> %1 200B -> %1
151]] 201]]
152g = m.P{ 202g = m.P{
153 "S", 203 "S",
154 S = m.Lc(m.V"A", m.P"a", 1), 204 S = m.Rec(m.V"A", m.P"a", 1),
155 A = m.V"B", 205 A = m.V"B",
156 B = m.T(1), 206 B = m.T(1),
157} 207}
@@ -177,66 +227,96 @@ r, l, serror = g:match("a;a")
177assert(r == nil and l == 1 and serror == "") 227assert(r == nil and l == 1 and serror == "")
178 228
179 229
180-- %1 /{1,3} %2 /{2} 'a' 230-- %1 //{1,3} %2 //{2} 'a'
181p = m.Lc(m.Lc(m.T(1), m.T(2), 1, 3), m.P"a", 2) 231p = m.Rec(m.Rec(m.T(1), m.T(2), 1, 3), m.P"a", 2)
182assert(p:match("abc") == 2) 232assert(p:match("abc") == 2)
183 233
184r, l, serror = p:match("") 234r, l, serror = p:match("")
185assert(r == nil and l == 0 and serror == "") 235assert(r == nil and l == 0 and serror == "")
186 236
187p = m.Lc(m.T(1), m.Lc(m.T(2), m.P"a", 2), 1, 3) 237p = m.Rec(m.T(1), m.Rec(m.T(2), m.P"a", 2), 1, 3)
188assert(p:match("abc") == 2) 238assert(p:match("abc") == 2)
189 239
190r, l, serror = p:match("") 240r, l, serror = p:match("")
191assert(r == nil and l == 0 and serror == "") 241assert(r == nil and l == 0 and serror == "")
192]==] 242
243
244-- Infinte Loop TODO: check the semantics
245-- %1 //{1} %1
246p = m.Rec(m.T(1), m.T(1), 1)
247--r, l, serror = p:match("ab")
248--assert(r == nil and l == 1 and serror == "ab")
249
250-- %1 //{1} 'a' (!. / %1)
251p = m.Rec(m.T(1), m.P"a" * (-m.P(1) + m.T(1)), 1)
252r, l, serror = p:match("ab")
253assert(r == nil and l == 0 and serror == "b")
254
255r, l, serror = p:match("cd")
256assert(r == nil and l == 0 and serror == "cd")
257
258-- %1 //{1} . (!. / %1)
259p = m.Rec(m.T(1), m.P(1) * (-m.P(1) + m.T(1)), 1)
260assert(p:match("abc") == 4)
261
193 262
194-- testing the limit of labels 263-- testing the limit of labels
195p = m.T(0) 264-- can only throw labels between 1 and 255
196s = "abc" 265local r = pcall(m.Rec, m.P"b", m.P"a", 0)
197r, l, serror = p:match(s) 266assert(r == false)
198assert(r == nil and l == 0 and serror == "abc")
199 267
200p = m.T(255) 268local r = pcall(m.Rec, m.P"b", m.P"a", 256)
201s = "abc" 269assert(r == false)
202r, l, serror = p:match(s)
203assert(r == nil and l == 255 and serror == "abc")
204 270
205local r = pcall(m.T, -1) 271local r = pcall(m.Rec, m.P"b", m.P"a", -1)
272assert(r == false)
273
274local r = pcall(m.T, 0)
206assert(r == false) 275assert(r == false)
207 276
208local r = pcall(m.T, 256) 277local r = pcall(m.T, 256)
209assert(r == false) 278assert(r == false)
210 279
280local r = pcall(m.T, -1)
281assert(r == false)
282
283
284local r = m.Rec(m.P"b", m.P"a", 255)
285assert(p:match("a") == 2)
286
287p = m.T(255)
288s = "abc"
289r, l, serror = p:match(s)
290assert(r == nil and l == 255 and serror == "abc")
291
292
211 293
212print("+") 294print("+")
213 295
214--[==[ TODO: labeled choice does not work anymore
215--[[ grammar based on Figure 8 of paper submitted to SCP 296--[[ grammar based on Figure 8 of paper submitted to SCP
216S -> S0 /{1} ID /{2} ID '=' Exp /{3} 'unsigned'* 'int' ID /{4} 'unsigned'* ID ID / %error 297S -> S0 //{1} ID //{2} ID '=' Exp //{3} 'unsigned'* 'int' ID //{4} 'unsigned'* ID ID / %error
217S0 -> ID S1 / 'unsigned' S2 / 'int' %3 298S0 -> S1 / S2 / &'int' %3
218S1 -> '=' %2 / !. %1 / ID %4 299S1 -> &(ID '=') %2 / &(ID !.) %1 / &ID %4
219S2 -> 'unsigned' S2 / ID %4 / 'int' %3 300S2 -> &('unsigned'+ ID) %4 / & ('unsigned'+ 'int') %3
220]] 301]]
221
222local sp = m.S" \t\n"^0 302local sp = m.S" \t\n"^0
223local eq = sp * m.P"=" 303local eq = sp * m.P"="
224 304
225g = m.P{ 305g = m.P{
226 "S", 306 "S",
227 S = m.Lc( 307 S = m.Rec(
228 m.Lc( 308 m.Rec(
229 m.Lc( 309 m.Rec(
230 m.Lc(m.V"S0", m.V"ID" * (m.P(1) + ""), 1), 310 m.Rec(m.V"S0", m.V"ID", 1),
231 m.V"ID" * eq * m.V"Exp", 2 311 m.V"ID" * eq * m.V"Exp", 2
232 ), 312 ),
233 m.V"U"^0 * m.V"I" * m.V"ID", 3 313 m.V"U"^0 * m.V"I" * m.V"ID", 3
234 ), 314 ),
235 m.V"U"^0 * m.V"ID" * m.V"ID", 4) 315 m.V"U"^0 * m.V"ID" * m.V"ID", 4)
236 + m.T(5), -- error 316 + m.T(5), -- error
237 S0 = m.V"ID" * m.V"S1" + m.V"U" * m.V"S2" + m.V"I" * m.T(3), 317 S0 = m.V"S1" + m.V"S2" + #m.V"I" * m.T(3),
238 S1 = eq * m.T(2) + sp * -m.P(1) * m.T(1) + m.V"ID" * m.T(4), 318 S1 = #(m.V"ID" * eq) * m.T(2) + sp * #(m.V"ID" * -m.P(1)) * m.T(1) + #m.V"ID" * m.T(4),
239 S2 = m.V"U" * m.V"S2" + m.V"ID" * m.T(4) + m.V"I" * m.T(3), 319 S2 = #(m.V"U"^1 * m.V"ID") * m.T(4) + #(m.V"U"^1 * m.V"I") * m.T(3),
240 ID = sp * m.P"a", 320 ID = sp * m.P"a",
241 U = sp * m.P"unsigned", 321 U = sp * m.P"unsigned",
242 I = sp * m.P"int", 322 I = sp * m.P"int",
@@ -273,53 +353,59 @@ assert(r == nil and l == 5 and serror == s)
273 353
274print("+") 354print("+")
275 355
276local re = require 'relabel'
277 356
278g = re.compile[['a' /{4,9} [a-z] 357local re = require 'relabelrec'
358
359g = re.compile[['a' //{4,9} [a-z]
279]] 360]]
280assert(g:match("a") == 2) 361assert(g:match("a") == 2)
281r, l, serror = g:match("b") 362r, l, serror = g:match("b")
282assert(r == nil and l == 0 and serror == "b") 363assert(r == nil and l == 0 and serror == "b")
283 364
284g = re.compile[['a' /{4,9} [a-f] /{5, 7} [a-z] 365g = re.compile[['a' //{4,9} [a-f] //{5, 7} [a-z]
285]] 366]]
286assert(g:match("a") == 2) 367assert(g:match("a") == 2)
287r, l, serror = g:match("b") 368r, l, serror = g:match("b")
288assert(r == nil and l == 0 and serror == "b") 369assert(r == nil and l == 0 and serror == "b")
289 370
290g = re.compile[[%{1} /{4,9} [a-z] 371g = re.compile[[%{1} //{4,9} [a-z]
291]] 372]]
292r, l, serror = g:match("a") 373r, l, serror = g:match("a")
293assert(r == nil and l == 1 and serror == "a") 374assert(r == nil and l == 1 and serror == "a")
294 375
295 376
296g = re.compile[[%{1} /{4,1} [a-f] 377g = re.compile[[%{1} //{4,1} [a-f]
297]] 378]]
298assert(g:match("a") == 2) 379assert(g:match("a") == 2)
299r, l, serror = g:match("h") 380r, l, serror = g:match("h")
300assert(r == nil and l == 0 and serror == "h") 381assert(r == nil and l == 0 and serror == "h")
301 382
302g = re.compile[[[a-f]%{9} /{4,9} [a-c]%{7} /{5, 7} [a-z] ]] 383g = re.compile[[[a-f]%{9} //{4,9} [a-c]%{7} //{5, 7} [a-z] ]]
303assert(g:match("a") == 2) 384r, l, serror = g:match("a")
304assert(g:match("c") == 2) 385assert(r == nil and l == 0 and serror == "")
305r, l, serror = g:match("d") 386r, l, serror = g:match("aa")
387assert(r == nil and l == 0 and serror == "")
388assert(g:match("aaa") == 4)
389
390r, l, serror = g:match("ad")
306assert(r == nil and l == 0 and serror == "d") 391assert(r == nil and l == 0 and serror == "d")
392
307r, l, serror = g:match("g") 393r, l, serror = g:match("g")
308assert(r == nil and l == 0 and serror == "g") 394assert(r == nil and l == 0 and serror == "g")
309 395
396
310--[[ grammar based on Figure 8 of paper submitted to SCP 397--[[ grammar based on Figure 8 of paper submitted to SCP
311S -> S0 /{1} ID /{2} ID '=' Exp /{3} 'unsigned'* 'int' ID /{4} 'unsigned'* ID ID / %error 398S -> S0 //{1} ID //{2} ID '=' Exp //{3} 'unsigned'* 'int' ID //{4} 'unsigned'* ID ID / %error
312S0 -> ID S1 / 'unsigned' S2 / 'int' %3 399S0 -> S1 / S2 / &'int' %3
313S1 -> '=' %2 / !. %1 / ID %4 400S1 -> &(ID '=') %2 / &(ID !.) %1 / &ID %4
314S2 -> 'unsigned' S2 / ID %4 / 'int' %3 401S2 -> &('unsigned'+ ID) %4 / & ('unsigned'+ 'int') %3
315]] 402]]
316 403
317
318g = re.compile([[ 404g = re.compile([[
319 S <- S0 /{1} ID /{2} ID %s* '=' Exp /{3} U* Int ID /{4} U ID ID /{0} %{5} 405 S <- S0 //{1} ID //{2} ID %s* '=' Exp //{3} U* Int ID //{4} U ID ID / %{5}
320 S0 <- ID S1 / U S2 / Int %{3} 406 S0 <- S1 / S2 / &Int %{3}
321 S1 <- %s* '=' %{2} / !. %{1} / ID %{4} 407 S1 <- &(ID %s* '=') %{2} / &(ID !.) %{1} / &ID %{4}
322 S2 <- U S2 / ID %{4} / Int %{3} 408 S2 <- &(U+ ID) %{4} / &(U+ Int) %{3}
323 ID <- %s* 'a' 409 ID <- %s* 'a'
324 U <- %s* 'unsigned' 410 U <- %s* 'unsigned'
325 Int <- %s* 'int' 411 Int <- %s* 'int'
@@ -349,6 +435,8 @@ s = "unsigned int"
349r, l, serror = g:match(s) 435r, l, serror = g:match(s)
350assert(r == nil and l == 5 and serror == s) 436assert(r == nil and l == 5 and serror == s)
351 437
438
439
352local terror = { ['cmdSeq'] = "Missing ';' in CmdSeq", 440local terror = { ['cmdSeq'] = "Missing ';' in CmdSeq",
353 ['ifExp'] = "Error in expresion of 'if'", 441 ['ifExp'] = "Error in expresion of 'if'",
354 ['ifThen'] = "Error matching 'then' keyword", 442 ['ifThen'] = "Error matching 'then' keyword",
@@ -370,12 +458,12 @@ local terror = { ['cmdSeq'] = "Missing ';' in CmdSeq",
370 ['undefined'] = "Undefined Error"} 458 ['undefined'] = "Undefined Error"}
371 459
372g = re.compile([[ 460g = re.compile([[
373 Tiny <- CmdSeq /{1} '' -> cmdSeq /{2} '' -> ifExp /{3} '' -> ifThen /{4} '' -> ifThenCmdSeq 461 Tiny <- CmdSeq //{1} '' -> cmdSeq //{2} '' -> ifExp //{3} '' -> ifThen //{4} '' -> ifThenCmdSeq
374 /{5} '' -> ifElseCmdSeq /{6} '' -> ifEnd /{7} '' -> repeatCmdSeq 462 //{5} '' -> ifElseCmdSeq //{6} '' -> ifEnd //{7} '' -> repeatCmdSeq
375 /{8} '' -> repeatUntil /{9} '' -> repeatExp /{10} '' -> assignOp 463 //{8} '' -> repeatUntil //{9} '' -> repeatExp //{10} '' -> assignOp
376 /{11} '' -> assignExp /{12} '' -> readName /{13} '' -> writeExp 464 //{11} '' -> assignExp //{12} '' -> readName //{13} '' -> writeExp
377 /{14} '' -> simpleExp /{15} '' -> term /{16} '' -> factor 465 //{14} '' -> simpleExp //{15} '' -> term //{16} '' -> factor
378 /{17} '' -> openParExp /{18} '' -> closePar /{0} '' -> undefined 466 //{17} '' -> openParExp //{18} '' -> closePar / '' -> undefined
379 CmdSeq <- (Cmd (SEMICOLON / %{1})) (Cmd (SEMICOLON / %{1}))* 467 CmdSeq <- (Cmd (SEMICOLON / %{1})) (Cmd (SEMICOLON / %{1}))*
380 Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd 468 Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd
381 IfCmd <- IF (Exp / %{2}) (THEN / %{3}) (CmdSeq / %{4}) (ELSE (CmdSeq / %{5}) / '') (END / %{6}) 469 IfCmd <- IF (Exp / %{2}) (THEN / %{3}) (CmdSeq / %{4}) (ELSE (CmdSeq / %{5}) / '') (END / %{6})
@@ -551,21 +639,14 @@ assert(g:match(s) == terror['undefined'])
551 639
552 640
553print("+") 641print("+")
554]==]
555 642
556-- test recovery operator
557p = m.Rec("a", "b")
558assert(p:match("a") == 2)
559--assert(p:match("b") == 2)
560checkeqlab({nil, 0, "b"}, p:match("b"))
561checkeqlab({nil, 0, "c"}, p:match("c"))
562 643
563p = m.Rec("a", "b", 3) 644p = m.Rec("a", "b", 3)
564assert(p:match("a") == 2) 645assert(p:match("a") == 2)
565checkeqlab({nil, 0, "b"}, p:match("b")) 646checkeqlab({nil, 0, "b"}, p:match("b"))
566checkeqlab({nil, 0, "c"}, p:match("c")) 647checkeqlab({nil, 0, "c"}, p:match("c"))
567 648
568p = m.Rec(m.T(3), "b") 649p = m.Rec(m.T(3), "b", 1)
569checkeqlab({nil, 3, "a"}, p:match("a")) 650checkeqlab({nil, 3, "a"}, p:match("a"))
570checkeqlab({nil, 3, "b"}, p:match("b")) 651checkeqlab({nil, 3, "b"}, p:match("b"))
571 652
@@ -574,56 +655,26 @@ checkeqlab({nil, 0, "a"}, p:match("a"))
574assert(p:match("b") == 2) 655assert(p:match("b") == 2)
575 656
576--[[ 657--[[
577S -> (A //{fail} (!c .)*) C 658S -> (A //{128} (!c .)*) C
578A -> a*b 659A -> a*b / %128
579C -> c+
580]]
581g = m.P{
582 "S",
583 S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0) * m.V"C",
584 A = m.P"a"^0 * "b",
585 C = m.P"c"^1,
586}
587
588assert(g:match("abc") == 4)
589assert(g:match("aabc") == 5)
590--assert(g:match("aadc") == 5) --old semantics
591checkeqlab({nil, 0, "dc"}, g:match("aadc")) --new semantics
592assert(g:match("bc") == 3) -- new semantics
593checkeqlab({nil, 0, "bc"}, g:match("bbc"))
594--assert(g:match("xxc") == 4) old semantics
595checkeqlab({nil, 0, "xxc"}, g:match("xxc")) --new semantics
596--assert(g:match("c") == 2) --old semantics
597checkeqlab({nil, 0, "c"}, g:match("c")) --new semantics
598--checkeqlab({nil, 0, ""}, g:match("fail")) --old semantics
599checkeqlab({nil, 0, "fail"}, g:match("fail")) --new semantics
600--checkeqlab({nil, 0, ""}, g:match("aaxx")) --old semantics
601checkeqlab({nil, 0, "xx"}, g:match("aaxx")) --new semantics
602
603
604--[[
605S -> (A //{0} (!c .)*) C
606A -> a*b / ^{0}
607C -> c+ 660C -> c+
608]] 661]]
609g = m.P{ 662g = m.P{
610 "S", 663 "S",
611 S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0, 0) * m.V"C", --explicitly put 0 in Rec 664 S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0, 128) * m.V"C",
612 A = m.P"a"^0 * m.P"b" + m.T(0), 665 A = m.P"a"^0 * "b" + m.T(128),
613 C = m.P"c"^1, 666 C = m.P"c"^1,
614} 667}
615 668
616assert(g:match("abc") == 4) 669assert(g:match("abc") == 4)
617assert(g:match("aabc") == 5) 670assert(g:match("aabc") == 5)
618assert(g:match("aadc") == 5) --updated 671assert(g:match("aadc") == 5)
619assert(g:match("bc") == 3) -- new semantics 672assert(g:match("dc") == 3)
620checkeqlab({nil, 0, "bc"}, g:match("bbc")) 673checkeqlab({nil, 0, "bc"}, g:match("bbc"))
621assert(g:match("xxc") == 4) 674assert(g:match("xxc") == 4)
622assert(g:match("c") == 2) --old semantics updated 675assert(g:match("c") == 2)
623checkeqlab({nil, 0, ""}, g:match("fail")) --old semantics updated 676checkeqlab({nil, 0, ""}, g:match("fail"))
624checkeqlab({nil, 0, ""}, g:match("aaxx")) --old semantics updated 677checkeqlab({nil, 0, ""}, g:match("aaxx"))
625
626
627 678
628 679
629--[[ 680--[[
@@ -810,6 +861,120 @@ checkeqlab({nil, 4, "dc"}, g3:match("dc"))
810checkeqlab({nil, 4, "d"}, g3:match(".d")) 861checkeqlab({nil, 4, "d"}, g3:match(".d"))
811 862
812 863
864-- testing more captures
865local g = re.compile[[
866 S <- ( %s* &. {A} )*
867 A <- [0-9]+ / %{5}
868]]
813 869
814print("OK") 870checkeq({"523", "624", "346", "888"} , {g:match("523 624 346\n888")})
871checkeq({nil, 5, "a 123"}, {g:match("44 a 123")})
872
873local g2 = m.Rec(g, ((-m.R("09") * m.P(1))^0) / "58", 5)
874
875checkeq({"523", "624", "346", "888"} , {g2:match("523 624 346\n888")})
876checkeq({"44", "a ", "58", "123"}, {g2:match("44 a 123")})
877
878
879local g = re.compile[[
880 S <- ( %s* &. A )*
881 A <- {[0-9]+} / %{5}
882]]
883
884checkeq({"523", "624", "346", "888"} , {g:match("523 624 346\n888")})
885checkeq({nil, 5, "a 123"}, {g:match("44 a 123")})
886
887local g2 = m.Rec(g, ((-m.R("09") * m.P(1))^0) / "58", 5)
888
889checkeq({"523", "624", "346", "888"} , {g2:match("523 624 346\n888")})
890checkeq({"44", "58", "123"}, {g2:match("44 a 123")})
891
892
893local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V
894local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt
895local T, Lc, Rec = lpeg.T, lpeg.Lc, lpeg.Rec
896
897local labels = {
898 {"NoExp", "no expression found"},
899 {"Extra", "extra characters found after the expression"},
900 {"ExpTerm", "expected a term after the operator"},
901 {"ExpExp", "expected an expression after the parenthesis"},
902 {"MisClose", "missing a closing ')' after the expression"},
903}
904
905local function labelindex(labname)
906 for i, elem in ipairs(labels) do
907 if elem[1] == labname then
908 return i
909 end
910 end
911 error("could not find label: " .. labname)
912end
913
914local errors = {}
915
916local function expect(patt, labname, recpatt)
917 local i = labelindex(labname)
918 function recorderror(input, pos)
919 table.insert(errors, {i, pos})
920 return true
921 end
922 if not recpatt then recpatt = P"" end
923 --return Rec(patt, Cmt("", recorderror) * recpatt)
924 return patt + T(i)
925end
926
927local num = R("09")^1 / tonumber
928local op = S("+-*/")
929
930local function compute(tokens)
931 local result = tokens[1]
932 for i = 2, #tokens, 2 do
933 if tokens[i] == '+' then
934 result = result + tokens[i+1]
935 elseif tokens[i] == '-' then
936 result = result - tokens[i+1]
937 elseif tokens[i] == '*' then
938 result = result * tokens[i+1]
939 elseif tokens[i] == '/' then
940 result = result / tokens[i+1]
941 else
942 error('unknown operation: ' .. tokens[i])
943 end
944 end
945 return result
946end
815 947
948
949local g = P {
950"Exp",
951Exp = Ct(V"Term" * (C(op) * V"Operand")^0) / compute,
952Operand = expect(V"Term", "ExpTerm"),
953Term = num,
954}
955local rg = Rec(g, Cc(3), labelindex("ExpTerm"))
956
957local function eval(input)
958 local result, label, suffix = rg:match(input)
959 if #errors == 0 then
960 return result
961 else
962 local out = {}
963 for i, err in ipairs(errors) do
964 local pos = err[2]
965 local msg = labels[err[1]][2]
966 table.insert(out, "syntax error: " .. msg .. " (at index " .. pos .. ")")
967 end
968 errors = {}
969 return nil, table.concat(out, "\n")
970 end
971end
972
973assert(eval("98-76*54/32") == 37.125)
974--> 37.125
975
976assert(eval("1+") == 4)
977--> syntax error: expected a term after the operator (at index 3)
978
979
980print("OK")