aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lpcode.c2
-rw-r--r--lptypes.h4
-rw-r--r--lpvm.c47
-rw-r--r--testlabel.lua33
4 files changed, 49 insertions, 37 deletions
diff --git a/lpcode.c b/lpcode.c
index ef357bc..c5869e8 100644
--- a/lpcode.c
+++ b/lpcode.c
@@ -759,7 +759,6 @@ static void codeand (CompileState *compst, TTree *tree, int tt) {
759 else */{ /* default: Choice L1; p1; BackCommit L2; L1: Fail; L2: */ 759 else */{ /* default: Choice L1; p1; BackCommit L2; L1: Fail; L2: */
760 int pcommit; 760 int pcommit;
761 int pchoice = addoffsetinst(compst, IPredChoice); /* labeled failure */ 761 int pchoice = addoffsetinst(compst, IPredChoice); /* labeled failure */
762 getinstr(compst, pchoice).i.aux = ANDPRED;
763 codegen(compst, tree, 0, tt, fullset); 762 codegen(compst, tree, 0, tt, fullset);
764 pcommit = addoffsetinst(compst, IBackCommit); 763 pcommit = addoffsetinst(compst, IBackCommit);
765 jumptohere(compst, pchoice); 764 jumptohere(compst, pchoice);
@@ -862,7 +861,6 @@ static void codenot (CompileState *compst, TTree *tree) {
862 else { 861 else {
863 /* test(fail(p))-> L1; choice L1; <p>; failtwice; L1: */ 862 /* test(fail(p))-> L1; choice L1; <p>; failtwice; L1: */
864 int pchoice = addoffsetinst(compst, IPredChoice); /* labeled failure */ 863 int pchoice = addoffsetinst(compst, IPredChoice); /* labeled failure */
865 getinstr(compst, pchoice).i.aux = NOTPRED;
866 codegen(compst, tree, 0, NOINST, fullset); 864 codegen(compst, tree, 0, NOINST, fullset);
867 addinstruction(compst, IFailTwice, 0); 865 addinstruction(compst, IFailTwice, 0);
868 jumptohere(compst, pchoice); 866 jumptohere(compst, pchoice);
diff --git a/lptypes.h b/lptypes.h
index d523e27..6158be1 100644
--- a/lptypes.h
+++ b/lptypes.h
@@ -150,11 +150,9 @@ typedef struct Charset {
150/* update the farthest failure */ 150/* update the farthest failure */
151#define updatefarthest(s1,s2) { if ((s2) > (s1)) s1 = s2; } 151#define updatefarthest(s1,s2) { if ((s2) > (s1)) s1 = s2; }
152 152
153/* indicate whether the machine is matching a predicate or not */
154#define OUTPRED 0 153#define OUTPRED 0
155#define NOTPRED 1
156#define ANDPRED 2
157 154
155#define INPRED 1
158/* labeled failure end */ 156/* labeled failure end */
159 157
160#endif 158#endif
diff --git a/lpvm.c b/lpvm.c
index 1eb7944..0c70766 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -18,11 +18,11 @@
18 18
19/* initial size for call/backtrack stack */ 19/* initial size for call/backtrack stack */
20#if !defined(INITBACK) 20#if !defined(INITBACK)
21#define INITBACK MAXBACK 21#define INITBACK MAXBACK
22#endif 22#endif
23 23
24 24
25#define getoffset(p) (((p) + 1)->offset) 25#define getoffset(p) (((p) + 1)->offset)
26 26
27static const Instruction giveup = {{IGiveup, 0, 0}}; 27static const Instruction giveup = {{IGiveup, 0, 0}};
28 28
@@ -43,7 +43,7 @@ typedef struct Stack {
43} Stack; 43} Stack;
44 44
45 45
46#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop))) 46#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop)))
47 47
48 48
49/* 49/*
@@ -159,7 +159,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
159 const Instruction *p = op; /* current instruction */ 159 const Instruction *p = op; /* current instruction */
160 byte insidepred = OUTPRED; /* labeled failure: label environment is off inside predicates */ 160 byte insidepred = OUTPRED; /* labeled failure: label environment is off inside predicates */
161 stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack->labenv = insidepred; stack++; /* labeled failure */ 161 stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack->labenv = insidepred; stack++; /* labeled failure */
162 *sfail = s; /* labeled failure */ 162 *sfail = s; /* labeled failure */
163 lua_pushlightuserdata(L, stackbase); 163 lua_pushlightuserdata(L, stackbase);
164 for (;;) { 164 for (;;) {
165#if defined(DEBUG) 165#if defined(DEBUG)
@@ -170,7 +170,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
170 printinst(op, p); 170 printinst(op, p);
171#endif 171#endif
172 assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); 172 assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop);
173 assert(insidepred == NOTPRED || insidepred == ANDPRED || insidepred == OUTPRED); 173 assert(insidepred == INPRED || insidepred == OUTPRED);
174 switch ((Opcode)p->i.code) { 174 switch ((Opcode)p->i.code) {
175 case IEnd: { 175 case IEnd: {
176 assert(stack == getstackbase(L, ptop) + 1); 176 assert(stack == getstackbase(L, ptop) + 1);
@@ -191,8 +191,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
191 if (s < e) { p++; s++; } 191 if (s < e) { p++; s++; }
192 else { 192 else {
193 *labelf = LFAIL; /* labeled failure */ 193 *labelf = LFAIL; /* labeled failure */
194 if (insidepred == OUTPRED) 194 updatefarthest(*sfail, s); /*labeled failure */
195 updatefarthest(*sfail, s); /*labeled failure */
196 goto fail; 195 goto fail;
197 } 196 }
198 continue; 197 continue;
@@ -206,8 +205,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
206 if ((byte)*s == p->i.aux && s < e) { p++; s++; } 205 if ((byte)*s == p->i.aux && s < e) { p++; s++; }
207 else { 206 else {
208 *labelf = LFAIL; /* labeled failure */ 207 *labelf = LFAIL; /* labeled failure */
209 if (insidepred == OUTPRED) 208 updatefarthest(*sfail, s); /*labeled failure */
210 updatefarthest(*sfail, s); /*labeled failure */
211 goto fail; 209 goto fail;
212 } 210 }
213 continue; 211 continue;
@@ -223,8 +221,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
223 { p += CHARSETINSTSIZE; s++; } 221 { p += CHARSETINSTSIZE; s++; }
224 else { 222 else {
225 *labelf = LFAIL; /* labeled failure */ 223 *labelf = LFAIL; /* labeled failure */
226 if (insidepred == OUTPRED) 224 updatefarthest(*sfail, s); /*labeled failure */
227 updatefarthest(*sfail, s); /*labeled failure */
228 goto fail; 225 goto fail;
229 } 226 }
230 continue; 227 continue;
@@ -240,8 +237,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
240 int n = p->i.aux; 237 int n = p->i.aux;
241 if (n > s - o) { 238 if (n > s - o) {
242 *labelf = LFAIL; /* labeled failure */ 239 *labelf = LFAIL; /* labeled failure */
243 if (insidepred == OUTPRED) 240 updatefarthest(*sfail, s); /*labeled failure */
244 updatefarthest(*sfail, s); /*labeled failure */
245 goto fail; 241 goto fail;
246 } 242 }
247 s -= n; p++; 243 s -= n; p++;
@@ -280,7 +276,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
280 stack->labenv = insidepred; 276 stack->labenv = insidepred;
281 stack->predchoice = 1; 277 stack->predchoice = 1;
282 stack++; 278 stack++;
283 insidepred = p->i.aux; 279 insidepred = INPRED;
284 p += 2; 280 p += 2;
285 continue; 281 continue;
286 } 282 }
@@ -318,11 +314,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
318 case IThrow: { /* labeled failure */ 314 case IThrow: { /* labeled failure */
319 if (insidepred == OUTPRED) { 315 if (insidepred == OUTPRED) {
320 *labelf = (p+1)->i.key; 316 *labelf = (p+1)->i.key;
321 if (*labelf == LFAIL)
322 luaL_error(L, "labelf is %d", *labelf);
323 stack = getstackbase(L, ptop); 317 stack = getstackbase(L, ptop);
324 stack++; 318 stack++;
325 *sfail = s;
326 } 319 }
327 else { 320 else {
328 while (!(stack-1)->predchoice) { 321 while (!(stack-1)->predchoice) {
@@ -330,21 +323,19 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
330 } 323 }
331 *labelf = LFAIL; 324 *labelf = LFAIL;
332 } 325 }
326 *sfail = s;
333 goto fail; 327 goto fail;
334 } 328 }
335 case IThrowRec: { /* labeled failure */ 329 case IThrowRec: { /* labeled failure */
336 if (insidepred == OUTPRED) { 330 if (insidepred == OUTPRED) {
337 *labelf = (p+2)->i.key; 331 *labelf = (p+2)->i.key;
338 if (*labelf == LFAIL) 332 *sfail = s;
339 luaL_error(L, "labelf is %d", *labelf);
340 *sfail = s;
341 if (stack == stacklimit) 333 if (stack == stacklimit)
342 stack = doublestack(L, &stacklimit, ptop); 334 stack = doublestack(L, &stacklimit, ptop);
343 stack->s = NULL; 335 stack->s = NULL;
344 stack->p = p + 3; 336 stack->p = p + 3;
345 stack->caplevel = captop; 337 stack->caplevel = captop;
346 stack++; 338 stack++;
347 *sfail = s;
348 p += getoffset(p); 339 p += getoffset(p);
349 continue; 340 continue;
350 } else { 341 } else {
@@ -352,6 +343,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
352 --stack; 343 --stack;
353 } 344 }
354 *labelf = LFAIL; 345 *labelf = LFAIL;
346 *sfail = s;
355 } 347 }
356 goto fail; 348 goto fail;
357 } 349 }
@@ -361,8 +353,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
361 /* go through */ 353 /* go through */
362 case IFail: 354 case IFail:
363 *labelf = LFAIL; /* labeled failure */ 355 *labelf = LFAIL; /* labeled failure */
364 if (insidepred == OUTPRED) 356 updatefarthest(*sfail, s); /*labeled failure */
365 updatefarthest(*sfail, s); /*labeled failure */
366 fail: { /* pattern failed: try to backtrack */ 357 fail: { /* pattern failed: try to backtrack */
367 do { /* remove pending calls */ 358 do { /* remove pending calls */
368 assert(stack > getstackbase(L, ptop)); 359 assert(stack > getstackbase(L, ptop));
@@ -371,9 +362,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
371 if (ndyncap > 0) /* is there matchtime captures? */ 362 if (ndyncap > 0) /* is there matchtime captures? */
372 ndyncap -= removedyncap(L, capture, stack->caplevel, captop); 363 ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
373 captop = stack->caplevel; 364 captop = stack->caplevel;
374 assert(((insidepred == ANDPRED || insidepred == NOTPRED) && (stack->labenv == OUTPRED)) || insidepred == stack->labenv 365 assert((insidepred == INPRED && stack->labenv == OUTPRED) || insidepred == stack->labenv);
375 || (insidepred != OUTPRED && stack->labenv != OUTPRED)); 366 insidepred = stack->labenv; /* labeled failure */
376 insidepred = stack->labenv;
377 p = stack->p; 367 p = stack->p;
378#if defined(DEBUG) 368#if defined(DEBUG)
379 printf("**FAIL**\n"); 369 printf("**FAIL**\n");
@@ -391,9 +381,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
391 fr -= rem; /* 'rem' items were popped from Lua stack */ 381 fr -= rem; /* 'rem' items were popped from Lua stack */
392 res = resdyncaptures(L, fr, s - o, e - o); /* get result */ 382 res = resdyncaptures(L, fr, s - o, e - o); /* get result */
393 if (res == -1) { /* fail? */ 383 if (res == -1) { /* fail? */
394 *labelf = LFAIL; /* labeled failure */ 384 *labelf = LFAIL; /* labeled failure */
395 if (insidepred == OUTPRED) 385 updatefarthest(*sfail, s); /*labeled failure */
396 updatefarthest(*sfail, s); /*labeled failure */
397 goto fail; 386 goto fail;
398 } 387 }
399 s = o + res; /* else update current position */ 388 s = o + res; /* else update current position */
diff --git a/testlabel.lua b/testlabel.lua
index 7461206..d60bb54 100644
--- a/testlabel.lua
+++ b/testlabel.lua
@@ -237,12 +237,39 @@ assert(r == nil and l == 'fail' and poserr == 1)
237 237
238p = #(m.P"a" * m.T(1)) 238p = #(m.P"a" * m.T(1))
239r, l, poserr = p:match("abc") 239r, l, poserr = p:match("abc")
240assert(r == nil and l == 'fail' and poserr == 1) 240assert(r == nil and l == 'fail' and poserr == 2)
241 241
242p = #(m.P"a" * m.P'a') 242p = #(m.P"a" * m.P'a')
243r, l, poserr = p:match("abc") 243r, l, poserr = p:match("abc")
244assert(r == nil and l == 'fail' and poserr == 1) 244assert(r == nil and l == 'fail' and poserr == 2)
245 245
246p = m.P'a' * #m.P('a')
247r, l, poserr = p:match("abc")
248assert(r == nil and l == 'fail' and poserr == 2)
249
250p = m.P'a' * #m.P('ba')
251r, l, poserr = p:match("abc")
252assert(r == nil and l == 'fail' and poserr == 3)
253
254p = m.P'a' * -m.P('b')
255r, l, poserr = p:match("abc")
256assert(r == nil and l == 'fail' and poserr == 2)
257
258p = m.P'a' * -m.P('bc')
259r, l, poserr = p:match("abc")
260assert(r == nil and l == 'fail' and poserr == 4)
261
262p = m.P'a' * #m.T('a')
263r, l, poserr = p:match("abc")
264assert(r == nil and l == 'fail' and poserr == 2)
265
266p = m.P'a' * #(m.P'b' * m.T('a'))
267r, l, poserr = p:match("abc")
268assert(r == nil and l == 'fail' and poserr == 3)
269
270p = m.P'a' * (m.P'b' * m.T('a'))
271r, l, poserr = p:match("abc")
272assert(r == nil and l == 'a' and poserr == 3)
246 273
247p = -(-m.T(1)) 274p = -(-m.T(1))
248r, l, poserr = p:match("bbc") 275r, l, poserr = p:match("bbc")
@@ -295,7 +322,7 @@ p = m.P{
295 ["22"] = m.T(15) 322 ["22"] = m.T(15)
296} 323}
297r, l, poserr = p:match("abc") 324r, l, poserr = p:match("abc")
298assert(r == nil and l == 'fail' and poserr == 1) 325assert(r == nil and l == 'fail' and poserr == 2)
299 326
300 327
301-- tests related to repetition 328-- tests related to repetition