diff options
-rw-r--r-- | lpcode.c | 6 | ||||
-rw-r--r-- | lptree.c | 6 | ||||
-rw-r--r-- | lptypes.h | 2 | ||||
-rw-r--r-- | lpvm.c | 77 | ||||
-rw-r--r-- | makefile | 14 | ||||
-rwxr-xr-x | test.lua | 2 | ||||
-rw-r--r-- | testlabel.lua | 5 |
7 files changed, 52 insertions, 60 deletions
@@ -725,17 +725,17 @@ static void codelabchoice (CompileState *compst, TTree *p1, TTree *p2, int opt, | |||
725 | static void coderecovery (CompileState *compst, TTree *p1, TTree *p2, int opt, | 725 | static 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 | ||
@@ -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 | ||
1364 | int luaopen_lpeglabel (lua_State *L); /* labeled failure */ | 1364 | int luaopen_lpeglabelrec (lua_State *L); /* labeled failure */ |
1365 | int luaopen_lpeglabel (lua_State *L) { /* labeled failure */ | 1365 | int 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); |
@@ -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 |
@@ -48,12 +48,6 @@ typedef struct Stack { | |||
48 | } Stack; | 48 | } Stack; |
49 | 49 | ||
50 | 50 | ||
51 | typedef 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, | |||
162 | const char *match (lua_State *L, const char *o, const char *s, const char *e, | 156 | const 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 */ |
@@ -1,4 +1,4 @@ | |||
1 | LIBNAME = lpeglabel | 1 | LIBNAME = lpeglabelrec |
2 | LUADIR = ../lua/ | 2 | LUADIR = ../lua/ |
3 | 3 | ||
4 | COPT = -O2 | 4 | COPT = -O2 |
@@ -29,24 +29,24 @@ FILES = lpvm.o lpcap.o lptree.o lpcode.o lpprint.o | |||
29 | 29 | ||
30 | # For Linux | 30 | # For Linux |
31 | linux: | 31 | linux: |
32 | make lpeglabel.so "DLLFLAGS = -shared -fPIC" | 32 | make lpeglabelrec.so "DLLFLAGS = -shared -fPIC" |
33 | 33 | ||
34 | # For Mac OS | 34 | # For Mac OS |
35 | macosx: | 35 | macosx: |
36 | make lpeglabel.so "DLLFLAGS = -bundle -undefined dynamic_lookup" | 36 | make lpeglabelrec.so "DLLFLAGS = -bundle -undefined dynamic_lookup" |
37 | 37 | ||
38 | lpeglabel.so: $(FILES) | 38 | lpeglabelrec.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 | ||
43 | test: test.lua testlabel.lua testerrors.lua relabel.lua lpeglabel.so | 43 | test: 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 | ||
48 | clean: | 48 | clean: |
49 | rm -f $(FILES) lpeglabel.so | 49 | rm -f $(FILES) lpeglabelrec.so |
50 | 50 | ||
51 | 51 | ||
52 | lpcap.o: lpcap.c lpcap.h lptypes.h | 52 | lpcap.o: lpcap.c lpcap.h lptypes.h |
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | -- require"strict" -- just to be pedantic | 5 | -- require"strict" -- just to be pedantic |
6 | 6 | ||
7 | local m = require"lpeglabel" | 7 | local 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 @@ | |||
1 | local m = require 'lpeglabel' | 1 | local m = require 'lpeglabelrec' |
2 | 2 | ||
3 | local p, r, l, s, serror | 3 | local p, r, l, s, serror |
4 | 4 | ||
@@ -557,6 +557,7 @@ print("+") | |||
557 | p = m.Rec("a", "b") | 557 | p = m.Rec("a", "b") |
558 | assert(p:match("a") == 2) | 558 | assert(p:match("a") == 2) |
559 | --assert(p:match("b") == 2) | 559 | --assert(p:match("b") == 2) |
560 | checkeqlab({nil, 0, "b"}, p:match("b")) | ||
560 | checkeqlab({nil, 0, "c"}, p:match("c")) | 561 | checkeqlab({nil, 0, "c"}, p:match("c")) |
561 | 562 | ||
562 | p = m.Rec("a", "b", 3) | 563 | p = m.Rec("a", "b", 3) |
@@ -607,7 +608,7 @@ C -> c+ | |||
607 | ]] | 608 | ]] |
608 | g = m.P{ | 609 | g = 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 | } |