aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSérgio Queiroz <sqmedeiros@gmail.com>2017-12-15 16:31:41 -0300
committerSérgio Queiroz <sqmedeiros@gmail.com>2017-12-15 16:31:41 -0300
commit4bdf8d40a9ca5f00e454a38d301a3ab35c9b50d5 (patch)
treee59c5041761c237f27fe51589901da5a963ee103
parent0f53a65f4a32c8be2d84c4a8172b885065f7c1e5 (diff)
downloadlpeglabel-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.c39
-rw-r--r--lptree.c36
-rw-r--r--lptree.h4
-rw-r--r--lptypes.h15
-rw-r--r--lpvm.c69
-rw-r--r--lpvm.h1
-rw-r--r--testlabel.lua239
7 files changed, 102 insertions, 301 deletions
diff --git a/lpcode.c b/lpcode.c
index 43e83b5..0b813b8 100644
--- a/lpcode.c
+++ b/lpcode.c
@@ -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) {
522static int addoffsetinst (CompileState *compst, Opcode op) { 517static 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 */
750static 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;
diff --git a/lptree.c b/lptree.c
index 90e82ef..6d6b399 100644
--- a/lptree.c
+++ b/lptree.c
@@ -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
537static 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*/
744static 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
diff --git a/lptree.h b/lptree.h
index 2980821..27aa476 100644
--- a/lptree.h
+++ b/lptree.h
@@ -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
diff --git a/lptypes.h b/lptypes.h
index 0fe250b..25e84a2 100644
--- a/lptypes.h
+++ b/lptypes.h
@@ -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
152typedef 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 */
diff --git a/lpvm.c b/lpvm.c
index dfbda74..251fa0a 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -26,13 +26,6 @@
26 26
27static const Instruction giveup = {{IGiveup, 0, 0}}; 27static const Instruction giveup = {{IGiveup, 0, 0}};
28 28
29/* labeled failure */
30static 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) {
44typedef struct Stack { 37typedef 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 }
diff --git a/lpvm.h b/lpvm.h
index e4c5353..a56da32 100644
--- a/lpvm.h
+++ b/lpvm.h
@@ -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
203p = ##m.T(1) + m.P"a" 203p = ##m.T(1) + m.P"a"
204r, l, poserr = p:match("abc") 204r, l, poserr = p:match("abc")
205assert(r == nil and l == 1 and poserr == 1) 205assert(r == nil and l == '1' and poserr == 1)
206 206
207p = -m.T(1) * m.P"a" 207p = -m.T(1) * m.P"a"
208r, l, poserr = p:match("abc") 208r, l, poserr = p:match("abc")
209assert(r == nil and l == 1 and poserr == 1) 209assert(r == nil and l == '1' and poserr == 1)
210 210
211p = -m.T(1) * m.P"a" 211p = -m.T(1) * m.P"a"
212r, l, poserr = p:match("bbc") 212r, l, poserr = p:match("bbc")
213assert(r == nil and l == 1 and poserr == 1) 213assert(r == nil and l == '1' and poserr == 1)
214 214
215p = -(-m.T(1)) * m.P"a" 215p = -(-m.T(1)) * m.P"a"
216r, l, poserr = p:match("abc") 216r, l, poserr = p:match("abc")
217assert(r == nil and l == 1 and poserr == 1) 217assert(r == nil and l == '1' and poserr == 1)
218 218
219p = m.Rec(-m.T(22), m.P"a", 22) 219p = m.P{
220 "S",
221 S = -m.T(22),
222 ["22"] = m.P"a"
223}
220r, l, poserr = p:match("abc") 224r, l, poserr = p:match("abc")
221assert(r == nil and l == 0 and poserr == 2) 225assert(r == nil and l == 'fail' and poserr == 2)
222 226
223assert(p:match("bbc") == 1) 227assert(p:match("bbc") == 1)
224 228
225p = m.Rec(#m.T(22), m.P"a", 22) 229p = m.P{
226assert(p:match("abc") == 1) 230 "S",
227 231 S = #m.T(22),
228p = #m.Rec(m.T(22), m.P"a", 22) 232 ["22"] = m.P"a"
229assert(p:match("abc") == 1) 233}
230
231p = m.Rec(m.T(22), #m.P"a", 22)
232assert(p:match("abc") == 1)
233
234p = m.Rec(#m.T(22), m.P"a", 22)
235r, l, poserr = p:match("bbc")
236assert(r == nil and l == 0 and poserr == 1)
237
238p = m.Rec(#m.P("a") * m.T(22), m.T(15), 22)
239r, l, poserr = p:match("abc")
240assert(r == nil and l == 15 and poserr == 1)
241
242p = m.Rec(#(m.P("a") * m.T(22)), m.T(15), 22)
243r, l, poserr = p:match("abc")
244assert(r == nil and l == 15 and poserr == 2)
245
246p = m.Lc(#m.T(22), m.P"a", 22)
247assert(p:match("abc") == 2)
248
249p = #m.Lc(m.T(22), m.P"a", 22)
250assert(p:match("abc") == 1) 234assert(p:match("abc") == 1)
251 235
252p = m.Lc(m.T(22), #m.P"a", 22) 236p = m.P{
237 "S",
238 S = m.T(22),
239 ["22"] = #m.P"a"
240}
253assert(p:match("abc") == 1) 241assert(p:match("abc") == 1)
254 242
255p = m.Lc(#m.T(22), m.P"a", 22) 243p = m.P{
244 "S",
245 S = #m.T(22),
246 ["22"] = m.P"a"
247}
256r, l, poserr = p:match("bbc") 248r, l, poserr = p:match("bbc")
257assert(r == nil and l == 0 and poserr == 1) 249assert(r == nil and l == 'fail' and poserr == 1)
258 250
259p = m.Lc(#m.P("a") * m.T(22), m.T(15), 22) 251p = m.P{
252 "S",
253 S = #m.P"a" * m.T(22),
254 ["22"] = m.T(15)
255}
260r, l, poserr = p:match("abc") 256r, l, poserr = p:match("abc")
261assert(r == nil and l == 15 and poserr == 1) 257assert(r == nil and l == '15' and poserr == 1)
262 258
263p = m.Lc(#(m.P("a") * m.T(22)), m.T(15), 22) 259p = m.P{
260 "S",
261 S = #(m.P"a" * m.T(22)),
262 ["22"] = m.T(15)
263}
264r, l, poserr = p:match("abc") 264r, l, poserr = p:match("abc")
265assert(r == nil and l == 15 and poserr == 1) 265assert(r == nil and l == '15' and poserr == 2)
266
267 266
268 267
269-- tests related to repetition 268-- tests related to repetition
270p = m.T(1)^0 269p = m.T(1)^0
271r, l, poserr = p:match("ab") 270r, l, poserr = p:match("ab")
272assert(r == nil and l == 1 and poserr == 1) 271assert(r == nil and l == '1' and poserr == 1)
273 272
274p = (m.P"a" + m.T(1))^0 273p = (m.P"a" + m.T(1))^0
275r, l, poserr = p:match("aa") 274r, l, poserr = p:match("aa")
276assert(r == nil and l == 1 and poserr == 3) 275assert(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
284p = m.Rec(m.P"A", m.P(true), 1) + m.P("B") 283p = m.P{
285assert(p:match("B") == 2) 284 "S",
286 285 S = m.P"A" + m.P"B",
287p = m.Rec(m.P"A", m.P(false), 1) + m.P("B") 286 ["2"] = m.P(true)
288assert(p:match("B") == 2) 287}
289
290 288
291-- labeled choices
292p = m.Lc(m.P"A", m.P(true), 1) + m.P("B")
293assert(p:match("B") == 2) 289assert(p:match("B") == 2)
294 290
295p = m.Lc(m.P"A", m.P(false), 1) + m.P("B") 291p = m.P{
292 "S",
293 S = m.P"A" + m.P"B",
294 ["2"] = m.P(false)
295}
296assert(p:match("B") == 2) 296assert(p:match("B") == 2)
297 297
298 298
@@ -303,152 +303,73 @@ B -> %1
303]] 303]]
304g = m.P{ 304g = 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}
310assert(g:match("ab") == 2) 311assert(g:match("ab") == 2)
311r, l, poserr = g:match("bc") 312r, l, poserr = g:match("bc")
312assert(r == nil and l == 0 and poserr == 1) 313assert(r == nil and l == 'fail' and poserr == 1)
313 314
314 315
315--[[ 316--[[
316S -> A 317S -> A
317A -> (B (';' / %{1}))* 318A -> (B (';' / %{2}))*
318B -> 'a' 319B -> 'a'
319]] 320]]
320g = m.P{ 321g = 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}
326assert(g:match("a;a;") == 5) 327assert(g:match("a;a;") == 5)
327 328
328r, l, poserr = g:match("a;a") 329r, l, poserr = g:match("a;a")
329assert(r == nil and l == 1 and poserr == 4) 330assert(r == nil and l == '2' and poserr == 4)
330
331 331
332-- %1 //{1,3} %2 //{2} 'a'
333p = m.Rec(m.Rec(m.T(1), m.T(2), 1, 3), m.P"a", 2)
334assert(p:match("abc") == 2)
335
336r, l, poserr = p:match("")
337assert(r == nil and l == 0 and poserr == 1)
338 332
339p = m.Rec(m.T(1), m.Rec(m.T(2), m.P"a", 2), 1, 3) 333p = m.P{
340assert(p:match("abc") == 2) 334 "S",
341 335 S = m.T'A',
342r, l, poserr = p:match("") 336 A = m.T'B',
343assert(r == nil and l == 0 and poserr == 1) 337 B = m.P'a'
344
345-- labeled choice
346--[[
347S -> A /{1} 'a'
348A -> B
349B -> %1
350]]
351g = 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}
357assert(g:match("ab") == 2)
358r, l, poserr = g:match("bc")
359assert(r == nil and l == 0 and poserr == 1)
360
361
362--[[
363S -> A
364A -> (B (';' / %{1}))*
365B -> 'a'
366]]
367g = 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}
373assert(g:match("a;a;") == 5)
374
375r, l, poserr = g:match("a;a")
376assert(r == nil and l == 1 and poserr == 4)
377
378
379-- %1 /{1,3} %2 /{2} 'a'
380p = m.Lc(m.Lc(m.T(1), m.T(2), 1, 3), m.P"a", 2)
381assert(p:match("abc") == 2)
382
383r, l, poserr = p:match("")
384assert(r == nil and l == 0 and poserr == 1)
385
386p = m.Lc(m.T(1), m.Lc(m.T(2), m.P"a", 2), 1, 3)
387assert(p:match("abc") == 2) 339assert(p:match("abc") == 2)
388 340
389r, l, poserr = p:match("") 341r, l, poserr = p:match("")
390assert(r == nil and l == 0 and poserr == 1) 342assert(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 346p = m.P{
395p = 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) 354p = m.P{
400p = 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}
401r, l, poserr = p:match("ab") 359r, l, poserr = p:match("ab")
402assert(r == nil and l == 0 and poserr == 2) 360assert(r == nil and l == 'fail' and poserr == 2)
403 361
404r, l, poserr = p:match("cd") 362r, l, poserr = p:match("cd")
405assert(r == nil and l == 0 and poserr == 1) 363assert(r == nil and l == 'fail' and poserr == 1)
406 364
407-- %1 //{1} . (!. / %1) 365p = m.P{
408p = 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}
409assert(p:match("abc") == 4) 370assert(p:match("abc") == 4)
410 371
411 372
412-- testing the limit of labels
413-- can only throw labels between 1 and 255
414local r = pcall(m.Rec, m.P"b", m.P"a", 0)
415assert(r == false)
416
417local r = pcall(m.Rec, m.P"b", m.P"a", 256)
418assert(r == false)
419
420local r = pcall(m.Rec, m.P"b", m.P"a", -1)
421assert(r == false)
422
423local r = pcall(m.Lc, m.P"b", m.P"a", 0)
424assert(r == false)
425
426local r = pcall(m.Lc, m.P"b", m.P"a", 256)
427assert(r == false)
428
429local r = pcall(m.Lc, m.P"b", m.P"a", -1)
430assert(r == false)
431
432local r = pcall(m.T, 0)
433assert(r == false)
434
435local r = pcall(m.T, 256)
436assert(r == false)
437
438local r = pcall(m.T, -1)
439assert(r == false)
440
441
442local r = m.Rec(m.P"b", m.P"a", 255)
443assert(p:match("a") == 2)
444
445p = m.T(255)
446s = "abc"
447r, l, poserr = p:match(s)
448assert(r == nil and l == 255 and poserr == 1)
449
450
451
452print("+") 373print("+")
453 374
454--[[ grammar based on Figure 8 of paper submitted to SCP 375--[[ grammar based on Figure 8 of paper submitted to SCP