lua-users home
lua-l archive

adding match state to Lpeg

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I also have a suggestion for Lpeg, an optional parameter to match, a Lua object that gets passed as the first argument in any function captures, if present:

lpeg.match(_expression_, subject, idx, state)

If state is nil the function captures receive only the captures, as usual. This lets you write Lpeg parsers that have match-local state, instead of having to fake this with closures. It is specially useful with re-based parsers.

A patch to lpeg.c that implements this is attached.

--
Fabio Mascarenhas

--- lpeg.c	2007年10月10日 15:56:59.000000000 -0300
+++ ../lpeg-0.7-patched/lpeg.c	2008年01月23日 04:38:33.000000000 -0200
@@ -1648,6 +1648,7 @@
 lua_State *L;
 const char *s; /* original string */
 int valuecached; /* value stored in cache slot */
+ int state;
 } CapState;
 
 
@@ -1756,10 +1757,14 @@
 
 
 static int functioncap (CapState *cs) {
- int n;
+ int n = 0;
 int top = lua_gettop(cs->L);
 pushluaval(cs);
- n = pushallcaptures(cs, 0);
+ if(cs->state != LUA_REFNIL) {
+ lua_rawgeti(cs->L, LUA_REGISTRYINDEX, cs->state);
+ n++;
+ }
+ n += pushallcaptures(cs, 0);
 lua_call(cs->L, n, LUA_MULTRET);
 return lua_gettop(cs->L) - top;
 }
@@ -1883,17 +1888,18 @@
 }
 
 
-static int getcaptures (lua_State *L, const char *s, const char *r) {
+static int getcaptures (lua_State *L, const char *s, const char *r, int state) {
 Capture *capture = (Capture *)lua_touserdata(L, CAPLISTIDX);
 CapState cs;
 int n = 0;
- cs.cap = capture; cs.L = L; cs.s = s; cs.valuecached = 0;
+ cs.cap = capture; cs.L = L; cs.s = s; cs.valuecached = 0; cs.state = state;
 while (!isclosecap(cs.cap))
 n += pushcapture(&cs);
 if (n == 0) { /* no captures? */
 lua_pushinteger(L, r - s + 1); /* return only end position */
 n = 1;
 }
+ if(state != LUA_REFNIL) luaL_unref(L, LUA_REGISTRYINDEX, state);
 return n;
 }
 
@@ -1923,11 +1929,14 @@
 
 static int matchl (lua_State *L) {
 Capture capture[IMAXCAPTURES];
+ int state;
 const char *r;
 size_t l;
 Instruction *p = getpatt(L, 1, NULL);
 const char *s = luaL_checklstring(L, SUBJIDX, &l);
 lua_Integer i = luaL_optinteger(L, 3, 1);
+ lua_pushvalue(L, 4);
+ state = luaL_ref(L, LUA_REGISTRYINDEX);
 i = (i > 0) ?
 ((i <= (lua_Integer)l) ? i - 1 : (lua_Integer)l) :
 (((lua_Integer)l + i >= 0) ? (lua_Integer)l + i : 0);
@@ -1940,7 +1949,7 @@
 return 1;
 }
 assert(lua_gettop(L) == PENVIDX);
- return getcaptures(L, s, r);
+ return getcaptures(L, s, r, state);
 }
 
 

AltStyle によって変換されたページ (->オリジナル) /