diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-04-30 18:23:40 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-04-30 18:23:40 -0300 |
| commit | 1cc484a05cf9c7da8c859f3f52ea5a85009c4509 (patch) | |
| tree | 68983c515343cb1759e6b94a14f911fa8405f0d7 | |
| parent | eb8b906d5eb5113e7377f06afbfd641c1c5e6a1e (diff) | |
| download | lpeg-1cc484a05cf9c7da8c859f3f52ea5a85009c4509.tar.gz lpeg-1cc484a05cf9c7da8c859f3f52ea5a85009c4509.tar.bz2 lpeg-1cc484a05cf9c7da8c859f3f52ea5a85009c4509.zip | |
'nullable' ('checkaux') uses tag from 'verifyrule'
When checking whether a rule is nullable, 'checkaux' reuses tag
previously set by 'verifyrule'.
| -rw-r--r-- | lpcode.c | 7 | ||||
| -rw-r--r-- | lpprint.c | 23 | ||||
| -rw-r--r-- | lptree.c | 7 | ||||
| -rw-r--r-- | lptree.h | 7 | ||||
| -rwxr-xr-x | test.lua | 44 |
5 files changed, 75 insertions, 13 deletions
| @@ -139,7 +139,12 @@ int checkaux (TTree *tree, int pred) { | |||
| 139 | if (checkaux(sib2(tree), pred)) return 1; | 139 | if (checkaux(sib2(tree), pred)) return 1; |
| 140 | /* else return checkaux(sib1(tree), pred); */ | 140 | /* else return checkaux(sib1(tree), pred); */ |
| 141 | tree = sib1(tree); goto tailcall; | 141 | tree = sib1(tree); goto tailcall; |
| 142 | case TCapture: case TGrammar: case TRule: case TXInfo: | 142 | case TRule: |
| 143 | assert(tree->cap == RLNULL || tree->cap == RLNONNULL); | ||
| 144 | if (pred == PEnullable) | ||
| 145 | return (tree->cap == RLNULL); | ||
| 146 | /* else */ /* FALLTHROUGH */ | ||
| 147 | case TCapture: case TGrammar: case TXInfo: | ||
| 143 | /* return checkaux(sib1(tree), pred); */ | 148 | /* return checkaux(sib1(tree), pred); */ |
| 144 | tree = sib1(tree); goto tailcall; | 149 | tree = sib1(tree); goto tailcall; |
| 145 | case TCall: /* return checkaux(sib2(tree), pred); */ | 150 | case TCall: /* return checkaux(sib2(tree), pred); */ |
| @@ -278,10 +278,16 @@ static void printktable (lua_State *L, int idx) { | |||
| 278 | /* }====================================================== */ | 278 | /* }====================================================== */ |
| 279 | 279 | ||
| 280 | 280 | ||
| 281 | static int lp_printtree (lua_State *L) { | 281 | static Pattern * getp (lua_State *L, int compile) { |
| 282 | Pattern *p = (Pattern *)luaL_checkudata(L, 1, PATTERN_T); | 282 | Pattern *p = (Pattern *)luaL_checkudata(L, 1, PATTERN_T); |
| 283 | if (lua_toboolean(L, 2)) | 283 | if (compile && p->code == NULL) /* not compiled yet? */ |
| 284 | prepcompile(L, p, 1); | 284 | prepcompile(L, p, 1); |
| 285 | return p; | ||
| 286 | } | ||
| 287 | |||
| 288 | |||
| 289 | static int lp_printtree (lua_State *L) { | ||
| 290 | Pattern *p = getp(L, lua_toboolean(L, 2)); | ||
| 285 | printktable(L, 1); | 291 | printktable(L, 1); |
| 286 | printtree(p->tree, 0); | 292 | printtree(p->tree, 0); |
| 287 | return 0; | 293 | return 0; |
| @@ -289,17 +295,24 @@ static int lp_printtree (lua_State *L) { | |||
| 289 | 295 | ||
| 290 | 296 | ||
| 291 | static int lp_printcode (lua_State *L) { | 297 | static int lp_printcode (lua_State *L) { |
| 292 | Pattern *p = (Pattern *)luaL_checkudata(L, 1, PATTERN_T); | 298 | Pattern *p = getp(L, 1); |
| 293 | printktable(L, 1); | 299 | printktable(L, 1); |
| 294 | if (p->code == NULL) /* not compiled yet? */ | ||
| 295 | prepcompile(L, p, 1); | ||
| 296 | printpatt(p->code); | 300 | printpatt(p->code); |
| 297 | return 0; | 301 | return 0; |
| 298 | } | 302 | } |
| 299 | 303 | ||
| 304 | |||
| 305 | static int lp_nullable (lua_State *L) { | ||
| 306 | Pattern *p = getp(L, 0); | ||
| 307 | lua_pushboolean(L, nullable(p->tree)); | ||
| 308 | return 1; | ||
| 309 | } | ||
| 310 | |||
| 311 | |||
| 300 | static struct luaL_Reg debugreg[] = { | 312 | static struct luaL_Reg debugreg[] = { |
| 301 | {"ptree", lp_printtree}, | 313 | {"ptree", lp_printtree}, |
| 302 | {"pcode", lp_printcode}, | 314 | {"pcode", lp_printcode}, |
| 315 | {"nullable", lp_nullable}, | ||
| 303 | {NULL, NULL} | 316 | {NULL, NULL} |
| 304 | }; | 317 | }; |
| 305 | 318 | ||
| @@ -1016,13 +1016,6 @@ static int collectrules (lua_State *L, int arg, int *totalsize) { | |||
| 1016 | } | 1016 | } |
| 1017 | 1017 | ||
| 1018 | 1018 | ||
| 1019 | /* Status of a Rule */ | ||
| 1020 | #define RLNOTVISITED 0 /* rule not visited yet */ | ||
| 1021 | #define RLBEINGVISITED 1 /* rule is being visited */ | ||
| 1022 | #define RLNULL 2 /* rule was visited and is nullable */ | ||
| 1023 | #define RLNONNULL 3 /* rule was visited and is not nullable */ | ||
| 1024 | |||
| 1025 | |||
| 1026 | static void buildgrammar (lua_State *L, TTree *grammar, int frule, int n) { | 1019 | static void buildgrammar (lua_State *L, TTree *grammar, int frule, int n) { |
| 1027 | int i; | 1020 | int i; |
| 1028 | TTree *nd = sib1(grammar); /* auxiliary pointer to traverse the tree */ | 1021 | TTree *nd = sib1(grammar); /* auxiliary pointer to traverse the tree */ |
| @@ -63,6 +63,13 @@ typedef struct TTree { | |||
| 63 | } TTree; | 63 | } TTree; |
| 64 | 64 | ||
| 65 | 65 | ||
| 66 | /* Status of a Rule */ | ||
| 67 | #define RLNOTVISITED 0 /* rule not visited yet */ | ||
| 68 | #define RLBEINGVISITED 1 /* rule is being visited */ | ||
| 69 | #define RLNULL 2 /* rule was visited and is nullable */ | ||
| 70 | #define RLNONNULL 3 /* rule was visited and is not nullable */ | ||
| 71 | |||
| 72 | |||
| 66 | /* access to charset */ | 73 | /* access to charset */ |
| 67 | #define treebuffer(t) ((t)->u.set.bitmap) | 74 | #define treebuffer(t) ((t)->u.set.bitmap) |
| 68 | 75 | ||
| @@ -1662,6 +1662,50 @@ errmsg("x <- 'a' x <- 'b'", 'already defined') | |||
| 1662 | errmsg("'a' -", "near '-'") | 1662 | errmsg("'a' -", "near '-'") |
| 1663 | 1663 | ||
| 1664 | 1664 | ||
| 1665 | if m.nullable then | ||
| 1666 | print "testing nullable predicate" | ||
| 1667 | |||
| 1668 | |||
| 1669 | local bg = re.compile[[ | ||
| 1670 | A31 <- A30 A30 | ||
| 1671 | A30 <- A29 A29 | ||
| 1672 | A29 <- A28 A28 | ||
| 1673 | A28 <- A27 A27 | ||
| 1674 | A27 <- A26 A26 | ||
| 1675 | A26 <- A25 A25 | ||
| 1676 | A25 <- A24 A24 | ||
| 1677 | A24 <- A23 A23 | ||
| 1678 | A23 <- A22 A22 | ||
| 1679 | A22 <- A21 A21 | ||
| 1680 | A21 <- A20 A20 | ||
| 1681 | A20 <- A19 A19 | ||
| 1682 | A19 <- A18 A18 | ||
| 1683 | A18 <- A17 A17 | ||
| 1684 | A17 <- A16 A16 | ||
| 1685 | A16 <- A15 A15 | ||
| 1686 | A15 <- A14 A14 | ||
| 1687 | A14 <- A13 A13 | ||
| 1688 | A13 <- A12 A12 | ||
| 1689 | A12 <- A11 A11 | ||
| 1690 | A11 <- A10 A10 | ||
| 1691 | A10 <- A9 A9 | ||
| 1692 | A9 <- A8 A8 | ||
| 1693 | A8 <- A7 A7 | ||
| 1694 | A7 <- A6 A6 | ||
| 1695 | A6 <- A5 A5 | ||
| 1696 | A5 <- A4 A4 | ||
| 1697 | A4 <- A3 A3 | ||
| 1698 | A3 <- A2 A2 | ||
| 1699 | A2 <- A1 A1 | ||
| 1700 | A1 <- "" | ||
| 1701 | ]] | ||
| 1702 | |||
| 1703 | assert(bg:nullable()) | ||
| 1704 | assert((bg * bg):nullable()) | ||
| 1705 | assert(not (bg * bg * "a"):nullable()) | ||
| 1706 | assert(m.P(-1):nullable()) | ||
| 1707 | end | ||
| 1708 | |||
| 1665 | print"OK" | 1709 | print"OK" |
| 1666 | 1710 | ||
| 1667 | 1711 | ||
