diff options
| author | Sergio Queiroz <sqmedeiros@gmail.com> | 2017-07-06 16:01:44 -0300 |
|---|---|---|
| committer | Sergio Queiroz <sqmedeiros@gmail.com> | 2017-07-06 16:01:44 -0300 |
| commit | e2a8e1c789a7a769c83a66d6fd2f191b0e465cba (patch) | |
| tree | e2aecc3d439e44db98439c26cf23625da1bedb3f | |
| parent | a36fe71ac0271d9013f76d9342f9a2fca40f64fc (diff) | |
| download | lpeglabel-e2a8e1c789a7a769c83a66d6fd2f191b0e465cba.tar.gz lpeglabel-e2a8e1c789a7a769c83a66d6fd2f191b0e465cba.tar.bz2 lpeglabel-e2a8e1c789a7a769c83a66d6fd2f191b0e465cba.zip | |
Reintroducing the labeled ordered choice (tests without it passed)
| -rw-r--r-- | lpcode.c | 35 | ||||
| -rw-r--r-- | lpprint.c | 8 | ||||
| -rw-r--r-- | lptree.c | 35 | ||||
| -rw-r--r-- | lptree.h | 4 | ||||
| -rw-r--r-- | lpvm.c | 11 | ||||
| -rw-r--r-- | lpvm.h | 3 | ||||
| -rw-r--r-- | relabel.lua | 30 |
7 files changed, 95 insertions, 31 deletions
| @@ -220,7 +220,7 @@ int checkaux (TTree *tree, int pred) { | |||
| 220 | if (checkaux(sib2(tree), pred)) return 1; | 220 | if (checkaux(sib2(tree), pred)) return 1; |
| 221 | /* else return checkaux(sib1(tree), pred); */ | 221 | /* else return checkaux(sib1(tree), pred); */ |
| 222 | tree = sib1(tree); goto tailcall; | 222 | tree = sib1(tree); goto tailcall; |
| 223 | case TRecov: /* labeled failure */ | 223 | case TRecov: case TLabChoice: /* labeled failure */ |
| 224 | /* we do not know whether sib2 will be evaluated */ | 224 | /* we do not know whether sib2 will be evaluated */ |
| 225 | tree = sib1(tree); goto tailcall; | 225 | tree = sib1(tree); goto tailcall; |
| 226 | case TCapture: case TGrammar: case TRule: | 226 | case TCapture: case TGrammar: case TRule: |
| @@ -264,7 +264,7 @@ int fixedlen (TTree *tree) { | |||
| 264 | /* else return fixedlen(sib2(tree)) + len; */ | 264 | /* else return fixedlen(sib2(tree)) + len; */ |
| 265 | len += n1; tree = sib2(tree); goto tailcall; | 265 | len += n1; tree = sib2(tree); goto tailcall; |
| 266 | } | 266 | } |
| 267 | case TChoice: { | 267 | case TChoice: case TLabChoice: { /* labeled failure */ |
| 268 | int n1 = fixedlen(sib1(tree)); | 268 | int n1 = fixedlen(sib1(tree)); |
| 269 | int n2 = fixedlen(sib2(tree)); | 269 | int n2 = fixedlen(sib2(tree)); |
| 270 | if (n1 != n2 || n1 < 0) | 270 | if (n1 != n2 || n1 < 0) |
| @@ -314,7 +314,7 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) { | |||
| 314 | loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */ | 314 | loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */ |
| 315 | return 1; | 315 | return 1; |
| 316 | } | 316 | } |
| 317 | case TChoice: { | 317 | case TChoice: case TLabChoice: { /*(?) labeled failure */ |
| 318 | Charset csaux; | 318 | Charset csaux; |
| 319 | int e1 = getfirst(sib1(tree), follow, firstset); | 319 | int e1 = getfirst(sib1(tree), follow, firstset); |
| 320 | int e2 = getfirst(sib2(tree), follow, &csaux); | 320 | int e2 = getfirst(sib2(tree), follow, &csaux); |
| @@ -405,7 +405,7 @@ static int headfail (TTree *tree) { | |||
| 405 | if (!nofail(sib2(tree))) return 0; | 405 | if (!nofail(sib2(tree))) return 0; |
| 406 | /* else return headfail(sib1(tree)); */ | 406 | /* else return headfail(sib1(tree)); */ |
| 407 | tree = sib1(tree); goto tailcall; | 407 | tree = sib1(tree); goto tailcall; |
| 408 | case TChoice: case TRecov: /* labeled failure */ | 408 | case TChoice: case TRecov: case TLabChoice: /* labeled failure */ |
| 409 | if (!headfail(sib1(tree))) return 0; | 409 | if (!headfail(sib1(tree))) return 0; |
| 410 | /* else return headfail(sib2(tree)); */ | 410 | /* else return headfail(sib2(tree)); */ |
| 411 | tree = sib2(tree); goto tailcall; | 411 | tree = sib2(tree); goto tailcall; |
| @@ -425,7 +425,7 @@ static int needfollow (TTree *tree) { | |||
| 425 | case TChar: case TSet: case TAny: | 425 | case TChar: case TSet: case TAny: |
| 426 | case TFalse: case TTrue: case TAnd: case TNot: | 426 | case TFalse: case TTrue: case TAnd: case TNot: |
| 427 | case TRunTime: case TGrammar: case TCall: case TBehind: | 427 | case TRunTime: case TGrammar: case TCall: case TBehind: |
| 428 | case TThrow: case TRecov: /* (?)labeled failure */ | 428 | case TThrow: case TRecov: case TLabChoice: /* (?)labeled failure */ |
| 429 | return 0; | 429 | return 0; |
| 430 | case TChoice: case TRep: | 430 | case TChoice: case TRep: |
| 431 | return 1; | 431 | return 1; |
| @@ -460,7 +460,7 @@ int sizei (const Instruction *i) { | |||
| 460 | return 2; | 460 | return 2; |
| 461 | case IThrow: /* labeled failure */ | 461 | case IThrow: /* labeled failure */ |
| 462 | return 1; | 462 | return 1; |
| 463 | case IRecov: | 463 | case IRecov: case ILabChoice: |
| 464 | return (CHARSETINSTSIZE - 1) + 2; /* labeled failure */ | 464 | return (CHARSETINSTSIZE - 1) + 2; /* labeled failure */ |
| 465 | 465 | ||
| 466 | default: return 1; | 466 | default: return 1; |
| @@ -527,7 +527,7 @@ static int addoffsetinst (CompileState *compst, Opcode op) { | |||
| 527 | int i = addinstruction(compst, op, 0); /* instruction */ | 527 | int i = addinstruction(compst, op, 0); /* instruction */ |
| 528 | addinstruction(compst, (Opcode)0, 0); /* open space for offset */ | 528 | addinstruction(compst, (Opcode)0, 0); /* open space for offset */ |
| 529 | assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2 || | 529 | assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2 || |
| 530 | op == IRecov); /* labeled failure */ | 530 | op == IRecov || op == ILabChoice); /* labeled failure */ |
| 531 | return i; | 531 | return i; |
| 532 | } | 532 | } |
| 533 | 533 | ||
| @@ -750,6 +750,21 @@ static void coderecovery (CompileState *compst, TTree *p1, TTree *p2, int opt, | |||
| 750 | addinstruction(compst, IRet, 0); | 750 | addinstruction(compst, IRet, 0); |
| 751 | jumptohere(compst, pcommit); | 751 | jumptohere(compst, pcommit); |
| 752 | } | 752 | } |
| 753 | |||
| 754 | static void codelabchoice (CompileState *compst, TTree *p1, TTree *p2, int opt, | ||
| 755 | const Charset *fl, const byte *cs) { | ||
| 756 | int emptyp2 = (p2->tag == TTrue); | ||
| 757 | int pcommit; | ||
| 758 | int test = NOINST; | ||
| 759 | int pchoice = addoffsetinst(compst, ILabChoice); | ||
| 760 | addcharset(compst, cs); | ||
| 761 | codegen(compst, p1, emptyp2, test, fullset); | ||
| 762 | pcommit = addoffsetinst(compst, ICommit); | ||
| 763 | jumptohere(compst, pchoice); | ||
| 764 | jumptohere(compst, test); | ||
| 765 | codegen(compst, p2, opt, NOINST, fl); | ||
| 766 | jumptohere(compst, pcommit); | ||
| 767 | } | ||
| 753 | /* labeled failure end */ | 768 | /* labeled failure end */ |
| 754 | 769 | ||
| 755 | 770 | ||
| @@ -988,6 +1003,10 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt, | |||
| 988 | coderecovery(compst, sib1(tree), sib2(tree), opt, fl, treelabelset(tree)); | 1003 | coderecovery(compst, sib1(tree), sib2(tree), opt, fl, treelabelset(tree)); |
| 989 | break; | 1004 | break; |
| 990 | } | 1005 | } |
| 1006 | case TLabChoice: { /* labeled failure */ | ||
| 1007 | codelabchoice(compst, sib1(tree), sib2(tree), opt, fl, treelabelset(tree)); | ||
| 1008 | break; | ||
| 1009 | } | ||
| 991 | default: assert(0); | 1010 | default: assert(0); |
| 992 | } | 1011 | } |
| 993 | } | 1012 | } |
| @@ -1010,7 +1029,7 @@ static void peephole (CompileState *compst) { | |||
| 1010 | switch (code[i].i.code) { | 1029 | switch (code[i].i.code) { |
| 1011 | case IChoice: case ICall: case ICommit: case IPartialCommit: | 1030 | case IChoice: case ICall: case ICommit: case IPartialCommit: |
| 1012 | case IBackCommit: case ITestChar: case ITestSet: | 1031 | case IBackCommit: case ITestChar: case ITestSet: |
| 1013 | case IRecov: /* labeled failure */ | 1032 | case IRecov: case ILabChoice: /* labeled failure */ |
| 1014 | case ITestAny: { /* instructions with labels */ | 1033 | case ITestAny: { /* instructions with labels */ |
| 1015 | jumptothere(compst, i, finallabel(code, i)); /* optimize label */ | 1034 | jumptothere(compst, i, finallabel(code, i)); /* optimize label */ |
| 1016 | break; | 1035 | break; |
| @@ -61,7 +61,7 @@ void printinst (const Instruction *op, const Instruction *p) { | |||
| 61 | "choice", "jmp", "call", "open_call", | 61 | "choice", "jmp", "call", "open_call", |
| 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", "recovery" /* labeled failure */ | 64 | "throw", "recovery", "labeled_choice" /* labeled failure */ |
| 65 | }; | 65 | }; |
| 66 | printf("%02ld: %s ", (long)(p - op), names[p->i.code]); | 66 | printf("%02ld: %s ", (long)(p - op), names[p->i.code]); |
| 67 | switch ((Opcode)p->i.code) { | 67 | switch ((Opcode)p->i.code) { |
| @@ -111,7 +111,7 @@ void printinst (const Instruction *op, const Instruction *p) { | |||
| 111 | printf("%d", p->i.aux); | 111 | printf("%d", p->i.aux); |
| 112 | break; | 112 | break; |
| 113 | } | 113 | } |
| 114 | case IRecov: { /* labeled failure */ | 114 | case IRecov: case ILabChoice: { /* labeled failure */ |
| 115 | printjmp(op, p); | 115 | printjmp(op, p); |
| 116 | printcharset((p+2)->buff); | 116 | printcharset((p+2)->buff); |
| 117 | break; | 117 | break; |
| @@ -164,7 +164,7 @@ static const char *tagnames[] = { | |||
| 164 | "call", "opencall", "rule", "grammar", | 164 | "call", "opencall", "rule", "grammar", |
| 165 | "behind", | 165 | "behind", |
| 166 | "capture", "run-time", | 166 | "capture", "run-time", |
| 167 | "throw", "labeled-choice", "recov" /* labeled failure */ | 167 | "throw", "recov", "labeled-choice" /* labeled failure */ |
| 168 | }; | 168 | }; |
| 169 | 169 | ||
| 170 | 170 | ||
| @@ -223,7 +223,7 @@ void printtree (TTree *tree, int ident) { | |||
| 223 | default: { | 223 | default: { |
| 224 | int sibs = numsiblings[tree->tag]; | 224 | int sibs = numsiblings[tree->tag]; |
| 225 | printf("\n"); | 225 | printf("\n"); |
| 226 | if (tree->tag == TRecov) { /* labeled failure */ | 226 | if (tree->tag == TRecov || tree->tag == TLabChoice) { /* labeled failure */ |
| 227 | printcharset(treelabelset(tree)); | 227 | printcharset(treelabelset(tree)); |
| 228 | printf("\n"); | 228 | printf("\n"); |
| 229 | } | 229 | } |
| @@ -28,7 +28,7 @@ const byte numsiblings[] = { | |||
| 28 | 0, 0, 2, 1, /* call, opencall, rule, grammar */ | 28 | 0, 0, 2, 1, /* call, opencall, rule, grammar */ |
| 29 | 1, /* behind */ | 29 | 1, /* behind */ |
| 30 | 1, 1, /* capture, runtime capture */ | 30 | 1, 1, /* capture, runtime capture */ |
| 31 | 0, 2 /* labeled failure throw, recovery */ | 31 | 0, 2, 2 /* labeled failure throw, recovery, labeled choice */ |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | 34 | ||
| @@ -734,16 +734,28 @@ static int lp_throw (lua_State *L) { | |||
| 734 | static int lp_recovery (lua_State *L) { | 734 | static int lp_recovery (lua_State *L) { |
| 735 | int n = lua_gettop(L); | 735 | int n = lua_gettop(L); |
| 736 | TTree *tree = newrootlab2sib(L, TRecov); | 736 | TTree *tree = newrootlab2sib(L, TRecov); |
| 737 | int i; | ||
| 737 | luaL_argcheck(L, n >= 3, 3, "non-nil value expected"); | 738 | luaL_argcheck(L, n >= 3, 3, "non-nil value expected"); |
| 738 | if (n == 2) { /* catches fail as default */ | 739 | for (i = 3; i <= n; i++) { |
| 739 | /*setlabel(treelabelset(tree), LFAIL); recovery does not catch regular fail */ | 740 | int d = luaL_checkinteger(L, i); |
| 740 | } else { | 741 | luaL_argcheck(L, d >= 1 && d < MAXLABELS, i, "the number of a label must be between 1 and 255"); |
| 741 | int i; | 742 | setlabel(treelabelset(tree), (byte)d); |
| 742 | for (i = 3; i <= n; i++) { | 743 | } |
| 743 | int d = luaL_checkinteger(L, i); | 744 | return 1; |
| 744 | luaL_argcheck(L, d >= 1 && d < MAXLABELS, i, "the number of a label must be between 1 and 255"); | 745 | } |
| 745 | setlabel(treelabelset(tree), (byte)d); | 746 | |
| 746 | } | 747 | |
| 748 | /* | ||
| 749 | ** labeled choice function | ||
| 750 | */ | ||
| 751 | static int lp_labchoice (lua_State *L) { | ||
| 752 | int n = lua_gettop(L); | ||
| 753 | TTree *tree = newrootlab2sib(L, TLabChoice); | ||
| 754 | int i; | ||
| 755 | for (i = 3; i <= n; i++) { | ||
| 756 | int d = luaL_checkinteger(L, i); | ||
| 757 | luaL_argcheck(L, d >= 1 && d < MAXLABELS, i, "the number of a label must be between 1 and 255"); | ||
| 758 | setlabel(treelabelset(tree), (byte)d); | ||
| 747 | } | 759 | } |
| 748 | return 1; | 760 | return 1; |
| 749 | } | 761 | } |
| @@ -1083,7 +1095,7 @@ static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed, | |||
| 1083 | return nb; | 1095 | return nb; |
| 1084 | /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */ | 1096 | /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */ |
| 1085 | tree = sib2(tree); goto tailcall; | 1097 | tree = sib2(tree); goto tailcall; |
| 1086 | case TChoice: case TRecov: /* must check both children */ /* labeled failure */ | 1098 | case TChoice: case TRecov: case TLabChoice: /* must check both children */ /* labeled failure */ |
| 1087 | nb = verifyrule(L, sib1(tree), passed, npassed, nb); | 1099 | nb = verifyrule(L, sib1(tree), passed, npassed, nb); |
| 1088 | /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ | 1100 | /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ |
| 1089 | tree = sib2(tree); goto tailcall; | 1101 | tree = sib2(tree); goto tailcall; |
| @@ -1337,6 +1349,7 @@ static struct luaL_Reg pattreg[] = { | |||
| 1337 | {"type", lp_type}, | 1349 | {"type", lp_type}, |
| 1338 | {"T", lp_throw}, /* labeled failure throw */ | 1350 | {"T", lp_throw}, /* labeled failure throw */ |
| 1339 | {"Rec", lp_recovery}, /* labeled failure recovery */ | 1351 | {"Rec", lp_recovery}, /* labeled failure recovery */ |
| 1352 | {"Lc", lp_labchoice}, /* labeled failure choice */ | ||
| 1340 | {NULL, NULL} | 1353 | {NULL, NULL} |
| 1341 | }; | 1354 | }; |
| 1342 | 1355 | ||
| @@ -36,7 +36,9 @@ typedef enum TTag { | |||
| 36 | TRunTime, /* run-time capture: 'key' is Lua function; | 36 | TRunTime, /* run-time capture: 'key' is Lua function; |
| 37 | 'sib1' is capture body */ | 37 | 'sib1' is capture body */ |
| 38 | TThrow, /* labeled failure: 'label' = l */ | 38 | TThrow, /* labeled failure: 'label' = l */ |
| 39 | TRecov /* labed failure: 'sib1' // 'sib2' */ | 39 | TRecov, /* labed failure: 'sib1' //{labels} 'sib2' */ |
| 40 | /* the set of labels is stored in next CHARSETSIZE bytes */ | ||
| 41 | TLabChoice /* labed failure: 'sib1' /{labels} 'sib2' */ | ||
| 40 | /* the set of labels is stored in next CHARSETSIZE bytes */ | 42 | /* the set of labels is stored in next CHARSETSIZE bytes */ |
| 41 | } TTag; | 43 | } TTag; |
| 42 | 44 | ||
| @@ -277,6 +277,17 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
| 277 | p += 2; | 277 | p += 2; |
| 278 | continue; | 278 | continue; |
| 279 | } | 279 | } |
| 280 | case ILabChoice: { /* labeled failure */ | ||
| 281 | if (stack == stacklimit) | ||
| 282 | stack = doublestack(L, &stacklimit, ptop); | ||
| 283 | stack->p = p + getoffset(p); | ||
| 284 | stack->s = s; | ||
| 285 | stack->ls = (const Labelset *) ((p + 2)->buff); | ||
| 286 | stack->caplevel = captop; | ||
| 287 | stack++; | ||
| 288 | p += (CHARSETINSTSIZE - 1) + 2; | ||
| 289 | continue; | ||
| 290 | } | ||
| 280 | case IRecov: { /* labeled failure */ | 291 | case IRecov: { /* labeled failure */ |
| 281 | if (stack == stacklimit) | 292 | if (stack == stacklimit) |
| 282 | stack = doublestack(L, &stacklimit, ptop); | 293 | stack = doublestack(L, &stacklimit, ptop); |
| @@ -35,7 +35,8 @@ typedef enum Opcode { | |||
| 35 | ICloseCapture, | 35 | ICloseCapture, |
| 36 | ICloseRunTime, | 36 | ICloseRunTime, |
| 37 | IThrow, /* "fails" with a specific label labeled failure */ | 37 | IThrow, /* "fails" with a specific label labeled failure */ |
| 38 | IRecov /* stack a recovery; next fail with label 'f' will jump to 'offset' */ | 38 | IRecov, /* stack a recovery; next fail with label 'f' will jump to 'offset' */ |
| 39 | ILabChoice /* stack a choice; next fail with label 'f' will jump to 'offset' */ | ||
| 39 | } Opcode; | 40 | } Opcode; |
| 40 | 41 | ||
| 41 | 42 | ||
diff --git a/relabel.lua b/relabel.lua index b02c95d..cfe5f2e 100644 --- a/relabel.lua +++ b/relabel.lua | |||
| @@ -31,7 +31,7 @@ local errinfo = { | |||
| 31 | {"NoPatt", "no pattern found"}, | 31 | {"NoPatt", "no pattern found"}, |
| 32 | {"ExtraChars", "unexpected characters after the pattern"}, | 32 | {"ExtraChars", "unexpected characters after the pattern"}, |
| 33 | 33 | ||
| 34 | {"ExpPatt1", "expected a pattern after '/' or '//{...}'"}, | 34 | {"ExpPatt1", "expected a pattern after '/' and '//{...}', or the label(s) after '/{' and '//{'"}, |
| 35 | 35 | ||
| 36 | {"ExpPatt2", "expected a pattern after '&'"}, | 36 | {"ExpPatt2", "expected a pattern after '&'"}, |
| 37 | {"ExpPatt3", "expected a pattern after '!'"}, | 37 | {"ExpPatt3", "expected a pattern after '!'"}, |
| @@ -221,10 +221,28 @@ local function choicerec (...) | |||
| 221 | local n = #t | 221 | local n = #t |
| 222 | local p = t[1] | 222 | local p = t[1] |
| 223 | local i = 2 | 223 | local i = 2 |
| 224 | while i + 1 <= n do | 224 | --print("eu") |
| 225 | -- t[i] == false when there are no labels | 225 | --for i, v in ipairs(t) do |
| 226 | p = t[i] and mm.Rec(p, t[i+1], unpack(t[i])) or mt.__add(p, t[i+1]) | 226 | -- print(i, v) |
| 227 | i = i + 2 | 227 | --end |
| 228 | --print"fim" | ||
| 229 | |||
| 230 | while i + 2 <= n do | ||
| 231 | -- t[i] is '/' or '//' | ||
| 232 | -- t[i+1] == false when there are no labels | ||
| 233 | -- t[i+2] is a pattern | ||
| 234 | if t[i] == '/' then | ||
| 235 | if not t[i+1] then | ||
| 236 | p = mt.__add(p, t[i+2]) | ||
| 237 | --print("foi aqui", t[i], t[i+1], t[i+2]) | ||
| 238 | --p:pcode() | ||
| 239 | else | ||
| 240 | p = mm.Lc(p, t[i+2], unpack(t[i+1])) | ||
| 241 | end | ||
| 242 | else -- t[i] is '//' | ||
| 243 | p = mm.Rec(p, t[i+2], unpack(t[i+1])) | ||
| 244 | end | ||
| 245 | i = i + 3 | ||
| 228 | end | 246 | end |
| 229 | 247 | ||
| 230 | return p | 248 | return p |
| @@ -232,7 +250,7 @@ end | |||
| 232 | 250 | ||
| 233 | local exp = m.P{ "Exp", | 251 | local exp = m.P{ "Exp", |
| 234 | Exp = S * ( m.V"Grammar" | 252 | Exp = S * ( m.V"Grammar" |
| 235 | + (m.V"Seq" * (S * (("//" * m.Ct(m.V"Labels")) + ("/" * m.Cc(false))) | 253 | + (m.V"Seq" * (S * ((m.C(m.P"//" + "/") * m.Ct(m.V"Labels")) + (m.C"/" * m.Cc(false))) |
| 236 | * expect(S * m.V"Seq", "ExpPatt1") | 254 | * expect(S * m.V"Seq", "ExpPatt1") |
| 237 | )^0 | 255 | )^0 |
| 238 | ) / choicerec); | 256 | ) / choicerec); |
