mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 11:03:12 +00:00
update lpeg to 1.0.2 (#1557)
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
HISTORY for LPeg 1.0
|
||||
HISTORY for LPeg 1.0.2
|
||||
|
||||
* Changes from version 0.12 to 1.0
|
||||
* Changes from version 1.0.1 to 1.0.2
|
||||
---------------------------------
|
||||
+ some bugs fixed
|
||||
|
||||
* Changes from version 0.12 to 1.0.1
|
||||
---------------------------------
|
||||
+ group "names" can be any Lua value
|
||||
+ some bugs fixed
|
||||
@@ -13,14 +17,14 @@ HISTORY for LPeg 1.0
|
||||
+ some bugs fixed
|
||||
|
||||
* Changes from version 0.10 to 0.11
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ complete reimplementation of the code generator
|
||||
+ new syntax for table captures
|
||||
+ new functions in module 're'
|
||||
+ other small improvements
|
||||
|
||||
* Changes from version 0.9 to 0.10
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ backtrack stack has configurable size
|
||||
+ better error messages
|
||||
+ Notation for non-terminals in 're' back to A instead o <A>
|
||||
@@ -32,34 +36,34 @@ HISTORY for LPeg 1.0
|
||||
- "and" predicates do not keep captures
|
||||
|
||||
* Changes from version 0.8 to 0.9
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ The accumulator capture was replaced by a fold capture;
|
||||
programs that used the old 'lpeg.Ca' will need small changes.
|
||||
+ Some support for character classes from old C locales.
|
||||
+ A new named-group capture.
|
||||
|
||||
* Changes from version 0.7 to 0.8
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ New "match-time" capture.
|
||||
+ New "argument capture" that allows passing arguments into the pattern.
|
||||
+ Better documentation for 're'.
|
||||
+ Several small improvements for 're'.
|
||||
+ The 're' module has an incompatibility with previous versions:
|
||||
now, any use of a non-terminal must be enclosed in angle brackets
|
||||
+ The 're' module has an incompatibility with previous versions:
|
||||
now, any use of a non-terminal must be enclosed in angle brackets
|
||||
(like <B>).
|
||||
|
||||
* Changes from version 0.6 to 0.7
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ Several improvements in module 're':
|
||||
- better documentation;
|
||||
- support for most captures (all but accumulator);
|
||||
- limited repetitions p{n,m}.
|
||||
+ Small improvements in efficiency.
|
||||
+ Several small bugs corrected (special thanks to Hans Hagen
|
||||
+ Several small bugs corrected (special thanks to Hans Hagen
|
||||
and Taco Hoekwater).
|
||||
|
||||
* Changes from version 0.5 to 0.6
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ Support for non-numeric indices in grammars.
|
||||
+ Some bug fixes (thanks to the luatex team).
|
||||
+ Some new optimizations; (thanks to Mike Pall).
|
||||
@@ -67,7 +71,7 @@ HISTORY for LPeg 1.0
|
||||
+ Minimal documentation for module 're'.
|
||||
|
||||
* Changes from version 0.4 to 0.5
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ Several optimizations.
|
||||
+ lpeg.P now accepts booleans.
|
||||
+ Some new examples.
|
||||
@@ -75,18 +79,18 @@ HISTORY for LPeg 1.0
|
||||
+ Several small improvements.
|
||||
|
||||
* Changes from version 0.3 to 0.4
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ Static check for loops in repetitions and grammars.
|
||||
+ Removed label option in captures.
|
||||
+ The implementation of captures uses less memory.
|
||||
|
||||
* Changes from version 0.2 to 0.3
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ User-defined patterns in Lua.
|
||||
+ Several new captures.
|
||||
|
||||
* Changes from version 0.1 to 0.2
|
||||
-------------------------------
|
||||
-------------------------------
|
||||
+ Several small corrections.
|
||||
+ Handles embedded zeros like any other character.
|
||||
+ Capture "name" can be any Lua value.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $
|
||||
** $Id: lpcap.c $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -271,15 +271,15 @@ int finddyncap (Capture *cap, Capture *last) {
|
||||
|
||||
|
||||
/*
|
||||
** Calls a runtime capture. Returns number of captures removed by
|
||||
** the call, including the initial Cgroup. (Captures to be added are
|
||||
** on the Lua stack.)
|
||||
** Calls a runtime capture. Returns number of captures "removed" by the
|
||||
** call, that is, those inside the group capture. Captures to be added
|
||||
** are on the Lua stack.
|
||||
*/
|
||||
int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) {
|
||||
int n, id;
|
||||
lua_State *L = cs->L;
|
||||
int otop = lua_gettop(L);
|
||||
Capture *open = findopen(close);
|
||||
Capture *open = findopen(close); /* get open group capture */
|
||||
assert(captype(open) == Cgroup);
|
||||
id = finddyncap(open, close); /* get first dynamic capture argument */
|
||||
close->kind = Cclose; /* closes the group */
|
||||
@@ -299,7 +299,7 @@ int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) {
|
||||
}
|
||||
else
|
||||
*rem = 0; /* no dynamic captures removed */
|
||||
return close - open; /* number of captures of all kinds removed */
|
||||
return close - open - 1; /* number of captures to be removed */
|
||||
}
|
||||
|
||||
|
||||
@@ -441,70 +441,88 @@ static int addonestring (luaL_Buffer *b, CapState *cs, const char *what) {
|
||||
}
|
||||
|
||||
|
||||
#if !defined(MAXRECLEVEL)
|
||||
#define MAXRECLEVEL 200
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Push all values of the current capture into the stack; returns
|
||||
** number of values pushed
|
||||
*/
|
||||
static int pushcapture (CapState *cs) {
|
||||
lua_State *L = cs->L;
|
||||
int res;
|
||||
luaL_checkstack(L, 4, "too many captures");
|
||||
if (cs->reclevel++ > MAXRECLEVEL)
|
||||
return luaL_error(L, "subcapture nesting too deep");
|
||||
switch (captype(cs->cap)) {
|
||||
case Cposition: {
|
||||
lua_pushinteger(L, cs->cap->s - cs->s + 1);
|
||||
cs->cap++;
|
||||
return 1;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Cconst: {
|
||||
pushluaval(cs);
|
||||
cs->cap++;
|
||||
return 1;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Carg: {
|
||||
int arg = (cs->cap++)->idx;
|
||||
if (arg + FIXEDARGS > cs->ptop)
|
||||
return luaL_error(L, "reference to absent extra argument #%d", arg);
|
||||
lua_pushvalue(L, arg + FIXEDARGS);
|
||||
return 1;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Csimple: {
|
||||
int k = pushnestedvalues(cs, 1);
|
||||
lua_insert(L, -k); /* make whole match be first result */
|
||||
return k;
|
||||
res = k;
|
||||
break;
|
||||
}
|
||||
case Cruntime: {
|
||||
lua_pushvalue(L, (cs->cap++)->idx); /* value is in the stack */
|
||||
return 1;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Cstring: {
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
stringcap(&b, cs);
|
||||
luaL_pushresult(&b);
|
||||
return 1;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Csubst: {
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
substcap(&b, cs);
|
||||
luaL_pushresult(&b);
|
||||
return 1;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Cgroup: {
|
||||
if (cs->cap->idx == 0) /* anonymous group? */
|
||||
return pushnestedvalues(cs, 0); /* add all nested values */
|
||||
res = pushnestedvalues(cs, 0); /* add all nested values */
|
||||
else { /* named group: add no values */
|
||||
nextcap(cs); /* skip capture */
|
||||
return 0;
|
||||
res = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Cbackref: return backrefcap(cs);
|
||||
case Ctable: return tablecap(cs);
|
||||
case Cfunction: return functioncap(cs);
|
||||
case Cnum: return numcap(cs);
|
||||
case Cquery: return querycap(cs);
|
||||
case Cfold: return foldcap(cs);
|
||||
default: assert(0); return 0;
|
||||
case Cbackref: res = backrefcap(cs); break;
|
||||
case Ctable: res = tablecap(cs); break;
|
||||
case Cfunction: res = functioncap(cs); break;
|
||||
case Cnum: res = numcap(cs); break;
|
||||
case Cquery: res = querycap(cs); break;
|
||||
case Cfold: res = foldcap(cs); break;
|
||||
default: assert(0); res = 0;
|
||||
}
|
||||
cs->reclevel--;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -521,7 +539,7 @@ int getcaptures (lua_State *L, const char *s, const char *r, int ptop) {
|
||||
int n = 0;
|
||||
if (!isclosecap(capture)) { /* is there any capture? */
|
||||
CapState cs;
|
||||
cs.ocap = cs.cap = capture; cs.L = L;
|
||||
cs.ocap = cs.cap = capture; cs.L = L; cs.reclevel = 0;
|
||||
cs.s = s; cs.valuecached = 0; cs.ptop = ptop;
|
||||
do { /* collect their values */
|
||||
n += pushcapture(&cs);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcap.h,v 1.3 2016/09/13 17:45:58 roberto Exp $
|
||||
** $Id: lpcap.h $
|
||||
*/
|
||||
|
||||
#if !defined(lpcap_h)
|
||||
@@ -44,6 +44,7 @@ typedef struct CapState {
|
||||
int ptop; /* index of last argument to 'match' */
|
||||
const char *s; /* original string */
|
||||
int valuecached; /* value stored in cache slot */
|
||||
int reclevel; /* recursion level */
|
||||
} CapState;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcode.c,v 1.24 2016/09/15 17:46:13 roberto Exp $
|
||||
** $Id: lpcode.c $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcode.h,v 1.8 2016/09/15 17:46:13 roberto Exp $
|
||||
** $Id: lpcode.h $
|
||||
*/
|
||||
|
||||
#if !defined(lpcode_h)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- $Id: lpeg.html,v 1.77 2017/01/13 13:40:05 roberto Exp $ -->
|
||||
<!-- $Id: lpeg.html $ -->
|
||||
|
||||
<div id="container">
|
||||
|
||||
@@ -1391,13 +1391,13 @@ and the new term for each repetition.
|
||||
<h2><a name="download"></a>Download</h2>
|
||||
|
||||
<p>LPeg
|
||||
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.1.tar.gz">source code</a>.</p>
|
||||
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.2.tar.gz">source code</a>.</p>
|
||||
|
||||
|
||||
<h2><a name="license">License</a></h2>
|
||||
|
||||
<p>
|
||||
Copyright © 2007-2017 Lua.org, PUC-Rio.
|
||||
Copyright © 2007-2019 Lua.org, PUC-Rio.
|
||||
</p>
|
||||
<p>
|
||||
Permission is hereby granted, free of charge,
|
||||
@@ -1433,12 +1433,6 @@ THE SOFTWARE.
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><small>
|
||||
$Id: lpeg.html,v 1.77 2017/01/13 13:40:05 roberto Exp $
|
||||
</small></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpprint.c,v 1.10 2016/09/13 16:06:03 roberto Exp $
|
||||
** $Id: lpprint.c $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $
|
||||
** $Id: lpprint.h $
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lptree.c,v 1.22 2016/09/13 18:10:22 roberto Exp $
|
||||
** $Id: lptree.c $
|
||||
** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -716,6 +716,7 @@ static int capture_aux (lua_State *L, int cap, int labelidx) {
|
||||
|
||||
/*
|
||||
** Fill a tree with an empty capture, using an empty (TTrue) sibling.
|
||||
** (The 'key' field must be filled by the caller to finish the tree.)
|
||||
*/
|
||||
static TTree *auxemptycap (TTree *tree, int cap) {
|
||||
tree->tag = TCapture;
|
||||
@@ -726,15 +727,17 @@ static TTree *auxemptycap (TTree *tree, int cap) {
|
||||
|
||||
|
||||
/*
|
||||
** Create a tree for an empty capture
|
||||
** Create a tree for an empty capture.
|
||||
*/
|
||||
static TTree *newemptycap (lua_State *L, int cap) {
|
||||
return auxemptycap(newtree(L, 2), cap);
|
||||
static TTree *newemptycap (lua_State *L, int cap, int key) {
|
||||
TTree *tree = auxemptycap(newtree(L, 2), cap);
|
||||
tree->key = key;
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Create a tree for an empty capture with an associated Lua value
|
||||
** Create a tree for an empty capture with an associated Lua value.
|
||||
*/
|
||||
static TTree *newemptycapkey (lua_State *L, int cap, int idx) {
|
||||
TTree *tree = auxemptycap(newtree(L, 2), cap);
|
||||
@@ -795,16 +798,15 @@ static int lp_simplecapture (lua_State *L) {
|
||||
|
||||
|
||||
static int lp_poscapture (lua_State *L) {
|
||||
newemptycap(L, Cposition);
|
||||
newemptycap(L, Cposition, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int lp_argcapture (lua_State *L) {
|
||||
int n = (int)luaL_checkinteger(L, 1);
|
||||
TTree *tree = newemptycap(L, Carg);
|
||||
tree->key = n;
|
||||
luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index");
|
||||
newemptycap(L, Carg, n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lptree.h,v 1.3 2016/09/13 18:07:51 roberto Exp $
|
||||
** $Id: lptree.h $
|
||||
*/
|
||||
|
||||
#if !defined(lptree_h)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
** $Id: lptypes.h,v 1.16 2017/01/13 13:33:17 roberto Exp $
|
||||
** $Id: lptypes.h $
|
||||
** LPeg - PEG pattern matching for Lua
|
||||
** Copyright 2007-2017, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
** Copyright 2007-2019, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
** written by Roberto Ierusalimschy
|
||||
*/
|
||||
|
||||
@@ -9,17 +9,13 @@
|
||||
#define lptypes_h
|
||||
|
||||
|
||||
#if !defined(LPEG_DEBUG)
|
||||
#define NDEBUG
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
#define VERSION "1.0.1"
|
||||
#define VERSION "1.0.2"
|
||||
|
||||
|
||||
#define PATTERN_T "lpeg-pattern"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpvm.c,v 1.9 2016/06/03 20:11:18 roberto Exp $
|
||||
** $Id: lpvm.c $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -45,18 +45,29 @@ typedef struct Stack {
|
||||
|
||||
|
||||
/*
|
||||
** Make the size of the array of captures 'cap' twice as large as needed
|
||||
** (which is 'captop'). ('n' is the number of new elements.)
|
||||
** Ensures the size of array 'capture' (with size '*capsize' and
|
||||
** 'captop' elements being used) is enough to accomodate 'n' extra
|
||||
** elements plus one. (Because several opcodes add stuff to the capture
|
||||
** array, it is simpler to ensure the array always has at least one free
|
||||
** slot upfront and check its size later.)
|
||||
*/
|
||||
static Capture *doublecap (lua_State *L, Capture *cap, int captop,
|
||||
int n, int ptop) {
|
||||
Capture *newc;
|
||||
if (captop >= INT_MAX/((int)sizeof(Capture) * 2))
|
||||
luaL_error(L, "too many captures");
|
||||
newc = (Capture *)lua_newuserdata(L, captop * 2 * sizeof(Capture));
|
||||
memcpy(newc, cap, (captop - n) * sizeof(Capture));
|
||||
lua_replace(L, caplistidx(ptop));
|
||||
return newc;
|
||||
static Capture *growcap (lua_State *L, Capture *capture, int *capsize,
|
||||
int captop, int n, int ptop) {
|
||||
if (*capsize - captop > n)
|
||||
return capture; /* no need to grow array */
|
||||
else { /* must grow */
|
||||
Capture *newc;
|
||||
int newsize = captop + n + 1; /* minimum size needed */
|
||||
if (newsize < INT_MAX/((int)sizeof(Capture) * 2))
|
||||
newsize *= 2; /* twice that size, if not too big */
|
||||
else if (newsize >= INT_MAX/((int)sizeof(Capture)))
|
||||
luaL_error(L, "too many captures");
|
||||
newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture));
|
||||
memcpy(newc, capture, captop * sizeof(Capture));
|
||||
*capsize = newsize;
|
||||
lua_replace(L, caplistidx(ptop));
|
||||
return newc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,24 +120,24 @@ static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {
|
||||
|
||||
|
||||
/*
|
||||
** Add capture values returned by a dynamic capture to the capture list
|
||||
** 'base', nested inside a group capture. 'fd' indexes the first capture
|
||||
** value, 'n' is the number of values (at least 1).
|
||||
** Add capture values returned by a dynamic capture to the list
|
||||
** 'capture', nested inside a group. 'fd' indexes the first capture
|
||||
** value, 'n' is the number of values (at least 1). The open group
|
||||
** capture is already in 'capture', before the place for the new entries.
|
||||
*/
|
||||
static void adddyncaptures (const char *s, Capture *base, int n, int fd) {
|
||||
static void adddyncaptures (const char *s, Capture *capture, int n, int fd) {
|
||||
int i;
|
||||
base[0].kind = Cgroup; /* create group capture */
|
||||
base[0].siz = 0;
|
||||
base[0].idx = 0; /* make it an anonymous group */
|
||||
for (i = 1; i <= n; i++) { /* add runtime captures */
|
||||
base[i].kind = Cruntime;
|
||||
base[i].siz = 1; /* mark it as closed */
|
||||
base[i].idx = fd + i - 1; /* stack index of capture value */
|
||||
base[i].s = s;
|
||||
assert(capture[-1].kind == Cgroup && capture[-1].siz == 0);
|
||||
capture[-1].idx = 0; /* make group capture an anonymous group */
|
||||
for (i = 0; i < n; i++) { /* add runtime captures */
|
||||
capture[i].kind = Cruntime;
|
||||
capture[i].siz = 1; /* mark it as closed */
|
||||
capture[i].idx = fd + i; /* stack index of capture value */
|
||||
capture[i].s = s;
|
||||
}
|
||||
base[i].kind = Cclose; /* close group */
|
||||
base[i].siz = 1;
|
||||
base[i].s = s;
|
||||
capture[n].kind = Cclose; /* close group */
|
||||
capture[n].siz = 1;
|
||||
capture[n].s = s;
|
||||
}
|
||||
|
||||
|
||||
@@ -296,7 +307,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
CapState cs;
|
||||
int rem, res, n;
|
||||
int fr = lua_gettop(L) + 1; /* stack index of first result */
|
||||
cs.s = o; cs.L = L; cs.ocap = capture; cs.ptop = ptop;
|
||||
cs.reclevel = 0; cs.L = L;
|
||||
cs.s = o; cs.ocap = capture; cs.ptop = ptop;
|
||||
n = runtimecap(&cs, capture + captop, s, &rem); /* call function */
|
||||
captop -= n; /* remove nested captures */
|
||||
ndyncap -= rem; /* update number of dynamic captures */
|
||||
@@ -307,15 +319,15 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
s = o + res; /* else update current position */
|
||||
n = lua_gettop(L) - fr + 1; /* number of new captures */
|
||||
ndyncap += n; /* update number of dynamic captures */
|
||||
if (n > 0) { /* any new capture? */
|
||||
if (n == 0) /* no new captures? */
|
||||
captop--; /* remove open group */
|
||||
else { /* new captures; keep original open group */
|
||||
if (fr + n >= SHRT_MAX)
|
||||
luaL_error(L, "too many results in match-time capture");
|
||||
if ((captop += n + 2) >= capsize) {
|
||||
capture = doublecap(L, capture, captop, n + 2, ptop);
|
||||
capsize = 2 * captop;
|
||||
}
|
||||
/* add new captures to 'capture' list */
|
||||
adddyncaptures(s, capture + captop - n - 2, n, fr);
|
||||
/* add new captures + close group to 'capture' list */
|
||||
capture = growcap(L, capture, &capsize, captop, n + 1, ptop);
|
||||
adddyncaptures(s, capture + captop, n, fr);
|
||||
captop += n + 1; /* new captures + close group */
|
||||
}
|
||||
p++;
|
||||
continue;
|
||||
@@ -347,10 +359,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
pushcapture: {
|
||||
capture[captop].idx = p->i.key;
|
||||
capture[captop].kind = getkind(p);
|
||||
if (++captop >= capsize) {
|
||||
capture = doublecap(L, capture, captop, 0, ptop);
|
||||
capsize = 2 * captop;
|
||||
}
|
||||
captop++;
|
||||
capture = growcap(L, capture, &capsize, captop, 0, ptop);
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpvm.h,v 1.3 2014/02/21 13:06:41 roberto Exp $
|
||||
** $Id: lpvm.h $
|
||||
*/
|
||||
|
||||
#if !defined(lpvm_h)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
LIBNAME = lpeg
|
||||
LUADIR = ../lua/
|
||||
|
||||
COPT = -O2
|
||||
# COPT = -DLPEG_DEBUG -g
|
||||
COPT = -O2 -DNDEBUG
|
||||
# COPT = -g
|
||||
|
||||
CWARNS = -Wall -Wextra -pedantic \
|
||||
-Waggregate-return \
|
||||
@@ -29,11 +29,11 @@ FILES = lpvm.o lpcap.o lptree.o lpcode.o lpprint.o
|
||||
|
||||
# For Linux
|
||||
linux:
|
||||
make lpeg.so "DLLFLAGS = -shared -fPIC"
|
||||
$(MAKE) lpeg.so "DLLFLAGS = -shared -fPIC"
|
||||
|
||||
# For Mac OS
|
||||
macosx:
|
||||
make lpeg.so "DLLFLAGS = -bundle -undefined dynamic_lookup"
|
||||
$(MAKE) lpeg.so "DLLFLAGS = -bundle -undefined dynamic_lookup"
|
||||
|
||||
lpeg.so: $(FILES)
|
||||
env $(CC) $(DLLFLAGS) $(FILES) -o lpeg.so
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- $Id: re.html,v 1.24 2016/09/20 17:41:27 roberto Exp $ -->
|
||||
<!-- $Id: re.html $ -->
|
||||
|
||||
<div id="container">
|
||||
|
||||
@@ -93,6 +93,8 @@ Constructions are listed in order of decreasing precedence.
|
||||
equivalent to <code>p / defs[name]</code></td></tr>
|
||||
<tr><td><code>p => name</code></td> <td>match-time capture
|
||||
equivalent to <code>lpeg.Cmt(p, defs[name])</code></td></tr>
|
||||
<tr><td><code>p ~> name</code></td> <td>fold capture
|
||||
equivalent to <code>lpeg.Cf(p, defs[name])</code></td></tr>
|
||||
<tr><td><code>& p</code></td> <td>and predicate</td></tr>
|
||||
<tr><td><code>! p</code></td> <td>not predicate</td></tr>
|
||||
<tr><td><code>p1 p2</code></td> <td>concatenation</td></tr>
|
||||
@@ -486,12 +488,6 @@ THE SOFTWARE.
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><small>
|
||||
$Id: re.html,v 1.24 2016/09/20 17:41:27 roberto Exp $
|
||||
</small></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-- $Id: re.lua,v 1.44 2013/03/26 20:11:40 roberto Exp $
|
||||
-- $Id: re.lua $
|
||||
|
||||
-- imported functions and modules
|
||||
local tonumber, type, print, error = tonumber, type, print, error
|
||||
@@ -71,13 +71,6 @@ updatelocale()
|
||||
local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end)
|
||||
|
||||
|
||||
local function getdef (id, defs)
|
||||
local c = defs and defs[id]
|
||||
if not c then error("undefined name: " .. id) end
|
||||
return c
|
||||
end
|
||||
|
||||
|
||||
local function patt_error (s, i)
|
||||
local msg = (#s < i + 20) and s:sub(i)
|
||||
or s:sub(i,i+20) .. "..."
|
||||
@@ -116,6 +109,20 @@ name = m.C(name)
|
||||
-- a defined name only have meaning in a given environment
|
||||
local Def = name * m.Carg(1)
|
||||
|
||||
|
||||
local function getdef (id, defs)
|
||||
local c = defs and defs[id]
|
||||
if not c then error("undefined name: " .. id) end
|
||||
return c
|
||||
end
|
||||
|
||||
-- match a name and return a group of its corresponding definition
|
||||
-- and 'f' (to be folded in 'Suffix')
|
||||
local function defwithfunc (f)
|
||||
return m.Cg(Def / getdef * m.Cc(f))
|
||||
end
|
||||
|
||||
|
||||
local num = m.C(m.R"09"^1) * S / tonumber
|
||||
|
||||
local String = "'" * m.C((any - "'")^0) * "'" +
|
||||
@@ -130,7 +137,7 @@ end
|
||||
|
||||
local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R
|
||||
|
||||
local item = defined + Range + m.C(any)
|
||||
local item = (defined + Range + m.C(any)) / m.P
|
||||
|
||||
local Class =
|
||||
"["
|
||||
@@ -176,9 +183,10 @@ local exp = m.P{ "Exp",
|
||||
)
|
||||
+ "->" * S * ( m.Cg((String + num) * m.Cc(mt.__div))
|
||||
+ m.P"{}" * m.Cc(nil, m.Ct)
|
||||
+ m.Cg(Def / getdef * m.Cc(mt.__div))
|
||||
+ defwithfunc(mt.__div)
|
||||
)
|
||||
+ "=>" * S * m.Cg(Def / getdef * m.Cc(m.Cmt))
|
||||
+ "=>" * S * defwithfunc(m.Cmt)
|
||||
+ "~>" * S * defwithfunc(m.Cf)
|
||||
) * S
|
||||
)^0, function (a,b,f) return f(a,b) end );
|
||||
Primary = "(" * m.V"Exp" * ")"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- $Id: test.lua,v 1.112 2017/01/14 18:55:22 roberto Exp $
|
||||
-- $Id: test.lua $
|
||||
|
||||
-- require"strict" -- just to be pedantic
|
||||
|
||||
@@ -424,6 +424,16 @@ do
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
-- nesting of captures too deep
|
||||
local p = m.C(1)
|
||||
for i = 1, 300 do
|
||||
p = m.Ct(p)
|
||||
end
|
||||
checkerr("too deep", p.match, p, "x")
|
||||
end
|
||||
|
||||
|
||||
-- tests for non-pattern as arguments to pattern functions
|
||||
|
||||
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] + "))
|
||||
assert(match("abb\"de", '"abb"["]"de"') == 7)
|
||||
assert(match("abceeef", "'ac' ? 'ab' * 'c' { 'e' * } / 'abceeef' ") == "eee")
|
||||
assert(match("abceeef", "'ac'? 'ab'* 'c' { 'f'+ } / 'abceeef' ") == 8)
|
||||
|
||||
assert(re.match("aaand", "[a]^2") == 3)
|
||||
|
||||
local t = {match("abceefe", "( ( & 'e' {} ) ? . ) * ")}
|
||||
checkeq(t, {4, 5, 7})
|
||||
local t = {match("abceefe", "((&&'e' {})? .)*")}
|
||||
@@ -1360,6 +1373,13 @@ checkeq(x, {tag='x', 'hi', {tag = 'b', 'hello'}, 'but',
|
||||
{'totheend'}})
|
||||
|
||||
|
||||
-- test for folding captures
|
||||
c = re.compile([[
|
||||
S <- (number (%s+ number)*) ~> add
|
||||
number <- %d+ -> tonumber
|
||||
]], {tonumber = tonumber, add = function (a,b) return a + b end})
|
||||
assert(c:match("3 401 50") == 3 + 401 + 50)
|
||||
|
||||
-- tests for look-ahead captures
|
||||
x = {re.match("alo", "&(&{.}) !{'b'} {&(...)} &{..} {...} {!.}")}
|
||||
checkeq(x, {"", "alo", ""})
|
||||
|
||||
Reference in New Issue
Block a user