diff options
Diffstat (limited to 'lpprint.c')
-rw-r--r-- | lpprint.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/lpprint.c b/lpprint.c new file mode 100644 index 0000000..03239fd --- /dev/null +++ b/lpprint.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | ** $Id: lpprint.c,v 1.7 2013/04/12 16:29:49 roberto Exp $ | ||
3 | ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) | ||
4 | */ | ||
5 | |||
6 | #include <ctype.h> | ||
7 | #include <limits.h> | ||
8 | #include <stdio.h> | ||
9 | |||
10 | |||
11 | #include "lptypes.h" | ||
12 | #include "lpprint.h" | ||
13 | #include "lpcode.h" | ||
14 | |||
15 | |||
16 | #if defined(LPEG_DEBUG) | ||
17 | |||
18 | /* | ||
19 | ** {====================================================== | ||
20 | ** Printing patterns (for debugging) | ||
21 | ** ======================================================= | ||
22 | */ | ||
23 | |||
24 | |||
25 | void printcharset (const byte *st) { | ||
26 | int i; | ||
27 | printf("["); | ||
28 | for (i = 0; i <= UCHAR_MAX; i++) { | ||
29 | int first = i; | ||
30 | while (testchar(st, i) && i <= UCHAR_MAX) i++; | ||
31 | if (i - 1 == first) /* unary range? */ | ||
32 | printf("(%02x)", first); | ||
33 | else if (i - 1 > first) /* non-empty range? */ | ||
34 | printf("(%02x-%02x)", first, i - 1); | ||
35 | } | ||
36 | printf("]"); | ||
37 | } | ||
38 | |||
39 | |||
40 | static void printcapkind (int kind) { | ||
41 | const char *const modes[] = { | ||
42 | "close", "position", "constant", "backref", | ||
43 | "argument", "simple", "table", "function", | ||
44 | "query", "string", "num", "substitution", "fold", | ||
45 | "runtime", "group"}; | ||
46 | printf("%s", modes[kind]); | ||
47 | } | ||
48 | |||
49 | |||
50 | static void printjmp (const Instruction *op, const Instruction *p) { | ||
51 | printf("-> %d", (int)(p + (p + 1)->offset - op)); | ||
52 | } | ||
53 | |||
54 | |||
55 | void printinst (const Instruction *op, const Instruction *p) { | ||
56 | const char *const names[] = { | ||
57 | "any", "char", "set", | ||
58 | "testany", "testchar", "testset", | ||
59 | "span", "behind", | ||
60 | "ret", "end", | ||
61 | "choice", "jmp", "call", "open_call", | ||
62 | "commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup", | ||
63 | "fullcapture", "opencapture", "closecapture", "closeruntime", | ||
64 | "throw", "labeled_choice" /* labeled failure */ | ||
65 | }; | ||
66 | printf("%02ld: %s ", (long)(p - op), names[p->i.code]); | ||
67 | switch ((Opcode)p->i.code) { | ||
68 | case IChar: { | ||
69 | printf("'%c'", p->i.aux); | ||
70 | break; | ||
71 | } | ||
72 | case ITestChar: { | ||
73 | printf("'%c'", p->i.aux); printjmp(op, p); | ||
74 | break; | ||
75 | } | ||
76 | case IFullCapture: { | ||
77 | printcapkind(getkind(p)); | ||
78 | printf(" (size = %d) (idx = %d)", getoff(p), p->i.key); | ||
79 | break; | ||
80 | } | ||
81 | case IOpenCapture: { | ||
82 | printcapkind(getkind(p)); | ||
83 | printf(" (idx = %d)", p->i.key); | ||
84 | break; | ||
85 | } | ||
86 | case ISet: { | ||
87 | printcharset((p+1)->buff); | ||
88 | break; | ||
89 | } | ||
90 | case ITestSet: { | ||
91 | printcharset((p+2)->buff); printjmp(op, p); | ||
92 | break; | ||
93 | } | ||
94 | case ISpan: { | ||
95 | printcharset((p+1)->buff); | ||
96 | break; | ||
97 | } | ||
98 | case IOpenCall: { | ||
99 | printf("-> %d", (p + 1)->offset); | ||
100 | break; | ||
101 | } | ||
102 | case IBehind: { | ||
103 | printf("%d", p->i.aux); | ||
104 | break; | ||
105 | } | ||
106 | case IJmp: case ICall: case ICommit: case IChoice: | ||
107 | case IPartialCommit: case IBackCommit: case ITestAny: { | ||
108 | printjmp(op, p); | ||
109 | break; | ||
110 | } | ||
111 | case IThrow: { /* labeled failure */ | ||
112 | printf("%d", (p + 1)->labels); | ||
113 | break; | ||
114 | } | ||
115 | case ILabChoice: { /* labeled failure */ | ||
116 | printjmp(op, p); | ||
117 | printf(" %d", (p + 2)->labels); | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | default: break; | ||
122 | } | ||
123 | printf("\n"); | ||
124 | } | ||
125 | |||
126 | |||
127 | void printpatt (Instruction *p, int n) { | ||
128 | Instruction *op = p; | ||
129 | while (p < op + n) { | ||
130 | printinst(op, p); | ||
131 | p += sizei(p); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | |||
136 | #if defined(LPEG_DEBUG) | ||
137 | static void printcap (Capture *cap) { | ||
138 | printcapkind(cap->kind); | ||
139 | printf(" (idx: %d - size: %d) -> %p\n", cap->idx, cap->siz, cap->s); | ||
140 | } | ||
141 | |||
142 | |||
143 | void printcaplist (Capture *cap, Capture *limit) { | ||
144 | printf(">======\n"); | ||
145 | for (; cap->s && (limit == NULL || cap < limit); cap++) | ||
146 | printcap(cap); | ||
147 | printf("=======\n"); | ||
148 | } | ||
149 | #endif | ||
150 | |||
151 | /* }====================================================== */ | ||
152 | |||
153 | |||
154 | /* | ||
155 | ** {====================================================== | ||
156 | ** Printing trees (for debugging) | ||
157 | ** ======================================================= | ||
158 | */ | ||
159 | |||
160 | static const char *tagnames[] = { | ||
161 | "char", "set", "any", | ||
162 | "true", "false", | ||
163 | "rep", | ||
164 | "seq", "choice", | ||
165 | "not", "and", | ||
166 | "call", "opencall", "rule", "grammar", | ||
167 | "behind", | ||
168 | "capture", "run-time" | ||
169 | }; | ||
170 | |||
171 | |||
172 | void printtree (TTree *tree, int ident) { | ||
173 | int i; | ||
174 | for (i = 0; i < ident; i++) printf(" "); | ||
175 | printf("%s", tagnames[tree->tag]); | ||
176 | switch (tree->tag) { | ||
177 | case TChar: { | ||
178 | int c = tree->u.n; | ||
179 | if (isprint(c)) | ||
180 | printf(" '%c'\n", c); | ||
181 | else | ||
182 | printf(" (%02X)\n", c); | ||
183 | break; | ||
184 | } | ||
185 | case TSet: { | ||
186 | printcharset(treebuffer(tree)); | ||
187 | printf("\n"); | ||
188 | break; | ||
189 | } | ||
190 | case TOpenCall: case TCall: { | ||
191 | printf(" key: %d\n", tree->key); | ||
192 | break; | ||
193 | } | ||
194 | case TBehind: { | ||
195 | printf(" %d\n", tree->u.n); | ||
196 | printtree(sib1(tree), ident + 2); | ||
197 | break; | ||
198 | } | ||
199 | case TCapture: { | ||
200 | printf(" cap: %d key: %d n: %d\n", tree->cap, tree->key, tree->u.n); | ||
201 | printtree(sib1(tree), ident + 2); | ||
202 | break; | ||
203 | } | ||
204 | case TRule: { | ||
205 | printf(" n: %d key: %d\n", tree->cap, tree->key); | ||
206 | printtree(sib1(tree), ident + 2); | ||
207 | break; /* do not print next rule as a sibling */ | ||
208 | } | ||
209 | case TGrammar: { | ||
210 | TTree *rule = sib1(tree); | ||
211 | printf(" %d\n", tree->u.n); /* number of rules */ | ||
212 | for (i = 0; i < tree->u.n; i++) { | ||
213 | printtree(rule, ident + 2); | ||
214 | rule = sib2(rule); | ||
215 | } | ||
216 | assert(rule->tag == TTrue); /* sentinel */ | ||
217 | break; | ||
218 | } | ||
219 | default: { | ||
220 | int sibs = numsiblings[tree->tag]; | ||
221 | printf("\n"); | ||
222 | if (sibs >= 1) { | ||
223 | printtree(sib1(tree), ident + 2); | ||
224 | if (sibs >= 2) | ||
225 | printtree(sib2(tree), ident + 2); | ||
226 | } | ||
227 | break; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | |||
233 | void printktable (lua_State *L, int idx) { | ||
234 | int n, i; | ||
235 | lua_getfenv(L, idx); | ||
236 | if (lua_isnil(L, -1)) /* no ktable? */ | ||
237 | return; | ||
238 | n = lua_objlen(L, -1); | ||
239 | printf("["); | ||
240 | for (i = 1; i <= n; i++) { | ||
241 | printf("%d = ", i); | ||
242 | lua_rawgeti(L, -1, i); | ||
243 | if (lua_isstring(L, -1)) | ||
244 | printf("%s ", lua_tostring(L, -1)); | ||
245 | else | ||
246 | printf("%s ", lua_typename(L, lua_type(L, -1))); | ||
247 | lua_pop(L, 1); | ||
248 | } | ||
249 | printf("]\n"); | ||
250 | /* leave ktable at the stack */ | ||
251 | } | ||
252 | |||
253 | /* }====================================================== */ | ||
254 | |||
255 | #endif | ||