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