1 | /* |
2 | ** $Id: lpprint.c,v 1.10 2016/09/13 16:06:03 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 const char *capkind (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 | return 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 | }; |
65 | printf("%02ld: %s " , (long)(p - op), names[p->i.code]); |
66 | switch ((Opcode)p->i.code) { |
67 | case IChar: { |
68 | printf("'%c'" , p->i.aux); |
69 | break; |
70 | } |
71 | case ITestChar: { |
72 | printf("'%c'" , p->i.aux); printjmp(op, p); |
73 | break; |
74 | } |
75 | case IFullCapture: { |
76 | printf("%s (size = %d) (idx = %d)" , |
77 | capkind(getkind(p)), getoff(p), p->i.key); |
78 | break; |
79 | } |
80 | case IOpenCapture: { |
81 | printf("%s (idx = %d)" , capkind(getkind(p)), p->i.key); |
82 | break; |
83 | } |
84 | case ISet: { |
85 | printcharset((p+1)->buff); |
86 | break; |
87 | } |
88 | case ITestSet: { |
89 | printcharset((p+2)->buff); printjmp(op, p); |
90 | break; |
91 | } |
92 | case ISpan: { |
93 | printcharset((p+1)->buff); |
94 | break; |
95 | } |
96 | case IOpenCall: { |
97 | printf("-> %d" , (p + 1)->offset); |
98 | break; |
99 | } |
100 | case IBehind: { |
101 | printf("%d" , p->i.aux); |
102 | break; |
103 | } |
104 | case IJmp: case ICall: case ICommit: case IChoice: |
105 | case IPartialCommit: case IBackCommit: case ITestAny: { |
106 | printjmp(op, p); |
107 | break; |
108 | } |
109 | default: break; |
110 | } |
111 | printf("\n" ); |
112 | } |
113 | |
114 | |
115 | void printpatt (Instruction *p, int n) { |
116 | Instruction *op = p; |
117 | while (p < op + n) { |
118 | printinst(op, p); |
119 | p += sizei(p); |
120 | } |
121 | } |
122 | |
123 | |
124 | #if defined(LPEG_DEBUG) |
125 | static void printcap (Capture *cap) { |
126 | printf("%s (idx: %d - size: %d) -> %p\n" , |
127 | capkind(cap->kind), cap->idx, cap->siz, cap->s); |
128 | } |
129 | |
130 | |
131 | void printcaplist (Capture *cap, Capture *limit) { |
132 | printf(">======\n" ); |
133 | for (; cap->s && (limit == NULL || cap < limit); cap++) |
134 | printcap(cap); |
135 | printf("=======\n" ); |
136 | } |
137 | #endif |
138 | |
139 | /* }====================================================== */ |
140 | |
141 | |
142 | /* |
143 | ** {====================================================== |
144 | ** Printing trees (for debugging) |
145 | ** ======================================================= |
146 | */ |
147 | |
148 | static const char *tagnames[] = { |
149 | "char" , "set" , "any" , |
150 | "true" , "false" , |
151 | "rep" , |
152 | "seq" , "choice" , |
153 | "not" , "and" , |
154 | "call" , "opencall" , "rule" , "grammar" , |
155 | "behind" , |
156 | "capture" , "run-time" |
157 | }; |
158 | |
159 | |
160 | void printtree (TTree *tree, int ident) { |
161 | int i; |
162 | for (i = 0; i < ident; i++) printf(" " ); |
163 | printf("%s" , tagnames[tree->tag]); |
164 | switch (tree->tag) { |
165 | case TChar: { |
166 | int c = tree->u.n; |
167 | if (isprint(c)) |
168 | printf(" '%c'\n" , c); |
169 | else |
170 | printf(" (%02X)\n" , c); |
171 | break; |
172 | } |
173 | case TSet: { |
174 | printcharset(treebuffer(tree)); |
175 | printf("\n" ); |
176 | break; |
177 | } |
178 | case TOpenCall: case TCall: { |
179 | assert(sib2(tree)->tag == TRule); |
180 | printf(" key: %d (rule: %d)\n" , tree->key, sib2(tree)->cap); |
181 | break; |
182 | } |
183 | case TBehind: { |
184 | printf(" %d\n" , tree->u.n); |
185 | printtree(sib1(tree), ident + 2); |
186 | break; |
187 | } |
188 | case TCapture: { |
189 | printf(" kind: '%s' key: %d\n" , capkind(tree->cap), tree->key); |
190 | printtree(sib1(tree), ident + 2); |
191 | break; |
192 | } |
193 | case TRule: { |
194 | printf(" n: %d key: %d\n" , tree->cap, tree->key); |
195 | printtree(sib1(tree), ident + 2); |
196 | break; /* do not print next rule as a sibling */ |
197 | } |
198 | case TGrammar: { |
199 | TTree *rule = sib1(tree); |
200 | printf(" %d\n" , tree->u.n); /* number of rules */ |
201 | for (i = 0; i < tree->u.n; i++) { |
202 | printtree(rule, ident + 2); |
203 | rule = sib2(rule); |
204 | } |
205 | assert(rule->tag == TTrue); /* sentinel */ |
206 | break; |
207 | } |
208 | default: { |
209 | int sibs = numsiblings[tree->tag]; |
210 | printf("\n" ); |
211 | if (sibs >= 1) { |
212 | printtree(sib1(tree), ident + 2); |
213 | if (sibs >= 2) |
214 | printtree(sib2(tree), ident + 2); |
215 | } |
216 | break; |
217 | } |
218 | } |
219 | } |
220 | |
221 | |
222 | void printktable (lua_State *L, int idx) { |
223 | int n, i; |
224 | lua_getuservalue(L, idx); |
225 | if (lua_isnil(L, -1)) /* no ktable? */ |
226 | return; |
227 | n = lua_rawlen(L, -1); |
228 | printf("[" ); |
229 | for (i = 1; i <= n; i++) { |
230 | printf("%d = " , i); |
231 | lua_rawgeti(L, -1, i); |
232 | if (lua_isstring(L, -1)) |
233 | printf("%s " , lua_tostring(L, -1)); |
234 | else |
235 | printf("%s " , lua_typename(L, lua_type(L, -1))); |
236 | lua_pop(L, 1); |
237 | } |
238 | printf("]\n" ); |
239 | /* leave ktable at the stack */ |
240 | } |
241 | |
242 | /* }====================================================== */ |
243 | |
244 | #endif |
245 | |