diff options
| -rw-r--r-- | lpcode.c | 2 | ||||
| -rw-r--r-- | lptypes.h | 4 | ||||
| -rw-r--r-- | lpvm.c | 47 | ||||
| -rw-r--r-- | testlabel.lua | 33 |
4 files changed, 49 insertions, 37 deletions
| @@ -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); |
| @@ -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 |
| @@ -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 | ||
| 27 | static const Instruction giveup = {{IGiveup, 0, 0}}; | 27 | static 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 | ||
| 238 | p = #(m.P"a" * m.T(1)) | 238 | p = #(m.P"a" * m.T(1)) |
| 239 | r, l, poserr = p:match("abc") | 239 | r, l, poserr = p:match("abc") |
| 240 | assert(r == nil and l == 'fail' and poserr == 1) | 240 | assert(r == nil and l == 'fail' and poserr == 2) |
| 241 | 241 | ||
| 242 | p = #(m.P"a" * m.P'a') | 242 | p = #(m.P"a" * m.P'a') |
| 243 | r, l, poserr = p:match("abc") | 243 | r, l, poserr = p:match("abc") |
| 244 | assert(r == nil and l == 'fail' and poserr == 1) | 244 | assert(r == nil and l == 'fail' and poserr == 2) |
| 245 | 245 | ||
| 246 | p = m.P'a' * #m.P('a') | ||
| 247 | r, l, poserr = p:match("abc") | ||
| 248 | assert(r == nil and l == 'fail' and poserr == 2) | ||
| 249 | |||
| 250 | p = m.P'a' * #m.P('ba') | ||
| 251 | r, l, poserr = p:match("abc") | ||
| 252 | assert(r == nil and l == 'fail' and poserr == 3) | ||
| 253 | |||
| 254 | p = m.P'a' * -m.P('b') | ||
| 255 | r, l, poserr = p:match("abc") | ||
| 256 | assert(r == nil and l == 'fail' and poserr == 2) | ||
| 257 | |||
| 258 | p = m.P'a' * -m.P('bc') | ||
| 259 | r, l, poserr = p:match("abc") | ||
| 260 | assert(r == nil and l == 'fail' and poserr == 4) | ||
| 261 | |||
| 262 | p = m.P'a' * #m.T('a') | ||
| 263 | r, l, poserr = p:match("abc") | ||
| 264 | assert(r == nil and l == 'fail' and poserr == 2) | ||
| 265 | |||
| 266 | p = m.P'a' * #(m.P'b' * m.T('a')) | ||
| 267 | r, l, poserr = p:match("abc") | ||
| 268 | assert(r == nil and l == 'fail' and poserr == 3) | ||
| 269 | |||
| 270 | p = m.P'a' * (m.P'b' * m.T('a')) | ||
| 271 | r, l, poserr = p:match("abc") | ||
| 272 | assert(r == nil and l == 'a' and poserr == 3) | ||
| 246 | 273 | ||
| 247 | p = -(-m.T(1)) | 274 | p = -(-m.T(1)) |
| 248 | r, l, poserr = p:match("bbc") | 275 | r, l, poserr = p:match("bbc") |
| @@ -295,7 +322,7 @@ p = m.P{ | |||
| 295 | ["22"] = m.T(15) | 322 | ["22"] = m.T(15) |
| 296 | } | 323 | } |
| 297 | r, l, poserr = p:match("abc") | 324 | r, l, poserr = p:match("abc") |
| 298 | assert(r == nil and l == 'fail' and poserr == 1) | 325 | assert(r == nil and l == 'fail' and poserr == 2) |
| 299 | 326 | ||
| 300 | 327 | ||
| 301 | -- tests related to repetition | 328 | -- tests related to repetition |
