diff options
| author | Sérgio Queiroz <sqmedeiros@gmail.com> | 2017-12-27 14:13:25 -0300 |
|---|---|---|
| committer | Sérgio Queiroz <sqmedeiros@gmail.com> | 2017-12-27 14:13:25 -0300 |
| commit | 772df00e061db3cd7d0af92c8ab65bc023d8121d (patch) | |
| tree | 48e343e06a4b3ea4a4423330e1256606db4d53f3 | |
| parent | e4cc8be34e590dc22f0a25ecfa269624b1569925 (diff) | |
| download | lpeglabel-772df00e061db3cd7d0af92c8ab65bc023d8121d.tar.gz lpeglabel-772df00e061db3cd7d0af92c8ab65bc023d8121d.tar.bz2 lpeglabel-772df00e061db3cd7d0af92c8ab65bc023d8121d.zip | |
Implementing the new semantics of predicates when a label is thrown
| -rw-r--r-- | lpcode.c | 15 | ||||
| -rw-r--r-- | lpprint.c | 5 | ||||
| -rw-r--r-- | lptypes.h | 5 | ||||
| -rw-r--r-- | lpvm.c | 82 | ||||
| -rw-r--r-- | lpvm.h | 2 | ||||
| -rw-r--r-- | testlabel.lua | 55 |
6 files changed, 114 insertions, 50 deletions
| @@ -449,7 +449,7 @@ int sizei (const Instruction *i) { | |||
| 449 | case ITestChar: case ITestAny: case IChoice: case IJmp: case ICall: | 449 | case ITestChar: case ITestAny: case IChoice: case IJmp: case ICall: |
| 450 | case IOpenCall: case ICommit: case IPartialCommit: case IBackCommit: | 450 | case IOpenCall: case ICommit: case IPartialCommit: case IBackCommit: |
| 451 | return 2; | 451 | return 2; |
| 452 | case IThrow: /* labeled failure */ | 452 | case IThrow: case IPredChoice: /* labeled failure */ |
| 453 | return 2; | 453 | return 2; |
| 454 | case IThrowRec: /* labeled failure */ | 454 | case IThrowRec: /* labeled failure */ |
| 455 | return 3; | 455 | return 3; |
| @@ -747,15 +747,19 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt, | |||
| 747 | ** (valid only when 'p' has no captures) | 747 | ** (valid only when 'p' has no captures) |
| 748 | */ | 748 | */ |
| 749 | static void codeand (CompileState *compst, TTree *tree, int tt) { | 749 | static void codeand (CompileState *compst, TTree *tree, int tt) { |
| 750 | int n = fixedlen(tree); | 750 | /* labeled failure: optimization disabled bacause in case of a failure it |
| 751 | does not report the expected error position (the current subject position | ||
| 752 | when begin the matching of <&p>) */ | ||
| 753 | /*int n = fixedlen(tree); | ||
| 751 | if (n >= 0 && n <= MAXBEHIND && !hascaptures(tree)) { | 754 | if (n >= 0 && n <= MAXBEHIND && !hascaptures(tree)) { |
| 752 | codegen(compst, tree, 0, tt, fullset); | 755 | codegen(compst, tree, 0, tt, fullset); |
| 753 | if (n > 0) | 756 | if (n > 0) |
| 754 | addinstruction(compst, IBehind, n); | 757 | addinstruction(compst, IBehind, n); |
| 755 | } | 758 | } |
| 756 | else { /* default: Choice L1; p1; BackCommit L2; L1: Fail; L2: */ | 759 | else */{ /* default: Choice L1; p1; BackCommit L2; L1: Fail; L2: */ |
| 757 | int pcommit; | 760 | int pcommit; |
| 758 | int pchoice = addoffsetinst(compst, IChoice); | 761 | int pchoice = addoffsetinst(compst, IPredChoice); /* labeled failure */ |
| 762 | getinstr(compst, pchoice).i.aux = ANDPRED; | ||
| 759 | codegen(compst, tree, 0, tt, fullset); | 763 | codegen(compst, tree, 0, tt, fullset); |
| 760 | pcommit = addoffsetinst(compst, IBackCommit); | 764 | pcommit = addoffsetinst(compst, IBackCommit); |
| 761 | jumptohere(compst, pchoice); | 765 | jumptohere(compst, pchoice); |
| @@ -857,7 +861,8 @@ static void codenot (CompileState *compst, TTree *tree) { | |||
| 857 | addinstruction(compst, IFail, 0); | 861 | addinstruction(compst, IFail, 0); |
| 858 | else { | 862 | else { |
| 859 | /* test(fail(p))-> L1; choice L1; <p>; failtwice; L1: */ | 863 | /* test(fail(p))-> L1; choice L1; <p>; failtwice; L1: */ |
| 860 | int pchoice = addoffsetinst(compst, IChoice); | 864 | int pchoice = addoffsetinst(compst, IPredChoice); /* labeled failure */ |
| 865 | getinstr(compst, pchoice).i.aux = NOTPRED; | ||
| 861 | codegen(compst, tree, 0, NOINST, fullset); | 866 | codegen(compst, tree, 0, NOINST, fullset); |
| 862 | addinstruction(compst, IFailTwice, 0); | 867 | addinstruction(compst, IFailTwice, 0); |
| 863 | jumptohere(compst, pchoice); | 868 | jumptohere(compst, pchoice); |
| @@ -58,7 +58,7 @@ void printinst (const Instruction *op, const Instruction *p) { | |||
| 58 | "testany", "testchar", "testset", | 58 | "testany", "testchar", "testset", |
| 59 | "span", "behind", | 59 | "span", "behind", |
| 60 | "ret", "end", | 60 | "ret", "end", |
| 61 | "choice", "jmp", "call", "open_call", | 61 | "choice", "pred_choice", "jmp", "call", "open_call", /* labeled failure */ |
| 62 | "commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup", | 62 | "commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup", |
| 63 | "fullcapture", "opencapture", "closecapture", "closeruntime", | 63 | "fullcapture", "opencapture", "closecapture", "closeruntime", |
| 64 | "throw", "throw_rec", /* labeled failure */ | 64 | "throw", "throw_rec", /* labeled failure */ |
| @@ -103,7 +103,8 @@ void printinst (const Instruction *op, const Instruction *p) { | |||
| 103 | break; | 103 | break; |
| 104 | } | 104 | } |
| 105 | case IJmp: case ICall: case ICommit: case IChoice: | 105 | case IJmp: case ICall: case ICommit: case IChoice: |
| 106 | case IPartialCommit: case IBackCommit: case ITestAny: { | 106 | case IPartialCommit: case IBackCommit: case ITestAny: |
| 107 | case IPredChoice: { /* labeled failure */ | ||
| 107 | printjmp(op, p); | 108 | printjmp(op, p); |
| 108 | break; | 109 | break; |
| 109 | } | 110 | } |
| @@ -150,6 +150,11 @@ 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 | ||
| 155 | #define NOTPRED 1 | ||
| 156 | #define ANDPRED 2 | ||
| 157 | |||
| 153 | /* labeled failure end */ | 158 | /* labeled failure end */ |
| 154 | 159 | ||
| 155 | #endif | 160 | #endif |
| @@ -39,6 +39,7 @@ typedef struct Stack { | |||
| 39 | const Instruction *p; /* next instruction */ | 39 | const Instruction *p; /* next instruction */ |
| 40 | int caplevel; | 40 | int caplevel; |
| 41 | byte labenv; /* labeled failure */ | 41 | byte labenv; /* labeled failure */ |
| 42 | byte predchoice; /* labeled failure */ | ||
| 42 | } Stack; | 43 | } Stack; |
| 43 | 44 | ||
| 44 | 45 | ||
| @@ -156,8 +157,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 156 | int captop = 0; /* point to first empty slot in captures */ | 157 | int captop = 0; /* point to first empty slot in captures */ |
| 157 | int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ | 158 | int ndyncap = 0; /* number of dynamic captures (in Lua stack) */ |
| 158 | const Instruction *p = op; /* current instruction */ | 159 | const Instruction *p = op; /* current instruction */ |
| 159 | byte labenv = 1; /* labeled failure: label environment is on */ | 160 | byte insidepred = OUTPRED; /* labeled failure: label environment is off inside predicates */ |
| 160 | stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack->labenv = 1; stack++; /* labeled failure */ | 161 | stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack->labenv = insidepred; stack++; /* labeled failure */ |
| 161 | *sfail = s; /* labeled failure */ | 162 | *sfail = s; /* labeled failure */ |
| 162 | lua_pushlightuserdata(L, stackbase); | 163 | lua_pushlightuserdata(L, stackbase); |
| 163 | for (;;) { | 164 | for (;;) { |
| @@ -168,9 +169,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 168 | s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop); | 169 | s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop); |
| 169 | printinst(op, p); | 170 | printinst(op, p); |
| 170 | #endif | 171 | #endif |
| 171 | printinst(op, p); | ||
| 172 | assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); | 172 | assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop); |
| 173 | assert(labenv == 1); | 173 | assert(insidepred == NOTPRED || insidepred == ANDPRED || 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,7 +191,8 @@ 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 | updatefarthest(*sfail, s); /*labeled failure */ | 194 | if (insidepred == OUTPRED) |
| 195 | updatefarthest(*sfail, s); /*labeled failure */ | ||
| 195 | goto fail; | 196 | goto fail; |
| 196 | } | 197 | } |
| 197 | continue; | 198 | continue; |
| @@ -205,7 +206,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 205 | if ((byte)*s == p->i.aux && s < e) { p++; s++; } | 206 | if ((byte)*s == p->i.aux && s < e) { p++; s++; } |
| 206 | else { | 207 | else { |
| 207 | *labelf = LFAIL; /* labeled failure */ | 208 | *labelf = LFAIL; /* labeled failure */ |
| 208 | updatefarthest(*sfail, s); /*labeled failure */ | 209 | if (insidepred == OUTPRED) |
| 210 | updatefarthest(*sfail, s); /*labeled failure */ | ||
| 209 | goto fail; | 211 | goto fail; |
| 210 | } | 212 | } |
| 211 | continue; | 213 | continue; |
| @@ -221,7 +223,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 221 | { p += CHARSETINSTSIZE; s++; } | 223 | { p += CHARSETINSTSIZE; s++; } |
| 222 | else { | 224 | else { |
| 223 | *labelf = LFAIL; /* labeled failure */ | 225 | *labelf = LFAIL; /* labeled failure */ |
| 224 | updatefarthest(*sfail, s); /*labeled failure */ | 226 | if (insidepred == OUTPRED) |
| 227 | updatefarthest(*sfail, s); /*labeled failure */ | ||
| 225 | goto fail; | 228 | goto fail; |
| 226 | } | 229 | } |
| 227 | continue; | 230 | continue; |
| @@ -237,7 +240,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 237 | int n = p->i.aux; | 240 | int n = p->i.aux; |
| 238 | if (n > s - o) { | 241 | if (n > s - o) { |
| 239 | *labelf = LFAIL; /* labeled failure */ | 242 | *labelf = LFAIL; /* labeled failure */ |
| 240 | updatefarthest(*sfail, s); /*labeled failure */ | 243 | if (insidepred == OUTPRED) |
| 244 | updatefarthest(*sfail, s); /*labeled failure */ | ||
| 241 | goto fail; | 245 | goto fail; |
| 242 | } | 246 | } |
| 243 | s -= n; p++; | 247 | s -= n; p++; |
| @@ -261,10 +265,24 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 261 | stack->p = p + getoffset(p); | 265 | stack->p = p + getoffset(p); |
| 262 | stack->s = s; | 266 | stack->s = s; |
| 263 | stack->caplevel = captop; | 267 | stack->caplevel = captop; |
| 264 | stack->labenv = labenv; /* labeled failure */ | 268 | stack->labenv = insidepred; /* labeled failure */ |
| 269 | stack->predchoice = 0; /* labeled failure */ | ||
| 265 | stack++; | 270 | stack++; |
| 266 | p += 2; | 271 | p += 2; |
| 267 | continue; | 272 | continue; |
| 273 | } | ||
| 274 | case IPredChoice: { /* labeled failure: new instruction */ | ||
| 275 | if (stack == stacklimit) | ||
| 276 | stack = doublestack(L, &stacklimit, ptop); | ||
| 277 | stack->p = p + getoffset(p); | ||
| 278 | stack->s = s; | ||
| 279 | stack->caplevel = captop; | ||
| 280 | stack->labenv = insidepred; | ||
| 281 | stack->predchoice = 1; | ||
| 282 | stack++; | ||
| 283 | insidepred = p->i.aux; | ||
| 284 | p += 2; | ||
| 285 | continue; | ||
| 268 | } | 286 | } |
| 269 | case ICall: { | 287 | case ICall: { |
| 270 | if (stack == stacklimit) | 288 | if (stack == stacklimit) |
| @@ -292,38 +310,30 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 292 | case IBackCommit: { | 310 | case IBackCommit: { |
| 293 | assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL); | 311 | assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL); |
| 294 | s = (--stack)->s; | 312 | s = (--stack)->s; |
| 295 | labenv = stack->labenv; /* labeled failure */ | 313 | insidepred = stack->labenv; /* labeled failure */ |
| 296 | assert(labenv == 1); /* labeled failure */ | ||
| 297 | captop = stack->caplevel; | 314 | captop = stack->caplevel; |
| 298 | p += getoffset(p); | 315 | p += getoffset(p); |
| 299 | continue; | 316 | continue; |
| 300 | } | 317 | } |
| 301 | case IThrow: { /* labeled failure */ | 318 | case IThrow: { /* labeled failure */ |
| 302 | /*printf("IThrow here: key=%d, key+1=%d aux = %d top = %d\n", p->i.key, (p+1)->i.key, p->i.aux, lua_gettop(L)); | 319 | if (insidepred == OUTPRED) { |
| 303 | lua_rawgeti(L, ktableidx(ptop), (p+1)->i.key); | ||
| 304 | printf("IThrow there %s top = %d\n", lua_tostring(L, -1), lua_gettop(L)); | ||
| 305 | lua_pop(L, 1);*/ | ||
| 306 | if (labenv) { | ||
| 307 | *labelf = (p+1)->i.key; | 320 | *labelf = (p+1)->i.key; |
| 308 | if (*labelf == LFAIL) | 321 | if (*labelf == LFAIL) |
| 309 | luaL_error(L, "labelf is %d", *labelf); | 322 | luaL_error(L, "labelf is %d", *labelf); |
| 310 | stack = getstackbase(L, ptop); | 323 | stack = getstackbase(L, ptop); |
| 311 | stack++; | 324 | stack++; |
| 312 | printf("IThrow stack->labenv = %d\n", stack->labenv); | 325 | *sfail = s; |
| 313 | } | 326 | } |
| 314 | else { | 327 | else { |
| 315 | labelf = LFAIL; | 328 | while (!(stack-1)->predchoice) { |
| 329 | --stack; | ||
| 330 | } | ||
| 331 | *labelf = LFAIL; | ||
| 316 | } | 332 | } |
| 317 | *sfail = s; | ||
| 318 | goto fail; | 333 | goto fail; |
| 319 | } | 334 | } |
| 320 | case IThrowRec: { /* labeled failure */ | 335 | case IThrowRec: { /* labeled failure */ |
| 321 | /*printf("IThrowRec here: key=%d, key+2=%d aux = %d top = %d\n", p->i.key, (p+2)->i.key, p->i.aux, lua_gettop(L)); | 336 | if (insidepred == OUTPRED) { |
| 322 | lua_rawgeti(L, ktableidx(ptop), (p+2)->i.key); | ||
| 323 | printf("IThrowRec there %s top = %d\n", lua_tostring(L, -1), lua_gettop(L)); | ||
| 324 | lua_pop(L, 1);*/ | ||
| 325 | printf("labenv here = %d\n", labenv); | ||
| 326 | if (labenv) { | ||
| 327 | *labelf = (p+2)->i.key; | 337 | *labelf = (p+2)->i.key; |
| 328 | if (*labelf == LFAIL) | 338 | if (*labelf == LFAIL) |
| 329 | luaL_error(L, "labelf is %d", *labelf); | 339 | luaL_error(L, "labelf is %d", *labelf); |
| @@ -334,12 +344,19 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 334 | stack->p = p + 3; | 344 | stack->p = p + 3; |
| 335 | stack->caplevel = captop; | 345 | stack->caplevel = captop; |
| 336 | stack++; | 346 | stack++; |
| 347 | *sfail = s; | ||
| 337 | p += getoffset(p); | 348 | p += getoffset(p); |
| 338 | continue; | 349 | continue; |
| 339 | } else { | 350 | } else { |
| 340 | labelf = LFAIL; | 351 | while (!(stack-1)->predchoice) { |
| 352 | --stack; | ||
| 353 | } | ||
| 354 | /*if ((stack-1)->labenv == ANDPRED) { | ||
| 355 | printf("ANDPRED: stack - 1\n"); | ||
| 356 | stack--; | ||
| 357 | }*/ | ||
| 358 | *labelf = LFAIL; | ||
| 341 | } | 359 | } |
| 342 | *sfail = s; | ||
| 343 | goto fail; | 360 | goto fail; |
| 344 | } | 361 | } |
| 345 | case IFailTwice: | 362 | case IFailTwice: |
| @@ -348,7 +365,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 348 | /* go through */ | 365 | /* go through */ |
| 349 | case IFail: | 366 | case IFail: |
| 350 | *labelf = LFAIL; /* labeled failure */ | 367 | *labelf = LFAIL; /* labeled failure */ |
| 351 | updatefarthest(*sfail, s); /*labeled failure */ | 368 | if (insidepred == OUTPRED) |
| 369 | updatefarthest(*sfail, s); /*labeled failure */ | ||
| 352 | fail: { /* pattern failed: try to backtrack */ | 370 | fail: { /* pattern failed: try to backtrack */ |
| 353 | do { /* remove pending calls */ | 371 | do { /* remove pending calls */ |
| 354 | assert(stack > getstackbase(L, ptop)); | 372 | assert(stack > getstackbase(L, ptop)); |
| @@ -357,8 +375,9 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 357 | if (ndyncap > 0) /* is there matchtime captures? */ | 375 | if (ndyncap > 0) /* is there matchtime captures? */ |
| 358 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); | 376 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); |
| 359 | captop = stack->caplevel; | 377 | captop = stack->caplevel; |
| 360 | labenv = stack->labenv; | 378 | assert(((insidepred == ANDPRED || insidepred == NOTPRED) && (stack->labenv == OUTPRED)) || insidepred == stack->labenv |
| 361 | assert(labenv == 1); | 379 | || (insidepred != OUTPRED && stack->labenv != OUTPRED)); |
| 380 | insidepred = stack->labenv; | ||
| 362 | p = stack->p; | 381 | p = stack->p; |
| 363 | #if defined(DEBUG) | 382 | #if defined(DEBUG) |
| 364 | printf("**FAIL**\n"); | 383 | printf("**FAIL**\n"); |
| @@ -377,7 +396,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 377 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ | 396 | res = resdyncaptures(L, fr, s - o, e - o); /* get result */ |
| 378 | if (res == -1) { /* fail? */ | 397 | if (res == -1) { /* fail? */ |
| 379 | *labelf = LFAIL; /* labeled failure */ | 398 | *labelf = LFAIL; /* labeled failure */ |
| 380 | updatefarthest(*sfail, s); /*labeled failure */ | 399 | if (insidepred == OUTPRED) |
| 400 | updatefarthest(*sfail, s); /*labeled failure */ | ||
| 381 | goto fail; | 401 | goto fail; |
| 382 | } | 402 | } |
| 383 | s = o + res; /* else update current position */ | 403 | s = o + res; /* else update current position */ |
| @@ -21,7 +21,7 @@ typedef enum Opcode { | |||
| 21 | IRet, /* return from a rule */ | 21 | IRet, /* return from a rule */ |
| 22 | IEnd, /* end of pattern */ | 22 | IEnd, /* end of pattern */ |
| 23 | IChoice, /* stack a choice; next fail will jump to 'offset' */ | 23 | IChoice, /* stack a choice; next fail will jump to 'offset' */ |
| 24 | /*IPredChoice,*/ /* labeld failure: stack a choice; changes label env next fail will jump to 'offset' */ | 24 | IPredChoice, /* labeld failure: stack a choice; changes label env next fail will jump to 'offset' */ |
| 25 | IJmp, /* jump to 'offset' */ | 25 | IJmp, /* jump to 'offset' */ |
| 26 | ICall, /* call rule at 'offset' */ | 26 | ICall, /* call rule at 'offset' */ |
| 27 | IOpenCall, /* call rule number 'key' (must be closed to a ICall) */ | 27 | IOpenCall, /* call rule number 'key' (must be closed to a ICall) */ |
diff --git a/testlabel.lua b/testlabel.lua index b834be3..7461206 100644 --- a/testlabel.lua +++ b/testlabel.lua | |||
| @@ -194,27 +194,59 @@ assert(p:match("bac") == 3) | |||
| 194 | r, l, poserr = p:match("cab") | 194 | r, l, poserr = p:match("cab") |
| 195 | assert(r == nil and l == 'fail' and poserr == 1) | 195 | assert(r == nil and l == 'fail' and poserr == 1) |
| 196 | 196 | ||
| 197 | |||
| 198 | -- tests related to predicates | 197 | -- tests related to predicates |
| 198 | p = #m.T(1) | ||
| 199 | r, l, poserr = p:match("abc") | ||
| 200 | assert(r == nil and l == 'fail' and poserr == 1) | ||
| 201 | |||
| 199 | p = #m.T(1) + m.P"a" | 202 | p = #m.T(1) + m.P"a" |
| 200 | r, l, poserr = p:match("abc") | 203 | r, l, poserr = p:match("abc") |
| 201 | assert(r == nil and l == 1 and poserr == 1) | 204 | assert(r == 2) |
| 205 | |||
| 206 | p = #m.T(1) * m.P"a" | ||
| 207 | r, l, poserr = p:match("abc") | ||
| 208 | assert(r == nil and l == 'fail' and poserr == 1) | ||
| 202 | 209 | ||
| 203 | p = ##m.T(1) + m.P"a" | 210 | p = ##m.T(1) + m.P"a" |
| 204 | r, l, poserr = p:match("abc") | 211 | r, l, poserr = p:match("abc") |
| 205 | assert(r == nil and l == 1 and poserr == 1) | 212 | assert(r == 2) |
| 206 | 213 | ||
| 207 | p = -m.T(1) * m.P"a" | 214 | p = -#m.T(1) + m.P"a" |
| 208 | r, l, poserr = p:match("abc") | 215 | r, l, poserr = p:match("abc") |
| 209 | assert(r == nil and l == 1 and poserr == 1) | 216 | assert(r == 1) |
| 210 | 217 | ||
| 211 | p = -m.T(1) * m.P"a" | 218 | p = -m.T(1) * m.P"a" |
| 219 | r, l, poserr = p:match("abc") | ||
| 220 | assert(r == 2) | ||
| 221 | |||
| 222 | p = -m.T(1) | ||
| 212 | r, l, poserr = p:match("bbc") | 223 | r, l, poserr = p:match("bbc") |
| 213 | assert(r == nil and l == 1 and poserr == 1) | 224 | assert(r == 1) |
| 225 | |||
| 226 | p = -#m.T(1) | ||
| 227 | r, l, poserr = p:match("bbc") | ||
| 228 | assert(r == 1) | ||
| 214 | 229 | ||
| 215 | p = -(-m.T(1)) * m.P"a" | 230 | p = -(-m.P'a') |
| 216 | r, l, poserr = p:match("abc") | 231 | r, l, poserr = p:match("abc") |
| 217 | assert(r == nil and l == 1 and poserr == 1) | 232 | assert(r == 1) |
| 233 | |||
| 234 | p = -(-m.P'a') | ||
| 235 | r, l, poserr = p:match("bbc") | ||
| 236 | assert(r == nil and l == 'fail' and poserr == 1) | ||
| 237 | |||
| 238 | p = #(m.P"a" * m.T(1)) | ||
| 239 | r, l, poserr = p:match("abc") | ||
| 240 | assert(r == nil and l == 'fail' and poserr == 1) | ||
| 241 | |||
| 242 | p = #(m.P"a" * m.P'a') | ||
| 243 | r, l, poserr = p:match("abc") | ||
| 244 | assert(r == nil and l == 'fail' and poserr == 1) | ||
| 245 | |||
| 246 | |||
| 247 | p = -(-m.T(1)) | ||
| 248 | r, l, poserr = p:match("bbc") | ||
| 249 | assert(r == nil and l == 'fail' and poserr == 1) | ||
| 218 | 250 | ||
| 219 | p = m.P{ | 251 | p = m.P{ |
| 220 | "S", | 252 | "S", |
| @@ -222,7 +254,7 @@ p = m.P{ | |||
| 222 | ["22"] = m.P"a" | 254 | ["22"] = m.P"a" |
| 223 | } | 255 | } |
| 224 | r, l, poserr = p:match("abc") | 256 | r, l, poserr = p:match("abc") |
| 225 | assert(r == nil and l == 'fail' and poserr == 2) | 257 | assert(r == 1) |
| 226 | 258 | ||
| 227 | assert(p:match("bbc") == 1) | 259 | assert(p:match("bbc") == 1) |
| 228 | 260 | ||
| @@ -231,7 +263,8 @@ p = m.P{ | |||
| 231 | S = #m.T(22), | 263 | S = #m.T(22), |
| 232 | ["22"] = m.P"a" | 264 | ["22"] = m.P"a" |
| 233 | } | 265 | } |
| 234 | assert(p:match("abc") == 1) | 266 | r, l, poserr = p:match("abc") |
| 267 | assert(r == nil and l == 'fail' and poserr == 1) | ||
| 235 | 268 | ||
| 236 | p = m.P{ | 269 | p = m.P{ |
| 237 | "S", | 270 | "S", |
| @@ -262,7 +295,7 @@ p = m.P{ | |||
| 262 | ["22"] = m.T(15) | 295 | ["22"] = m.T(15) |
| 263 | } | 296 | } |
| 264 | r, l, poserr = p:match("abc") | 297 | r, l, poserr = p:match("abc") |
| 265 | assert(r == nil and l == 15 and poserr == 2) | 298 | assert(r == nil and l == 'fail' and poserr == 1) |
| 266 | 299 | ||
| 267 | 300 | ||
| 268 | -- tests related to repetition | 301 | -- tests related to repetition |
