1 /*
2 ** $Id: lpprint.c $
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
printcharset(const byte * st)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
capkind(int kind)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
printjmp(const Instruction * op,const Instruction * p)50 static void printjmp (const Instruction *op, const Instruction *p) {
51 printf("-> %d", (int)(p + (p + 1)->offset - op));
52 }
53
54
printinst(const Instruction * op,const Instruction * p)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
printpatt(Instruction * p,int n)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)
printcap(Capture * cap)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
printcaplist(Capture * cap,Capture * limit)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
printtree(TTree * tree,int ident)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
printktable(lua_State * L,int idx)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