diff options
author | Sergio <sqmedeiros@gmail.com> | 2019-06-21 18:07:07 -0300 |
---|---|---|
committer | Sergio <sqmedeiros@gmail.com> | 2019-06-21 18:07:07 -0300 |
commit | 0671e873f50ba568074d1683e068d5dce88dd43b (patch) | |
tree | 373f46d1c3fac997803835155a5ba764bbcbd250 | |
parent | 0f48dada44ec37bec8ef1b44ef8b621716ca5c05 (diff) | |
download | lpeglabel-0671e873f50ba568074d1683e068d5dce88dd43b.tar.gz lpeglabel-0671e873f50ba568074d1683e068d5dce88dd43b.tar.bz2 lpeglabel-0671e873f50ba568074d1683e068d5dce88dd43b.zip |
Updating LPegLabel to the codebase of LPeg 1.0.2
-rw-r--r-- | lpcap.c | 64 | ||||
-rw-r--r-- | lpcap.h | 3 | ||||
-rw-r--r-- | lpcode.c | 2 | ||||
-rw-r--r-- | lpcode.h | 2 | ||||
-rw-r--r-- | lpprint.c | 2 | ||||
-rw-r--r-- | lpprint.h | 2 | ||||
-rw-r--r-- | lptree.c | 18 | ||||
-rw-r--r-- | lptree.h | 2 | ||||
-rw-r--r-- | lptypes.h | 10 | ||||
-rw-r--r-- | lpvm.c | 88 | ||||
-rw-r--r-- | lpvm.h | 2 | ||||
-rw-r--r-- | relabel.lua | 34 | ||||
-rwxr-xr-x | test.lua | 22 |
13 files changed, 152 insertions, 99 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $ | 2 | ** $Id: lpcap.c $ |
3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) | 3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -271,15 +271,15 @@ int finddyncap (Capture *cap, Capture *last) { | |||
271 | 271 | ||
272 | 272 | ||
273 | /* | 273 | /* |
274 | ** Calls a runtime capture. Returns number of captures removed by | 274 | ** Calls a runtime capture. Returns number of captures "removed" by the |
275 | ** the call, including the initial Cgroup. (Captures to be added are | 275 | ** call, that is, those inside the group capture. Captures to be added |
276 | ** on the Lua stack.) | 276 | ** are on the Lua stack. |
277 | */ | 277 | */ |
278 | int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) { | 278 | int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) { |
279 | int n, id; | 279 | int n, id; |
280 | lua_State *L = cs->L; | 280 | lua_State *L = cs->L; |
281 | int otop = lua_gettop(L); | 281 | int otop = lua_gettop(L); |
282 | Capture *open = findopen(close); | 282 | Capture *open = findopen(close); /* get open group capture */ |
283 | assert(captype(open) == Cgroup); | 283 | assert(captype(open) == Cgroup); |
284 | id = finddyncap(open, close); /* get first dynamic capture argument */ | 284 | id = finddyncap(open, close); /* get first dynamic capture argument */ |
285 | close->kind = Cclose; /* closes the group */ | 285 | close->kind = Cclose; /* closes the group */ |
@@ -299,7 +299,7 @@ int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) { | |||
299 | } | 299 | } |
300 | else | 300 | else |
301 | *rem = 0; /* no dynamic captures removed */ | 301 | *rem = 0; /* no dynamic captures removed */ |
302 | return close - open; /* number of captures of all kinds removed */ | 302 | return close - open - 1; /* number of captures to be removed */ |
303 | } | 303 | } |
304 | 304 | ||
305 | 305 | ||
@@ -441,70 +441,88 @@ static int addonestring (luaL_Buffer *b, CapState *cs, const char *what) { | |||
441 | } | 441 | } |
442 | 442 | ||
443 | 443 | ||
444 | #if !defined(MAXRECLEVEL) | ||
445 | #define MAXRECLEVEL 200 | ||
446 | #endif | ||
447 | |||
448 | |||
444 | /* | 449 | /* |
445 | ** Push all values of the current capture into the stack; returns | 450 | ** Push all values of the current capture into the stack; returns |
446 | ** number of values pushed | 451 | ** number of values pushed |
447 | */ | 452 | */ |
448 | static int pushcapture (CapState *cs) { | 453 | static int pushcapture (CapState *cs) { |
449 | lua_State *L = cs->L; | 454 | lua_State *L = cs->L; |
455 | int res; | ||
450 | luaL_checkstack(L, 4, "too many captures"); | 456 | luaL_checkstack(L, 4, "too many captures"); |
457 | if (cs->reclevel++ > MAXRECLEVEL) | ||
458 | return luaL_error(L, "subcapture nesting too deep"); | ||
451 | switch (captype(cs->cap)) { | 459 | switch (captype(cs->cap)) { |
452 | case Cposition: { | 460 | case Cposition: { |
453 | lua_pushinteger(L, cs->cap->s - cs->s + 1); | 461 | lua_pushinteger(L, cs->cap->s - cs->s + 1); |
454 | cs->cap++; | 462 | cs->cap++; |
455 | return 1; | 463 | res = 1; |
464 | break; | ||
456 | } | 465 | } |
457 | case Cconst: { | 466 | case Cconst: { |
458 | pushluaval(cs); | 467 | pushluaval(cs); |
459 | cs->cap++; | 468 | cs->cap++; |
460 | return 1; | 469 | res = 1; |
470 | break; | ||
461 | } | 471 | } |
462 | case Carg: { | 472 | case Carg: { |
463 | int arg = (cs->cap++)->idx; | 473 | int arg = (cs->cap++)->idx; |
464 | if (arg + FIXEDARGS > cs->ptop) | 474 | if (arg + FIXEDARGS > cs->ptop) |
465 | return luaL_error(L, "reference to absent extra argument #%d", arg); | 475 | return luaL_error(L, "reference to absent extra argument #%d", arg); |
466 | lua_pushvalue(L, arg + FIXEDARGS); | 476 | lua_pushvalue(L, arg + FIXEDARGS); |
467 | return 1; | 477 | res = 1; |
478 | break; | ||
468 | } | 479 | } |
469 | case Csimple: { | 480 | case Csimple: { |
470 | int k = pushnestedvalues(cs, 1); | 481 | int k = pushnestedvalues(cs, 1); |
471 | lua_insert(L, -k); /* make whole match be first result */ | 482 | lua_insert(L, -k); /* make whole match be first result */ |
472 | return k; | 483 | res = k; |
484 | break; | ||
473 | } | 485 | } |
474 | case Cruntime: { | 486 | case Cruntime: { |
475 | lua_pushvalue(L, (cs->cap++)->idx); /* value is in the stack */ | 487 | lua_pushvalue(L, (cs->cap++)->idx); /* value is in the stack */ |
476 | return 1; | 488 | res = 1; |
489 | break; | ||
477 | } | 490 | } |
478 | case Cstring: { | 491 | case Cstring: { |
479 | luaL_Buffer b; | 492 | luaL_Buffer b; |
480 | luaL_buffinit(L, &b); | 493 | luaL_buffinit(L, &b); |
481 | stringcap(&b, cs); | 494 | stringcap(&b, cs); |
482 | luaL_pushresult(&b); | 495 | luaL_pushresult(&b); |
483 | return 1; | 496 | res = 1; |
497 | break; | ||
484 | } | 498 | } |
485 | case Csubst: { | 499 | case Csubst: { |
486 | luaL_Buffer b; | 500 | luaL_Buffer b; |
487 | luaL_buffinit(L, &b); | 501 | luaL_buffinit(L, &b); |
488 | substcap(&b, cs); | 502 | substcap(&b, cs); |
489 | luaL_pushresult(&b); | 503 | luaL_pushresult(&b); |
490 | return 1; | 504 | res = 1; |
505 | break; | ||
491 | } | 506 | } |
492 | case Cgroup: { | 507 | case Cgroup: { |
493 | if (cs->cap->idx == 0) /* anonymous group? */ | 508 | if (cs->cap->idx == 0) /* anonymous group? */ |
494 | return pushnestedvalues(cs, 0); /* add all nested values */ | 509 | res = pushnestedvalues(cs, 0); /* add all nested values */ |
495 | else { /* named group: add no values */ | 510 | else { /* named group: add no values */ |
496 | nextcap(cs); /* skip capture */ | 511 | nextcap(cs); /* skip capture */ |
497 | return 0; | 512 | res = 0; |
498 | } | 513 | } |
514 | break; | ||
499 | } | 515 | } |
500 | case Cbackref: return backrefcap(cs); | 516 | case Cbackref: res = backrefcap(cs); break; |
501 | case Ctable: return tablecap(cs); | 517 | case Ctable: res = tablecap(cs); break; |
502 | case Cfunction: return functioncap(cs); | 518 | case Cfunction: res = functioncap(cs); break; |
503 | case Cnum: return numcap(cs); | 519 | case Cnum: res = numcap(cs); break; |
504 | case Cquery: return querycap(cs); | 520 | case Cquery: res = querycap(cs); break; |
505 | case Cfold: return foldcap(cs); | 521 | case Cfold: res = foldcap(cs); break; |
506 | default: assert(0); return 0; | 522 | default: assert(0); res = 0; |
507 | } | 523 | } |
524 | cs->reclevel--; | ||
525 | return res; | ||
508 | } | 526 | } |
509 | 527 | ||
510 | 528 | ||
@@ -521,7 +539,7 @@ int getcaptures (lua_State *L, const char *s, const char *r, int ptop) { | |||
521 | int n = 0; | 539 | int n = 0; |
522 | if (!isclosecap(capture)) { /* is there any capture? */ | 540 | if (!isclosecap(capture)) { /* is there any capture? */ |
523 | CapState cs; | 541 | CapState cs; |
524 | cs.ocap = cs.cap = capture; cs.L = L; | 542 | cs.ocap = cs.cap = capture; cs.L = L; cs.reclevel = 0; |
525 | cs.s = s; cs.valuecached = 0; cs.ptop = ptop; | 543 | cs.s = s; cs.valuecached = 0; cs.ptop = ptop; |
526 | do { /* collect their values */ | 544 | do { /* collect their values */ |
527 | n += pushcapture(&cs); | 545 | n += pushcapture(&cs); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpcap.h,v 1.3 2016/09/13 17:45:58 roberto Exp $ | 2 | ** $Id: lpcap.h $ |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #if !defined(lpcap_h) | 5 | #if !defined(lpcap_h) |
@@ -44,6 +44,7 @@ typedef struct CapState { | |||
44 | int ptop; /* index of last argument to 'match' */ | 44 | int ptop; /* index of last argument to 'match' */ |
45 | const char *s; /* original string */ | 45 | const char *s; /* original string */ |
46 | int valuecached; /* value stored in cache slot */ | 46 | int valuecached; /* value stored in cache slot */ |
47 | int reclevel; /* recursion level */ | ||
47 | } CapState; | 48 | } CapState; |
48 | 49 | ||
49 | 50 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpcode.c,v 1.24 2016/09/15 17:46:13 roberto Exp $ | 2 | ** $Id: lpcode.c $ |
3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) | 3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpcode.h,v 1.8 2016/09/15 17:46:13 roberto Exp $ | 2 | ** $Id: lpcode.h $ |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #if !defined(lpcode_h) | 5 | #if !defined(lpcode_h) |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpprint.c,v 1.10 2016/09/13 16:06:03 roberto Exp $ | 2 | ** $Id: lpprint.c $ |
3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) | 3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $ | 2 | ** $Id: lpprint.h $ |
3 | */ | 3 | */ |
4 | 4 | ||
5 | 5 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lptree.c,v 1.22 2016/09/13 18:10:22 roberto Exp $ | 2 | ** $Id: lptree.c $ |
3 | ** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license) | 3 | ** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license) |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -750,6 +750,7 @@ static int capture_aux (lua_State *L, int cap, int labelidx) { | |||
750 | 750 | ||
751 | /* | 751 | /* |
752 | ** Fill a tree with an empty capture, using an empty (TTrue) sibling. | 752 | ** Fill a tree with an empty capture, using an empty (TTrue) sibling. |
753 | ** (The 'key' field must be filled by the caller to finish the tree.) | ||
753 | */ | 754 | */ |
754 | static TTree *auxemptycap (TTree *tree, int cap) { | 755 | static TTree *auxemptycap (TTree *tree, int cap) { |
755 | tree->tag = TCapture; | 756 | tree->tag = TCapture; |
@@ -760,15 +761,17 @@ static TTree *auxemptycap (TTree *tree, int cap) { | |||
760 | 761 | ||
761 | 762 | ||
762 | /* | 763 | /* |
763 | ** Create a tree for an empty capture | 764 | ** Create a tree for an empty capture. |
764 | */ | 765 | */ |
765 | static TTree *newemptycap (lua_State *L, int cap) { | 766 | static TTree *newemptycap (lua_State *L, int cap, int key) { |
766 | return auxemptycap(newtree(L, 2), cap); | 767 | TTree *tree = auxemptycap(newtree(L, 2), cap); |
768 | tree->key = key; | ||
769 | return tree; | ||
767 | } | 770 | } |
768 | 771 | ||
769 | 772 | ||
770 | /* | 773 | /* |
771 | ** Create a tree for an empty capture with an associated Lua value | 774 | ** Create a tree for an empty capture with an associated Lua value. |
772 | */ | 775 | */ |
773 | static TTree *newemptycapkey (lua_State *L, int cap, int idx) { | 776 | static TTree *newemptycapkey (lua_State *L, int cap, int idx) { |
774 | TTree *tree = auxemptycap(newtree(L, 2), cap); | 777 | TTree *tree = auxemptycap(newtree(L, 2), cap); |
@@ -829,16 +832,15 @@ static int lp_simplecapture (lua_State *L) { | |||
829 | 832 | ||
830 | 833 | ||
831 | static int lp_poscapture (lua_State *L) { | 834 | static int lp_poscapture (lua_State *L) { |
832 | newemptycap(L, Cposition); | 835 | newemptycap(L, Cposition, 0); |
833 | return 1; | 836 | return 1; |
834 | } | 837 | } |
835 | 838 | ||
836 | 839 | ||
837 | static int lp_argcapture (lua_State *L) { | 840 | static int lp_argcapture (lua_State *L) { |
838 | int n = (int)luaL_checkinteger(L, 1); | 841 | int n = (int)luaL_checkinteger(L, 1); |
839 | TTree *tree = newemptycap(L, Carg); | ||
840 | tree->key = n; | ||
841 | luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index"); | 842 | luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index"); |
843 | newemptycap(L, Carg, n); | ||
842 | return 1; | 844 | return 1; |
843 | } | 845 | } |
844 | 846 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lptree.h,v 1.3 2016/09/13 18:07:51 roberto Exp $ | 2 | ** $Id: lptree.h $ |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #if !defined(lptree_h) | 5 | #if !defined(lptree_h) |
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lptypes.h,v 1.16 2017/01/13 13:33:17 roberto Exp $ | 2 | ** $Id: lptypes.h $ |
3 | ** LPeg - PEG pattern matching for Lua | 3 | ** LPeg - PEG pattern matching for Lua |
4 | ** Copyright 2007-2017, Lua.org & PUC-Rio (see 'lpeg.html' for license) | 4 | ** Copyright 2007-2019, Lua.org & PUC-Rio (see 'lpeg.html' for license) |
5 | ** written by Roberto Ierusalimschy | 5 | ** written by Roberto Ierusalimschy |
6 | */ | 6 | */ |
7 | 7 | ||
@@ -9,17 +9,13 @@ | |||
9 | #define lptypes_h | 9 | #define lptypes_h |
10 | 10 | ||
11 | 11 | ||
12 | #if !defined(LPEG_DEBUG) | ||
13 | #define NDEBUG | ||
14 | #endif | ||
15 | |||
16 | #include <assert.h> | 12 | #include <assert.h> |
17 | #include <limits.h> | 13 | #include <limits.h> |
18 | 14 | ||
19 | #include "lua.h" | 15 | #include "lua.h" |
20 | 16 | ||
21 | 17 | ||
22 | #define VERSION "1.5.1" | 18 | #define VERSION "1.5.2" |
23 | 19 | ||
24 | 20 | ||
25 | #define PATTERN_T "lpeg-pattern" | 21 | #define PATTERN_T "lpeg-pattern" |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpvm.c,v 1.9 2016/06/03 20:11:18 roberto Exp $ | 2 | ** $Id: lpvm.c $ |
3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) | 3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -47,18 +47,29 @@ typedef struct Stack { | |||
47 | 47 | ||
48 | 48 | ||
49 | /* | 49 | /* |
50 | ** Make the size of the array of captures 'cap' twice as large as needed | 50 | ** Ensures the size of array 'capture' (with size '*capsize' and |
51 | ** (which is 'captop'). ('n' is the number of new elements.) | 51 | ** 'captop' elements being used) is enough to accomodate 'n' extra |
52 | ** elements plus one. (Because several opcodes add stuff to the capture | ||
53 | ** array, it is simpler to ensure the array always has at least one free | ||
54 | ** slot upfront and check its size later.) | ||
52 | */ | 55 | */ |
53 | static Capture *doublecap (lua_State *L, Capture *cap, int captop, | 56 | static Capture *growcap (lua_State *L, Capture *capture, int *capsize, |
54 | int n, int ptop) { | 57 | int captop, int n, int ptop) { |
55 | Capture *newc; | 58 | if (*capsize - captop > n) |
56 | if (captop >= INT_MAX/((int)sizeof(Capture) * 2)) | 59 | return capture; /* no need to grow array */ |
57 | luaL_error(L, "too many captures"); | 60 | else { /* must grow */ |
58 | newc = (Capture *)lua_newuserdata(L, captop * 2 * sizeof(Capture)); | 61 | Capture *newc; |
59 | memcpy(newc, cap, (captop - n) * sizeof(Capture)); | 62 | int newsize = captop + n + 1; /* minimum size needed */ |
60 | lua_replace(L, caplistidx(ptop)); | 63 | if (newsize < INT_MAX/((int)sizeof(Capture) * 2)) |
61 | return newc; | 64 | newsize *= 2; /* twice that size, if not too big */ |
65 | else if (newsize >= INT_MAX/((int)sizeof(Capture))) | ||
66 | luaL_error(L, "too many captures"); | ||
67 | newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture)); | ||
68 | memcpy(newc, capture, captop * sizeof(Capture)); | ||
69 | *capsize = newsize; | ||
70 | lua_replace(L, caplistidx(ptop)); | ||
71 | return newc; | ||
72 | } | ||
62 | } | 73 | } |
63 | 74 | ||
64 | 75 | ||
@@ -111,24 +122,24 @@ static int resdyncaptures (lua_State *L, int fr, int curr, int limit) { | |||
111 | 122 | ||
112 | 123 | ||
113 | /* | 124 | /* |
114 | ** Add capture values returned by a dynamic capture to the capture list | 125 | ** Add capture values returned by a dynamic capture to the list |
115 | ** 'base', nested inside a group capture. 'fd' indexes the first capture | 126 | ** 'capture', nested inside a group. 'fd' indexes the first capture |
116 | ** value, 'n' is the number of values (at least 1). | 127 | ** value, 'n' is the number of values (at least 1). The open group |
128 | ** capture is already in 'capture', before the place for the new entries. | ||
117 | */ | 129 | */ |
118 | static void adddyncaptures (const char *s, Capture *base, int n, int fd) { | 130 | static void adddyncaptures (const char *s, Capture *capture, int n, int fd) { |
119 | int i; | 131 | int i; |
120 | base[0].kind = Cgroup; /* create group capture */ | 132 | assert(capture[-1].kind == Cgroup && capture[-1].siz == 0); |
121 | base[0].siz = 0; | 133 | capture[-1].idx = 0; /* make group capture an anonymous group */ |
122 | base[0].idx = 0; /* make it an anonymous group */ | 134 | for (i = 0; i < n; i++) { /* add runtime captures */ |
123 | for (i = 1; i <= n; i++) { /* add runtime captures */ | 135 | capture[i].kind = Cruntime; |
124 | base[i].kind = Cruntime; | 136 | capture[i].siz = 1; /* mark it as closed */ |
125 | base[i].siz = 1; /* mark it as closed */ | 137 | capture[i].idx = fd + i; /* stack index of capture value */ |
126 | base[i].idx = fd + i - 1; /* stack index of capture value */ | 138 | capture[i].s = s; |
127 | base[i].s = s; | ||
128 | } | 139 | } |
129 | base[i].kind = Cclose; /* close group */ | 140 | capture[n].kind = Cclose; /* close group */ |
130 | base[i].siz = 1; | 141 | capture[n].siz = 1; |
131 | base[i].s = s; | 142 | capture[n].s = s; |
132 | } | 143 | } |
133 | 144 | ||
134 | 145 | ||
@@ -374,7 +385,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
374 | CapState cs; | 385 | CapState cs; |
375 | int rem, res, n; | 386 | int rem, res, n; |
376 | int fr = lua_gettop(L) + 1; /* stack index of first result */ | 387 | int fr = lua_gettop(L) + 1; /* stack index of first result */ |
377 | cs.s = o; cs.L = L; cs.ocap = capture; cs.ptop = ptop; | 388 | cs.reclevel = 0; cs.L = L; |
389 | cs.s = o; cs.ocap = capture; cs.ptop = ptop; | ||
378 | n = runtimecap(&cs, capture + captop, s, &rem); /* call function */ | 390 | n = runtimecap(&cs, capture + captop, s, &rem); /* call function */ |
379 | captop -= n; /* remove nested captures */ | 391 | captop -= n; /* remove nested captures */ |
380 | ndyncap -= rem; /* update number of dynamic captures */ | 392 | ndyncap -= rem; /* update number of dynamic captures */ |
@@ -388,15 +400,15 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
388 | s = o + res; /* else update current position */ | 400 | s = o + res; /* else update current position */ |
389 | n = lua_gettop(L) - fr + 1; /* number of new captures */ | 401 | n = lua_gettop(L) - fr + 1; /* number of new captures */ |
390 | ndyncap += n; /* update number of dynamic captures */ | 402 | ndyncap += n; /* update number of dynamic captures */ |
391 | if (n > 0) { /* any new capture? */ | 403 | if (n == 0) /* no new captures? */ |
404 | captop--; /* remove open group */ | ||
405 | else { /* new captures; keep original open group */ | ||
392 | if (fr + n >= SHRT_MAX) | 406 | if (fr + n >= SHRT_MAX) |
393 | luaL_error(L, "too many results in match-time capture"); | 407 | luaL_error(L, "too many results in match-time capture"); |
394 | if ((captop += n + 2) >= capsize) { | 408 | /* add new captures + close group to 'capture' list */ |
395 | capture = doublecap(L, capture, captop, n + 2, ptop); | 409 | capture = growcap(L, capture, &capsize, captop, n + 1, ptop); |
396 | capsize = 2 * captop; | 410 | adddyncaptures(s, capture + captop, n, fr); |
397 | } | 411 | captop += n + 1; /* new captures + close group */ |
398 | /* add new captures to 'capture' list */ | ||
399 | adddyncaptures(s, capture + captop - n - 2, n, fr); | ||
400 | } | 412 | } |
401 | p++; | 413 | p++; |
402 | continue; | 414 | continue; |
@@ -428,10 +440,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
428 | pushcapture: { | 440 | pushcapture: { |
429 | capture[captop].idx = p->i.key; | 441 | capture[captop].idx = p->i.key; |
430 | capture[captop].kind = getkind(p); | 442 | capture[captop].kind = getkind(p); |
431 | if (++captop >= capsize) { | 443 | captop++; |
432 | capture = doublecap(L, capture, captop, 0, ptop); | 444 | capture = growcap(L, capture, &capsize, captop, 0, ptop); |
433 | capsize = 2 * captop; | ||
434 | } | ||
435 | p++; | 445 | p++; |
436 | continue; | 446 | continue; |
437 | } | 447 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpvm.h,v 1.3 2014/02/21 13:06:41 roberto Exp $ | 2 | ** $Id: lpvm.h $ |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #if !defined(lpvm_h) | 5 | #if !defined(lpvm_h) |
diff --git a/relabel.lua b/relabel.lua index f668086..eb71dd0 100644 --- a/relabel.lua +++ b/relabel.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | -- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $ | 1 | -- $Id: re.lua $ |
2 | 2 | ||
3 | -- imported functions and modules | 3 | -- imported functions and modules |
4 | local tonumber, type, print, error = tonumber, type, print, error | 4 | local tonumber, type, print, error = tonumber, type, print, error |
@@ -126,15 +126,6 @@ updatelocale() | |||
126 | local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end) | 126 | local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end) |
127 | 127 | ||
128 | 128 | ||
129 | local function getdef (id, defs) | ||
130 | local c = defs and defs[id] | ||
131 | if not c then | ||
132 | error("undefined name: " .. id) | ||
133 | end | ||
134 | return c | ||
135 | end | ||
136 | |||
137 | |||
138 | local function mult (p, n) | 129 | local function mult (p, n) |
139 | local np = mm.P(true) | 130 | local np = mm.P(true) |
140 | while n >= 1 do | 131 | while n >= 1 do |
@@ -161,6 +152,20 @@ local arrow = S * "<-" | |||
161 | -- a defined name only have meaning in a given environment | 152 | -- a defined name only have meaning in a given environment |
162 | local Def = name * m.Carg(1) | 153 | local Def = name * m.Carg(1) |
163 | 154 | ||
155 | |||
156 | local function getdef (id, defs) | ||
157 | local c = defs and defs[id] | ||
158 | if not c then error("undefined name: " .. id) end | ||
159 | return c | ||
160 | end | ||
161 | |||
162 | -- match a name and return a group of its corresponding definition | ||
163 | -- and 'f' (to be folded in 'Suffix') | ||
164 | local function defwithfunc (f) | ||
165 | return m.Cg(Def / getdef * m.Cc(f)) | ||
166 | end | ||
167 | |||
168 | |||
164 | local num = m.C(m.R"09"^1) * S / tonumber | 169 | local num = m.C(m.R"09"^1) * S / tonumber |
165 | 170 | ||
166 | local String = "'" * m.C((any - "'" - m.P"\n")^0) * expect("'", "MisTerm1") | 171 | local String = "'" * m.C((any - "'" - m.P"\n")^0) * expect("'", "MisTerm1") |
@@ -177,7 +182,7 @@ end | |||
177 | 182 | ||
178 | local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R | 183 | local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R |
179 | 184 | ||
180 | local item = defined + Range + m.C(any - m.P"\n") | 185 | local item = (defined + Range + m.C(any - m.P"\n")) / m.P |
181 | 186 | ||
182 | local Class = | 187 | local Class = |
183 | "[" | 188 | "[" |
@@ -224,12 +229,13 @@ local exp = m.P{ "Exp", | |||
224 | "ExpNumName") | 229 | "ExpNumName") |
225 | + "->" * expect(S * ( m.Cg((String + num) * m.Cc(mt.__div)) | 230 | + "->" * expect(S * ( m.Cg((String + num) * m.Cc(mt.__div)) |
226 | + m.P"{}" * m.Cc(nil, m.Ct) | 231 | + m.P"{}" * m.Cc(nil, m.Ct) |
227 | + m.Cg(Def / getdef * m.Cc(mt.__div)) | 232 | + defwithfunc(mt.__div) |
228 | ), | 233 | ), |
229 | "ExpCap") | 234 | "ExpCap") |
230 | + "=>" * expect(S * m.Cg(Def / getdef * m.Cc(m.Cmt)), | 235 | + "=>" * expect(S * defwithfunc(m.Cmt), |
231 | "ExpName1") | 236 | "ExpName1") |
232 | ) | 237 | + "~>" * S * defwithfunc(m.Cf) |
238 | ) --* S | ||
233 | )^0, function (a,b,f) if f == "lab" then return a + mm.T(b) else return f(a,b) end end ); | 239 | )^0, function (a,b,f) if f == "lab" then return a + mm.T(b) else return f(a,b) end end ); |
234 | Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") | 240 | Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") |
235 | + String / mm.P | 241 | + String / mm.P |
@@ -1,6 +1,6 @@ | |||
1 | #!/usr/bin/env lua | 1 | #!/usr/bin/env lua |
2 | 2 | ||
3 | -- $Id: test.lua,v 1.112 2017/01/14 18:55:22 roberto Exp $ | 3 | -- $Id: test.lua $ |
4 | 4 | ||
5 | -- require"strict" -- just to be pedantic | 5 | -- require"strict" -- just to be pedantic |
6 | 6 | ||
@@ -424,6 +424,16 @@ do | |||
424 | end | 424 | end |
425 | 425 | ||
426 | 426 | ||
427 | do | ||
428 | -- nesting of captures too deep | ||
429 | local p = m.C(1) | ||
430 | for i = 1, 300 do | ||
431 | p = m.Ct(p) | ||
432 | end | ||
433 | checkerr("too deep", p.match, p, "x") | ||
434 | end | ||
435 | |||
436 | |||
427 | -- tests for non-pattern as arguments to pattern functions | 437 | -- tests for non-pattern as arguments to pattern functions |
428 | 438 | ||
429 | p = { ('a' * m.V(1))^-1 } * m.P'b' * { 'a' * m.V(2); m.V(1)^-1 } | 439 | p = { ('a' * m.V(1))^-1 } * m.P'b' * { 'a' * m.V(2); m.V(1)^-1 } |
@@ -1186,6 +1196,9 @@ assert(not match("abbcde", " [b-z] + ")) | |||
1186 | assert(match("abb\"de", '"abb"["]"de"') == 7) | 1196 | assert(match("abb\"de", '"abb"["]"de"') == 7) |
1187 | assert(match("abceeef", "'ac' ? 'ab' * 'c' { 'e' * } / 'abceeef' ") == "eee") | 1197 | assert(match("abceeef", "'ac' ? 'ab' * 'c' { 'e' * } / 'abceeef' ") == "eee") |
1188 | assert(match("abceeef", "'ac'? 'ab'* 'c' { 'f'+ } / 'abceeef' ") == 8) | 1198 | assert(match("abceeef", "'ac'? 'ab'* 'c' { 'f'+ } / 'abceeef' ") == 8) |
1199 | |||
1200 | assert(re.match("aaand", "[a]^2") == 3) | ||
1201 | |||
1189 | local t = {match("abceefe", "( ( & 'e' {} ) ? . ) * ")} | 1202 | local t = {match("abceefe", "( ( & 'e' {} ) ? . ) * ")} |
1190 | checkeq(t, {4, 5, 7}) | 1203 | checkeq(t, {4, 5, 7}) |
1191 | local t = {match("abceefe", "((&&'e' {})? .)*")} | 1204 | local t = {match("abceefe", "((&&'e' {})? .)*")} |
@@ -1360,6 +1373,13 @@ checkeq(x, {tag='x', 'hi', {tag = 'b', 'hello'}, 'but', | |||
1360 | {'totheend'}}) | 1373 | {'totheend'}}) |
1361 | 1374 | ||
1362 | 1375 | ||
1376 | -- test for folding captures | ||
1377 | c = re.compile([[ | ||
1378 | S <- (number (%s+ number)*) ~> add | ||
1379 | number <- %d+ -> tonumber | ||
1380 | ]], {tonumber = tonumber, add = function (a,b) return a + b end}) | ||
1381 | assert(c:match("3 401 50") == 3 + 401 + 50) | ||
1382 | |||
1363 | -- tests for look-ahead captures | 1383 | -- tests for look-ahead captures |
1364 | x = {re.match("alo", "&(&{.}) !{'b'} {&(...)} &{..} {...} {!.}")} | 1384 | x = {re.match("alo", "&(&{.}) !{'b'} {&(...)} &{..} {...} {!.}")} |
1365 | checkeq(x, {"", "alo", ""}) | 1385 | checkeq(x, {"", "alo", ""}) |