diff options
-rw-r--r-- | lptypes.h | 4 | ||||
-rw-r--r-- | lpvm.c | 13 | ||||
-rw-r--r-- | testfarthest.lua | 16 | ||||
-rw-r--r-- | testlabel.lua | 209 |
4 files changed, 150 insertions, 92 deletions
@@ -161,6 +161,10 @@ typedef Charset Labelset; | |||
161 | #define IDXLFAIL 0 | 161 | #define IDXLFAIL 0 |
162 | 162 | ||
163 | #define LFAIL 0 | 163 | #define LFAIL 0 |
164 | |||
165 | /* update the farthest failure */ | ||
166 | #define updatefarthest(s1,s2) { if ((s2) > (s1)) s1 = s2; } | ||
167 | |||
164 | /* labeled failure end */ | 168 | /* labeled failure end */ |
165 | 169 | ||
166 | #endif | 170 | #endif |
@@ -166,6 +166,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
166 | Labelset lsfail; | 166 | Labelset lsfail; |
167 | setlabelfail(&lsfail); | 167 | setlabelfail(&lsfail); |
168 | stack->p = &giveup; stack->s = s; stack->ls = &lsfail; stack->caplevel = 0; stack++; /* labeled failure */ | 168 | stack->p = &giveup; stack->s = s; stack->ls = &lsfail; stack->caplevel = 0; stack++; /* labeled failure */ |
169 | *sfail = s; /* labeled failure */ | ||
169 | lua_pushlightuserdata(L, stackbase); | 170 | lua_pushlightuserdata(L, stackbase); |
170 | for (;;) { | 171 | for (;;) { |
171 | #if defined(DEBUG) | 172 | #if defined(DEBUG) |
@@ -196,7 +197,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
196 | else { | 197 | else { |
197 | *labelf = LFAIL; /* labeled failure */ | 198 | *labelf = LFAIL; /* labeled failure */ |
198 | pk = p + 1; | 199 | pk = p + 1; |
199 | *sfail = s; | 200 | updatefarthest(*sfail, s); /*labeled failure */ |
200 | goto fail; | 201 | goto fail; |
201 | } | 202 | } |
202 | continue; | 203 | continue; |
@@ -211,7 +212,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
211 | else { | 212 | else { |
212 | *labelf = LFAIL; /* labeled failure */ | 213 | *labelf = LFAIL; /* labeled failure */ |
213 | pk = p + 1; | 214 | pk = p + 1; |
214 | *sfail = s; | 215 | updatefarthest(*sfail, s); /*labeled failure */ |
215 | goto fail; | 216 | goto fail; |
216 | } | 217 | } |
217 | continue; | 218 | continue; |
@@ -228,7 +229,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
228 | else { | 229 | else { |
229 | *labelf = LFAIL; /* labeled failure */ | 230 | *labelf = LFAIL; /* labeled failure */ |
230 | pk = p + CHARSETINSTSIZE; | 231 | pk = p + CHARSETINSTSIZE; |
231 | *sfail = s; | 232 | updatefarthest(*sfail, s); /*labeled failure */ |
232 | goto fail; | 233 | goto fail; |
233 | } | 234 | } |
234 | continue; | 235 | continue; |
@@ -245,7 +246,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
245 | if (n > s - o) { | 246 | if (n > s - o) { |
246 | *labelf = LFAIL; /* labeled failure */ | 247 | *labelf = LFAIL; /* labeled failure */ |
247 | pk = p + 1; | 248 | pk = p + 1; |
248 | *sfail = s; | 249 | updatefarthest(*sfail, s); /*labeled failure */ |
249 | goto fail; | 250 | goto fail; |
250 | } | 251 | } |
251 | s -= n; p++; | 252 | s -= n; p++; |
@@ -329,7 +330,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
329 | case IFail: | 330 | case IFail: |
330 | *labelf = LFAIL; /* labeled failure */ | 331 | *labelf = LFAIL; /* labeled failure */ |
331 | pk = NULL; | 332 | pk = NULL; |
332 | *sfail = s; | 333 | updatefarthest(*sfail, s); /*labeled failure */ |
333 | fail: { /* pattern failed: try to backtrack */ | 334 | fail: { /* pattern failed: try to backtrack */ |
334 | const Labelset *auxlab = NULL; | 335 | const Labelset *auxlab = NULL; |
335 | Stack *pstack = stack; | 336 | Stack *pstack = stack; |
@@ -366,8 +367,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
366 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ | 367 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ |
367 | if (res == -1) { /* fail? */ | 368 | if (res == -1) { /* fail? */ |
368 | *labelf = LFAIL; /* labeled failure */ | 369 | *labelf = LFAIL; /* labeled failure */ |
369 | *sfail = (const char *) s; | ||
370 | pk = NULL; | 370 | pk = NULL; |
371 | updatefarthest(*sfail, s); /*labeled failure */ | ||
371 | goto fail; | 372 | goto fail; |
372 | } | 373 | } |
373 | s = o + res; /* else update current position */ | 374 | s = o + res; /* else update current position */ |
diff --git a/testfarthest.lua b/testfarthest.lua index 386cbbd..e862d87 100644 --- a/testfarthest.lua +++ b/testfarthest.lua | |||
@@ -6,20 +6,8 @@ function matchPrint(p, s) | |||
6 | print("Result:", r, l, sfail) | 6 | print("Result:", r, l, sfail) |
7 | end | 7 | end |
8 | 8 | ||
9 | local p = m.P"a"^0 * m.P"b" + m.P"c" | ||
10 | 9 | ||
10 | local p = (m.P"c" + m.P"a") * m.P("b" + m.P"d") + m.P"xxx" | ||
11 | p:pcode() | 11 | p:pcode() |
12 | matchPrint(p, "ba") | ||
12 | 13 | ||
13 | matchPrint(p, "aab") | ||
14 | matchPrint(p, "ck") | ||
15 | matchPrint(p, "dk") | ||
16 | matchPrint(p, "aak") | ||
17 | |||
18 | local p = m.P"a"^0 * m.P(1) * m.P(1) + m.P"a"^0 * m.P"c" | ||
19 | |||
20 | p:pcode() | ||
21 | |||
22 | matchPrint(p, "aabc") | ||
23 | matchPrint(p, "aac") | ||
24 | matchPrint(p, "aak") | ||
25 | matchPrint(p, "x") | ||
diff --git a/testlabel.lua b/testlabel.lua index 9fcdcfc..e2833ea 100644 --- a/testlabel.lua +++ b/testlabel.lua | |||
@@ -2,7 +2,7 @@ local m = require 'lpeglabel' | |||
2 | 2 | ||
3 | local p, r, l, s, serror | 3 | local p, r, l, s, serror |
4 | 4 | ||
5 | local function checkeqlab (x, ...) | 5 | local function checklabeq (x, ...) |
6 | y = { ... } | 6 | y = { ... } |
7 | assert(type(x) == "table") | 7 | assert(type(x) == "table") |
8 | assert(#x == #y) | 8 | assert(#x == #y) |
@@ -12,7 +12,7 @@ local function checkeqlab (x, ...) | |||
12 | end | 12 | end |
13 | 13 | ||
14 | local function checkeq (x, y, p) | 14 | local function checkeq (x, y, p) |
15 | if p then print(x,y) end | 15 | if p then print(x,y) end |
16 | if type(x) ~= "table" then assert(x == y) | 16 | if type(x) ~= "table" then assert(x == y) |
17 | else | 17 | else |
18 | for k,v in pairs(x) do checkeq(v, y[k], p) end | 18 | for k,v in pairs(x) do checkeq(v, y[k], p) end |
@@ -20,27 +20,92 @@ if p then print(x,y) end | |||
20 | end | 20 | end |
21 | end | 21 | end |
22 | 22 | ||
23 | |||
24 | -- tests related to reporting the farthest failure position | ||
25 | -- when a label is not thrown | ||
26 | |||
27 | p = m.P"a"^0 * m.P"b" + m.P"c" | ||
28 | checklabeq({4, nil, nil}, p:match("aabk")) | ||
29 | checklabeq({2, nil, nil}, p:match("ck")) | ||
30 | checklabeq({nil, 0, "dk"}, p:match("dk")) | ||
31 | checklabeq({nil, 0, "k"}, p:match("aak")) | ||
32 | |||
33 | p = (m.P"a" + m.P"c")^0 * m.P"b" + m.P"c" | ||
34 | checklabeq({4, nil, nil}, p:match("aabk")) | ||
35 | checklabeq({2, nil, nil}, p:match("ck")) | ||
36 | checklabeq({nil, 0, "dk"}, p:match("dk")) | ||
37 | checklabeq({nil, 0, "k"}, p:match("aak")) | ||
38 | |||
39 | p = m.P"a"^0 * m.P"b" + m.P(1)^0 * m.P(1) | ||
40 | checklabeq({4, nil, nil}, p:match("aabk")) | ||
41 | checklabeq({nil, 0, ""}, p:match("ck")) | ||
42 | checklabeq({nil, 0, ""}, p:match("aak")) | ||
43 | |||
44 | p = m.P(1) * m.P"a" + m.P"c" | ||
45 | checklabeq({3, nil, nil}, p:match("bac")) | ||
46 | checklabeq({2, nil, nil}, p:match("c")) | ||
47 | checklabeq({nil, 0, ""}, p:match("x")) | ||
48 | checklabeq({nil, 0, "x"}, p:match("kx")) | ||
49 | |||
50 | p = m.P"a"^0 * m.P(1) * m.P(1) + m.P"a"^0 * m.P"c" | ||
51 | checklabeq({5, nil, nil}, p:match("aabc")) | ||
52 | checklabeq({4, nil, nil}, p:match("aac")) | ||
53 | checklabeq({nil, 0, ""}, p:match("aak")) | ||
54 | checklabeq({nil, 0, ""}, p:match("x")) | ||
55 | |||
56 | p = m.P"a"^0 * m.P(1) * m.P(1) + m.P"a"^0 * m.P"c" | ||
57 | checklabeq({5, nil, nil}, p:match("aabc")) | ||
58 | checklabeq({4, nil, nil}, p:match("aac")) | ||
59 | checklabeq({nil, 0, ""}, p:match("aak")) | ||
60 | checklabeq({nil, 0, ""}, p:match("x")) | ||
61 | |||
62 | p = m.Cmt(m.P"a"^0, function() return nil end) + m.P"x" | ||
63 | checklabeq({2, nil, nil}, p:match("xabc")) | ||
64 | checklabeq({nil, 0, "c"}, p:match("aac")) | ||
65 | checklabeq({nil, 0, "kx"}, p:match("kx")) | ||
66 | |||
67 | p = m.P"b" * -m.P"a" + m.P"c" | ||
68 | checklabeq({nil, 0, "a"}, p:match("ba")) | ||
69 | checklabeq({nil, 0, "kx"}, p:match("kx")) | ||
70 | |||
71 | p = (m.P"c" + m.P"a") * m.P("b" + m.P"d") + m.P"xxx" | ||
72 | checklabeq({nil, 0, "kk"}, p:match("kk")) | ||
73 | checklabeq({nil, 0, "k"}, p:match("ak")) | ||
74 | checklabeq({nil, 0, "y"}, p:match("xxy")) | ||
75 | checklabeq({nil, 0, "yz"}, p:match("xyz")) | ||
76 | |||
77 | print"+" | ||
78 | |||
79 | |||
23 | -- throws a label | 80 | -- throws a label |
24 | p = m.T(1) | 81 | p = m.T(1) |
25 | s = "abc" | 82 | s = "abc" |
26 | r, l, serror = p:match(s) | 83 | r, l, serror = p:match(s) |
27 | assert(r == nil and l == 1 and serror == "abc") | 84 | assert(r == nil and l == 1 and serror == "abc") |
28 | 85 | ||
29 | -- throws a label that is not caught by ordinary choice | 86 | -- throws a label, choice does not catch labels |
30 | p = m.T(1) + m.P"a" | 87 | p = m.T(1) + m.P"a" |
31 | r, l, serror = p:match(s) | 88 | r, l, serror = p:match(s) |
32 | assert(r == nil and l == 1 and serror == "abc") | 89 | assert(r == nil and l == 1 and serror == "abc") |
33 | 90 | ||
34 | -- again throws a label that is not caught by ordinary choice | 91 | -- again throws a label that is not caught by choice |
35 | local g = m.P{ | 92 | local g = m.P{ |
36 | "S", | 93 | "S", |
37 | S = m.V"A" + m.V"B", | 94 | S = m.V"A" + m.V"B", |
38 | A = m.T(1), | 95 | A = m.T(1), |
39 | B = m.P"a" | 96 | B = m.P"a" |
40 | } | 97 | } |
41 | r, l, serror = g:match(s) | 98 | r, l, serror = g:match(s) |
42 | assert(r == nil and l == 1 and serror == "abc") | 99 | assert(r == nil and l == 1 and serror == "abc") |
43 | 100 | ||
101 | -- throws a label in a position that is not the farthest one | ||
102 | -- but it is the position that should be reported | ||
103 | p = m.P(1) * m.P"a" + m.T(11) | ||
104 | checklabeq({3, nil, nil}, p:match("bac")) | ||
105 | checklabeq({nil, 11, "c"}, p:match("c")) | ||
106 | checklabeq({nil, 11, "x"}, p:match("x")) | ||
107 | checklabeq({nil, 11, "kx"}, p:match("kx")) | ||
108 | |||
44 | 109 | ||
45 | -- throws a label that is not caught by the recovery operator | 110 | -- throws a label that is not caught by the recovery operator |
46 | p = m.Rec(m.T(2), m.P"a", 1, 3) | 111 | p = m.Rec(m.T(2), m.P"a", 1, 3) |
@@ -209,10 +274,10 @@ A -> B | |||
209 | B -> %1 | 274 | B -> %1 |
210 | ]] | 275 | ]] |
211 | g = m.P{ | 276 | g = m.P{ |
212 | "S", | 277 | "S", |
213 | S = m.Rec(m.V"A", m.P"a", 1), | 278 | S = m.Rec(m.V"A", m.P"a", 1), |
214 | A = m.V"B", | 279 | A = m.V"B", |
215 | B = m.T(1), | 280 | B = m.T(1), |
216 | } | 281 | } |
217 | assert(g:match("ab") == 2) | 282 | assert(g:match("ab") == 2) |
218 | r, l, serror = g:match("bc") | 283 | r, l, serror = g:match("bc") |
@@ -225,10 +290,10 @@ A -> (B (';' / %{1}))* | |||
225 | B -> 'a' | 290 | B -> 'a' |
226 | ]] | 291 | ]] |
227 | g = m.P{ | 292 | g = m.P{ |
228 | "S", | 293 | "S", |
229 | S = m.V"A", | 294 | S = m.V"A", |
230 | A = m.P(m.V"B" * (";" + m.T(1)))^0, | 295 | A = m.P(m.V"B" * (";" + m.T(1)))^0, |
231 | B = m.P'a', | 296 | B = m.P'a', |
232 | } | 297 | } |
233 | assert(g:match("a;a;") == 5) | 298 | assert(g:match("a;a;") == 5) |
234 | 299 | ||
@@ -312,8 +377,8 @@ local sp = m.S" \t\n"^0 | |||
312 | local eq = sp * m.P"=" | 377 | local eq = sp * m.P"=" |
313 | 378 | ||
314 | g = m.P{ | 379 | g = m.P{ |
315 | "S", | 380 | "S", |
316 | S = m.Rec( | 381 | S = m.Rec( |
317 | m.Rec( | 382 | m.Rec( |
318 | m.Rec( | 383 | m.Rec( |
319 | m.Rec(m.V"S0", m.V"ID", 1), | 384 | m.Rec(m.V"S0", m.V"ID", 1), |
@@ -323,13 +388,13 @@ g = m.P{ | |||
323 | ), | 388 | ), |
324 | m.V"U"^0 * m.V"ID" * m.V"ID", 4) | 389 | m.V"U"^0 * m.V"ID" * m.V"ID", 4) |
325 | + m.T(5), -- error | 390 | + m.T(5), -- error |
326 | S0 = m.V"S1" + m.V"S2" + #m.V"I" * m.T(3), | 391 | S0 = m.V"S1" + m.V"S2" + #m.V"I" * m.T(3), |
327 | S1 = #(m.V"ID" * eq) * m.T(2) + sp * #(m.V"ID" * -m.P(1)) * m.T(1) + #m.V"ID" * m.T(4), | 392 | S1 = #(m.V"ID" * eq) * m.T(2) + sp * #(m.V"ID" * -m.P(1)) * m.T(1) + #m.V"ID" * m.T(4), |
328 | S2 = #(m.V"U"^1 * m.V"ID") * m.T(4) + #(m.V"U"^1 * m.V"I") * m.T(3), | 393 | S2 = #(m.V"U"^1 * m.V"ID") * m.T(4) + #(m.V"U"^1 * m.V"I") * m.T(3), |
329 | ID = sp * m.P"a", | 394 | ID = sp * m.P"a", |
330 | U = sp * m.P"unsigned", | 395 | U = sp * m.P"unsigned", |
331 | I = sp * m.P"int", | 396 | I = sp * m.P"int", |
332 | Exp = sp * m.P"E", | 397 | Exp = sp * m.P"E", |
333 | } | 398 | } |
334 | 399 | ||
335 | local s = "a" | 400 | local s = "a" |
@@ -411,7 +476,7 @@ S2 -> &('unsigned'+ ID) %4 / & ('unsigned'+ 'int') %3 | |||
411 | ]] | 476 | ]] |
412 | 477 | ||
413 | g = re.compile([[ | 478 | g = re.compile([[ |
414 | S <- S0 //{1} ID //{2} ID %s* '=' Exp //{3} U* Int ID //{4} U ID ID / %{5} | 479 | S <- S0 //{1} ID //{2} ID %s* '=' Exp //{3} U* Int ID //{4} U ID ID / %{5} |
415 | S0 <- S1 / S2 / &Int %{3} | 480 | S0 <- S1 / S2 / &Int %{3} |
416 | S1 <- &(ID %s* '=') %{2} / &(ID !.) %{1} / &ID %{4} | 481 | S1 <- &(ID %s* '=') %{2} / &(ID !.) %{1} / &ID %{4} |
417 | S2 <- &(U+ ID) %{4} / &(U+ Int) %{3} | 482 | S2 <- &(U+ ID) %{4} / &(U+ Int) %{3} |
@@ -504,8 +569,8 @@ g = re.compile([[ | |||
504 | THEN <- Sp 'then' | 569 | THEN <- Sp 'then' |
505 | UNTIL <- Sp 'until' | 570 | UNTIL <- Sp 'until' |
506 | WRITE <- Sp 'write' | 571 | WRITE <- Sp 'write' |
507 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ | 572 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ |
508 | Sp <- (%s / %nl)* | 573 | Sp <- (%s / %nl)* |
509 | ]], terror) | 574 | ]], terror) |
510 | 575 | ||
511 | s = [[ | 576 | s = [[ |
@@ -652,15 +717,15 @@ print("+") | |||
652 | 717 | ||
653 | p = m.Rec("a", "b", 3) | 718 | p = m.Rec("a", "b", 3) |
654 | assert(p:match("a") == 2) | 719 | assert(p:match("a") == 2) |
655 | checkeqlab({nil, 0, "b"}, p:match("b")) | 720 | checklabeq({nil, 0, "b"}, p:match("b")) |
656 | checkeqlab({nil, 0, "c"}, p:match("c")) | 721 | checklabeq({nil, 0, "c"}, p:match("c")) |
657 | 722 | ||
658 | p = m.Rec(m.T(3), "b", 1) | 723 | p = m.Rec(m.T(3), "b", 1) |
659 | checkeqlab({nil, 3, "a"}, p:match("a")) | 724 | checklabeq({nil, 3, "a"}, p:match("a")) |
660 | checkeqlab({nil, 3, "b"}, p:match("b")) | 725 | checklabeq({nil, 3, "b"}, p:match("b")) |
661 | 726 | ||
662 | p = m.Rec(m.T(3), "b", 3) | 727 | p = m.Rec(m.T(3), "b", 3) |
663 | checkeqlab({nil, 0, "a"}, p:match("a")) | 728 | checklabeq({nil, 0, "a"}, p:match("a")) |
664 | assert(p:match("b") == 2) | 729 | assert(p:match("b") == 2) |
665 | 730 | ||
666 | --[[ | 731 | --[[ |
@@ -669,21 +734,21 @@ A -> a*b / %128 | |||
669 | C -> c+ | 734 | C -> c+ |
670 | ]] | 735 | ]] |
671 | g = m.P{ | 736 | g = m.P{ |
672 | "S", | 737 | "S", |
673 | S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0, 128) * m.V"C", | 738 | S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0, 128) * m.V"C", |
674 | A = m.P"a"^0 * "b" + m.T(128), | 739 | A = m.P"a"^0 * "b" + m.T(128), |
675 | C = m.P"c"^1, | 740 | C = m.P"c"^1, |
676 | } | 741 | } |
677 | 742 | ||
678 | assert(g:match("abc") == 4) | 743 | assert(g:match("abc") == 4) |
679 | assert(g:match("aabc") == 5) | 744 | assert(g:match("aabc") == 5) |
680 | assert(g:match("aadc") == 5) | 745 | assert(g:match("aadc") == 5) |
681 | assert(g:match("dc") == 3) | 746 | assert(g:match("dc") == 3) |
682 | checkeqlab({nil, 0, "bc"}, g:match("bbc")) | 747 | checklabeq({nil, 0, "bc"}, g:match("bbc")) |
683 | assert(g:match("xxc") == 4) | 748 | assert(g:match("xxc") == 4) |
684 | assert(g:match("c") == 2) | 749 | assert(g:match("c") == 2) |
685 | checkeqlab({nil, 0, ""}, g:match("fail")) | 750 | checklabeq({nil, 0, ""}, g:match("fail")) |
686 | checkeqlab({nil, 0, ""}, g:match("aaxx")) | 751 | checklabeq({nil, 0, ""}, g:match("aaxx")) |
687 | 752 | ||
688 | 753 | ||
689 | --[[ | 754 | --[[ |
@@ -692,23 +757,23 @@ A -> a+ (b / ^99) | |||
692 | C -> c+ | 757 | C -> c+ |
693 | ]] | 758 | ]] |
694 | g = m.P{ | 759 | g = m.P{ |
695 | "S", | 760 | "S", |
696 | S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0, 99) * m.V"C", | 761 | S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0, 99) * m.V"C", |
697 | A = m.P"a"^1 * ("b" + m.T(99)), | 762 | A = m.P"a"^1 * ("b" + m.T(99)), |
698 | C = m.P"c"^1, | 763 | C = m.P"c"^1, |
699 | } | 764 | } |
700 | 765 | ||
701 | assert(g:match("abc") == 4) | 766 | assert(g:match("abc") == 4) |
702 | assert(g:match("aabc") == 5) | 767 | assert(g:match("aabc") == 5) |
703 | assert(g:match("aadc") == 5) | 768 | assert(g:match("aadc") == 5) |
704 | checkeqlab({nil, 0, "bc"}, g:match("bc")) | 769 | checklabeq({nil, 0, "bc"}, g:match("bc")) |
705 | checkeqlab({nil, 0, "bbc"}, g:match("bbc")) | 770 | checklabeq({nil, 0, "bbc"}, g:match("bbc")) |
706 | checkeqlab({nil, 0, "b"}, g:match("abb")) | 771 | checklabeq({nil, 0, "b"}, g:match("abb")) |
707 | checkeqlab({nil, 0, ""}, g:match("axx")) | 772 | checklabeq({nil, 0, ""}, g:match("axx")) |
708 | assert(g:match("accc") == 5) | 773 | assert(g:match("accc") == 5) |
709 | assert(g:match("axxc") == 5) | 774 | assert(g:match("axxc") == 5) |
710 | checkeqlab({nil, 0, "c"}, g:match("c")) | 775 | checklabeq({nil, 0, "c"}, g:match("c")) |
711 | checkeqlab({nil, 0, "fail"}, g:match("fail")) | 776 | checklabeq({nil, 0, "fail"}, g:match("fail")) |
712 | 777 | ||
713 | 778 | ||
714 | 779 | ||
@@ -824,25 +889,25 @@ print(eval "(1+1-1*(2/2+)-():") | |||
824 | print("+") | 889 | print("+") |
825 | 890 | ||
826 | local g = m.P{ | 891 | local g = m.P{ |
827 | "S", | 892 | "S", |
828 | S = V"End" + V'A' * V'S', | 893 | S = V"End" + V'A' * V'S', |
829 | A = P'a' + T(1), | 894 | A = P'a' + T(1), |
830 | End = P"." * (-P(1) + T(2)), | 895 | End = P"." * (-P(1) + T(2)), |
831 | } | 896 | } |
832 | 897 | ||
833 | assert(g:match("a.") == 3) | 898 | assert(g:match("a.") == 3) |
834 | assert(g:match("aa.") == 4) | 899 | assert(g:match("aa.") == 4) |
835 | assert(g:match(".") == 2) | 900 | assert(g:match(".") == 2) |
836 | checkeqlab({nil, 1, "ba."}, g:match("ba.")) | 901 | checklabeq({nil, 1, "ba."}, g:match("ba.")) |
837 | checkeqlab({nil, 1, "ba."}, g:match("aba.")) | 902 | checklabeq({nil, 1, "ba."}, g:match("aba.")) |
838 | checkeqlab({nil, 1, "cba."}, g:match("cba.")) | 903 | checklabeq({nil, 1, "cba."}, g:match("cba.")) |
839 | checkeqlab({nil, 2, "a"}, g:match("a.a")) | 904 | checklabeq({nil, 2, "a"}, g:match("a.a")) |
840 | 905 | ||
841 | 906 | ||
842 | local g2 = m.P{ | 907 | local g2 = m.P{ |
843 | "S", | 908 | "S", |
844 | S = m.Rec(g, V"B", 1), | 909 | S = m.Rec(g, V"B", 1), |
845 | B = P'b'^1 + T(3) | 910 | B = P'b'^1 + T(3) |
846 | } | 911 | } |
847 | 912 | ||
848 | assert(g2:match("a.") == 3) | 913 | assert(g2:match("a.") == 3) |
@@ -850,13 +915,13 @@ assert(g2:match("aa.") == 4) | |||
850 | assert(g2:match(".") == 2) | 915 | assert(g2:match(".") == 2) |
851 | assert(g2:match("ba.") == 4) | 916 | assert(g2:match("ba.") == 4) |
852 | assert(g2:match("aba.") == 5) | 917 | assert(g2:match("aba.") == 5) |
853 | checkeqlab({nil, 3, "cba."}, g2:match("cba.")) | 918 | checklabeq({nil, 3, "cba."}, g2:match("cba.")) |
854 | checkeqlab({nil, 2, "a"}, g2:match("a.a")) | 919 | checklabeq({nil, 2, "a"}, g2:match("a.a")) |
855 | 920 | ||
856 | local g3 = m.P{ | 921 | local g3 = m.P{ |
857 | "S", | 922 | "S", |
858 | S = m.Rec(g2, V"C", 2, 3), | 923 | S = m.Rec(g2, V"C", 2, 3), |
859 | C = P'c'^1 + T(4) | 924 | C = P'c'^1 + T(4) |
860 | } | 925 | } |
861 | 926 | ||
862 | assert(g3:match("a.") == 3) | 927 | assert(g3:match("a.") == 3) |
@@ -865,14 +930,14 @@ assert(g3:match(".") == 2) | |||
865 | assert(g3:match("ba.") == 4) | 930 | assert(g3:match("ba.") == 4) |
866 | assert(g3:match("aba.") == 5) | 931 | assert(g3:match("aba.") == 5) |
867 | assert(g3:match("cba.") == 5) | 932 | assert(g3:match("cba.") == 5) |
868 | checkeqlab({nil, 4, "a"}, g3:match("a.a")) | 933 | checklabeq({nil, 4, "a"}, g3:match("a.a")) |
869 | checkeqlab({nil, 4, "dc"}, g3:match("dc")) | 934 | checklabeq({nil, 4, "dc"}, g3:match("dc")) |
870 | checkeqlab({nil, 4, "d"}, g3:match(".d")) | 935 | checklabeq({nil, 4, "d"}, g3:match(".d")) |
871 | 936 | ||
872 | 937 | ||
873 | -- testing more captures | 938 | -- testing more captures |
874 | local g = re.compile[[ | 939 | local g = re.compile[[ |
875 | S <- ( %s* &. {A} )* | 940 | S <- ( %s* &. {A} )* |
876 | A <- [0-9]+ / %{5} | 941 | A <- [0-9]+ / %{5} |
877 | ]] | 942 | ]] |
878 | 943 | ||
@@ -886,7 +951,7 @@ checkeq({"44", "a ", "58", "123"}, {g2:match("44 a 123")}) | |||
886 | 951 | ||
887 | 952 | ||
888 | local g = re.compile[[ | 953 | local g = re.compile[[ |
889 | S <- ( %s* &. A )* | 954 | S <- ( %s* &. A )* |
890 | A <- {[0-9]+} / %{5} | 955 | A <- {[0-9]+} / %{5} |
891 | ]] | 956 | ]] |
892 | 957 | ||
@@ -928,7 +993,7 @@ local function expect(patt, labname, recpatt) | |||
928 | table.insert(errors, {i, pos}) | 993 | table.insert(errors, {i, pos}) |
929 | return true | 994 | return true |
930 | end | 995 | end |
931 | if not recpatt then recpatt = P"" end | 996 | if not recpatt then recpatt = P"" end |
932 | --return Rec(patt, Cmt("", recorderror) * recpatt) | 997 | --return Rec(patt, Cmt("", recorderror) * recpatt) |
933 | return patt + T(i) | 998 | return patt + T(i) |
934 | end | 999 | end |