]>
Commit | Line | Data |
---|---|---|
1 | /*\r | |
2 | * build.c -- functions associated with building syntax diagrams.\r | |
3 | *\r | |
4 | * SOFTWARE RIGHTS\r | |
5 | *\r | |
6 | * We reserve no LEGAL rights to the Purdue Compiler Construction Tool\r | |
7 | * Set (PCCTS) -- PCCTS is in the public domain. An individual or\r | |
8 | * company may do whatever they wish with source code distributed with\r | |
9 | * PCCTS or the code generated by PCCTS, including the incorporation of\r | |
10 | * PCCTS, or its output, into commerical software.\r | |
11 | *\r | |
12 | * We encourage users to develop software with PCCTS. However, we do ask\r | |
13 | * that credit is given to us for developing PCCTS. By "credit",\r | |
14 | * we mean that if you incorporate our source code into one of your\r | |
15 | * programs (commercial product, research project, or otherwise) that you\r | |
16 | * acknowledge this fact somewhere in the documentation, research report,\r | |
17 | * etc... If you like PCCTS and have developed a nice tool with the\r | |
18 | * output, please mention that you developed it using PCCTS. In\r | |
19 | * addition, we ask that this header remain intact in our source code.\r | |
20 | * As long as these guidelines are kept, we expect to continue enhancing\r | |
21 | * this system and expect to make other tools available as they are\r | |
22 | * completed.\r | |
23 | *\r | |
24 | * ANTLR 1.33\r | |
25 | * Terence Parr\r | |
26 | * Parr Research Corporation\r | |
27 | * with Purdue University and AHPCRC, University of Minnesota\r | |
28 | * 1989-2001\r | |
29 | */\r | |
30 | \r | |
31 | #include <stdio.h>\r | |
32 | #include <stdlib.h>\r | |
33 | #include <ctype.h>\r | |
34 | #include "pcctscfg.h"\r | |
35 | #include "set.h"\r | |
36 | #include "syn.h"\r | |
37 | #include "hash.h"\r | |
38 | #include "generic.h"\r | |
39 | #include "dlgdef.h"\r | |
40 | \r | |
41 | #define SetBlk(g, t, approx, first_set_symbol) { \\r | |
42 | ((Junction *)g.left)->jtype = t; \\r | |
43 | ((Junction *)g.left)->approx = approx; \\r | |
44 | ((Junction *)g.left)->pFirstSetSymbol = first_set_symbol; \\r | |
45 | ((Junction *)g.left)->end = (Junction *) g.right; \\r | |
46 | ((Junction *)g.right)->jtype = EndBlk;}\r | |
47 | \r | |
48 | /* Add the parameter string 'parm' to the parms field of a block-type junction\r | |
49 | * g.left points to the sentinel node on a block. i.e. g.left->p1 points to\r | |
50 | * the actual junction with its jtype == some block-type.\r | |
51 | */\r | |
52 | void\r | |
53 | #ifdef __USE_PROTOS\r | |
54 | addParm( Node *p, char *parm )\r | |
55 | #else\r | |
56 | addParm( p, parm )\r | |
57 | Node *p;\r | |
58 | char *parm;\r | |
59 | #endif\r | |
60 | {\r | |
61 | char *q = (char *) malloc( strlen(parm) + 1 );\r | |
62 | require(p!=NULL, "addParm: NULL object\n");\r | |
63 | require(q!=NULL, "addParm: unable to alloc parameter\n");\r | |
64 | \r | |
65 | strcpy(q, parm);\r | |
66 | if ( p->ntype == nRuleRef )\r | |
67 | {\r | |
68 | ((RuleRefNode *)p)->parms = q;\r | |
69 | }\r | |
70 | else if ( p->ntype == nJunction )\r | |
71 | {\r | |
72 | ((Junction *)p)->parm = q; /* only one parameter allowed on subrules */\r | |
73 | }\r | |
74 | else fatal_internal("addParm: invalid node for adding parm");\r | |
75 | }\r | |
76 | \r | |
77 | /*\r | |
78 | * Build an action node for the syntax diagram\r | |
79 | *\r | |
80 | * buildAction(ACTION) ::= --o-->ACTION-->o--\r | |
81 | *\r | |
82 | * Where o is a junction node.\r | |
83 | */\r | |
84 | Graph\r | |
85 | #ifdef __USE_PROTOS\r | |
86 | buildAction( char *action, int file, int line, int is_predicate )\r | |
87 | #else\r | |
88 | buildAction( action, file, line, is_predicate )\r | |
89 | char *action;\r | |
90 | int file;\r | |
91 | int line;\r | |
92 | int is_predicate;\r | |
93 | #endif\r | |
94 | {\r | |
95 | Junction *j1, *j2;\r | |
96 | Graph g;\r | |
97 | ActionNode *a;\r | |
98 | require(action!=NULL, "buildAction: invalid action");\r | |
99 | \r | |
100 | j1 = newJunction();\r | |
101 | j2 = newJunction();\r | |
102 | a = newActionNode();\r | |
103 | a->action = (char *) malloc( strlen(action)+1 );\r | |
104 | require(a->action!=NULL, "buildAction: cannot alloc space for action\n");\r | |
105 | strcpy(a->action, action);\r | |
106 | j1->p1 = (Node *) a;\r | |
107 | a->next = (Node *) j2;\r | |
108 | a->is_predicate = is_predicate;\r | |
109 | \r | |
110 | if (is_predicate) {\r | |
111 | PredEntry *predEntry;\r | |
112 | char *t;\r | |
113 | char *key;\r | |
114 | char *u;\r | |
115 | int inverted=0;\r | |
116 | \r | |
117 | t=key=(char *)calloc(1,strlen(a->action)+1);\r | |
118 | \r | |
119 | for (u=a->action; *u != '\0' ; u++) {\r | |
120 | if (*u != ' ') {\r | |
121 | if (t==key && *u=='!') {\r | |
122 | inverted=!inverted;\r | |
123 | } else {\r | |
124 | *t++=*u;\r | |
125 | };\r | |
126 | };\r | |
127 | };\r | |
128 | \r | |
129 | *t='\0';\r | |
130 | \r | |
131 | \r | |
132 | predEntry=(PredEntry *)hash_get(Pname,key);\r | |
133 | a->predEntry=predEntry;\r | |
134 | if (predEntry != NULL) a->inverted=inverted;\r | |
135 | } else {\r | |
136 | /* MR12c */ char *strStart=a->action;\r | |
137 | /* MR12c */ char *strEnd;\r | |
138 | /* MR12c */ strEnd=strStart+strlen(strStart)-1;\r | |
139 | /* MR12c */ for ( ; strEnd >= strStart && isspace(*strEnd); strEnd--) *strEnd=0;\r | |
140 | /* MR12c */ while (*strStart != '\0' && isspace(*strStart)) strStart++;\r | |
141 | /* MR12c */ if (ci_strequ(strStart,"nohoist")) {\r | |
142 | /* MR12c */ a->noHoist=1;\r | |
143 | /* MR12c */ }\r | |
144 | }\r | |
145 | \r | |
146 | g.left = (Node *) j1; g.right = (Node *) j2;\r | |
147 | a->file = file;\r | |
148 | a->line = line;\r | |
149 | a->rname = CurRule; /* MR10 */\r | |
150 | return g;\r | |
151 | }\r | |
152 | \r | |
153 | /*\r | |
154 | * Build a token node for the syntax diagram\r | |
155 | *\r | |
156 | * buildToken(TOKEN) ::= --o-->TOKEN-->o--\r | |
157 | *\r | |
158 | * Where o is a junction node.\r | |
159 | */\r | |
160 | Graph\r | |
161 | #ifdef __USE_PROTOS\r | |
162 | buildToken( char *text )\r | |
163 | #else\r | |
164 | buildToken( text )\r | |
165 | char *text;\r | |
166 | #endif\r | |
167 | {\r | |
168 | Junction *j1, *j2;\r | |
169 | Graph g;\r | |
170 | TokNode *t;\r | |
171 | require(text!=NULL, "buildToken: invalid token name");\r | |
172 | \r | |
173 | j1 = newJunction();\r | |
174 | j2 = newJunction();\r | |
175 | t = newTokNode();\r | |
176 | t->altstart = CurAltStart;\r | |
177 | if ( *text == '"' ) {t->label=FALSE; t->token = addTexpr( text );}\r | |
178 | else {t->label=TRUE; t->token = addTname( text );}\r | |
179 | j1->p1 = (Node *) t;\r | |
180 | t->next = (Node *) j2;\r | |
181 | g.left = (Node *) j1; g.right = (Node *) j2;\r | |
182 | return g;\r | |
183 | }\r | |
184 | \r | |
185 | /*\r | |
186 | * Build a wild-card node for the syntax diagram\r | |
187 | *\r | |
188 | * buildToken(TOKEN) ::= --o-->'.'-->o--\r | |
189 | *\r | |
190 | * Where o is a junction node.\r | |
191 | */\r | |
192 | Graph\r | |
193 | #ifdef __USE_PROTOS\r | |
194 | buildWildCard( char *text )\r | |
195 | #else\r | |
196 | buildWildCard( text )\r | |
197 | char *text;\r | |
198 | #endif\r | |
199 | {\r | |
200 | Junction *j1, *j2;\r | |
201 | Graph g;\r | |
202 | TokNode *t;\r | |
203 | TCnode *w;\r | |
204 | TermEntry *p;\r | |
205 | require(text!=NULL, "buildWildCard: invalid token name");\r | |
206 | \r | |
207 | j1 = newJunction();\r | |
208 | j2 = newJunction();\r | |
209 | t = newTokNode();\r | |
210 | \r | |
211 | /* If the ref a wild card, make a token class for it */\r | |
212 | if ( Tnum(WildCardString) == 0 )\r | |
213 | {\r | |
214 | w = newTCnode;\r | |
215 | w->tok = addTname( WildCardString );\r | |
216 | set_orel(w->tok, &imag_tokens);\r | |
217 | set_orel(w->tok, &tokclasses);\r | |
218 | WildCardToken = w->tok;\r | |
219 | require((p=(TermEntry *)hash_get(Tname, WildCardString)) != NULL,\r | |
220 | "hash table mechanism is broken");\r | |
221 | p->classname = 1; /* entry is class name, not token */\r | |
222 | p->tclass = w; /* save ptr to this tclass def */\r | |
223 | list_add(&tclasses, (char *)w);\r | |
224 | }\r | |
225 | else {\r | |
226 | p=(TermEntry *)hash_get(Tname, WildCardString);\r | |
227 | require( p!= NULL, "hash table mechanism is broken");\r | |
228 | w = p->tclass;\r | |
229 | }\r | |
230 | \r | |
231 | t->token = w->tok;\r | |
232 | t->wild_card = 1;\r | |
233 | t->tclass = w;\r | |
234 | \r | |
235 | t->altstart = CurAltStart;\r | |
236 | j1->p1 = (Node *) t;\r | |
237 | t->next = (Node *) j2;\r | |
238 | g.left = (Node *) j1; g.right = (Node *) j2;\r | |
239 | return g;\r | |
240 | }\r | |
241 | \r | |
242 | void\r | |
243 | #ifdef __USE_PROTOS\r | |
244 | setUpperRange(TokNode *t, char *text)\r | |
245 | #else\r | |
246 | setUpperRange(t, text)\r | |
247 | TokNode *t;\r | |
248 | char *text;\r | |
249 | #endif\r | |
250 | {\r | |
251 | require(t!=NULL, "setUpperRange: NULL token node");\r | |
252 | require(text!=NULL, "setUpperRange: NULL token string");\r | |
253 | \r | |
254 | if ( *text == '"' ) {t->upper_range = addTexpr( text );}\r | |
255 | else {t->upper_range = addTname( text );}\r | |
256 | }\r | |
257 | \r | |
258 | /*\r | |
259 | * Build a rule reference node of the syntax diagram\r | |
260 | *\r | |
261 | * buildRuleRef(RULE) ::= --o-->RULE-->o--\r | |
262 | *\r | |
263 | * Where o is a junction node.\r | |
264 | *\r | |
265 | * If rule 'text' has been defined already, don't alloc new space to store string.\r | |
266 | * Set r->text to point to old copy in string table.\r | |
267 | */\r | |
268 | Graph\r | |
269 | #ifdef __USE_PROTOS\r | |
270 | buildRuleRef( char *text )\r | |
271 | #else\r | |
272 | buildRuleRef( text )\r | |
273 | char *text;\r | |
274 | #endif\r | |
275 | {\r | |
276 | Junction *j1, *j2;\r | |
277 | Graph g;\r | |
278 | RuleRefNode *r;\r | |
279 | RuleEntry *p;\r | |
280 | require(text!=NULL, "buildRuleRef: invalid rule name");\r | |
281 | \r | |
282 | j1 = newJunction();\r | |
283 | j2 = newJunction();\r | |
284 | r = newRNode();\r | |
285 | r->altstart = CurAltStart;\r | |
286 | r->assign = NULL;\r | |
287 | if ( (p=(RuleEntry *)hash_get(Rname, text)) != NULL ) r->text = p->str;\r | |
288 | else r->text = mystrdup( text );\r | |
289 | j1->p1 = (Node *) r;\r | |
290 | r->next = (Node *) j2;\r | |
291 | g.left = (Node *) j1; g.right = (Node *) j2;\r | |
292 | return g;\r | |
293 | }\r | |
294 | \r | |
295 | /*\r | |
296 | * Or two subgraphs into one graph via:\r | |
297 | *\r | |
298 | * Or(G1, G2) ::= --o-G1-o--\r | |
299 | * | ^\r | |
300 | * v |\r | |
301 | * o-G2-o\r | |
302 | *\r | |
303 | * Set the altnum of junction starting G2 to 1 + altnum of junction starting G1.\r | |
304 | * If, however, the G1 altnum is 0, make it 1 and then\r | |
305 | * make G2 altnum = G1 altnum + 1.\r | |
306 | */\r | |
307 | Graph\r | |
308 | #ifdef __USE_PROTOS\r | |
309 | Or( Graph g1, Graph g2 )\r | |
310 | #else\r | |
311 | Or( g1, g2 )\r | |
312 | Graph g1;\r | |
313 | Graph g2;\r | |
314 | #endif\r | |
315 | {\r | |
316 | Graph g;\r | |
317 | require(g1.left != NULL, "Or: invalid graph");\r | |
318 | require(g2.left != NULL && g2.right != NULL, "Or: invalid graph");\r | |
319 | \r | |
320 | ((Junction *)g1.left)->p2 = g2.left;\r | |
321 | ((Junction *)g2.right)->p1 = g1.right;\r | |
322 | /* set altnums */\r | |
323 | if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;\r | |
324 | ((Junction *)g2.left)->altnum = ((Junction *)g1.left)->altnum + 1;\r | |
325 | g.left = g2.left;\r | |
326 | g.right = g1.right;\r | |
327 | return g;\r | |
328 | }\r | |
329 | \r | |
330 | /*\r | |
331 | * Catenate two subgraphs\r | |
332 | *\r | |
333 | * Cat(G1, G2) ::= --o-G1-o-->o-G2-o--\r | |
334 | * Cat(NULL,G2)::= --o-G2-o--\r | |
335 | * Cat(G1,NULL)::= --o-G1-o--\r | |
336 | */\r | |
337 | Graph\r | |
338 | #ifdef __USE_PROTOS\r | |
339 | Cat( Graph g1, Graph g2 )\r | |
340 | #else\r | |
341 | Cat( g1, g2 )\r | |
342 | Graph g1;\r | |
343 | Graph g2;\r | |
344 | #endif\r | |
345 | {\r | |
346 | Graph g;\r | |
347 | \r | |
348 | if ( g1.left == NULL && g1.right == NULL ) return g2;\r | |
349 | if ( g2.left == NULL && g2.right == NULL ) return g1;\r | |
350 | ((Junction *)g1.right)->p1 = g2.left;\r | |
351 | g.left = g1.left;\r | |
352 | g.right = g2.right;\r | |
353 | return g;\r | |
354 | }\r | |
355 | \r | |
356 | /*\r | |
357 | * Make a subgraph an optional block\r | |
358 | *\r | |
359 | * makeOpt(G) ::= --o-->o-G-o-->o--\r | |
360 | * | ^\r | |
361 | * v |\r | |
362 | * o-------o\r | |
363 | *\r | |
364 | * Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found.\r | |
365 | *\r | |
366 | * The node on the far right is added so that every block owns its own\r | |
367 | * EndBlk node.\r | |
368 | */\r | |
369 | Graph\r | |
370 | #ifdef __USE_PROTOS\r | |
371 | makeOpt( Graph g1, int approx, char * pFirstSetSymbol )\r | |
372 | #else\r | |
373 | makeOpt( g1, approx, pFirstSetSymbol )\r | |
374 | Graph g1;\r | |
375 | int approx;\r | |
376 | char * pFirstSetSymbol;\r | |
377 | #endif\r | |
378 | {\r | |
379 | Junction *j1,*j2,*p;\r | |
380 | Graph g;\r | |
381 | require(g1.left != NULL && g1.right != NULL, "makeOpt: invalid graph");\r | |
382 | \r | |
383 | j1 = newJunction();\r | |
384 | j2 = newJunction();\r | |
385 | ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */\r | |
386 | \r | |
387 | /* MR21\r | |
388 | *\r | |
389 | * There is code in genBlk which recognizes the node created\r | |
390 | * by emptyAlt() as a special case and bypasses it. We don't\r | |
391 | * want this to happen for the optBlk.\r | |
392 | */\r | |
393 | \r | |
394 | g = emptyAlt3(); /* MR21 */\r | |
395 | if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;\r | |
396 | ((Junction *)g.left)->altnum = ((Junction *)g1.left)->altnum + 1;\r | |
397 | for(p=(Junction *)g1.left; p->p2!=NULL; p=(Junction *)p->p2)\r | |
398 | {;} /* find last alt */\r | |
399 | p->p2 = g.left; /* add optional alternative */\r | |
400 | ((Junction *)g.right)->p1 = (Node *)j2; /* opt alt points to EndBlk */\r | |
401 | g1.right = (Node *)j2;\r | |
402 | SetBlk(g1, aOptBlk, approx, pFirstSetSymbol);\r | |
403 | j1->p1 = g1.left; /* add generic node in front */\r | |
404 | g.left = (Node *) j1;\r | |
405 | g.right = g1.right;\r | |
406 | return g;\r | |
407 | }\r | |
408 | \r | |
409 | /*\r | |
410 | * Make a graph into subblock\r | |
411 | *\r | |
412 | * makeBlk(G) ::= --o-->o-G-o-->o--\r | |
413 | *\r | |
414 | * The node on the far right is added so that every block owns its own\r | |
415 | * EndBlk node.\r | |
416 | */\r | |
417 | Graph\r | |
418 | #ifdef __USE_PROTOS\r | |
419 | makeBlk( Graph g1, int approx, char * pFirstSetSymbol )\r | |
420 | #else\r | |
421 | makeBlk( g1, approx, pFirstSetSymbol )\r | |
422 | Graph g1;\r | |
423 | int approx;\r | |
424 | char * pFirstSetSymbol;\r | |
425 | #endif\r | |
426 | {\r | |
427 | Junction *j,*j2;\r | |
428 | Graph g;\r | |
429 | require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph");\r | |
430 | \r | |
431 | j = newJunction();\r | |
432 | j2 = newJunction();\r | |
433 | ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */\r | |
434 | g1.right = (Node *)j2;\r | |
435 | SetBlk(g1, aSubBlk, approx, pFirstSetSymbol);\r | |
436 | j->p1 = g1.left; /* add node in front */\r | |
437 | g.left = (Node *) j;\r | |
438 | g.right = g1.right;\r | |
439 | \r | |
440 | return g;\r | |
441 | }\r | |
442 | \r | |
443 | /*\r | |
444 | * Make a subgraph into a loop (closure) block -- (...)*\r | |
445 | *\r | |
446 | * makeLoop(G) ::= |---|\r | |
447 | * v |\r | |
448 | * --o-->o-->o-G-o-->o--\r | |
449 | * | ^\r | |
450 | * v |\r | |
451 | * o-----------o\r | |
452 | *\r | |
453 | * After making loop, always place generic node out front. It becomes\r | |
454 | * the start of enclosing block. The aLoopBlk is the target of the loop.\r | |
455 | *\r | |
456 | * Loop blks have TWO EndBlk nodes--the far right and the node that loops back\r | |
457 | * to the aLoopBlk node. Node with which we can branch past loop == aLoopBegin and\r | |
458 | * one which is loop target == aLoopBlk.\r | |
459 | * The branch-past (initial) aLoopBegin node has end\r | |
460 | * pointing to the last EndBlk node. The loop-target node has end==NULL.\r | |
461 | *\r | |
462 | * Loop blocks have a set of locks (from 1..CLL_k) on the aLoopBlk node.\r | |
463 | */\r | |
464 | Graph\r | |
465 | #ifdef __USE_PROTOS\r | |
466 | makeLoop( Graph g1, int approx, char * pFirstSetSymbol )\r | |
467 | #else\r | |
468 | makeLoop( g1, approx, pFirstSetSymbol)\r | |
469 | Graph g1;\r | |
470 | int approx;\r | |
471 | char * pFirstSetSymbol;\r | |
472 | #endif\r | |
473 | {\r | |
474 | Junction *back, *front, *begin;\r | |
475 | Graph g;\r | |
476 | require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph");\r | |
477 | \r | |
478 | back = newJunction();\r | |
479 | front = newJunction();\r | |
480 | begin = newJunction();\r | |
481 | g = emptyAlt3();\r | |
482 | ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */\r | |
483 | ((Junction *)g1.right)->p1 = (Node *) back; /* add node to G at end */\r | |
484 | ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */\r | |
485 | ((Junction *)g1.left)->jtype = aLoopBlk; /* mark 2nd aLoopBlk node */\r | |
486 | ((Junction *)g1.left)->end = (Junction *) g1.right;\r | |
487 | ((Junction *)g1.left)->lock = makelocks();\r | |
488 | ((Junction *)g1.left)->pred_lock = makelocks();\r | |
489 | g1.right = (Node *) back;\r | |
490 | begin->p1 = (Node *) g1.left;\r | |
491 | g1.left = (Node *) begin;\r | |
492 | begin->p2 = (Node *) g.left; /* make bypass arc */\r | |
493 | ((Junction *)g.right)->p1 = (Node *) back;\r | |
494 | SetBlk(g1, aLoopBegin, approx, pFirstSetSymbol);\r | |
495 | front->p1 = g1.left; /* add node to front */\r | |
496 | g1.left = (Node *) front;\r | |
497 | \r | |
498 | return g1;\r | |
499 | }\r | |
500 | \r | |
501 | /*\r | |
502 | * Make a subgraph into a plus block -- (...)+ -- 1 or more times\r | |
503 | *\r | |
504 | * makePlus(G) ::= |---|\r | |
505 | * v |\r | |
506 | * --o-->o-G-o-->o--\r | |
507 | *\r | |
508 | * After making loop, always place generic node out front. It becomes\r | |
509 | * the start of enclosing block. The aPlusBlk is the target of the loop.\r | |
510 | *\r | |
511 | * Plus blks have TWO EndBlk nodes--the far right and the node that loops back\r | |
512 | * to the aPlusBlk node.\r | |
513 | *\r | |
514 | * Plus blocks have a set of locks (from 1..CLL_k) on the aPlusBlk node.\r | |
515 | */\r | |
516 | Graph\r | |
517 | #ifdef __USE_PROTOS\r | |
518 | makePlus( Graph g1, int approx, char * pFirstSetSymbol)\r | |
519 | #else\r | |
520 | makePlus( g1, approx, pFirstSetSymbol)\r | |
521 | Graph g1;\r | |
522 | int approx;\r | |
523 | char * pFirstSetSymbol;\r | |
524 | #endif\r | |
525 | {\r | |
526 | int has_empty_alt_already = 0;\r | |
527 | Graph g;\r | |
528 | Junction *j2, *j3, *first_alt;\r | |
529 | Junction *last_alt=NULL, *p;\r | |
530 | require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph");\r | |
531 | \r | |
532 | first_alt = (Junction *)g1.left;\r | |
533 | j2 = newJunction();\r | |
534 | j3 = newJunction();\r | |
535 | if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1;\r | |
536 | ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */\r | |
537 | ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */\r | |
538 | ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */\r | |
539 | g1.right = (Node *) j2;\r | |
540 | SetBlk(g1, aPlusBlk, approx, pFirstSetSymbol);\r | |
541 | ((Junction *)g1.left)->lock = makelocks();\r | |
542 | ((Junction *)g1.left)->pred_lock = makelocks();\r | |
543 | j3->p1 = g1.left; /* add node to front */\r | |
544 | g1.left = (Node *) j3;\r | |
545 | \r | |
546 | /* add an optional branch which is the "exit" branch of loop */\r | |
547 | /* FIRST, check to ensure that there does not already exist\r | |
548 | * an optional path.\r | |
549 | */\r | |
550 | /* find last alt */\r | |
551 | for(p=first_alt; p!=NULL; p=(Junction *)p->p2)\r | |
552 | {\r | |
553 | if ( p->p1->ntype == nJunction &&\r | |
554 | p->p1!=NULL &&\r | |
555 | ((Junction *)p->p1)->jtype==Generic &&\r | |
556 | ((Junction *)p->p1)->p1!=NULL &&\r | |
557 | ((Junction *)((Junction *)p->p1)->p1)->jtype==EndBlk )\r | |
558 | {\r | |
559 | has_empty_alt_already = 1;\r | |
560 | }\r | |
561 | last_alt = p;\r | |
562 | }\r | |
563 | if ( !has_empty_alt_already )\r | |
564 | {\r | |
565 | require(last_alt!=NULL, "last_alt==NULL; bad (..)+");\r | |
566 | g = emptyAlt();\r | |
567 | last_alt->p2 = g.left;\r | |
568 | ((Junction *)g.right)->p1 = (Node *) j2;\r | |
569 | \r | |
570 | /* make sure lookahead computation ignores this alt for\r | |
571 | * FIRST("(..)+"); but it's still used for computing the FIRST\r | |
572 | * of each alternative.\r | |
573 | */\r | |
574 | ((Junction *)g.left)->ignore = 1;\r | |
575 | }\r | |
576 | \r | |
577 | return g1;\r | |
578 | }\r | |
579 | \r | |
580 | /*\r | |
581 | * Return an optional path: --o-->o--\r | |
582 | */\r | |
583 | \r | |
584 | Graph\r | |
585 | #ifdef __USE_PROTOS\r | |
586 | emptyAlt( void )\r | |
587 | #else\r | |
588 | emptyAlt( )\r | |
589 | #endif\r | |
590 | {\r | |
591 | Junction *j1, *j2;\r | |
592 | Graph g;\r | |
593 | \r | |
594 | j1 = newJunction();\r | |
595 | j2 = newJunction();\r | |
596 | j1->p1 = (Node *) j2;\r | |
597 | g.left = (Node *) j1;\r | |
598 | g.right = (Node *) j2;\r | |
599 | \r | |
600 | return g;\r | |
601 | }\r | |
602 | \r | |
603 | /* MR21\r | |
604 | *\r | |
605 | * There is code in genBlk which recognizes the node created\r | |
606 | * by emptyAlt() as a special case and bypasses it. We don't\r | |
607 | * want this to happen for the optBlk.\r | |
608 | */\r | |
609 | \r | |
610 | Graph\r | |
611 | #ifdef __USE_PROTOS\r | |
612 | emptyAlt3( void )\r | |
613 | #else\r | |
614 | emptyAlt3( )\r | |
615 | #endif\r | |
616 | {\r | |
617 | Junction *j1, *j2, *j3;\r | |
618 | Graph g;\r | |
619 | \r | |
620 | j1 = newJunction();\r | |
621 | j2 = newJunction();\r | |
622 | j3 = newJunction();\r | |
623 | j1->p1 = (Node *) j2;\r | |
624 | j2->p1 = (Node *) j3;\r | |
625 | g.left = (Node *) j1;\r | |
626 | g.right = (Node *) j3;\r | |
627 | \r | |
628 | return g;\r | |
629 | }\r | |
630 | \r | |
631 | /* N o d e A l l o c a t i o n */\r | |
632 | \r | |
633 | TokNode *\r | |
634 | #ifdef __USE_PROTOS\r | |
635 | newTokNode( void )\r | |
636 | #else\r | |
637 | newTokNode( )\r | |
638 | #endif\r | |
639 | {\r | |
640 | static TokNode *FreeList = NULL;\r | |
641 | TokNode *p, *newblk;\r | |
642 | \r | |
643 | if ( FreeList == NULL )\r | |
644 | {\r | |
645 | newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode));\r | |
646 | if ( newblk == NULL )\r | |
647 | fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));\r | |
648 | for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++)\r | |
649 | {\r | |
650 | p->next = (Node *)FreeList; /* add all new token nodes to FreeList */\r | |
651 | FreeList = p;\r | |
652 | }\r | |
653 | }\r | |
654 | p = FreeList;\r | |
655 | FreeList = (TokNode *)FreeList->next;/* remove a TokNode node */\r | |
656 | p->next = NULL; /* NULL the ptr we used */\r | |
657 | memset( (char *) p, 0, sizeof(TokNode)); /* MR10 */\r | |
658 | p->ntype = nToken;\r | |
659 | p->rname = CurRule;\r | |
660 | p->file = CurFile;\r | |
661 | p->line = zzline;\r | |
662 | p->altstart = NULL;\r | |
663 | \r | |
664 | return p;\r | |
665 | }\r | |
666 | \r | |
667 | RuleRefNode *\r | |
668 | #ifdef __USE_PROTOS\r | |
669 | newRNode( void )\r | |
670 | #else\r | |
671 | newRNode( )\r | |
672 | #endif\r | |
673 | {\r | |
674 | static RuleRefNode *FreeList = NULL;\r | |
675 | RuleRefNode *p, *newblk;\r | |
676 | \r | |
677 | if ( FreeList == NULL )\r | |
678 | {\r | |
679 | newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode));\r | |
680 | if ( newblk == NULL )\r | |
681 | fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));\r | |
682 | for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++)\r | |
683 | {\r | |
684 | p->next = (Node *)FreeList; /* add all new rref nodes to FreeList */\r | |
685 | FreeList = p;\r | |
686 | }\r | |
687 | }\r | |
688 | p = FreeList;\r | |
689 | FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */\r | |
690 | p->next = NULL; /* NULL the ptr we used */\r | |
691 | memset( (char *) p, 0, sizeof(RuleRefNode)); /* MR10 */\r | |
692 | p->ntype = nRuleRef;\r | |
693 | p->rname = CurRule;\r | |
694 | p->file = CurFile;\r | |
695 | p->line = zzline;\r | |
696 | p->astnode = ASTinclude;\r | |
697 | p->altstart = NULL;\r | |
698 | \r | |
699 | return p;\r | |
700 | }\r | |
701 | \r | |
702 | static int junctionSeqNumber=0; /* MR10 */\r | |
703 | \r | |
704 | Junction *\r | |
705 | #ifdef __USE_PROTOS\r | |
706 | newJunction( void )\r | |
707 | #else\r | |
708 | newJunction( )\r | |
709 | #endif\r | |
710 | {\r | |
711 | static Junction *FreeList = NULL;\r | |
712 | Junction *p, *newblk;\r | |
713 | \r | |
714 | if ( FreeList == NULL )\r | |
715 | {\r | |
716 | newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction));\r | |
717 | if ( newblk == NULL )\r | |
718 | fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));\r | |
719 | for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++)\r | |
720 | {\r | |
721 | p->p1 = (Node *)FreeList; /* add all new Junction nodes to FreeList */\r | |
722 | FreeList = p;\r | |
723 | }\r | |
724 | }\r | |
725 | p = FreeList;\r | |
726 | FreeList = (Junction *)FreeList->p1;/* remove a Junction node */\r | |
727 | p->p1 = NULL; /* NULL the ptr we used */\r | |
728 | memset( (char *) p, 0, sizeof(Junction)); /* MR10 */\r | |
729 | p->ntype = nJunction;\r | |
730 | p->visited = 0;\r | |
731 | p->jtype = Generic;\r | |
732 | p->rname = CurRule;\r | |
733 | p->file = CurFile;\r | |
734 | p->line = zzline;\r | |
735 | p->exception_label = NULL;\r | |
736 | p->fset = (set *) calloc(CLL_k+1, sizeof(set));\r | |
737 | require(p->fset!=NULL, "cannot allocate fset in newJunction");\r | |
738 | p->seq=++junctionSeqNumber; /* MR10 */\r | |
739 | \r | |
740 | return p;\r | |
741 | }\r | |
742 | \r | |
743 | ActionNode *\r | |
744 | #ifdef __USE_PROTOS\r | |
745 | newActionNode( void )\r | |
746 | #else\r | |
747 | newActionNode( )\r | |
748 | #endif\r | |
749 | {\r | |
750 | static ActionNode *FreeList = NULL;\r | |
751 | ActionNode *p, *newblk;\r | |
752 | \r | |
753 | if ( FreeList == NULL )\r | |
754 | {\r | |
755 | newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode));\r | |
756 | if ( newblk == NULL )\r | |
757 | fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule));\r | |
758 | for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++)\r | |
759 | {\r | |
760 | p->next = (Node *)FreeList; /* add all new Action nodes to FreeList */\r | |
761 | FreeList = p;\r | |
762 | }\r | |
763 | }\r | |
764 | p = FreeList;\r | |
765 | FreeList = (ActionNode *)FreeList->next;/* remove an Action node */\r | |
766 | memset( (char *) p, 0, sizeof(ActionNode)); /* MR10 */\r | |
767 | p->ntype = nAction;\r | |
768 | p->next = NULL; /* NULL the ptr we used */\r | |
769 | p->done = 0;\r | |
770 | p->pred_fail = NULL;\r | |
771 | p->guardpred = NULL;\r | |
772 | p->ampersandPred = NULL;\r | |
773 | return p;\r | |
774 | }\r | |
775 | \r | |
776 | /*\r | |
777 | * allocate the array of locks (1..CLL_k) used to inhibit infinite recursion.\r | |
778 | * Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs.\r | |
779 | * Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes.\r | |
780 | *\r | |
781 | * if ( lock[k]==TRUE ) then we have been here before looking for k tokens\r | |
782 | * of lookahead.\r | |
783 | */\r | |
784 | char *\r | |
785 | #ifdef __USE_PROTOS\r | |
786 | makelocks( void )\r | |
787 | #else\r | |
788 | makelocks( )\r | |
789 | #endif\r | |
790 | {\r | |
791 | char *p = (char *) calloc(CLL_k+1, sizeof(char));\r | |
792 | require(p!=NULL, "cannot allocate lock array");\r | |
793 | \r | |
794 | return p;\r | |
795 | }\r | |
796 | \r | |
797 | #if 0\r | |
798 | ** #ifdef __USE_PROTOS\r | |
799 | ** void my_memset(char *p,char value,int count)\r | |
800 | ** #else\r | |
801 | ** void my_memset(p,value,count)\r | |
802 | ** char *p;\r | |
803 | ** char value;\r | |
804 | ** int count;\r | |
805 | ** #endif\r | |
806 | ** {\r | |
807 | ** int i;\r | |
808 | **\r | |
809 | ** for (i=0; i<count; i++) {\r | |
810 | ** p[i]=value;\r | |
811 | ** };\r | |
812 | ** }\r | |
813 | #endif\r |