diff options
author | Sergio Queiroz <sqmedeiros@gmail.com> | 2017-07-06 11:21:56 -0300 |
---|---|---|
committer | Sergio Queiroz <sqmedeiros@gmail.com> | 2017-07-06 11:21:56 -0300 |
commit | 8ee42c29131e1c7de48575d6d8a9b24ea6977cbd (patch) | |
tree | 4267e0cf0609a909be1f2eaea17d11b0efc12c98 /lpcode.c | |
parent | aad9b29e755d67d6cb4e4b861111df0d173819ce (diff) | |
download | lpeglabel-8ee42c29131e1c7de48575d6d8a9b24ea6977cbd.tar.gz lpeglabel-8ee42c29131e1c7de48575d6d8a9b24ea6977cbd.tar.bz2 lpeglabel-8ee42c29131e1c7de48575d6d8a9b24ea6977cbd.zip |
Updating lpeglabel to the codebase of LPeg 1.0.1
Diffstat (limited to 'lpcode.c')
-rw-r--r-- | lpcode.c | 87 |
1 files changed, 58 insertions, 29 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpcode.c,v 1.23 2015/06/12 18:36:47 roberto Exp $ | 2 | ** $Id: lpcode.c,v 1.24 2016/09/15 17:46:13 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,6 +126,27 @@ int tocharset (TTree *tree, Charset *cs) { | |||
126 | 126 | ||
127 | 127 | ||
128 | /* | 128 | /* |
129 | ** Visit a TCall node taking care to stop recursion. If node not yet | ||
130 | ** visited, return 'f(sib2(tree))', otherwise return 'def' (default | ||
131 | ** value) | ||
132 | */ | ||
133 | static int callrecursive (TTree *tree, int f (TTree *t), int def) { | ||
134 | int key = tree->key; | ||
135 | assert(tree->tag == TCall); | ||
136 | assert(sib2(tree)->tag == TRule); | ||
137 | if (key == 0) /* node already visited? */ | ||
138 | return def; /* return default value */ | ||
139 | else { /* first visit */ | ||
140 | int result; | ||
141 | tree->key = 0; /* mark call as already visited */ | ||
142 | result = f(sib2(tree)); /* go to called rule */ | ||
143 | tree->key = key; /* restore tree */ | ||
144 | return result; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | |||
149 | /* | ||
129 | ** Check whether a pattern tree has captures | 150 | ** Check whether a pattern tree has captures |
130 | */ | 151 | */ |
131 | int hascaptures (TTree *tree) { | 152 | int hascaptures (TTree *tree) { |
@@ -134,14 +155,17 @@ int hascaptures (TTree *tree) { | |||
134 | case TCapture: case TRunTime: | 155 | case TCapture: case TRunTime: |
135 | return 1; | 156 | return 1; |
136 | case TCall: | 157 | case TCall: |
137 | tree = sib2(tree); goto tailcall; /* return hascaptures(sib2(tree)); */ | 158 | return callrecursive(tree, hascaptures, 0); |
159 | case TRule: /* do not follow siblings */ | ||
160 | tree = sib1(tree); goto tailcall; | ||
138 | case TOpenCall: assert(0); | 161 | case TOpenCall: assert(0); |
139 | default: { | 162 | default: { |
140 | switch (numsiblings[tree->tag]) { | 163 | switch (numsiblings[tree->tag]) { |
141 | case 1: /* return hascaptures(sib1(tree)); */ | 164 | case 1: /* return hascaptures(sib1(tree)); */ |
142 | tree = sib1(tree); goto tailcall; | 165 | tree = sib1(tree); goto tailcall; |
143 | case 2: | 166 | case 2: |
144 | if (hascaptures(sib1(tree))) return 1; | 167 | if (hascaptures(sib1(tree))) |
168 | return 1; | ||
145 | /* else return hascaptures(sib2(tree)); */ | 169 | /* else return hascaptures(sib2(tree)); */ |
146 | tree = sib2(tree); goto tailcall; | 170 | tree = sib2(tree); goto tailcall; |
147 | default: assert(numsiblings[tree->tag] == 0); return 0; | 171 | default: assert(numsiblings[tree->tag] == 0); return 0; |
@@ -211,39 +235,42 @@ int checkaux (TTree *tree, int pred) { | |||
211 | 235 | ||
212 | /* | 236 | /* |
213 | ** number of characters to match a pattern (or -1 if variable) | 237 | ** number of characters to match a pattern (or -1 if variable) |
214 | ** ('count' avoids infinite loops for grammars) | ||
215 | */ | 238 | */ |
216 | int fixedlenx (TTree *tree, int count, int len) { | 239 | int fixedlen (TTree *tree) { |
240 | int len = 0; /* to accumulate in tail calls */ | ||
217 | tailcall: | 241 | tailcall: |
218 | switch (tree->tag) { | 242 | switch (tree->tag) { |
219 | case TChar: case TSet: case TAny: | 243 | case TChar: case TSet: case TAny: |
220 | return len + 1; | 244 | return len + 1; |
221 | case TFalse: case TTrue: case TNot: case TAnd: case TBehind: | 245 | case TFalse: case TTrue: case TNot: case TAnd: case TBehind: |
222 | return len; | 246 | return len; |
223 | case TRep: case TRunTime: case TOpenCall: | 247 | case TRep: case TRunTime: case TOpenCall: |
224 | case TThrow: /* labeled failure */ | 248 | case TThrow: /* labeled failure */ |
225 | return -1; | 249 | return -1; |
226 | case TCapture: case TRule: case TGrammar: | 250 | case TCapture: case TRule: case TGrammar: |
227 | /* return fixedlenx(sib1(tree), count); */ | 251 | /* return fixedlen(sib1(tree)); */ |
228 | tree = sib1(tree); goto tailcall; | 252 | tree = sib1(tree); goto tailcall; |
229 | case TCall: | 253 | case TCall: { |
230 | if (count++ >= MAXRULES) | 254 | int n1 = callrecursive(tree, fixedlen, -1); |
231 | return -1; /* may be a loop */ | 255 | if (n1 < 0) |
232 | /* else return fixedlenx(sib2(tree), count); */ | 256 | return -1; |
233 | tree = sib2(tree); goto tailcall; | 257 | else |
258 | return len + n1; | ||
259 | } | ||
234 | case TSeq: case TRecov: { /* labeled failure */ | 260 | case TSeq: case TRecov: { /* labeled failure */ |
235 | len = fixedlenx(sib1(tree), count, len); | 261 | int n1 = fixedlen(sib1(tree)); |
236 | if (len < 0) return -1; | 262 | if (n1 < 0) |
237 | /* else return fixedlenx(sib2(tree), count, len); */ | 263 | return -1; |
238 | tree = sib2(tree); goto tailcall; | 264 | /* else return fixedlen(sib2(tree)) + len; */ |
265 | len += n1; tree = sib2(tree); goto tailcall; | ||
239 | } | 266 | } |
240 | case TChoice: { | 267 | case TChoice: { |
241 | int n1, n2; | 268 | int n1 = fixedlen(sib1(tree)); |
242 | n1 = fixedlenx(sib1(tree), count, len); | 269 | int n2 = fixedlen(sib2(tree)); |
243 | if (n1 < 0) return -1; | 270 | if (n1 != n2 || n1 < 0) |
244 | n2 = fixedlenx(sib2(tree), count, len); | 271 | return -1; |
245 | if (n1 == n2) return n1; | 272 | else |
246 | else return -1; | 273 | return len + n1; |
247 | } | 274 | } |
248 | default: assert(0); return 0; | 275 | default: assert(0); return 0; |
249 | }; | 276 | }; |
@@ -287,7 +314,7 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) { | |||
287 | loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */ | 314 | loopset(i, firstset->cs[i] = follow->cs[i]); /* follow = fullset(?) */ |
288 | return 1; | 315 | return 1; |
289 | } | 316 | } |
290 | case TChoice: { | 317 | case TChoice: { |
291 | Charset csaux; | 318 | Charset csaux; |
292 | int e1 = getfirst(sib1(tree), follow, firstset); | 319 | int e1 = getfirst(sib1(tree), follow, firstset); |
293 | int e2 = getfirst(sib2(tree), follow, &csaux); | 320 | int e2 = getfirst(sib2(tree), follow, &csaux); |
@@ -378,7 +405,7 @@ static int headfail (TTree *tree) { | |||
378 | if (!nofail(sib2(tree))) return 0; | 405 | if (!nofail(sib2(tree))) return 0; |
379 | /* else return headfail(sib1(tree)); */ | 406 | /* else return headfail(sib1(tree)); */ |
380 | tree = sib1(tree); goto tailcall; | 407 | tree = sib1(tree); goto tailcall; |
381 | case TChoice: case TRecov: /* labeled failure */ | 408 | case TChoice: case TRecov: /* labeled failure */ |
382 | if (!headfail(sib1(tree))) return 0; | 409 | if (!headfail(sib1(tree))) return 0; |
383 | /* else return headfail(sib2(tree)); */ | 410 | /* else return headfail(sib2(tree)); */ |
384 | tree = sib2(tree); goto tailcall; | 411 | tree = sib2(tree); goto tailcall; |
@@ -433,8 +460,9 @@ int sizei (const Instruction *i) { | |||
433 | return 2; | 460 | return 2; |
434 | case IThrow: /* labeled failure */ | 461 | case IThrow: /* labeled failure */ |
435 | return 1; | 462 | return 1; |
436 | case IRecov: | 463 | case IRecov: |
437 | return (CHARSETINSTSIZE - 1) + 2; /* labeled failure */ | 464 | return (CHARSETINSTSIZE - 1) + 2; /* labeled failure */ |
465 | |||
438 | default: return 1; | 466 | default: return 1; |
439 | } | 467 | } |
440 | } | 468 | } |
@@ -750,9 +778,10 @@ static void codeand (CompileState *compst, TTree *tree, int tt) { | |||
750 | 778 | ||
751 | 779 | ||
752 | /* | 780 | /* |
753 | ** Captures: if pattern has fixed (and not too big) length, use | 781 | ** Captures: if pattern has fixed (and not too big) length, and it |
754 | ** a single IFullCapture instruction after the match; otherwise, | 782 | ** has no nested captures, use a single IFullCapture instruction |
755 | ** enclose the pattern with OpenCapture - CloseCapture. | 783 | ** after the match; otherwise, enclose the pattern with OpenCapture - |
784 | ** CloseCapture. | ||
756 | */ | 785 | */ |
757 | static void codecapture (CompileState *compst, TTree *tree, int tt, | 786 | static void codecapture (CompileState *compst, TTree *tree, int tt, |
758 | const Charset *fl) { | 787 | const Charset *fl) { |