diff options
author | Sérgio Queiroz <sqmedeiros@gmail.com> | 2017-12-15 16:31:41 -0300 |
---|---|---|
committer | Sérgio Queiroz <sqmedeiros@gmail.com> | 2017-12-15 16:31:41 -0300 |
commit | 4bdf8d40a9ca5f00e454a38d301a3ab35c9b50d5 (patch) | |
tree | e59c5041761c237f27fe51589901da5a963ee103 | |
parent | 0f53a65f4a32c8be2d84c4a8172b885065f7c1e5 (diff) | |
download | lpeglabel-4bdf8d40a9ca5f00e454a38d301a3ab35c9b50d5.tar.gz lpeglabel-4bdf8d40a9ca5f00e454a38d301a3ab35c9b50d5.tar.bz2 lpeglabel-4bdf8d40a9ca5f00e454a38d301a3ab35c9b50d5.zip |
Removing code related to labeled choice and recovery operators and updating tests
-rw-r--r-- | lpcode.c | 39 | ||||
-rw-r--r-- | lptree.c | 36 | ||||
-rw-r--r-- | lptree.h | 4 | ||||
-rw-r--r-- | lptypes.h | 15 | ||||
-rw-r--r-- | lpvm.c | 69 | ||||
-rw-r--r-- | lpvm.h | 1 | ||||
-rw-r--r-- | testlabel.lua | 239 |
7 files changed, 102 insertions, 301 deletions
@@ -220,9 +220,6 @@ int checkaux (TTree *tree, int pred) { | |||
220 | if (checkaux(sib2(tree), pred)) return 1; | 220 | if (checkaux(sib2(tree), pred)) return 1; |
221 | /* else return checkaux(sib1(tree), pred); */ | 221 | /* else return checkaux(sib1(tree), pred); */ |
222 | tree = sib1(tree); goto tailcall; | 222 | tree = sib1(tree); goto tailcall; |
223 | case TLabChoice: /* labeled failure */ | ||
224 | /* we do not know whether sib2 will be evaluated */ | ||
225 | tree = sib1(tree); goto tailcall; | ||
226 | case TCapture: case TGrammar: case TRule: | 223 | case TCapture: case TGrammar: case TRule: |
227 | /* return checkaux(sib1(tree), pred); */ | 224 | /* return checkaux(sib1(tree), pred); */ |
228 | tree = sib1(tree); goto tailcall; | 225 | tree = sib1(tree); goto tailcall; |
@@ -264,7 +261,7 @@ int fixedlen (TTree *tree) { | |||
264 | /* else return fixedlen(sib2(tree)) + len; */ | 261 | /* else return fixedlen(sib2(tree)) + len; */ |
265 | len += n1; tree = sib2(tree); goto tailcall; | 262 | len += n1; tree = sib2(tree); goto tailcall; |
266 | } | 263 | } |
267 | case TChoice: case TLabChoice: { /* labeled failure */ | 264 | case TChoice: { |
268 | int n1 = fixedlen(sib1(tree)); | 265 | int n1 = fixedlen(sib1(tree)); |
269 | int n2 = fixedlen(sib2(tree)); | 266 | int n2 = fixedlen(sib2(tree)); |
270 | if (n1 != n2 || n1 < 0) | 267 | if (n1 != n2 || n1 < 0) |
@@ -314,7 +311,7 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) { | |||
314 | loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */ | 311 | loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */ |
315 | return 1; | 312 | return 1; |
316 | } | 313 | } |
317 | case TChoice: case TLabChoice: { /*(?) labeled failure */ | 314 | case TChoice: { |
318 | Charset csaux; | 315 | Charset csaux; |
319 | int e1 = getfirst(sib1(tree), follow, firstset); | 316 | int e1 = getfirst(sib1(tree), follow, firstset); |
320 | int e2 = getfirst(sib2(tree), follow, &csaux); | 317 | int e2 = getfirst(sib2(tree), follow, &csaux); |
@@ -399,7 +396,7 @@ static int headfail (TTree *tree) { | |||
399 | if (!nofail(sib2(tree))) return 0; | 396 | if (!nofail(sib2(tree))) return 0; |
400 | /* else return headfail(sib1(tree)); */ | 397 | /* else return headfail(sib1(tree)); */ |
401 | tree = sib1(tree); goto tailcall; | 398 | tree = sib1(tree); goto tailcall; |
402 | case TChoice: case TLabChoice: /* labeled failure */ | 399 | case TChoice: |
403 | if (!headfail(sib1(tree))) return 0; | 400 | if (!headfail(sib1(tree))) return 0; |
404 | /* else return headfail(sib2(tree)); */ | 401 | /* else return headfail(sib2(tree)); */ |
405 | tree = sib2(tree); goto tailcall; | 402 | tree = sib2(tree); goto tailcall; |
@@ -419,7 +416,7 @@ static int needfollow (TTree *tree) { | |||
419 | case TChar: case TSet: case TAny: | 416 | case TChar: case TSet: case TAny: |
420 | case TFalse: case TTrue: case TAnd: case TNot: | 417 | case TFalse: case TTrue: case TAnd: case TNot: |
421 | case TRunTime: case TGrammar: case TCall: case TBehind: | 418 | case TRunTime: case TGrammar: case TCall: case TBehind: |
422 | case TThrow: case TLabChoice: /* (?)labeled failure */ | 419 | case TThrow: /* (?)labeled failure */ |
423 | return 0; | 420 | return 0; |
424 | case TChoice: case TRep: | 421 | case TChoice: case TRep: |
425 | return 1; | 422 | return 1; |
@@ -456,8 +453,6 @@ int sizei (const Instruction *i) { | |||
456 | return 2; | 453 | return 2; |
457 | case IThrowRec: /* labeled failure */ | 454 | case IThrowRec: /* labeled failure */ |
458 | return 3; | 455 | return 3; |
459 | case ILabChoice: | ||
460 | return (CHARSETINSTSIZE - 1) + 2; /* labeled failure */ | ||
461 | 456 | ||
462 | default: return 1; | 457 | default: return 1; |
463 | } | 458 | } |
@@ -522,8 +517,7 @@ static int addinstruction (CompileState *compst, Opcode op, int aux) { | |||
522 | static int addoffsetinst (CompileState *compst, Opcode op) { | 517 | static int addoffsetinst (CompileState *compst, Opcode op) { |
523 | int i = addinstruction(compst, op, 0); /* instruction */ | 518 | int i = addinstruction(compst, op, 0); /* instruction */ |
524 | addinstruction(compst, (Opcode)0, 0); /* open space for offset */ | 519 | addinstruction(compst, (Opcode)0, 0); /* open space for offset */ |
525 | assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2 || | 520 | assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2); |
526 | op == ILabChoice); /* labeled failure */ | ||
527 | return i; | 521 | return i; |
528 | } | 522 | } |
529 | 523 | ||
@@ -746,24 +740,6 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt, | |||
746 | } | 740 | } |
747 | 741 | ||
748 | 742 | ||
749 | /* labeled failure begin */ | ||
750 | static void codelabchoice (CompileState *compst, TTree *p1, TTree *p2, int opt, | ||
751 | const Charset *fl, const byte *cs) { | ||
752 | int emptyp2 = (p2->tag == TTrue); | ||
753 | int pcommit; | ||
754 | int test = NOINST; | ||
755 | int pchoice = addoffsetinst(compst, ILabChoice); | ||
756 | addcharset(compst, cs); | ||
757 | codegen(compst, p1, emptyp2, test, fullset); | ||
758 | pcommit = addoffsetinst(compst, ICommit); | ||
759 | jumptohere(compst, pchoice); | ||
760 | jumptohere(compst, test); | ||
761 | codegen(compst, p2, opt, NOINST, fl); | ||
762 | jumptohere(compst, pcommit); | ||
763 | } | ||
764 | /* labeled failure end */ | ||
765 | |||
766 | |||
767 | /* | 743 | /* |
768 | ** And predicate | 744 | ** And predicate |
769 | ** optimization: fixedlen(p) = n ==> <&p> == <p>; behind n | 745 | ** optimization: fixedlen(p) = n ==> <&p> == <p>; behind n |
@@ -1001,10 +977,6 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt, | |||
1001 | codethrow(compst, tree); | 977 | codethrow(compst, tree); |
1002 | break; | 978 | break; |
1003 | } | 979 | } |
1004 | case TLabChoice: { /* labeled failure */ | ||
1005 | codelabchoice(compst, sib1(tree), sib2(tree), opt, fl, treelabelset(tree)); | ||
1006 | break; | ||
1007 | } | ||
1008 | default: assert(0); | 980 | default: assert(0); |
1009 | } | 981 | } |
1010 | } | 982 | } |
@@ -1027,7 +999,6 @@ static void peephole (CompileState *compst) { | |||
1027 | switch (code[i].i.code) { | 999 | switch (code[i].i.code) { |
1028 | case IChoice: case ICall: case ICommit: case IPartialCommit: | 1000 | case IChoice: case ICall: case ICommit: case IPartialCommit: |
1029 | case IBackCommit: case ITestChar: case ITestSet: | 1001 | case IBackCommit: case ITestChar: case ITestSet: |
1030 | case ILabChoice: /* labeled failure */ | ||
1031 | case ITestAny: { /* instructions with labels */ | 1002 | case ITestAny: { /* instructions with labels */ |
1032 | jumptothere(compst, i, finallabel(code, i)); /* optimize label */ | 1003 | jumptothere(compst, i, finallabel(code, i)); /* optimize label */ |
1033 | break; | 1004 | break; |
@@ -28,7 +28,7 @@ const byte numsiblings[] = { | |||
28 | 0, 0, 2, 1, /* call, opencall, rule, grammar */ | 28 | 0, 0, 2, 1, /* call, opencall, rule, grammar */ |
29 | 1, /* behind */ | 29 | 1, /* behind */ |
30 | 1, 1, /* capture, runtime capture */ | 30 | 1, 1, /* capture, runtime capture */ |
31 | 0, 2, 2 /* labeled failure throw, recovery, labeled choice */ | 31 | 0 /* labeled failure throw */ |
32 | }; | 32 | }; |
33 | 33 | ||
34 | 34 | ||
@@ -533,21 +533,6 @@ static TTree *newthrowleaf (lua_State *L) { | |||
533 | tree->u.s.ps = 0; /* there is no recovery rule associated */ | 533 | tree->u.s.ps = 0; /* there is no recovery rule associated */ |
534 | return tree; | 534 | return tree; |
535 | } | 535 | } |
536 | |||
537 | static TTree *newrootlab2sib (lua_State *L, int tag) { | ||
538 | int s1, s2; | ||
539 | TTree *tree1 = getpatt(L, 1, &s1); | ||
540 | TTree *tree2 = getpatt(L, 2, &s2); | ||
541 | TTree *tree = newtree(L, bytes2slots(LABELSETSIZE) + 1 + s1 + s2); /* create new tree */ | ||
542 | tree->tag = tag; | ||
543 | tree->u.s.ps = 1 + s1; | ||
544 | tree->u.s.plab = 1 + s1 + s2; | ||
545 | memcpy(sib1(tree), tree1, s1 * sizeof(TTree)); | ||
546 | memcpy(sib2(tree), tree2, s2 * sizeof(TTree)); | ||
547 | loopset(i, treelabelset(tree)[i] = 0); | ||
548 | joinktables(L, 1, sib2(tree), 2); | ||
549 | return tree; | ||
550 | } | ||
551 | /* labeled failure end */ | 536 | /* labeled failure end */ |
552 | 537 | ||
553 | 538 | ||
@@ -736,22 +721,6 @@ static int lp_throw (lua_State *L) { | |||
736 | tree->key = addtonewktable(L, 0, 1); | 721 | tree->key = addtonewktable(L, 0, 1); |
737 | return 1; | 722 | return 1; |
738 | } | 723 | } |
739 | |||
740 | |||
741 | /* | ||
742 | ** labeled choice function | ||
743 | */ | ||
744 | static int lp_labchoice (lua_State *L) { | ||
745 | int n = lua_gettop(L); | ||
746 | TTree *tree = newrootlab2sib(L, TLabChoice); | ||
747 | int i; | ||
748 | for (i = 3; i <= n; i++) { | ||
749 | int d = luaL_checkinteger(L, i); | ||
750 | luaL_argcheck(L, d >= 1 && d < MAXLABELS, i, "the number of a label must be between 1 and 255"); | ||
751 | setlabel(treelabelset(tree), (byte)d); | ||
752 | } | ||
753 | return 1; | ||
754 | } | ||
755 | /* labeled failure end */ | 724 | /* labeled failure end */ |
756 | 725 | ||
757 | 726 | ||
@@ -1088,7 +1057,7 @@ static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed, | |||
1088 | return nb; | 1057 | return nb; |
1089 | /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */ | 1058 | /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */ |
1090 | tree = sib2(tree); goto tailcall; | 1059 | tree = sib2(tree); goto tailcall; |
1091 | case TChoice: case TLabChoice: /* must check both children */ /* labeled failure */ | 1060 | case TChoice: /* must check both children */ |
1092 | nb = verifyrule(L, sib1(tree), passed, npassed, nb); | 1061 | nb = verifyrule(L, sib1(tree), passed, npassed, nb); |
1093 | /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ | 1062 | /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ |
1094 | tree = sib2(tree); goto tailcall; | 1063 | tree = sib2(tree); goto tailcall; |
@@ -1344,7 +1313,6 @@ static struct luaL_Reg pattreg[] = { | |||
1344 | {"setmaxstack", lp_setmax}, | 1313 | {"setmaxstack", lp_setmax}, |
1345 | {"type", lp_type}, | 1314 | {"type", lp_type}, |
1346 | {"T", lp_throw}, /* labeled failure throw */ | 1315 | {"T", lp_throw}, /* labeled failure throw */ |
1347 | {"Lc", lp_labchoice}, /* labeled failure choice */ | ||
1348 | {NULL, NULL} | 1316 | {NULL, NULL} |
1349 | }; | 1317 | }; |
1350 | 1318 | ||
@@ -35,9 +35,7 @@ typedef enum TTag { | |||
35 | 'sib1' is capture body */ | 35 | 'sib1' is capture body */ |
36 | TRunTime, /* run-time capture: 'key' is Lua function; | 36 | TRunTime, /* run-time capture: 'key' is Lua function; |
37 | 'sib1' is capture body */ | 37 | 'sib1' is capture body */ |
38 | TThrow, /* labeled failure: ktable[key] is label's */ | 38 | TThrow, /* labeled failure: ktable[key] is label's name */ |
39 | TLabChoice /* labed failure: 'sib1' /{labels} 'sib2' */ | ||
40 | /* the set of labels is stored in next CHARSETSIZE bytes */ | ||
41 | } TTag; | 39 | } TTag; |
42 | 40 | ||
43 | 41 | ||
@@ -145,21 +145,6 @@ typedef struct Charset { | |||
145 | #define testchar(st,c) (((int)(st)[((c) >> 3)] & (1 << ((c) & 7)))) | 145 | #define testchar(st,c) (((int)(st)[((c) >> 3)] & (1 << ((c) & 7)))) |
146 | 146 | ||
147 | /* labeled failure begin */ | 147 | /* labeled failure begin */ |
148 | #define MAXLABELS (UCHAR_MAX + 1) | ||
149 | |||
150 | #define LABELSETSIZE CHARSETSIZE | ||
151 | |||
152 | typedef Charset Labelset; | ||
153 | |||
154 | #define setlabel setchar | ||
155 | |||
156 | #define testlabel testchar | ||
157 | |||
158 | /* access to labelset */ | ||
159 | #define treelabelset(t) ((byte *)((t) + (t)->u.s.plab)) | ||
160 | |||
161 | #define IDXLFAIL 0 | ||
162 | |||
163 | #define LFAIL 0 | 148 | #define LFAIL 0 |
164 | 149 | ||
165 | /* update the farthest failure */ | 150 | /* update the farthest failure */ |
@@ -26,13 +26,6 @@ | |||
26 | 26 | ||
27 | static const Instruction giveup = {{IGiveup, 0, 0}}; | 27 | static const Instruction giveup = {{IGiveup, 0, 0}}; |
28 | 28 | ||
29 | /* labeled failure */ | ||
30 | static void setlabelfail(Labelset *ls) { | ||
31 | loopset(i, ls->cs[i] = 0); | ||
32 | ls->cs[IDXLFAIL] = 1; | ||
33 | } | ||
34 | /* labeled failure end */ | ||
35 | |||
36 | 29 | ||
37 | /* | 30 | /* |
38 | ** {====================================================== | 31 | ** {====================================================== |
@@ -44,7 +37,6 @@ static void setlabelfail(Labelset *ls) { | |||
44 | typedef struct Stack { | 37 | typedef struct Stack { |
45 | const char *s; /* saved position (or NULL for calls) */ | 38 | const char *s; /* saved position (or NULL for calls) */ |
46 | const Instruction *p; /* next instruction */ | 39 | const Instruction *p; /* next instruction */ |
47 | const Labelset *ls; /* labeled failure */ | ||
48 | int caplevel; | 40 | int caplevel; |
49 | } Stack; | 41 | } Stack; |
50 | 42 | ||
@@ -163,10 +155,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
163 | int captop = 0; /* point to first empty slot in captures */ | 155 | int captop = 0; /* point to first empty slot in captures */ |
164 | int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ | 156 | int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ |
165 | const Instruction *p = op; /* current instruction */ | 157 | const Instruction *p = op; /* current instruction */ |
166 | const Instruction *pk = NULL; /* resume instruction */ | 158 | stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++; /* labeled failure */ |
167 | Labelset lsfail; | ||
168 | setlabelfail(&lsfail); | ||
169 | stack->p = &giveup; stack->s = s; stack->ls = &lsfail; stack->caplevel = 0; stack++; /* labeled failure */ | ||
170 | *sfail = s; /* labeled failure */ | 159 | *sfail = s; /* labeled failure */ |
171 | lua_pushlightuserdata(L, stackbase); | 160 | lua_pushlightuserdata(L, stackbase); |
172 | for (;;) { | 161 | for (;;) { |
@@ -198,7 +187,6 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
198 | if (s < e) { p++; s++; } | 187 | if (s < e) { p++; s++; } |
199 | else { | 188 | else { |
200 | *labelf = LFAIL; /* labeled failure */ | 189 | *labelf = LFAIL; /* labeled failure */ |
201 | pk = p + 1; | ||
202 | updatefarthest(*sfail, s); /*labeled failure */ | 190 | updatefarthest(*sfail, s); /*labeled failure */ |
203 | goto fail; | 191 | goto fail; |
204 | } | 192 | } |
@@ -213,7 +201,6 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
213 | if ((byte)*s == p->i.aux && s < e) { p++; s++; } | 201 | if ((byte)*s == p->i.aux && s < e) { p++; s++; } |
214 | else { | 202 | else { |
215 | *labelf = LFAIL; /* labeled failure */ | 203 | *labelf = LFAIL; /* labeled failure */ |
216 | pk = p + 1; | ||
217 | updatefarthest(*sfail, s); /*labeled failure */ | 204 | updatefarthest(*sfail, s); /*labeled failure */ |
218 | goto fail; | 205 | goto fail; |
219 | } | 206 | } |
@@ -230,7 +217,6 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
230 | { p += CHARSETINSTSIZE; s++; } | 217 | { p += CHARSETINSTSIZE; s++; } |
231 | else { | 218 | else { |
232 | *labelf = LFAIL; /* labeled failure */ | 219 | *labelf = LFAIL; /* labeled failure */ |
233 | pk = p + CHARSETINSTSIZE; | ||
234 | updatefarthest(*sfail, s); /*labeled failure */ | 220 | updatefarthest(*sfail, s); /*labeled failure */ |
235 | goto fail; | 221 | goto fail; |
236 | } | 222 | } |
@@ -247,7 +233,6 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
247 | int n = p->i.aux; | 233 | int n = p->i.aux; |
248 | if (n > s - o) { | 234 | if (n > s - o) { |
249 | *labelf = LFAIL; /* labeled failure */ | 235 | *labelf = LFAIL; /* labeled failure */ |
250 | pk = p + 1; | ||
251 | updatefarthest(*sfail, s); /*labeled failure */ | 236 | updatefarthest(*sfail, s); /*labeled failure */ |
252 | goto fail; | 237 | goto fail; |
253 | } | 238 | } |
@@ -271,35 +256,22 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
271 | stack = doublestack(L, &stacklimit, ptop); | 256 | stack = doublestack(L, &stacklimit, ptop); |
272 | stack->p = p + getoffset(p); | 257 | stack->p = p + getoffset(p); |
273 | stack->s = s; | 258 | stack->s = s; |
274 | stack->ls = &lsfail; /* labeled failure */ | ||
275 | stack->caplevel = captop; | 259 | stack->caplevel = captop; |
276 | stack++; | 260 | stack++; |
277 | p += 2; | 261 | p += 2; |
278 | continue; | 262 | continue; |
279 | } | 263 | } |
280 | case ILabChoice: { /* labeled failure */ | ||
281 | if (stack == stacklimit) | ||
282 | stack = doublestack(L, &stacklimit, ptop); | ||
283 | stack->p = p + getoffset(p); | ||
284 | stack->s = s; | ||
285 | stack->ls = (const Labelset *) ((p + 2)->buff); | ||
286 | stack->caplevel = captop; | ||
287 | stack++; | ||
288 | p += (CHARSETINSTSIZE - 1) + 2; | ||
289 | continue; | ||
290 | } | ||
291 | case ICall: { | 264 | case ICall: { |
292 | if (stack == stacklimit) | 265 | if (stack == stacklimit) |
293 | stack = doublestack(L, &stacklimit, ptop); | 266 | stack = doublestack(L, &stacklimit, ptop); |
294 | stack->s = NULL; | 267 | stack->s = NULL; |
295 | stack->p = p + 2; /* save return address */ | 268 | stack->p = p + 2; /* save return address */ |
296 | stack->ls = NULL; | ||
297 | stack++; | 269 | stack++; |
298 | p += getoffset(p); | 270 | p += getoffset(p); |
299 | continue; | 271 | continue; |
300 | } | 272 | } |
301 | case ICommit: { | 273 | case ICommit: { |
302 | assert(stack > getstackbase(L, ptop) && (stack - 1)->ls != NULL); /* labeled failure */ | 274 | assert(stack > getstackbase(L, ptop)); |
303 | assert((stack - 1)->s != NULL); | 275 | assert((stack - 1)->s != NULL); |
304 | stack--; | 276 | stack--; |
305 | p += getoffset(p); | 277 | p += getoffset(p); |
@@ -325,8 +297,10 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
325 | printf("IThrow there %s top = %d\n", lua_tostring(L, -1), lua_gettop(L)); | 297 | printf("IThrow there %s top = %d\n", lua_tostring(L, -1), lua_gettop(L)); |
326 | lua_pop(L, 1);*/ | 298 | lua_pop(L, 1);*/ |
327 | *labelf = (p+1)->i.key; | 299 | *labelf = (p+1)->i.key; |
328 | pk = p + 1; | 300 | if (*labelf == LFAIL) |
301 | luaL_error(L, "labelf is %d", *labelf); | ||
329 | *sfail = s; | 302 | *sfail = s; |
303 | stack = getstackbase(L, ptop); | ||
330 | goto fail; | 304 | goto fail; |
331 | } | 305 | } |
332 | case IThrowRec: { /* labeled failure */ | 306 | case IThrowRec: { /* labeled failure */ |
@@ -335,12 +309,13 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
335 | printf("IThrowRec there %s top = %d\n", lua_tostring(L, -1), lua_gettop(L)); | 309 | printf("IThrowRec there %s top = %d\n", lua_tostring(L, -1), lua_gettop(L)); |
336 | lua_pop(L, 1);*/ | 310 | lua_pop(L, 1);*/ |
337 | *labelf = (p+2)->i.key; | 311 | *labelf = (p+2)->i.key; |
312 | if (*labelf == LFAIL) | ||
313 | luaL_error(L, "labelf is %d", *labelf); | ||
338 | *sfail = s; | 314 | *sfail = s; |
339 | if (stack == stacklimit) | 315 | if (stack == stacklimit) |
340 | stack = doublestack(L, &stacklimit, ptop); | 316 | stack = doublestack(L, &stacklimit, ptop); |
341 | stack->s = NULL; | 317 | stack->s = NULL; |
342 | stack->p = p + 3; | 318 | stack->p = p + 3; |
343 | stack->ls = NULL; | ||
344 | stack->caplevel = captop; | 319 | stack->caplevel = captop; |
345 | stack++; | 320 | stack++; |
346 | p += getoffset(p); | 321 | p += getoffset(p); |
@@ -352,31 +327,16 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
352 | /* go through */ | 327 | /* go through */ |
353 | case IFail: | 328 | case IFail: |
354 | *labelf = LFAIL; /* labeled failure */ | 329 | *labelf = LFAIL; /* labeled failure */ |
355 | pk = NULL; | ||
356 | updatefarthest(*sfail, s); /*labeled failure */ | 330 | updatefarthest(*sfail, s); /*labeled failure */ |
357 | fail: { /* pattern failed: try to backtrack */ | 331 | fail: { /* pattern failed: try to backtrack */ |
358 | const Labelset *auxlab = NULL; | ||
359 | Stack *pstack = stack; | ||
360 | do { /* remove pending calls */ | 332 | do { /* remove pending calls */ |
361 | assert(pstack > getstackbase(L, ptop)); | 333 | assert(stack > getstackbase(L, ptop)); |
362 | auxlab = (--pstack)->ls; | 334 | s = (--stack)->s; |
363 | } while (auxlab == NULL || !(pstack->p == &giveup || testlabel(pstack->ls->cs, *labelf))); | 335 | } while (s == NULL); |
364 | if (pstack->s != NULL) { /* labeled failure: giveup or backtrack frame */ | 336 | if (ndyncap > 0) /* is there matchtime captures? */ |
365 | stack = pstack; | 337 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); |
366 | s = stack->s; | 338 | captop = stack->caplevel; |
367 | if (ndyncap > 0) /* is there matchtime captures? */ | 339 | p = stack->p; |
368 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); | ||
369 | captop = stack->caplevel; | ||
370 | } else { /* labeled failure: recovery frame */ | ||
371 | if (stack == stacklimit) | ||
372 | stack = doublestack(L, &stacklimit, ptop); | ||
373 | stack->s = NULL; | ||
374 | stack->p = pk; /* save return address */ | ||
375 | stack->ls = NULL; | ||
376 | stack->caplevel = captop; /* TODO: really necessary?? */ | ||
377 | stack++; | ||
378 | } | ||
379 | p = pstack->p; | ||
380 | #if defined(DEBUG) | 340 | #if defined(DEBUG) |
381 | printf("**FAIL**\n"); | 341 | printf("**FAIL**\n"); |
382 | #endif | 342 | #endif |
@@ -394,7 +354,6 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
394 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ | 354 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ |
395 | if (res == -1) { /* fail? */ | 355 | if (res == -1) { /* fail? */ |
396 | *labelf = LFAIL; /* labeled failure */ | 356 | *labelf = LFAIL; /* labeled failure */ |
397 | pk = NULL; | ||
398 | updatefarthest(*sfail, s); /*labeled failure */ | 357 | updatefarthest(*sfail, s); /*labeled failure */ |
399 | goto fail; | 358 | goto fail; |
400 | } | 359 | } |
@@ -36,7 +36,6 @@ typedef enum Opcode { | |||
36 | ICloseRunTime, | 36 | ICloseRunTime, |
37 | IThrow, /* fails with a given label */ | 37 | IThrow, /* fails with a given label */ |
38 | IThrowRec, /* fails with a given label and call rule at 'offset' */ | 38 | IThrowRec, /* fails with a given label and call rule at 'offset' */ |
39 | ILabChoice /* stack a choice; next fail with label 'f' will jump to 'offset' */ | ||
40 | } Opcode; | 39 | } Opcode; |
41 | 40 | ||
42 | 41 | ||
diff --git a/testlabel.lua b/testlabel.lua index 90a8f9e..9e2a586 100644 --- a/testlabel.lua +++ b/testlabel.lua | |||
@@ -202,78 +202,77 @@ assert(r == nil and l == '1' and poserr == 1) | |||
202 | 202 | ||
203 | p = ##m.T(1) + m.P"a" | 203 | p = ##m.T(1) + m.P"a" |
204 | r, l, poserr = p:match("abc") | 204 | r, l, poserr = p:match("abc") |
205 | assert(r == nil and l == 1 and poserr == 1) | 205 | assert(r == nil and l == '1' and poserr == 1) |
206 | 206 | ||
207 | p = -m.T(1) * m.P"a" | 207 | p = -m.T(1) * m.P"a" |
208 | r, l, poserr = p:match("abc") | 208 | r, l, poserr = p:match("abc") |
209 | assert(r == nil and l == 1 and poserr == 1) | 209 | assert(r == nil and l == '1' and poserr == 1) |
210 | 210 | ||
211 | p = -m.T(1) * m.P"a" | 211 | p = -m.T(1) * m.P"a" |
212 | r, l, poserr = p:match("bbc") | 212 | r, l, poserr = p:match("bbc") |
213 | assert(r == nil and l == 1 and poserr == 1) | 213 | assert(r == nil and l == '1' and poserr == 1) |
214 | 214 | ||
215 | p = -(-m.T(1)) * m.P"a" | 215 | p = -(-m.T(1)) * m.P"a" |
216 | r, l, poserr = p:match("abc") | 216 | r, l, poserr = p:match("abc") |
217 | assert(r == nil and l == 1 and poserr == 1) | 217 | assert(r == nil and l == '1' and poserr == 1) |
218 | 218 | ||
219 | p = m.Rec(-m.T(22), m.P"a", 22) | 219 | p = m.P{ |
220 | "S", | ||
221 | S = -m.T(22), | ||
222 | ["22"] = m.P"a" | ||
223 | } | ||
220 | r, l, poserr = p:match("abc") | 224 | r, l, poserr = p:match("abc") |
221 | assert(r == nil and l == 0 and poserr == 2) | 225 | assert(r == nil and l == 'fail' and poserr == 2) |
222 | 226 | ||
223 | assert(p:match("bbc") == 1) | 227 | assert(p:match("bbc") == 1) |
224 | 228 | ||
225 | p = m.Rec(#m.T(22), m.P"a", 22) | 229 | p = m.P{ |
226 | assert(p:match("abc") == 1) | 230 | "S", |
227 | 231 | S = #m.T(22), | |
228 | p = #m.Rec(m.T(22), m.P"a", 22) | 232 | ["22"] = m.P"a" |
229 | assert(p:match("abc") == 1) | 233 | } |
230 | |||
231 | p = m.Rec(m.T(22), #m.P"a", 22) | ||
232 | assert(p:match("abc") == 1) | ||
233 | |||
234 | p = m.Rec(#m.T(22), m.P"a", 22) | ||
235 | r, l, poserr = p:match("bbc") | ||
236 | assert(r == nil and l == 0 and poserr == 1) | ||
237 | |||
238 | p = m.Rec(#m.P("a") * m.T(22), m.T(15), 22) | ||
239 | r, l, poserr = p:match("abc") | ||
240 | assert(r == nil and l == 15 and poserr == 1) | ||
241 | |||
242 | p = m.Rec(#(m.P("a") * m.T(22)), m.T(15), 22) | ||
243 | r, l, poserr = p:match("abc") | ||
244 | assert(r == nil and l == 15 and poserr == 2) | ||
245 | |||
246 | p = m.Lc(#m.T(22), m.P"a", 22) | ||
247 | assert(p:match("abc") == 2) | ||
248 | |||
249 | p = #m.Lc(m.T(22), m.P"a", 22) | ||
250 | assert(p:match("abc") == 1) | 234 | assert(p:match("abc") == 1) |
251 | 235 | ||
252 | p = m.Lc(m.T(22), #m.P"a", 22) | 236 | p = m.P{ |
237 | "S", | ||
238 | S = m.T(22), | ||
239 | ["22"] = #m.P"a" | ||
240 | } | ||
253 | assert(p:match("abc") == 1) | 241 | assert(p:match("abc") == 1) |
254 | 242 | ||
255 | p = m.Lc(#m.T(22), m.P"a", 22) | 243 | p = m.P{ |
244 | "S", | ||
245 | S = #m.T(22), | ||
246 | ["22"] = m.P"a" | ||
247 | } | ||
256 | r, l, poserr = p:match("bbc") | 248 | r, l, poserr = p:match("bbc") |
257 | assert(r == nil and l == 0 and poserr == 1) | 249 | assert(r == nil and l == 'fail' and poserr == 1) |
258 | 250 | ||
259 | p = m.Lc(#m.P("a") * m.T(22), m.T(15), 22) | 251 | p = m.P{ |
252 | "S", | ||
253 | S = #m.P"a" * m.T(22), | ||
254 | ["22"] = m.T(15) | ||
255 | } | ||
260 | r, l, poserr = p:match("abc") | 256 | r, l, poserr = p:match("abc") |
261 | assert(r == nil and l == 15 and poserr == 1) | 257 | assert(r == nil and l == '15' and poserr == 1) |
262 | 258 | ||
263 | p = m.Lc(#(m.P("a") * m.T(22)), m.T(15), 22) | 259 | p = m.P{ |
260 | "S", | ||
261 | S = #(m.P"a" * m.T(22)), | ||
262 | ["22"] = m.T(15) | ||
263 | } | ||
264 | r, l, poserr = p:match("abc") | 264 | r, l, poserr = p:match("abc") |
265 | assert(r == nil and l == 15 and poserr == 1) | 265 | assert(r == nil and l == '15' and poserr == 2) |
266 | |||
267 | 266 | ||
268 | 267 | ||
269 | -- tests related to repetition | 268 | -- tests related to repetition |
270 | p = m.T(1)^0 | 269 | p = m.T(1)^0 |
271 | r, l, poserr = p:match("ab") | 270 | r, l, poserr = p:match("ab") |
272 | assert(r == nil and l == 1 and poserr == 1) | 271 | assert(r == nil and l == '1' and poserr == 1) |
273 | 272 | ||
274 | p = (m.P"a" + m.T(1))^0 | 273 | p = (m.P"a" + m.T(1))^0 |
275 | r, l, poserr = p:match("aa") | 274 | r, l, poserr = p:match("aa") |
276 | assert(r == nil and l == 1 and poserr == 3) | 275 | assert(r == nil and l == '1' and poserr == 3) |
277 | 276 | ||
278 | 277 | ||
279 | -- Bug reported by Matthew Allen | 278 | -- Bug reported by Matthew Allen |
@@ -281,18 +280,19 @@ assert(r == nil and l == 1 and poserr == 3) | |||
281 | -- applied in case of labels | 280 | -- applied in case of labels |
282 | 281 | ||
283 | -- recovery operator | 282 | -- recovery operator |
284 | p = m.Rec(m.P"A", m.P(true), 1) + m.P("B") | 283 | p = m.P{ |
285 | assert(p:match("B") == 2) | 284 | "S", |
286 | 285 | S = m.P"A" + m.P"B", | |
287 | p = m.Rec(m.P"A", m.P(false), 1) + m.P("B") | 286 | ["2"] = m.P(true) |
288 | assert(p:match("B") == 2) | 287 | } |
289 | |||
290 | 288 | ||
291 | -- labeled choices | ||
292 | p = m.Lc(m.P"A", m.P(true), 1) + m.P("B") | ||
293 | assert(p:match("B") == 2) | 289 | assert(p:match("B") == 2) |
294 | 290 | ||
295 | p = m.Lc(m.P"A", m.P(false), 1) + m.P("B") | 291 | p = m.P{ |
292 | "S", | ||
293 | S = m.P"A" + m.P"B", | ||
294 | ["2"] = m.P(false) | ||
295 | } | ||
296 | assert(p:match("B") == 2) | 296 | assert(p:match("B") == 2) |
297 | 297 | ||
298 | 298 | ||
@@ -303,152 +303,73 @@ B -> %1 | |||
303 | ]] | 303 | ]] |
304 | g = m.P{ | 304 | g = m.P{ |
305 | "S", | 305 | "S", |
306 | S = m.Rec(m.V"A", m.P"a", 1), | 306 | S = m.V"A", |
307 | A = m.V"B", | 307 | A = m.V"B", |
308 | B = m.T(1), | 308 | B = m.T(2), |
309 | ["2"] = m.P'a' | ||
309 | } | 310 | } |
310 | assert(g:match("ab") == 2) | 311 | assert(g:match("ab") == 2) |
311 | r, l, poserr = g:match("bc") | 312 | r, l, poserr = g:match("bc") |
312 | assert(r == nil and l == 0 and poserr == 1) | 313 | assert(r == nil and l == 'fail' and poserr == 1) |
313 | 314 | ||
314 | 315 | ||
315 | --[[ | 316 | --[[ |
316 | S -> A | 317 | S -> A |
317 | A -> (B (';' / %{1}))* | 318 | A -> (B (';' / %{2}))* |
318 | B -> 'a' | 319 | B -> 'a' |
319 | ]] | 320 | ]] |
320 | g = m.P{ | 321 | g = m.P{ |
321 | "S", | 322 | "S", |
322 | S = m.V"A", | 323 | S = m.V"A", |
323 | A = m.P(m.V"B" * (";" + m.T(1)))^0, | 324 | A = m.P(m.V"B" * (";" + m.T(2)))^0, |
324 | B = m.P'a', | 325 | B = m.P'a', |
325 | } | 326 | } |
326 | assert(g:match("a;a;") == 5) | 327 | assert(g:match("a;a;") == 5) |
327 | 328 | ||
328 | r, l, poserr = g:match("a;a") | 329 | r, l, poserr = g:match("a;a") |
329 | assert(r == nil and l == 1 and poserr == 4) | 330 | assert(r == nil and l == '2' and poserr == 4) |
330 | |||
331 | 331 | ||
332 | -- %1 //{1,3} %2 //{2} 'a' | ||
333 | p = m.Rec(m.Rec(m.T(1), m.T(2), 1, 3), m.P"a", 2) | ||
334 | assert(p:match("abc") == 2) | ||
335 | |||
336 | r, l, poserr = p:match("") | ||
337 | assert(r == nil and l == 0 and poserr == 1) | ||
338 | 332 | ||
339 | p = m.Rec(m.T(1), m.Rec(m.T(2), m.P"a", 2), 1, 3) | 333 | p = m.P{ |
340 | assert(p:match("abc") == 2) | 334 | "S", |
341 | 335 | S = m.T'A', | |
342 | r, l, poserr = p:match("") | 336 | A = m.T'B', |
343 | assert(r == nil and l == 0 and poserr == 1) | 337 | B = m.P'a' |
344 | |||
345 | -- labeled choice | ||
346 | --[[ | ||
347 | S -> A /{1} 'a' | ||
348 | A -> B | ||
349 | B -> %1 | ||
350 | ]] | ||
351 | g = m.P{ | ||
352 | "S", | ||
353 | S = m.Lc(m.V"A", m.P"a", 1), | ||
354 | A = m.V"B", | ||
355 | B = m.T(1), | ||
356 | } | ||
357 | assert(g:match("ab") == 2) | ||
358 | r, l, poserr = g:match("bc") | ||
359 | assert(r == nil and l == 0 and poserr == 1) | ||
360 | |||
361 | |||
362 | --[[ | ||
363 | S -> A | ||
364 | A -> (B (';' / %{1}))* | ||
365 | B -> 'a' | ||
366 | ]] | ||
367 | g = m.P{ | ||
368 | "S", | ||
369 | S = m.V"A", | ||
370 | A = m.P(m.V"B" * (";" + m.T(1)))^0, | ||
371 | B = m.P'a', | ||
372 | } | 338 | } |
373 | assert(g:match("a;a;") == 5) | ||
374 | |||
375 | r, l, poserr = g:match("a;a") | ||
376 | assert(r == nil and l == 1 and poserr == 4) | ||
377 | |||
378 | |||
379 | -- %1 /{1,3} %2 /{2} 'a' | ||
380 | p = m.Lc(m.Lc(m.T(1), m.T(2), 1, 3), m.P"a", 2) | ||
381 | assert(p:match("abc") == 2) | ||
382 | |||
383 | r, l, poserr = p:match("") | ||
384 | assert(r == nil and l == 0 and poserr == 1) | ||
385 | |||
386 | p = m.Lc(m.T(1), m.Lc(m.T(2), m.P"a", 2), 1, 3) | ||
387 | assert(p:match("abc") == 2) | 339 | assert(p:match("abc") == 2) |
388 | 340 | ||
389 | r, l, poserr = p:match("") | 341 | r, l, poserr = p:match("") |
390 | assert(r == nil and l == 0 and poserr == 1) | 342 | assert(r == nil and l == 'fail' and poserr == 1) |
391 | 343 | ||
392 | 344 | ||
393 | -- Infinte Loop TODO: check the semantics | 345 | -- Infinte Loop TODO: check the semantics |
394 | -- %1 //{1} %1 | 346 | p = m.P{ |
395 | p = m.Rec(m.T(1), m.T(1), 1) | 347 | "S", |
348 | S = m.T"A", | ||
349 | A = m.T"S", | ||
350 | } | ||
396 | --r, l, poserr = p:match("ab") | 351 | --r, l, poserr = p:match("ab") |
397 | --assert(r == nil and l == 1 and poserr == "ab") | 352 | --assert(r == nil and l == 1 and poserr == "ab") |
398 | 353 | ||
399 | -- %1 //{1} 'a' (!. / %1) | 354 | p = m.P{ |
400 | p = m.Rec(m.T(1), m.P"a" * (-m.P(1) + m.T(1)), 1) | 355 | "S", |
356 | S = m.T"A", | ||
357 | A = m.P'a' * (-m.P(1) + m.T"A"), | ||
358 | } | ||
401 | r, l, poserr = p:match("ab") | 359 | r, l, poserr = p:match("ab") |
402 | assert(r == nil and l == 0 and poserr == 2) | 360 | assert(r == nil and l == 'fail' and poserr == 2) |
403 | 361 | ||
404 | r, l, poserr = p:match("cd") | 362 | r, l, poserr = p:match("cd") |
405 | assert(r == nil and l == 0 and poserr == 1) | 363 | assert(r == nil and l == 'fail' and poserr == 1) |
406 | 364 | ||
407 | -- %1 //{1} . (!. / %1) | 365 | p = m.P{ |
408 | p = m.Rec(m.T(1), m.P(1) * (-m.P(1) + m.T(1)), 1) | 366 | "S", |
367 | S = m.T"A", | ||
368 | A = m.P(1) * (-m.P(1) + m.T"A"), | ||
369 | } | ||
409 | assert(p:match("abc") == 4) | 370 | assert(p:match("abc") == 4) |
410 | 371 | ||
411 | 372 | ||
412 | -- testing the limit of labels | ||
413 | -- can only throw labels between 1 and 255 | ||
414 | local r = pcall(m.Rec, m.P"b", m.P"a", 0) | ||
415 | assert(r == false) | ||
416 | |||
417 | local r = pcall(m.Rec, m.P"b", m.P"a", 256) | ||
418 | assert(r == false) | ||
419 | |||
420 | local r = pcall(m.Rec, m.P"b", m.P"a", -1) | ||
421 | assert(r == false) | ||
422 | |||
423 | local r = pcall(m.Lc, m.P"b", m.P"a", 0) | ||
424 | assert(r == false) | ||
425 | |||
426 | local r = pcall(m.Lc, m.P"b", m.P"a", 256) | ||
427 | assert(r == false) | ||
428 | |||
429 | local r = pcall(m.Lc, m.P"b", m.P"a", -1) | ||
430 | assert(r == false) | ||
431 | |||
432 | local r = pcall(m.T, 0) | ||
433 | assert(r == false) | ||
434 | |||
435 | local r = pcall(m.T, 256) | ||
436 | assert(r == false) | ||
437 | |||
438 | local r = pcall(m.T, -1) | ||
439 | assert(r == false) | ||
440 | |||
441 | |||
442 | local r = m.Rec(m.P"b", m.P"a", 255) | ||
443 | assert(p:match("a") == 2) | ||
444 | |||
445 | p = m.T(255) | ||
446 | s = "abc" | ||
447 | r, l, poserr = p:match(s) | ||
448 | assert(r == nil and l == 255 and poserr == 1) | ||
449 | |||
450 | |||
451 | |||
452 | print("+") | 373 | print("+") |
453 | 374 | ||
454 | --[[ grammar based on Figure 8 of paper submitted to SCP | 375 | --[[ grammar based on Figure 8 of paper submitted to SCP |