aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE2
-rw-r--r--lpcap.c4
-rw-r--r--lpcode.c28
-rw-r--r--lpcode.h10
-rw-r--r--lpprint.c8
-rw-r--r--lpprint.h3
-rw-r--r--lptree.c104
-rw-r--r--lptypes.h34
-rw-r--r--lpvm.c6
-rw-r--r--makefile2
-rwxr-xr-xtest.lua40
11 files changed, 140 insertions, 101 deletions
diff --git a/LICENSE b/LICENSE
index 9c488ad..27faf04 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
1The MIT License (MIT) 1The MIT License (MIT)
2 2
3Copyright (c) 2014-2015 Sérgio Medeiros 3Copyright (c) 2014-2016 Sérgio Medeiros
4 4
5Permission is hereby granted, free of charge, to any person obtaining a copy 5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal 6of this software and associated documentation files (the "Software"), to deal
diff --git a/lpcap.c b/lpcap.c
index b6911cb..c9085de 100644
--- a/lpcap.c
+++ b/lpcap.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lpcap.c,v 1.5 2014/12/12 16:58:47 roberto Exp $ 2** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $
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
@@ -126,7 +126,7 @@ static Capture *findback (CapState *cs, Capture *cap) {
126 continue; /* opening an enclosing capture: skip and get previous */ 126 continue; /* opening an enclosing capture: skip and get previous */
127 if (captype(cap) == Cgroup) { 127 if (captype(cap) == Cgroup) {
128 getfromktable(cs, cap->idx); /* get group name */ 128 getfromktable(cs, cap->idx); /* get group name */
129 if (lua_equal(L, -2, -1)) { /* right group? */ 129 if (lp_equal(L, -2, -1)) { /* right group? */
130 lua_pop(L, 2); /* remove reference name and group name */ 130 lua_pop(L, 2); /* remove reference name and group name */
131 return cap; 131 return cap;
132 } 132 }
diff --git a/lpcode.c b/lpcode.c
index 70a8d3c..2a85e02 100644
--- a/lpcode.c
+++ b/lpcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lpcode.c,v 1.21 2014/12/12 17:01:29 roberto Exp $ 2** $Id: lpcode.c,v 1.23 2015/06/12 18:36:47 roberto Exp $
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
@@ -192,7 +192,7 @@ int checkaux (TTree *tree, int pred) {
192 if (!checkaux(sib1(tree), pred)) return 0; 192 if (!checkaux(sib1(tree), pred)) return 0;
193 /* else return checkaux(sib2(tree), pred); */ 193 /* else return checkaux(sib2(tree), pred); */
194 tree = sib2(tree); goto tailcall; 194 tree = sib2(tree); goto tailcall;
195 case TChoice: 195 case TChoice:
196 if (checkaux(sib2(tree), pred)) return 1; 196 if (checkaux(sib2(tree), pred)) return 1;
197 /* else return checkaux(sib1(tree), pred); */ 197 /* else return checkaux(sib1(tree), pred); */
198 tree = sib1(tree); goto tailcall; 198 tree = sib1(tree); goto tailcall;
@@ -425,9 +425,9 @@ int sizei (const Instruction *i) {
425 case ITestChar: case ITestAny: case IChoice: case IJmp: case ICall: 425 case ITestChar: case ITestAny: case IChoice: case IJmp: case ICall:
426 case IOpenCall: case ICommit: case IPartialCommit: case IBackCommit: 426 case IOpenCall: case ICommit: case IPartialCommit: case IBackCommit:
427 case IThrow: /* labeled failure */ 427 case IThrow: /* labeled failure */
428 return 2;
429 case ILabChoice: return 3; /* labeled failure */
430 return 2; 428 return 2;
429 case ILabChoice:
430 return 3; /* labeled failure */
431 default: return 1; 431 default: return 1;
432 } 432 }
433} 433}
@@ -444,11 +444,11 @@ typedef struct CompileState {
444 444
445 445
446/* 446/*
447** code generation is recursive; 'opt' indicates that the code is 447** code generation is recursive; 'opt' indicates that the code is being
448** being generated under a 'IChoice' operator jumping to its end 448** generated as the last thing inside an optional pattern (so, if that
449** (that is, the match is "optional"). 449** code is optional too, it can reuse the 'IChoice' already in place for
450** 'tt' points to a previous test protecting this code. 'fl' is 450** the outer pattern). 'tt' points to a previous test protecting this
451** the follow set of the pattern. 451** code (or NOINST). 'fl' is the follow set of the pattern.
452*/ 452*/
453static void codegen (CompileState *compst, TTree *tree, int opt, int tt, 453static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
454 const Charset *fl); 454 const Charset *fl);
@@ -669,13 +669,13 @@ static void codebehind (CompileState *compst, TTree *tree) {
669 669
670/* 670/*
671** Choice; optimizations: 671** Choice; optimizations:
672** - when p1 is headfail 672** - when p1 is headfail or
673** - when first(p1) and first(p2) are disjoint; than 673** when first(p1) and first(p2) are disjoint, than
674** a character not in first(p1) cannot go to p1, and a character 674** a character not in first(p1) cannot go to p1, and a character
675** in first(p1) cannot go to p2 (at it is not in first(p2)). 675** in first(p1) cannot go to p2 (at it is not in first(p2)).
676** (The optimization is not valid if p1 accepts the empty string, 676** (The optimization is not valid if p1 accepts the empty string,
677** as then there is no character at all...) 677** as then there is no character at all...)
678** - when p2 is empty and opt is true; a IPartialCommit can resuse 678** - when p2 is empty and opt is true; a IPartialCommit can reuse
679** the Choice already active in the stack. 679** the Choice already active in the stack.
680*/ 680*/
681static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt, 681static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
@@ -702,7 +702,7 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
702 } 702 }
703 else { 703 else {
704 /* <p1 / p2> == 704 /* <p1 / p2> ==
705 test(fail(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */ 705 test(first(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */
706 int pcommit; 706 int pcommit;
707 int test = codetestset(compst, &cs1, e1); 707 int test = codetestset(compst, &cs1, e1);
708 int pchoice = addoffsetinst(compst, IChoice); 708 int pchoice = addoffsetinst(compst, IChoice);
@@ -808,7 +808,7 @@ static void coderep (CompileState *compst, TTree *tree, int opt,
808 /* L1: test (fail(p1)) -> L2; <p>; jmp L1; L2: */ 808 /* L1: test (fail(p1)) -> L2; <p>; jmp L1; L2: */
809 int jmp; 809 int jmp;
810 int test = codetestset(compst, &st, 0); 810 int test = codetestset(compst, &st, 0);
811 codegen(compst, tree, opt, test, fullset); 811 codegen(compst, tree, 0, test, fullset);
812 jmp = addoffsetinst(compst, IJmp); 812 jmp = addoffsetinst(compst, IJmp);
813 jumptohere(compst, test); 813 jumptohere(compst, test);
814 jumptothere(compst, jmp, test); 814 jumptothere(compst, jmp, test);
diff --git a/lpcode.h b/lpcode.h
index 72d2bb9..896d3c7 100644
--- a/lpcode.h
+++ b/lpcode.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lpcode.h,v 1.6 2013/11/28 14:56:02 roberto Exp $ 2** $Id: lpcode.h,v 1.7 2015/06/12 18:24:45 roberto Exp $
3*/ 3*/
4 4
5#if !defined(lpcode_h) 5#if !defined(lpcode_h)
@@ -24,7 +24,15 @@ int sizei (const Instruction *i);
24#define PEnullable 0 24#define PEnullable 0
25#define PEnofail 1 25#define PEnofail 1
26 26
27/*
28** nofail(t) implies that 't' cannot fail with any input
29*/
27#define nofail(t) checkaux(t, PEnofail) 30#define nofail(t) checkaux(t, PEnofail)
31
32/*
33** (not nullable(t)) implies 't' cannot match without consuming
34** something
35*/
28#define nullable(t) checkaux(t, PEnullable) 36#define nullable(t) checkaux(t, PEnullable)
29 37
30#define fixedlen(t) fixedlenx(t, 0, 0) 38#define fixedlen(t) fixedlenx(t, 0, 0)
diff --git a/lpprint.c b/lpprint.c
index d4a60a8..99cc3ac 100644
--- a/lpprint.c
+++ b/lpprint.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lpprint.c,v 1.7 2013/04/12 16:29:49 roberto Exp $ 2** $Id: lpprint.c,v 1.9 2015/06/15 16:09:57 roberto Exp $
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
@@ -52,7 +52,7 @@ static void printjmp (const Instruction *op, const Instruction *p) {
52} 52}
53 53
54 54
55static void printinst (const Instruction *op, const Instruction *p) { 55void printinst (const Instruction *op, const Instruction *p) {
56 const char *const names[] = { 56 const char *const names[] = {
57 "any", "char", "set", 57 "any", "char", "set",
58 "testany", "testchar", "testset", 58 "testany", "testchar", "testset",
@@ -239,10 +239,10 @@ void printtree (TTree *tree, int ident) {
239 239
240void printktable (lua_State *L, int idx) { 240void printktable (lua_State *L, int idx) {
241 int n, i; 241 int n, i;
242 lua_getfenv(L, idx); 242 lua_getuservalue(L, idx);
243 if (lua_isnil(L, -1)) /* no ktable? */ 243 if (lua_isnil(L, -1)) /* no ktable? */
244 return; 244 return;
245 n = lua_objlen(L, -1); 245 n = lua_rawlen(L, -1);
246 printf("["); 246 printf("[");
247 for (i = 1; i <= n; i++) { 247 for (i = 1; i <= n; i++) {
248 printf("%d = ", i); 248 printf("%d = ", i);
diff --git a/lpprint.h b/lpprint.h
index e640f74..6329760 100644
--- a/lpprint.h
+++ b/lpprint.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lpprint.h,v 1.1 2013/03/21 20:25:12 roberto Exp $ 2** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $
3*/ 3*/
4 4
5 5
@@ -18,6 +18,7 @@ void printtree (TTree *tree, int ident);
18void printktable (lua_State *L, int idx); 18void printktable (lua_State *L, int idx);
19void printcharset (const byte *st); 19void printcharset (const byte *st);
20void printcaplist (Capture *cap, Capture *limit); 20void printcaplist (Capture *cap, Capture *limit);
21void printinst (const Instruction *op, const Instruction *p);
21 22
22#else 23#else
23 24
diff --git a/lptree.c b/lptree.c
index 548128d..22cf606 100644
--- a/lptree.c
+++ b/lptree.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lptree.c,v 1.15 2015/03/04 17:23:00 roberto Exp $ 2** $Id: lptree.c,v 1.21 2015/09/28 17:01:25 roberto Exp $
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
@@ -147,7 +147,7 @@ static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) {
147*/ 147*/
148static void newktable (lua_State *L, int n) { 148static void newktable (lua_State *L, int n) {
149 lua_createtable(L, n, 0); /* create a fresh table */ 149 lua_createtable(L, n, 0); /* create a fresh table */
150 lua_setfenv(L, -2); /* set it as 'ktable' for pattern */ 150 lua_setuservalue(L, -2); /* set it as 'ktable' for pattern */
151} 151}
152 152
153 153
@@ -162,8 +162,8 @@ static int addtoktable (lua_State *L, int idx) {
162 return 0; 162 return 0;
163 else { 163 else {
164 int n; 164 int n;
165 lua_getfenv(L, -1); /* get ktable from pattern */ 165 lua_getuservalue(L, -1); /* get ktable from pattern */
166 n = lua_objlen(L, -1); 166 n = lua_rawlen(L, -1);
167 if (n >= USHRT_MAX) 167 if (n >= USHRT_MAX)
168 luaL_error(L, "too many Lua values in pattern"); 168 luaL_error(L, "too many Lua values in pattern");
169 lua_pushvalue(L, idx); /* element to be added */ 169 lua_pushvalue(L, idx); /* element to be added */
@@ -182,7 +182,7 @@ static int addtoktable (lua_State *L, int idx) {
182*/ 182*/
183static int ktablelen (lua_State *L, int idx) { 183static int ktablelen (lua_State *L, int idx) {
184 if (!lua_istable(L, idx)) return 0; 184 if (!lua_istable(L, idx)) return 0;
185 else return lua_objlen(L, idx); 185 else return lua_rawlen(L, idx);
186} 186}
187 187
188 188
@@ -245,18 +245,18 @@ static void correctkeys (TTree *tree, int n) {
245*/ 245*/
246static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { 246static void joinktables (lua_State *L, int p1, TTree *t2, int p2) {
247 int n1, n2; 247 int n1, n2;
248 lua_getfenv(L, p1); /* get ktables */ 248 lua_getuservalue(L, p1); /* get ktables */
249 lua_getfenv(L, p2); 249 lua_getuservalue(L, p2);
250 n1 = ktablelen(L, -2); 250 n1 = ktablelen(L, -2);
251 n2 = ktablelen(L, -1); 251 n2 = ktablelen(L, -1);
252 if (n1 == 0 && n2 == 0) /* are both tables empty? */ 252 if (n1 == 0 && n2 == 0) /* are both tables empty? */
253 lua_pop(L, 2); /* nothing to be done; pop tables */ 253 lua_pop(L, 2); /* nothing to be done; pop tables */
254 else if (n2 == 0 || lua_equal(L, -2, -1)) { /* 2nd table empty or equal? */ 254 else if (n2 == 0 || lp_equal(L, -2, -1)) { /* 2nd table empty or equal? */
255 lua_pop(L, 1); /* pop 2nd table */ 255 lua_pop(L, 1); /* pop 2nd table */
256 lua_setfenv(L, -2); /* set 1st ktable into new pattern */ 256 lua_setuservalue(L, -2); /* set 1st ktable into new pattern */
257 } 257 }
258 else if (n1 == 0) { /* first table is empty? */ 258 else if (n1 == 0) { /* first table is empty? */
259 lua_setfenv(L, -3); /* set 2nd table into new pattern */ 259 lua_setuservalue(L, -3); /* set 2nd table into new pattern */
260 lua_pop(L, 1); /* pop 1st table */ 260 lua_pop(L, 1); /* pop 1st table */
261 } 261 }
262 else { 262 else {
@@ -264,7 +264,7 @@ static void joinktables (lua_State *L, int p1, TTree *t2, int p2) {
264 /* stack: new p; ktable p1; ktable p2; new ktable */ 264 /* stack: new p; ktable p1; ktable p2; new ktable */
265 concattable(L, -3, -1); /* from p1 into new ktable */ 265 concattable(L, -3, -1); /* from p1 into new ktable */
266 concattable(L, -2, -1); /* from p2 into new ktable */ 266 concattable(L, -2, -1); /* from p2 into new ktable */
267 lua_setfenv(L, -4); /* new ktable becomes 'p' environment */ 267 lua_setuservalue(L, -4); /* new ktable becomes 'p' environment */
268 lua_pop(L, 2); /* pop other ktables */ 268 lua_pop(L, 2); /* pop other ktables */
269 correctkeys(t2, n1); /* correction for indices from p2 */ 269 correctkeys(t2, n1); /* correction for indices from p2 */
270 } 270 }
@@ -275,8 +275,8 @@ static void joinktables (lua_State *L, int p1, TTree *t2, int p2) {
275** copy 'ktable' of element 'idx' to new tree (on top of stack) 275** copy 'ktable' of element 'idx' to new tree (on top of stack)
276*/ 276*/
277static void copyktable (lua_State *L, int idx) { 277static void copyktable (lua_State *L, int idx) {
278 lua_getfenv(L, idx); 278 lua_getuservalue(L, idx);
279 lua_setfenv(L, -2); 279 lua_setuservalue(L, -2);
280} 280}
281 281
282 282
@@ -287,8 +287,8 @@ static void copyktable (lua_State *L, int idx) {
287*/ 287*/
288static void mergektable (lua_State *L, int idx, TTree *stree) { 288static void mergektable (lua_State *L, int idx, TTree *stree) {
289 int n; 289 int n;
290 lua_getfenv(L, -1); /* get ktables */ 290 lua_getuservalue(L, -1); /* get ktables */
291 lua_getfenv(L, idx); 291 lua_getuservalue(L, idx);
292 n = concattable(L, -1, -2); 292 n = concattable(L, -1, -2);
293 lua_pop(L, 2); /* remove both ktables */ 293 lua_pop(L, 2); /* remove both ktables */
294 correctkeys(stree, n); 294 correctkeys(stree, n);
@@ -339,7 +339,7 @@ static Pattern *getpattern (lua_State *L, int idx) {
339 339
340 340
341static int getsize (lua_State *L, int idx) { 341static int getsize (lua_State *L, int idx) {
342 return (lua_objlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1; 342 return (lua_rawlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1;
343} 343}
344 344
345 345
@@ -352,12 +352,16 @@ static TTree *gettree (lua_State *L, int idx, int *len) {
352 352
353 353
354/* 354/*
355** create a pattern 355** create a pattern. Set its uservalue (the 'ktable') equal to its
356** metatable. (It could be any empty sequence; the metatable is at
357** hand here, so we use it.)
356*/ 358*/
357static TTree *newtree (lua_State *L, int len) { 359static TTree *newtree (lua_State *L, int len) {
358 size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern); 360 size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern);
359 Pattern *p = (Pattern *)lua_newuserdata(L, size); 361 Pattern *p = (Pattern *)lua_newuserdata(L, size);
360 luaL_getmetatable(L, PATTERN_T); 362 luaL_getmetatable(L, PATTERN_T);
363 lua_pushvalue(L, -1);
364 lua_setuservalue(L, -3);
361 lua_setmetatable(L, -2); 365 lua_setmetatable(L, -2);
362 p->code = NULL; p->codesize = 0; 366 p->code = NULL; p->codesize = 0;
363 return p->tree; 367 return p->tree;
@@ -688,7 +692,7 @@ static int lp_behind (lua_State *L) {
688 TTree *tree; 692 TTree *tree;
689 TTree *tree1 = getpatt(L, 1, NULL); 693 TTree *tree1 = getpatt(L, 1, NULL);
690 int n = fixedlen(tree1); 694 int n = fixedlen(tree1);
691 luaL_argcheck(L, n > 0, 1, "pattern may not have fixed length"); 695 luaL_argcheck(L, n >= 0, 1, "pattern may not have fixed length");
692 luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures"); 696 luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures");
693 luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind"); 697 luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind");
694 tree = newroot1sib(L, TBehind); 698 tree = newroot1sib(L, TBehind);
@@ -822,10 +826,8 @@ static int lp_tablecapture (lua_State *L) {
822static int lp_groupcapture (lua_State *L) { 826static int lp_groupcapture (lua_State *L) {
823 if (lua_isnoneornil(L, 2)) 827 if (lua_isnoneornil(L, 2))
824 return capture_aux(L, Cgroup, 0); 828 return capture_aux(L, Cgroup, 0);
825 else { 829 else
826 luaL_checkstring(L, 2);
827 return capture_aux(L, Cgroup, 2); 830 return capture_aux(L, Cgroup, 2);
828 }
829} 831}
830 832
831 833
@@ -856,7 +858,7 @@ static int lp_argcapture (lua_State *L) {
856 858
857 859
858static int lp_backref (lua_State *L) { 860static int lp_backref (lua_State *L) {
859 luaL_checkstring(L, 1); 861 luaL_checkany(L, 1);
860 newemptycapkey(L, Cbackref, 1); 862 newemptycapkey(L, Cbackref, 1);
861 return 1; 863 return 1;
862} 864}
@@ -954,7 +956,7 @@ static int collectrules (lua_State *L, int arg, int *totalsize) {
954 lua_pushnil(L); /* prepare to traverse grammar table */ 956 lua_pushnil(L); /* prepare to traverse grammar table */
955 while (lua_next(L, arg) != 0) { 957 while (lua_next(L, arg) != 0) {
956 if (lua_tonumber(L, -2) == 1 || 958 if (lua_tonumber(L, -2) == 1 ||
957 lua_equal(L, -2, postab + 1)) { /* initial rule? */ 959 lp_equal(L, -2, postab + 1)) { /* initial rule? */
958 lua_pop(L, 1); /* remove value (keep key for lua_next) */ 960 lua_pop(L, 1); /* remove value (keep key for lua_next) */
959 continue; 961 continue;
960 } 962 }
@@ -1031,36 +1033,40 @@ static int verifyerror (lua_State *L, int *passed, int npassed) {
1031 1033
1032/* 1034/*
1033** Check whether a rule can be left recursive; raise an error in that 1035** Check whether a rule can be left recursive; raise an error in that
1034** case; otherwise return 1 iff pattern is nullable. Assume ktable at 1036** case; otherwise return 1 iff pattern is nullable.
1035** the top of the stack. 1037** The return value is used to check sequences, where the second pattern
1038** is only relevant if the first is nullable.
1039** Parameter 'nb' works as an accumulator, to allow tail calls in
1040** choices. ('nb' true makes function returns true.)
1041** Assume ktable at the top of the stack.
1036*/ 1042*/
1037static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed, 1043static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed,
1038 int nullable) { 1044 int nb) {
1039 tailcall: 1045 tailcall:
1040 switch (tree->tag) { 1046 switch (tree->tag) {
1041 case TChar: case TSet: case TAny: 1047 case TChar: case TSet: case TAny:
1042 case TFalse: case TThrow: /* labeled failure */ 1048 case TFalse: case TThrow: /* labeled failure */
1043 return nullable; /* cannot pass from here */ 1049 return nb; /* cannot pass from here */
1044 case TTrue: 1050 case TTrue:
1045 case TBehind: /* look-behind cannot have calls */ 1051 case TBehind: /* look-behind cannot have calls */
1046 return 1; 1052 return 1;
1047 case TNot: case TAnd: case TRep: 1053 case TNot: case TAnd: case TRep:
1048 /* return verifyrule(L, sib1(tree), passed, npassed, 1); */ 1054 /* return verifyrule(L, sib1(tree), passed, npassed, 1); */
1049 tree = sib1(tree); nullable = 1; goto tailcall; 1055 tree = sib1(tree); nb = 1; goto tailcall;
1050 case TCapture: case TRunTime: 1056 case TCapture: case TRunTime:
1051 /* return verifyrule(L, sib1(tree), passed, npassed); */ 1057 /* return verifyrule(L, sib1(tree), passed, npassed, nb); */
1052 tree = sib1(tree); goto tailcall; 1058 tree = sib1(tree); goto tailcall;
1053 case TCall: 1059 case TCall:
1054 /* return verifyrule(L, sib2(tree), passed, npassed); */ 1060 /* return verifyrule(L, sib2(tree), passed, npassed, nb); */
1055 tree = sib2(tree); goto tailcall; 1061 tree = sib2(tree); goto tailcall;
1056 case TSeq: /* only check 2nd child if first is nullable */ 1062 case TSeq: /* only check 2nd child if first is nb */
1057 if (!verifyrule(L, sib1(tree), passed, npassed, 0)) 1063 if (!verifyrule(L, sib1(tree), passed, npassed, 0))
1058 return nullable; 1064 return nb;
1059 /* else return verifyrule(L, sib2(tree), passed, npassed); */ 1065 /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */
1060 tree = sib2(tree); goto tailcall; 1066 tree = sib2(tree); goto tailcall;
1061 case TChoice: case TLabChoice: /* must check both children */ /* labeled failure */ 1067 case TChoice: case TLabChoice: /* must check both children */ /* labeled failure */
1062 nullable = verifyrule(L, sib1(tree), passed, npassed, nullable); 1068 nb = verifyrule(L, sib1(tree), passed, npassed, nb);
1063 /* return verifyrule(L, sib2(tree), passed, npassed, nullable); */ 1069 /* return verifyrule(L, sib2(tree), passed, npassed, nb); */
1064 tree = sib2(tree); goto tailcall; 1070 tree = sib2(tree); goto tailcall;
1065 case TRule: 1071 case TRule:
1066 if (npassed >= MAXRULES) 1072 if (npassed >= MAXRULES)
@@ -1103,7 +1109,7 @@ static void verifygrammar (lua_State *L, TTree *grammar) {
1103*/ 1109*/
1104static void initialrulename (lua_State *L, TTree *grammar, int frule) { 1110static void initialrulename (lua_State *L, TTree *grammar, int frule) {
1105 if (sib1(grammar)->key == 0) { /* initial rule is not referenced? */ 1111 if (sib1(grammar)->key == 0) { /* initial rule is not referenced? */
1106 int n = lua_objlen(L, -1) + 1; /* index for name */ 1112 int n = lua_rawlen(L, -1) + 1; /* index for name */
1107 lua_pushvalue(L, frule); /* rule's name */ 1113 lua_pushvalue(L, frule); /* rule's name */
1108 lua_rawseti(L, -2, n); /* ktable was on the top of the stack */ 1114 lua_rawseti(L, -2, n); /* ktable was on the top of the stack */
1109 sib1(grammar)->key = n; 1115 sib1(grammar)->key = n;
@@ -1119,9 +1125,9 @@ static TTree *newgrammar (lua_State *L, int arg) {
1119 luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules"); 1125 luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules");
1120 g->tag = TGrammar; g->u.n = n; 1126 g->tag = TGrammar; g->u.n = n;
1121 lua_newtable(L); /* create 'ktable' */ 1127 lua_newtable(L); /* create 'ktable' */
1122 lua_setfenv(L, -2); 1128 lua_setuservalue(L, -2);
1123 buildgrammar(L, g, frule, n); 1129 buildgrammar(L, g, frule, n);
1124 lua_getfenv(L, -1); /* get 'ktable' for new tree */ 1130 lua_getuservalue(L, -1); /* get 'ktable' for new tree */
1125 finalfix(L, frule - 1, g, sib1(g)); 1131 finalfix(L, frule - 1, g, sib1(g));
1126 initialrulename(L, g, frule); 1132 initialrulename(L, g, frule);
1127 verifygrammar(L, g); 1133 verifygrammar(L, g);
@@ -1135,7 +1141,7 @@ static TTree *newgrammar (lua_State *L, int arg) {
1135 1141
1136 1142
1137static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) { 1143static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) {
1138 lua_getfenv(L, idx); /* push 'ktable' (may be used by 'finalfix') */ 1144 lua_getuservalue(L, idx); /* push 'ktable' (may be used by 'finalfix') */
1139 finalfix(L, 0, NULL, p->tree); 1145 finalfix(L, 0, NULL, p->tree);
1140 lua_pop(L, 1); /* remove 'ktable' */ 1146 lua_pop(L, 1); /* remove 'ktable' */
1141 return compile(L, p); 1147 return compile(L, p);
@@ -1146,7 +1152,7 @@ static int lp_printtree (lua_State *L) {
1146 TTree *tree = getpatt(L, 1, NULL); 1152 TTree *tree = getpatt(L, 1, NULL);
1147 int c = lua_toboolean(L, 2); 1153 int c = lua_toboolean(L, 2);
1148 if (c) { 1154 if (c) {
1149 lua_getfenv(L, 1); /* push 'ktable' (may be used by 'finalfix') */ 1155 lua_getuservalue(L, 1); /* push 'ktable' (may be used by 'finalfix') */
1150 finalfix(L, 0, NULL, tree); 1156 finalfix(L, 0, NULL, tree);
1151 lua_pop(L, 1); /* remove 'ktable' */ 1157 lua_pop(L, 1); /* remove 'ktable' */
1152 } 1158 }
@@ -1201,9 +1207,8 @@ static int lp_match (lua_State *L) {
1201 const char *sfail = NULL; /* labeled failure */ 1207 const char *sfail = NULL; /* labeled failure */
1202 lua_pushnil(L); /* initialize subscache */ 1208 lua_pushnil(L); /* initialize subscache */
1203 lua_pushlightuserdata(L, capture); /* initialize caplistidx */ 1209 lua_pushlightuserdata(L, capture); /* initialize caplistidx */
1204 lua_getfenv(L, 1); /* initialize penvidx */ 1210 lua_getuservalue(L, 1); /* initialize penvidx */
1205 r = match(L, s, s + i, s + l, code, capture, ptop, &labelf, &sfail); /* labeled failure */ 1211 r = match(L, s, s + i, s + l, code, capture, ptop, &labelf, &sfail); /* labeled failure */
1206 /*printf("sfail = %s\n", sfail);*/
1207 if (r == NULL) { /* labeled failure begin */ 1212 if (r == NULL) { /* labeled failure begin */
1208 long long int j = 0; 1213 long long int j = 0;
1209 int n = 1; 1214 int n = 1;
@@ -1230,8 +1235,12 @@ static int lp_match (lua_State *L) {
1230** ======================================================= 1235** =======================================================
1231*/ 1236*/
1232 1237
1238/* maximum limit for stack size */
1239#define MAXLIM (INT_MAX / 100)
1240
1233static int lp_setmax (lua_State *L) { 1241static int lp_setmax (lua_State *L) {
1234 luaL_optinteger(L, 1, -1); 1242 lua_Integer lim = luaL_checkinteger(L, 1);
1243 luaL_argcheck(L, 0 < lim && lim <= MAXLIM, 1, "out of range");
1235 lua_settop(L, 1); 1244 lua_settop(L, 1);
1236 lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); 1245 lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
1237 return 0; 1246 return 0;
@@ -1255,8 +1264,7 @@ static int lp_type (lua_State *L) {
1255 1264
1256int lp_gc (lua_State *L) { 1265int lp_gc (lua_State *L) {
1257 Pattern *p = getpattern(L, 1); 1266 Pattern *p = getpattern(L, 1);
1258 if (p->codesize > 0) 1267 realloccode(L, p, 0); /* delete code block */
1259 realloccode(L, p, 0);
1260 return 0; 1268 return 0;
1261} 1269}
1262 1270
@@ -1336,13 +1344,13 @@ static struct luaL_Reg metareg[] = {
1336}; 1344};
1337 1345
1338 1346
1339int luaopen_lpeglabel (lua_State *L); /* labeld failure */ 1347int luaopen_lpeglabel (lua_State *L); /* labeled failure */
1340int luaopen_lpeglabel (lua_State *L) { /* labeled failure */ 1348int luaopen_lpeglabel (lua_State *L) { /* labeled failure */
1341 luaL_newmetatable(L, PATTERN_T); 1349 luaL_newmetatable(L, PATTERN_T);
1342 lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */ 1350 lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */
1343 lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); 1351 lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
1344 luaL_register(L, NULL, metareg); 1352 luaL_setfuncs(L, metareg, 0);
1345 luaL_register(L, "lpeglabel", pattreg); /* labeled failure */ 1353 luaL_newlib(L, pattreg);
1346 lua_pushvalue(L, -1); 1354 lua_pushvalue(L, -1);
1347 lua_setfield(L, -3, "__index"); 1355 lua_setfield(L, -3, "__index");
1348 return 1; 1356 return 1;
diff --git a/lptypes.h b/lptypes.h
index 1f30bc4..560ddbb 100644
--- a/lptypes.h
+++ b/lptypes.h
@@ -1,7 +1,7 @@
1/* 1/*
2** $Id: lptypes.h,v 1.11 2015/03/04 16:38:00 roberto Exp $ 2** $Id: lptypes.h,v 1.14 2015/09/28 17:17:41 roberto Exp $
3** LPeg - PEG pattern matching for Lua 3** LPeg - PEG pattern matching for Lua
4** Copyright 2007-2014, Lua.org & PUC-Rio (see 'lpeg.html' for license) 4** Copyright 2007-2015, Lua.org & PUC-Rio (see 'lpeg.html' for license)
5** written by Roberto Ierusalimschy 5** written by Roberto Ierusalimschy
6*/ 6*/
7 7
@@ -19,7 +19,7 @@
19#include "lua.h" 19#include "lua.h"
20 20
21 21
22#define VERSION "0.12.2" 22#define VERSION "1.0.0"
23 23
24 24
25#define PATTERN_T "lpeg-pattern" 25#define PATTERN_T "lpeg-pattern"
@@ -27,31 +27,31 @@
27 27
28 28
29/* 29/*
30** compatibility with Lua 5.2 30** compatibility with Lua 5.1
31*/ 31*/
32#if (LUA_VERSION_NUM >= 502) 32#if (LUA_VERSION_NUM == 501)
33 33
34#undef lua_equal 34#define lp_equal lua_equal
35#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
36 35
37#undef lua_getfenv 36#define lua_getuservalue lua_getfenv
38#define lua_getfenv lua_getuservalue 37#define lua_setuservalue lua_setfenv
39#undef lua_setfenv
40#define lua_setfenv lua_setuservalue
41 38
42#undef lua_objlen 39#define lua_rawlen lua_objlen
43#define lua_objlen lua_rawlen
44 40
45#undef luaL_register 41#define luaL_setfuncs(L,f,n) luaL_register(L,NULL,f)
46#define luaL_register(L,n,f) \ 42#define luaL_newlib(L,f) luaL_register(L,"lpeg",f)
47 { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); }
48 43
49#endif 44#endif
50 45
51 46
47#if !defined(lp_equal)
48#define lp_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
49#endif
50
51
52/* default maximum size for call/backtrack stack */ 52/* default maximum size for call/backtrack stack */
53#if !defined(MAXBACK) 53#if !defined(MAXBACK)
54#define MAXBACK 100 54#define MAXBACK 400
55#endif 55#endif
56 56
57 57
diff --git a/lpvm.c b/lpvm.c
index 3ae22f5..c15d543 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lpvm.c,v 1.5 2013/04/12 16:29:49 roberto Exp $ 2** $Id: lpvm.c,v 1.6 2015/09/28 17:01:25 roberto Exp $
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
@@ -18,7 +18,7 @@
18 18
19/* initial size for call/backtrack stack */ 19/* initial size for call/backtrack stack */
20#if !defined(INITBACK) 20#if !defined(INITBACK)
21#define INITBACK 100 21#define INITBACK MAXBACK
22#endif 22#endif
23 23
24 24
@@ -71,7 +71,7 @@ static Stack *doublestack (lua_State *L, Stack **stacklimit, int ptop) {
71 max = lua_tointeger(L, -1); /* maximum allowed size */ 71 max = lua_tointeger(L, -1); /* maximum allowed size */
72 lua_pop(L, 1); 72 lua_pop(L, 1);
73 if (n >= max) /* already at maximum size? */ 73 if (n >= max) /* already at maximum size? */
74 luaL_error(L, "too many pending calls/choices"); 74 luaL_error(L, "backtrack stack overflow (current limit is %d)", max);
75 newn = 2 * n; /* new size */ 75 newn = 2 * n; /* new size */
76 if (newn > max) newn = max; 76 if (newn > max) newn = max;
77 newstack = (Stack *)lua_newuserdata(L, newn * sizeof(Stack)); 77 newstack = (Stack *)lua_newuserdata(L, newn * sizeof(Stack));
diff --git a/makefile b/makefile
index 51d3b15..5728b38 100644
--- a/makefile
+++ b/makefile
@@ -40,7 +40,7 @@ lpeglabel.so: $(FILES)
40 40
41$(FILES): makefile 41$(FILES): makefile
42 42
43test: test.lua relabel.lua lpeglabel.so 43test: test.lua testlabel.lua testerrors.lua relabel.lua lpeglabel.so
44 lua test.lua 44 lua test.lua
45 lua testlabel.lua 45 lua testlabel.lua
46 lua testerrors.lua 46 lua testerrors.lua
diff --git a/test.lua b/test.lua
index 86cda61..73297c6 100755
--- a/test.lua
+++ b/test.lua
@@ -1,6 +1,6 @@
1#!/usr/bin/env lua5.1 1#!/usr/bin/env lua
2 2
3-- $Id: test.lua,v 1.106 2015/03/04 17:31:33 roberto Exp $ 3-- $Id: test.lua,v 1.109 2015/09/28 17:01:25 roberto Exp $
4 4
5-- require"strict" -- just to be pedantic 5-- require"strict" -- just to be pedantic
6 6
@@ -16,9 +16,6 @@ local unpack = rawget(table, "unpack") or unpack
16local loadstring = rawget(_G, "loadstring") or load 16local loadstring = rawget(_G, "loadstring") or load
17 17
18 18
19-- most tests here do not need much stack space
20m.setmaxstack(5)
21
22local any = m.P(1) 19local any = m.P(1)
23local space = m.S" \t\n"^0 20local space = m.S" \t\n"^0
24 21
@@ -291,6 +288,13 @@ assert(m.match(m.P"ab"^-1 - "c", "abcd") == 3)
291 288
292p = ('Aa' * ('Bb' * ('Cc' * m.P'Dd'^0)^0)^0)^-1 289p = ('Aa' * ('Bb' * ('Cc' * m.P'Dd'^0)^0)^0)^-1
293assert(p:match("AaBbCcDdBbCcDdDdDdBb") == 21) 290assert(p:match("AaBbCcDdBbCcDdDdDdBb") == 21)
291
292
293-- bug in 0.12.2
294-- p = { ('ab' ('c' 'ef'?)*)? }
295p = m.C(('ab' * ('c' * m.P'ef'^-1)^0)^-1)
296s = "abcefccefc"
297assert(s == p:match(s))
294 298
295 299
296pi = "3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510" 300pi = "3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510"
@@ -352,10 +356,16 @@ checkeq(t, {hi = 10, ho = 20})
352t = p:match'abc' 356t = p:match'abc'
353checkeq(t, {hi = 10, ho = 20, 'a', 'b', 'c'}) 357checkeq(t, {hi = 10, ho = 20, 'a', 'b', 'c'})
354 358
359-- non-string group names
360p = m.Ct(m.Cg(1, print) * m.Cg(1, 23.5) * m.Cg(1, io))
361t = p:match('abcdefghij')
362assert(t[print] == 'a' and t[23.5] == 'b' and t[io] == 'c')
363
355 364
356-- test for error messages 365-- test for error messages
357local function checkerr (msg, f, ...) 366local function checkerr (msg, f, ...)
358 local st, err = pcall(f, ...) 367 local st, err = pcall(f, ...)
368 print(st, err)
359 assert(not st and m.match({ m.P(msg) + 1 * m.V(1) }, err)) 369 assert(not st and m.match({ m.P(msg) + 1 * m.V(1) }, err))
360end 370end
361 371
@@ -594,9 +604,9 @@ assert(not p:match(string.rep("011", 10001)))
594-- this grammar does need backtracking info. 604-- this grammar does need backtracking info.
595local lim = 10000 605local lim = 10000
596p = m.P{ '0' * m.V(1) + '0' } 606p = m.P{ '0' * m.V(1) + '0' }
597checkerr("too many pending", m.match, p, string.rep("0", lim)) 607checkerr("stack overflow", m.match, p, string.rep("0", lim))
598m.setmaxstack(2*lim) 608m.setmaxstack(2*lim)
599checkerr("too many pending", m.match, p, string.rep("0", lim)) 609checkerr("stack overflow", m.match, p, string.rep("0", lim))
600m.setmaxstack(2*lim + 4) 610m.setmaxstack(2*lim + 4)
601assert(m.match(p, string.rep("0", lim)) == lim + 1) 611assert(m.match(p, string.rep("0", lim)) == lim + 1)
602 612
@@ -605,7 +615,7 @@ p = m.P{ ('a' * m.V(1))^0 * 'b' + 'c' }
605m.setmaxstack(200) 615m.setmaxstack(200)
606assert(p:match(string.rep('a', 180) .. 'c' .. string.rep('b', 180)) == 362) 616assert(p:match(string.rep('a', 180) .. 'c' .. string.rep('b', 180)) == 362)
607 617
608m.setmaxstack(5) -- restore original limit 618m.setmaxstack(100) -- restore low limit
609 619
610-- tests for optional start position 620-- tests for optional start position
611assert(m.match("a", "abc", 1)) 621assert(m.match("a", "abc", 1))
@@ -737,6 +747,10 @@ t = {m.match(m.Cc(nil,nil,4) * m.Cc(nil,3) * m.Cc(nil, nil) / g / g, "")}
737t1 = {1,1,nil,nil,4,nil,3,nil,nil} 747t1 = {1,1,nil,nil,4,nil,3,nil,nil}
738for i=1,10 do assert(t[i] == t1[i]) end 748for i=1,10 do assert(t[i] == t1[i]) end
739 749
750-- bug in 0.12.2: ktable with only nil could be eliminated when joining
751-- with a pattern without ktable
752assert((m.P"aaa" * m.Cc(nil)):match"aaa" == nil)
753
740t = {m.match((m.C(1) / function (x) return x, x.."x" end)^0, "abc")} 754t = {m.match((m.C(1) / function (x) return x, x.."x" end)^0, "abc")}
741checkeq(t, {"a", "ax", "b", "bx", "c", "cx"}) 755checkeq(t, {"a", "ax", "b", "bx", "c", "cx"})
742 756
@@ -944,6 +958,13 @@ p = m.Cg(m.C(1) * m.C(1), "k") * m.Ct(m.Cb("k"))
944t = p:match("ab") 958t = p:match("ab")
945checkeq(t, {"a", "b"}) 959checkeq(t, {"a", "b"})
946 960
961p = m.P(true)
962for i = 1, 10 do p = p * m.Cg(1, i) end
963for i = 1, 10 do
964 local p = p * m.Cb(i)
965 assert(p:match('abcdefghij') == string.sub('abcdefghij', i, i))
966end
967
947 968
948t = {} 969t = {}
949function foo (p) t[#t + 1] = p; return p .. "x" end 970function foo (p) t[#t + 1] = p; return p .. "x" end
@@ -1420,7 +1441,8 @@ errmsg('aaaa', "rule 'aaaa'")
1420errmsg('a', 'outside') 1441errmsg('a', 'outside')
1421errmsg('b <- a', 'undefined') 1442errmsg('b <- a', 'undefined')
1422errmsg("x <- 'a' x <- 'b'", 'already defined') 1443errmsg("x <- 'a' x <- 'b'", 'already defined')
1423-- errmsg("'a' -", "near '-'") 1444-- error message is different because Matthew rewrote 're.lua'
1445--errmsg("'a' -", "near '-'")
1424 1446
1425 1447
1426print"OK" 1448print"OK"