lua-users home
lua-l archive

[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);
 }