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