aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lpcode.c6
-rw-r--r--lptree.c6
-rw-r--r--lptypes.h2
-rw-r--r--lpvm.c77
-rw-r--r--makefile14
-rwxr-xr-xtest.lua2
-rw-r--r--testlabel.lua5
7 files changed, 52 insertions, 60 deletions
diff --git a/lpcode.c b/lpcode.c
index f7246da..d5f8d68 100644
--- a/lpcode.c
+++ b/lpcode.c
@@ -725,17 +725,17 @@ static void codelabchoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
725static void coderecovery (CompileState *compst, TTree *p1, TTree *p2, int opt, 725static void coderecovery (CompileState *compst, TTree *p1, TTree *p2, int opt,
726 const Charset *fl, const byte *cs) { 726 const Charset *fl, const byte *cs) {
727 int emptyp2 = (p2->tag == TTrue); 727 int emptyp2 = (p2->tag == TTrue);
728 int pjmp; 728 int pcommit;
729 int test = NOINST; 729 int test = NOINST;
730 int precovery = addoffsetinst(compst, IRecov); 730 int precovery = addoffsetinst(compst, IRecov);
731 addcharset(compst, cs); 731 addcharset(compst, cs);
732 codegen(compst, p1, emptyp2, test, fullset); 732 codegen(compst, p1, emptyp2, test, fullset);
733 pjmp = addoffsetinst(compst, IJmp); 733 pcommit = addoffsetinst(compst, ICommit);
734 jumptohere(compst, precovery); 734 jumptohere(compst, precovery);
735 jumptohere(compst, test); 735 jumptohere(compst, test);
736 codegen(compst, p2, opt, NOINST, fl); 736 codegen(compst, p2, opt, NOINST, fl);
737 addinstruction(compst, IRet, 0); 737 addinstruction(compst, IRet, 0);
738 jumptohere(compst, pjmp); 738 jumptohere(compst, pcommit);
739} 739}
740/* labeled failure end */ 740/* labeled failure end */
741 741
diff --git a/lptree.c b/lptree.c
index 2044a5c..700398b 100644
--- a/lptree.c
+++ b/lptree.c
@@ -748,7 +748,7 @@ static int lp_recovery (lua_State *L) {
748 int n = lua_gettop(L); 748 int n = lua_gettop(L);
749 TTree *tree = newrootlab2sib(L, TRecov); 749 TTree *tree = newrootlab2sib(L, TRecov);
750 if (n == 2) { /* catches fail as default */ 750 if (n == 2) { /* catches fail as default */
751 setlabel(treelabelset(tree), LFAIL); 751 /*setlabel(treelabelset(tree), LFAIL); recovery does not catch regular fail */
752 } else { 752 } else {
753 int i; 753 int i;
754 for (i = 3; i <= n; i++) { 754 for (i = 3; i <= n; i++) {
@@ -1361,8 +1361,8 @@ static struct luaL_Reg metareg[] = {
1361}; 1361};
1362 1362
1363 1363
1364int luaopen_lpeglabel (lua_State *L); /* labeled failure */ 1364int luaopen_lpeglabelrec (lua_State *L); /* labeled failure */
1365int luaopen_lpeglabel (lua_State *L) { /* labeled failure */ 1365int luaopen_lpeglabelrec (lua_State *L) { /* labeled failure */
1366 luaL_newmetatable(L, PATTERN_T); 1366 luaL_newmetatable(L, PATTERN_T);
1367 lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */ 1367 lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */
1368 lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); 1368 lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
diff --git a/lptypes.h b/lptypes.h
index 85339a0..dc4ada6 100644
--- a/lptypes.h
+++ b/lptypes.h
@@ -161,8 +161,6 @@ typedef Charset Labelset;
161#define IDXLFAIL 0 161#define IDXLFAIL 0
162 162
163#define LFAIL 0 163#define LFAIL 0
164
165#define MAXRECOVERY 200
166/* labeled failure end */ 164/* labeled failure end */
167 165
168#endif 166#endif
diff --git a/lpvm.c b/lpvm.c
index 917a626..44975a1 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -48,12 +48,6 @@ typedef struct Stack {
48} Stack; 48} Stack;
49 49
50 50
51typedef struct RecStack {
52 const Labelset *ls; /* labeled failure */
53 const Instruction *prec; /* recovery instruction */
54} RecStack;
55
56
57#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop))) 51#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop)))
58 52
59 53
@@ -162,25 +156,22 @@ static int removedyncap (lua_State *L, Capture *capture,
162const char *match (lua_State *L, const char *o, const char *s, const char *e, 156const char *match (lua_State *L, const char *o, const char *s, const char *e,
163 Instruction *op, Capture *capture, int ptop, byte *labelf, const char **sfail) { /* labeled failure */ 157 Instruction *op, Capture *capture, int ptop, byte *labelf, const char **sfail) { /* labeled failure */
164 Stack stackbase[INITBACK]; 158 Stack stackbase[INITBACK];
165 RecStack recbase[MAXRECOVERY];
166 Stack *stacklimit = stackbase + INITBACK; 159 Stack *stacklimit = stackbase + INITBACK;
167 Stack *stack = stackbase; /* point to first empty slot in stack */ 160 Stack *stack = stackbase; /* point to first empty slot in stack */
168 RecStack *reclimit = recbase + MAXRECOVERY; 161 int capsize = INITCAPSIZE;
169 RecStack *recstack = recbase;
170 int capsize = INITCAPSIZE;
171 int captop = 0; /* point to first empty slot in captures */ 162 int captop = 0; /* point to first empty slot in captures */
172 int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ 163 int ndyncap = 0; /* number of dynamic captures (in Lua stack) */
173 const Instruction *p = op; /* current instruction */ 164 const Instruction *p = op; /* current instruction */
165 const Instruction *pk = NULL; /* resume instruction */
174 Labelset lsfail; 166 Labelset lsfail;
175 setlabelfail(&lsfail); 167 setlabelfail(&lsfail);
176 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 */
177 recstack->prec = &giveup; recstack->ls = &lsfail; recstack++; /* labeled failure */
178 lua_pushlightuserdata(L, stackbase); 169 lua_pushlightuserdata(L, stackbase);
179 for (;;) { 170 for (;;) {
180#if defined(DEBUG) 171#if defined(DEBUG)
172 printinst(op, p);
181 printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ", 173 printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ",
182 s, stack - getstackbase(L, ptop), ndyncap, captop); 174 s, stack - getstackbase(L, ptop), ndyncap, captop);
183 printinst(op, p);
184 printcaplist(capture, capture + captop); 175 printcaplist(capture, capture + captop);
185#endif 176#endif
186 assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); 177 assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop);
@@ -204,6 +195,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
204 if (s < e) { p++; s++; } 195 if (s < e) { p++; s++; }
205 else { 196 else {
206 *labelf = LFAIL; /* labeled failure */ 197 *labelf = LFAIL; /* labeled failure */
198 pk = p + 1;
207 *sfail = s; 199 *sfail = s;
208 goto fail; 200 goto fail;
209 } 201 }
@@ -218,6 +210,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
218 if ((byte)*s == p->i.aux && s < e) { p++; s++; } 210 if ((byte)*s == p->i.aux && s < e) { p++; s++; }
219 else { 211 else {
220 *labelf = LFAIL; /* labeled failure */ 212 *labelf = LFAIL; /* labeled failure */
213 pk = p + 1;
221 *sfail = s; 214 *sfail = s;
222 goto fail; 215 goto fail;
223 } 216 }
@@ -234,6 +227,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
234 { p += CHARSETINSTSIZE; s++; } 227 { p += CHARSETINSTSIZE; s++; }
235 else { 228 else {
236 *labelf = LFAIL; /* labeled failure */ 229 *labelf = LFAIL; /* labeled failure */
230 pk = p + CHARSETINSTSIZE;
237 *sfail = s; 231 *sfail = s;
238 goto fail; 232 goto fail;
239 } 233 }
@@ -250,6 +244,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
250 int n = p->i.aux; 244 int n = p->i.aux;
251 if (n > s - o) { 245 if (n > s - o) {
252 *labelf = LFAIL; /* labeled failure */ 246 *labelf = LFAIL; /* labeled failure */
247 pk = p + 1;
253 *sfail = s; 248 *sfail = s;
254 goto fail; 249 goto fail;
255 } 250 }
@@ -291,11 +286,13 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
291 continue; 286 continue;
292 } 287 }
293 case IRecov: { /* labeled failure */ 288 case IRecov: { /* labeled failure */
294 if (recstack == reclimit) 289 if (stack == stacklimit)
295 luaL_error(L, "recovery stack overflow (current limit is %d)", MAXRECOVERY); 290 stack = doublestack(L, &stacklimit, ptop);
296 recstack->prec = p + getoffset(p); 291 stack->p = p + getoffset(p);
297 recstack->ls = (const Labelset *) ((p + 2)->buff); 292 stack->s = NULL;
298 recstack++; 293 stack->ls = (const Labelset *) ((p + 2)->buff);
294 stack->caplevel = captop;
295 stack++;
299 p += (CHARSETINSTSIZE - 1) + 2; 296 p += (CHARSETINSTSIZE - 1) + 2;
300 continue; 297 continue;
301 } 298 }
@@ -310,8 +307,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
310 continue; 307 continue;
311 } 308 }
312 case ICommit: { 309 case ICommit: {
313 /*assert(stack > getstackbase(L, ptop) && (stack - 1)->ls != NULL); */ /* labeled failure */ 310 assert(stack > getstackbase(L, ptop) && (stack - 1)->ls != NULL); /* labeled failure */
314 assert((stack - 1)->s != NULL); /* labeled failure: IRecov does not push s onto the stack */ 311 /*assert((stack - 1)->s != NULL); labeled failure: IRecov does not push s onto the stack */
315 stack--; 312 stack--;
316 p += getoffset(p); 313 p += getoffset(p);
317 continue; 314 continue;
@@ -332,24 +329,9 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
332 } 329 }
333 case IThrow: { /* labeled failure */ 330 case IThrow: { /* labeled failure */
334 *labelf = p->i.aux; 331 *labelf = p->i.aux;
335 while ((--recstack)->prec != &giveup) { 332 pk = p + 1;
336 if (testlabel(recstack->ls->cs, *labelf)) {
337 /* Push resume/call frame */
338 stack->s = NULL;
339 stack->p = p + 1; /* resume to instruction after IThrow */
340 stack->ls = NULL;
341 stack++;
342 p = recstack->prec;
343 break;
344 }
345 }
346 if (recstack->prec != &giveup)
347 continue;
348 p = recstack->prec; /* p = IGiveup */
349 stack = getstackbase(L, ptop);
350 *sfail = s; 333 *sfail = s;
351 /*goto fail;*/ 334 goto fail;
352 continue;
353 } 335 }
354 case IFailTwice: 336 case IFailTwice:
355 assert(stack > getstackbase(L, ptop)); 337 assert(stack > getstackbase(L, ptop));
@@ -357,20 +339,30 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
357 /* go through */ 339 /* go through */
358 case IFail: 340 case IFail:
359 *labelf = LFAIL; /* labeled failure */ 341 *labelf = LFAIL; /* labeled failure */
342 pk = NULL;
360 *sfail = s; 343 *sfail = s;
361 fail: { /* pattern failed: try to backtrack */ 344 fail: { /* pattern failed: try to backtrack */
362 const Labelset *auxlab = NULL; 345 const Labelset *auxlab = NULL;
346 Stack *pstack = stack;
363 do { /* remove pending calls */ 347 do { /* remove pending calls */
364 assert(stack > getstackbase(L, ptop)); 348 assert(pstack > getstackbase(L, ptop));
365 auxlab = (--stack)->ls; 349 auxlab = (--pstack)->ls;
366 } while (auxlab == NULL || (stack->p != &giveup && !testlabel(stack->ls->cs, *labelf))); 350 } while (auxlab == NULL || (pstack->p != &giveup && labelf != LFAIL && !testlabel(pstack->ls->cs, *labelf)));
367 if (stack->p == &giveup || stack->s != NULL) { /* labeled failure */ 351 if (pstack->p == &giveup || pstack->s != NULL) { /* labeled failure: giveup or backtrack frame */
352 stack = pstack;
368 s = stack->s; 353 s = stack->s;
369 } 354 } else { /* labeled failure: recovery frame */
355 if (stack == stacklimit)
356 stack = doublestack(L, &stacklimit, ptop);
357 stack->s = NULL;
358 stack->p = pk; /* save return address */
359 stack->ls = NULL;
360 stack++;
361 }
370 if (ndyncap > 0) /* is there matchtime captures? */ 362 if (ndyncap > 0) /* is there matchtime captures? */
371 ndyncap -= removedyncap(L, capture, stack->caplevel, captop); 363 ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
372 captop = stack->caplevel; 364 captop = stack->caplevel;
373 p = stack->p; 365 p = pstack->p;
374 continue; 366 continue;
375 } 367 }
376 case ICloseRunTime: { 368 case ICloseRunTime: {
@@ -385,6 +377,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
385 if (res == -1) { /* fail? */ 377 if (res == -1) { /* fail? */
386 *labelf = LFAIL; /* labeled failure */ 378 *labelf = LFAIL; /* labeled failure */
387 *sfail = (const char *) s; /* TODO: ??? */ 379 *sfail = (const char *) s; /* TODO: ??? */
380 pk = NULL;
388 goto fail; 381 goto fail;
389 } 382 }
390 s = o + res; /* else update current position */ 383 s = o + res; /* else update current position */
diff --git a/makefile b/makefile
index 5728b38..414651e 100644
--- a/makefile
+++ b/makefile
@@ -1,4 +1,4 @@
1LIBNAME = lpeglabel 1LIBNAME = lpeglabelrec
2LUADIR = ../lua/ 2LUADIR = ../lua/
3 3
4COPT = -O2 4COPT = -O2
@@ -29,24 +29,24 @@ FILES = lpvm.o lpcap.o lptree.o lpcode.o lpprint.o
29 29
30# For Linux 30# For Linux
31linux: 31linux:
32 make lpeglabel.so "DLLFLAGS = -shared -fPIC" 32 make lpeglabelrec.so "DLLFLAGS = -shared -fPIC"
33 33
34# For Mac OS 34# For Mac OS
35macosx: 35macosx:
36 make lpeglabel.so "DLLFLAGS = -bundle -undefined dynamic_lookup" 36 make lpeglabelrec.so "DLLFLAGS = -bundle -undefined dynamic_lookup"
37 37
38lpeglabel.so: $(FILES) 38lpeglabelrec.so: $(FILES)
39 env $(CC) $(DLLFLAGS) $(FILES) -o lpeglabel.so 39 env $(CC) $(DLLFLAGS) $(FILES) -o lpeglabelrec.so
40 40
41$(FILES): makefile 41$(FILES): makefile
42 42
43test: test.lua testlabel.lua testerrors.lua relabel.lua lpeglabel.so 43test: test.lua testlabel.lua testerrors.lua relabel.lua lpeglabelrec.so
44 lua test.lua 44 lua test.lua
45 lua testlabel.lua 45 lua testlabel.lua
46 lua testerrors.lua 46 lua testerrors.lua
47 47
48clean: 48clean:
49 rm -f $(FILES) lpeglabel.so 49 rm -f $(FILES) lpeglabelrec.so
50 50
51 51
52lpcap.o: lpcap.c lpcap.h lptypes.h 52lpcap.o: lpcap.c lpcap.h lptypes.h
diff --git a/test.lua b/test.lua
index d5922ac..fc2b607 100755
--- a/test.lua
+++ b/test.lua
@@ -4,7 +4,7 @@
4 4
5-- require"strict" -- just to be pedantic 5-- require"strict" -- just to be pedantic
6 6
7local m = require"lpeglabel" 7local m = require"lpeglabelrec"
8 8
9 9
10-- for general use 10-- for general use
diff --git a/testlabel.lua b/testlabel.lua
index cbe623c..8cfb671 100644
--- a/testlabel.lua
+++ b/testlabel.lua
@@ -1,4 +1,4 @@
1local m = require 'lpeglabel' 1local m = require 'lpeglabelrec'
2 2
3local p, r, l, s, serror 3local p, r, l, s, serror
4 4
@@ -557,6 +557,7 @@ print("+")
557p = m.Rec("a", "b") 557p = m.Rec("a", "b")
558assert(p:match("a") == 2) 558assert(p:match("a") == 2)
559--assert(p:match("b") == 2) 559--assert(p:match("b") == 2)
560checkeqlab({nil, 0, "b"}, p:match("b"))
560checkeqlab({nil, 0, "c"}, p:match("c")) 561checkeqlab({nil, 0, "c"}, p:match("c"))
561 562
562p = m.Rec("a", "b", 3) 563p = m.Rec("a", "b", 3)
@@ -607,7 +608,7 @@ C -> c+
607]] 608]]
608g = m.P{ 609g = m.P{
609 "S", 610 "S",
610 S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0) * m.V"C", 611 S = m.Rec(m.V"A", (-m.P"c" * m.P(1))^0, 0) * m.V"C", --explicitly put 0 in Rec
611 A = m.P"a"^0 * m.P"b" + m.T(0), 612 A = m.P"a"^0 * m.P"b" + m.T(0),
612 C = m.P"c"^1, 613 C = m.P"c"^1,
613} 614}