From e2a8e1c789a7a769c83a66d6fd2f191b0e465cba Mon Sep 17 00:00:00 2001 From: Sergio Queiroz Date: Thu, 6 Jul 2017 16:01:44 -0300 Subject: Reintroducing the labeled ordered choice (tests without it passed) --- lpcode.c | 35 +++++++++++++++++++++++++++-------- lpprint.c | 8 ++++---- lptree.c | 35 ++++++++++++++++++++++++----------- lptree.h | 4 +++- lpvm.c | 11 +++++++++++ lpvm.h | 3 ++- relabel.lua | 30 ++++++++++++++++++++++++------ 7 files changed, 95 insertions(+), 31 deletions(-) diff --git a/lpcode.c b/lpcode.c index a5cf2e2..f335dcb 100644 --- a/lpcode.c +++ b/lpcode.c @@ -220,7 +220,7 @@ int checkaux (TTree *tree, int pred) { if (checkaux(sib2(tree), pred)) return 1; /* else return checkaux(sib1(tree), pred); */ tree = sib1(tree); goto tailcall; - case TRecov: /* labeled failure */ + case TRecov: case TLabChoice: /* labeled failure */ /* we do not know whether sib2 will be evaluated */ tree = sib1(tree); goto tailcall; case TCapture: case TGrammar: case TRule: @@ -264,7 +264,7 @@ int fixedlen (TTree *tree) { /* else return fixedlen(sib2(tree)) + len; */ len += n1; tree = sib2(tree); goto tailcall; } - case TChoice: { + case TChoice: case TLabChoice: { /* labeled failure */ int n1 = fixedlen(sib1(tree)); int n2 = fixedlen(sib2(tree)); if (n1 != n2 || n1 < 0) @@ -314,7 +314,7 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) { loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */ return 1; } - case TChoice: { + case TChoice: case TLabChoice: { /*(?) labeled failure */ Charset csaux; int e1 = getfirst(sib1(tree), follow, firstset); int e2 = getfirst(sib2(tree), follow, &csaux); @@ -405,7 +405,7 @@ static int headfail (TTree *tree) { if (!nofail(sib2(tree))) return 0; /* else return headfail(sib1(tree)); */ tree = sib1(tree); goto tailcall; - case TChoice: case TRecov: /* labeled failure */ + case TChoice: case TRecov: case TLabChoice: /* labeled failure */ if (!headfail(sib1(tree))) return 0; /* else return headfail(sib2(tree)); */ tree = sib2(tree); goto tailcall; @@ -425,7 +425,7 @@ static int needfollow (TTree *tree) { case TChar: case TSet: case TAny: case TFalse: case TTrue: case TAnd: case TNot: case TRunTime: case TGrammar: case TCall: case TBehind: - case TThrow: case TRecov: /* (?)labeled failure */ + case TThrow: case TRecov: case TLabChoice: /* (?)labeled failure */ return 0; case TChoice: case TRep: return 1; @@ -460,7 +460,7 @@ int sizei (const Instruction *i) { return 2; case IThrow: /* labeled failure */ return 1; - case IRecov: + case IRecov: case ILabChoice: return (CHARSETINSTSIZE - 1) + 2; /* labeled failure */ default: return 1; @@ -527,7 +527,7 @@ static int addoffsetinst (CompileState *compst, Opcode op) { int i = addinstruction(compst, op, 0); /* instruction */ addinstruction(compst, (Opcode)0, 0); /* open space for offset */ assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2 || - op == IRecov); /* labeled failure */ + op == IRecov || op == ILabChoice); /* labeled failure */ return i; } @@ -750,6 +750,21 @@ static void coderecovery (CompileState *compst, TTree *p1, TTree *p2, int opt, addinstruction(compst, IRet, 0); jumptohere(compst, pcommit); } + +static void codelabchoice (CompileState *compst, TTree *p1, TTree *p2, int opt, + const Charset *fl, const byte *cs) { + int emptyp2 = (p2->tag == TTrue); + int pcommit; + int test = NOINST; + int pchoice = addoffsetinst(compst, ILabChoice); + addcharset(compst, cs); + codegen(compst, p1, emptyp2, test, fullset); + pcommit = addoffsetinst(compst, ICommit); + jumptohere(compst, pchoice); + jumptohere(compst, test); + codegen(compst, p2, opt, NOINST, fl); + jumptohere(compst, pcommit); +} /* labeled failure end */ @@ -988,6 +1003,10 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt, coderecovery(compst, sib1(tree), sib2(tree), opt, fl, treelabelset(tree)); break; } + case TLabChoice: { /* labeled failure */ + codelabchoice(compst, sib1(tree), sib2(tree), opt, fl, treelabelset(tree)); + break; + } default: assert(0); } } @@ -1010,7 +1029,7 @@ static void peephole (CompileState *compst) { switch (code[i].i.code) { case IChoice: case ICall: case ICommit: case IPartialCommit: case IBackCommit: case ITestChar: case ITestSet: - case IRecov: /* labeled failure */ + case IRecov: case ILabChoice: /* labeled failure */ case ITestAny: { /* instructions with labels */ jumptothere(compst, i, finallabel(code, i)); /* optimize label */ break; diff --git a/lpprint.c b/lpprint.c index ecaa7f1..342a2b6 100644 --- a/lpprint.c +++ b/lpprint.c @@ -61,7 +61,7 @@ void printinst (const Instruction *op, const Instruction *p) { "choice", "jmp", "call", "open_call", "commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup", "fullcapture", "opencapture", "closecapture", "closeruntime", - "throw", "recovery" /* labeled failure */ + "throw", "recovery", "labeled_choice" /* labeled failure */ }; printf("%02ld: %s ", (long)(p - op), names[p->i.code]); switch ((Opcode)p->i.code) { @@ -111,7 +111,7 @@ void printinst (const Instruction *op, const Instruction *p) { printf("%d", p->i.aux); break; } - case IRecov: { /* labeled failure */ + case IRecov: case ILabChoice: { /* labeled failure */ printjmp(op, p); printcharset((p+2)->buff); break; @@ -164,7 +164,7 @@ static const char *tagnames[] = { "call", "opencall", "rule", "grammar", "behind", "capture", "run-time", - "throw", "labeled-choice", "recov" /* labeled failure */ + "throw", "recov", "labeled-choice" /* labeled failure */ }; @@ -223,7 +223,7 @@ void printtree (TTree *tree, int ident) { default: { int sibs = numsiblings[tree->tag]; printf("\n"); - if (tree->tag == TRecov) { /* labeled failure */ + if (tree->tag == TRecov || tree->tag == TLabChoice) { /* labeled failure */ printcharset(treelabelset(tree)); printf("\n"); } diff --git a/lptree.c b/lptree.c index fcf5ff9..19d6b1a 100644 --- a/lptree.c +++ b/lptree.c @@ -28,7 +28,7 @@ const byte numsiblings[] = { 0, 0, 2, 1, /* call, opencall, rule, grammar */ 1, /* behind */ 1, 1, /* capture, runtime capture */ - 0, 2 /* labeled failure throw, recovery */ + 0, 2, 2 /* labeled failure throw, recovery, labeled choice */ }; @@ -734,16 +734,28 @@ static int lp_throw (lua_State *L) { static int lp_recovery (lua_State *L) { int n = lua_gettop(L); TTree *tree = newrootlab2sib(L, TRecov); + int i; luaL_argcheck(L, n >= 3, 3, "non-nil value expected"); - if (n == 2) { /* catches fail as default */ - /*setlabel(treelabelset(tree), LFAIL); recovery does not catch regular fail */ - } else { - int i; - for (i = 3; i <= n; i++) { - int d = luaL_checkinteger(L, i); - luaL_argcheck(L, d >= 1 && d < MAXLABELS, i, "the number of a label must be between 1 and 255"); - setlabel(treelabelset(tree), (byte)d); - } + for (i = 3; i <= n; i++) { + int d = luaL_checkinteger(L, i); + luaL_argcheck(L, d >= 1 && d < MAXLABELS, i, "the number of a label must be between 1 and 255"); + setlabel(treelabelset(tree), (byte)d); + } + return 1; +} + + +/* +** labeled choice function +*/ +static int lp_labchoice (lua_State *L) { + int n = lua_gettop(L); + TTree *tree = newrootlab2sib(L, TLabChoice); + int i; + for (i = 3; i <= n; i++) { + int d = luaL_checkinteger(L, i); + luaL_argcheck(L, d >= 1 && d < MAXLABELS, i, "the number of a label must be between 1 and 255"); + setlabel(treelabelset(tree), (byte)d); } return 1; } @@ -1083,7 +1095,7 @@ static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed, return nb; /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */ tree = sib2(tree); goto tailcall; - case TChoice: case TRecov: /* must check both children */ /* labeled failure */ + case TChoice: case TRecov: case TLabChoice: /* must check both children */ /* labeled failure */ nb = verifyrule(L, sib1(tree), passed, npassed, nb); /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ tree = sib2(tree); goto tailcall; @@ -1337,6 +1349,7 @@ static struct luaL_Reg pattreg[] = { {"type", lp_type}, {"T", lp_throw}, /* labeled failure throw */ {"Rec", lp_recovery}, /* labeled failure recovery */ + {"Lc", lp_labchoice}, /* labeled failure choice */ {NULL, NULL} }; diff --git a/lptree.h b/lptree.h index e4e8901..d89da4d 100644 --- a/lptree.h +++ b/lptree.h @@ -36,7 +36,9 @@ typedef enum TTag { TRunTime, /* run-time capture: 'key' is Lua function; 'sib1' is capture body */ TThrow, /* labeled failure: 'label' = l */ - TRecov /* labed failure: 'sib1' // 'sib2' */ + TRecov, /* labed failure: 'sib1' //{labels} 'sib2' */ + /* the set of labels is stored in next CHARSETSIZE bytes */ + TLabChoice /* labed failure: 'sib1' /{labels} 'sib2' */ /* the set of labels is stored in next CHARSETSIZE bytes */ } TTag; diff --git a/lpvm.c b/lpvm.c index 911b4c5..d2b1f55 100644 --- a/lpvm.c +++ b/lpvm.c @@ -277,6 +277,17 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, p += 2; continue; } + case ILabChoice: { /* labeled failure */ + if (stack == stacklimit) + stack = doublestack(L, &stacklimit, ptop); + stack->p = p + getoffset(p); + stack->s = s; + stack->ls = (const Labelset *) ((p + 2)->buff); + stack->caplevel = captop; + stack++; + p += (CHARSETINSTSIZE - 1) + 2; + continue; + } case IRecov: { /* labeled failure */ if (stack == stacklimit) stack = doublestack(L, &stacklimit, ptop); diff --git a/lpvm.h b/lpvm.h index bcfc22f..713626e 100644 --- a/lpvm.h +++ b/lpvm.h @@ -35,7 +35,8 @@ typedef enum Opcode { ICloseCapture, ICloseRunTime, IThrow, /* "fails" with a specific label labeled failure */ - IRecov /* stack a recovery; next fail with label 'f' will jump to 'offset' */ + IRecov, /* stack a recovery; next fail with label 'f' will jump to 'offset' */ + ILabChoice /* stack a choice; next fail with label 'f' will jump to 'offset' */ } Opcode; diff --git a/relabel.lua b/relabel.lua index b02c95d..cfe5f2e 100644 --- a/relabel.lua +++ b/relabel.lua @@ -31,7 +31,7 @@ local errinfo = { {"NoPatt", "no pattern found"}, {"ExtraChars", "unexpected characters after the pattern"}, - {"ExpPatt1", "expected a pattern after '/' or '//{...}'"}, + {"ExpPatt1", "expected a pattern after '/' and '//{...}', or the label(s) after '/{' and '//{'"}, {"ExpPatt2", "expected a pattern after '&'"}, {"ExpPatt3", "expected a pattern after '!'"}, @@ -221,10 +221,28 @@ local function choicerec (...) local n = #t local p = t[1] local i = 2 - while i + 1 <= n do - -- t[i] == false when there are no labels - p = t[i] and mm.Rec(p, t[i+1], unpack(t[i])) or mt.__add(p, t[i+1]) - i = i + 2 + --print("eu") + --for i, v in ipairs(t) do + -- print(i, v) + --end + --print"fim" + + while i + 2 <= n do + -- t[i] is '/' or '//' + -- t[i+1] == false when there are no labels + -- t[i+2] is a pattern + if t[i] == '/' then + if not t[i+1] then + p = mt.__add(p, t[i+2]) + --print("foi aqui", t[i], t[i+1], t[i+2]) + --p:pcode() + else + p = mm.Lc(p, t[i+2], unpack(t[i+1])) + end + else -- t[i] is '//' + p = mm.Rec(p, t[i+2], unpack(t[i+1])) + end + i = i + 3 end return p @@ -232,7 +250,7 @@ end local exp = m.P{ "Exp", Exp = S * ( m.V"Grammar" - + (m.V"Seq" * (S * (("//" * m.Ct(m.V"Labels")) + ("/" * m.Cc(false))) + + (m.V"Seq" * (S * ((m.C(m.P"//" + "/") * m.Ct(m.V"Labels")) + (m.C"/" * m.Cc(false))) * expect(S * m.V"Seq", "ExpPatt1") )^0 ) / choicerec); -- cgit v1.2.3-55-g6feb