aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergio <sqmedeiros@gmail.com>2019-06-21 18:07:07 -0300
committerSergio <sqmedeiros@gmail.com>2019-06-21 18:07:07 -0300
commit0671e873f50ba568074d1683e068d5dce88dd43b (patch)
tree373f46d1c3fac997803835155a5ba764bbcbd250
parent0f48dada44ec37bec8ef1b44ef8b621716ca5c05 (diff)
downloadlpeglabel-0671e873f50ba568074d1683e068d5dce88dd43b.tar.gz
lpeglabel-0671e873f50ba568074d1683e068d5dce88dd43b.tar.bz2
lpeglabel-0671e873f50ba568074d1683e068d5dce88dd43b.zip
Updating LPegLabel to the codebase of LPeg 1.0.2
-rw-r--r--lpcap.c64
-rw-r--r--lpcap.h3
-rw-r--r--lpcode.c2
-rw-r--r--lpcode.h2
-rw-r--r--lpprint.c2
-rw-r--r--lpprint.h2
-rw-r--r--lptree.c18
-rw-r--r--lptree.h2
-rw-r--r--lptypes.h10
-rw-r--r--lpvm.c88
-rw-r--r--lpvm.h2
-rw-r--r--relabel.lua34
-rwxr-xr-xtest.lua22
13 files changed, 152 insertions, 99 deletions
diff --git a/lpcap.c b/lpcap.c
index c9085de..b332fde 100644
--- a/lpcap.c
+++ b/lpcap.c
@@ -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*/
278int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) { 278int 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*/
448static int pushcapture (CapState *cs) { 453static 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);
diff --git a/lpcap.h b/lpcap.h
index 6133df2..dc10d69 100644
--- a/lpcap.h
+++ b/lpcap.h
@@ -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
diff --git a/lpcode.c b/lpcode.c
index 6cf2933..ecc6fa3 100644
--- a/lpcode.c
+++ b/lpcode.c
@@ -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
diff --git a/lpcode.h b/lpcode.h
index 2a5861e..34ee276 100644
--- a/lpcode.h
+++ b/lpcode.h
@@ -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)
diff --git a/lpprint.c b/lpprint.c
index 3c6a8f6..76a7007 100644
--- a/lpprint.c
+++ b/lpprint.c
@@ -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
diff --git a/lpprint.h b/lpprint.h
index 6329760..15ef121 100644
--- a/lpprint.h
+++ b/lpprint.h
@@ -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
diff --git a/lptree.c b/lptree.c
index 33ae79d..b1a32c4 100644
--- a/lptree.c
+++ b/lptree.c
@@ -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*/
754static TTree *auxemptycap (TTree *tree, int cap) { 755static 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*/
765static TTree *newemptycap (lua_State *L, int cap) { 766static 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*/
773static TTree *newemptycapkey (lua_State *L, int cap, int idx) { 776static 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
831static int lp_poscapture (lua_State *L) { 834static 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
837static int lp_argcapture (lua_State *L) { 840static 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
diff --git a/lptree.h b/lptree.h
index 24a9ac7..0cf160a 100644
--- a/lptree.h
+++ b/lptree.h
@@ -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)
diff --git a/lptypes.h b/lptypes.h
index 8503223..3261428 100644
--- a/lptypes.h
+++ b/lptypes.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"
diff --git a/lpvm.c b/lpvm.c
index 0c70766..a791c44 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -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*/
53static Capture *doublecap (lua_State *L, Capture *cap, int captop, 56static 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*/
118static void adddyncaptures (const char *s, Capture *base, int n, int fd) { 130static 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 }
diff --git a/lpvm.h b/lpvm.h
index c5457c4..6633c4b 100644
--- a/lpvm.h
+++ b/lpvm.h
@@ -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
4local tonumber, type, print, error = tonumber, type, print, error 4local tonumber, type, print, error = tonumber, type, print, error
@@ -126,15 +126,6 @@ updatelocale()
126local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end) 126local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end)
127 127
128 128
129local 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
135end
136
137
138local function mult (p, n) 129local 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
162local Def = name * m.Carg(1) 153local Def = name * m.Carg(1)
163 154
155
156local function getdef (id, defs)
157 local c = defs and defs[id]
158 if not c then error("undefined name: " .. id) end
159 return c
160end
161
162-- match a name and return a group of its corresponding definition
163-- and 'f' (to be folded in 'Suffix')
164local function defwithfunc (f)
165 return m.Cg(Def / getdef * m.Cc(f))
166end
167
168
164local num = m.C(m.R"09"^1) * S / tonumber 169local num = m.C(m.R"09"^1) * S / tonumber
165 170
166local String = "'" * m.C((any - "'" - m.P"\n")^0) * expect("'", "MisTerm1") 171local String = "'" * m.C((any - "'" - m.P"\n")^0) * expect("'", "MisTerm1")
@@ -177,7 +182,7 @@ end
177 182
178local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R 183local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R
179 184
180local item = defined + Range + m.C(any - m.P"\n") 185local item = (defined + Range + m.C(any - m.P"\n")) / m.P
181 186
182local Class = 187local 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
diff --git a/test.lua b/test.lua
index a3b86bf..2c05dd0 100755
--- a/test.lua
+++ b/test.lua
@@ -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
424end 424end
425 425
426 426
427do
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")
434end
435
436
427-- tests for non-pattern as arguments to pattern functions 437-- tests for non-pattern as arguments to pattern functions
428 438
429p = { ('a' * m.V(1))^-1 } * m.P'b' * { 'a' * m.V(2); m.V(1)^-1 } 439p = { ('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] + "))
1186assert(match("abb\"de", '"abb"["]"de"') == 7) 1196assert(match("abb\"de", '"abb"["]"de"') == 7)
1187assert(match("abceeef", "'ac' ? 'ab' * 'c' { 'e' * } / 'abceeef' ") == "eee") 1197assert(match("abceeef", "'ac' ? 'ab' * 'c' { 'e' * } / 'abceeef' ") == "eee")
1188assert(match("abceeef", "'ac'? 'ab'* 'c' { 'f'+ } / 'abceeef' ") == 8) 1198assert(match("abceeef", "'ac'? 'ab'* 'c' { 'f'+ } / 'abceeef' ") == 8)
1199
1200assert(re.match("aaand", "[a]^2") == 3)
1201
1189local t = {match("abceefe", "( ( & 'e' {} ) ? . ) * ")} 1202local t = {match("abceefe", "( ( & 'e' {} ) ? . ) * ")}
1190checkeq(t, {4, 5, 7}) 1203checkeq(t, {4, 5, 7})
1191local t = {match("abceefe", "((&&'e' {})? .)*")} 1204local 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
1377c = re.compile([[
1378 S <- (number (%s+ number)*) ~> add
1379 number <- %d+ -> tonumber
1380]], {tonumber = tonumber, add = function (a,b) return a + b end})
1381assert(c:match("3 401 50") == 3 + 401 + 50)
1382
1363-- tests for look-ahead captures 1383-- tests for look-ahead captures
1364x = {re.match("alo", "&(&{.}) !{'b'} {&(...)} &{..} {...} {!.}")} 1384x = {re.match("alo", "&(&{.}) !{'b'} {&(...)} &{..} {...} {!.}")}
1365checkeq(x, {"", "alo", ""}) 1385checkeq(x, {"", "alo", ""})