misc.c
上传用户:itx_2006
上传日期:2007-01-06
资源大小:493k
文件大小:36k
源码类别:

编译器/解释器

开发平台:

Others

  1. /*
  2.  * misc.c
  3.  *
  4.  * Manage tokens, regular expressions.
  5.  * Print methods for debugging
  6.  * Compute follow lists onto tail ends of rules.
  7.  *
  8.  * The following functions are visible:
  9.  *
  10.  * int addTname(char *); Add token name
  11.  * int addTexpr(char *); Add token expression
  12.  * int Tnum(char *); Get number of expr/token
  13.  * void Tklink(char *, char *); Link a name with an expression
  14.  * int hasAction(expr); Does expr already have action assigned?
  15.  * void setHasAction(expr); Indicate that expr now has an action
  16.  * Entry *newEntry(char *,int); Create new table entry with certain size
  17.  * void list_add(ListNode **list, char *e)
  18.  *      void    list_free(ListNode **list, int freeData);   *** MR10 ***
  19.  * void list_apply(ListNode *list, void (*f)())
  20.  * void lexclass(char *m); switch to new/old lexical class
  21.  * void lexmode(int i); switch to old lexical class i
  22.  *
  23.  * SOFTWARE RIGHTS
  24.  *
  25.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  26.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  27.  * company may do whatever they wish with source code distributed with
  28.  * PCCTS or the code generated by PCCTS, including the incorporation of
  29.  * PCCTS, or its output, into commerical software.
  30.  *
  31.  * We encourage users to develop software with PCCTS.  However, we do ask
  32.  * that credit is given to us for developing PCCTS.  By "credit",
  33.  * we mean that if you incorporate our source code into one of your
  34.  * programs (commercial product, research project, or otherwise) that you
  35.  * acknowledge this fact somewhere in the documentation, research report,
  36.  * etc...  If you like PCCTS and have developed a nice tool with the
  37.  * output, please mention that you developed it using PCCTS.  In
  38.  * addition, we ask that this header remain intact in our source code.
  39.  * As long as these guidelines are kept, we expect to continue enhancing
  40.  * this system and expect to make other tools available as they are
  41.  * completed.
  42.  *
  43.  * ANTLR 1.33
  44.  * Terence Parr
  45.  * Parr Research Corporation
  46.  * with Purdue University and AHPCRC, University of Minnesota
  47.  * 1989-1998
  48.  */
  49. #include <stdio.h>
  50. #ifdef __cplusplus
  51. #ifndef __STDC__
  52. #define __STDC__
  53. #endif
  54. #endif
  55. #include "set.h"
  56. #include "syn.h"
  57. #include "hash.h"
  58. #include "generic.h"
  59. #include "dlgdef.h"
  60. static int tsize=TSChunk; /* size of token str arrays */
  61. static void
  62. #ifdef __STDC__
  63. RemapForcedTokensInSyntaxDiagram(Node *);
  64. #else
  65. RemapForcedTokensInSyntaxDiagram();
  66. #endif
  67. /* T o k e n  M a n i p u l a t i o n */
  68. /*
  69.  * add token 't' to the TokenStr/Expr array.  Make more room if necessary.
  70.  * 't' is either an expression or a token name.
  71.  *
  72.  * There is only one TokenStr array, but multiple ExprStr's.  Therefore,
  73.  * for each lex class (element of lclass) we must extend the ExprStr array.
  74.  * ExprStr's and TokenStr are always all the same size.
  75.  *
  76.  * Also, there is a Texpr hash table for each automaton.
  77.  */
  78. static void
  79. #ifdef __STDC__
  80. Ttrack( char *t )
  81. #else
  82. Ttrack( t )
  83. char *t;
  84. #endif
  85. {
  86. if ( TokenNum >= tsize ) /* terminal table overflow? */
  87. {
  88. char **p;
  89. int i, more, j;
  90. more = TSChunk * (1 + ((TokenNum-tsize) / TSChunk));
  91. tsize += more;
  92. TokenStr = (char **) realloc((char *)TokenStr, tsize*sizeof(char *));
  93. require(TokenStr != NULL, "Ttrack: can't extend TokenStr");
  94. for (i=0; i<NumLexClasses; i++)
  95. {
  96. lclass[i].exprs = (char **)
  97.   realloc((char *)lclass[i].exprs, tsize*sizeof(char *));
  98. require(lclass[i].exprs != NULL, "Ttrack: can't extend ExprStr");
  99. for (p= &lclass[i].exprs[tsize-more],j=1; j<=more; j++) *p++ = NULL;
  100. }
  101. for (p= &TokenStr[tsize-more],i=1; i<=more; i++) *p++ = NULL;
  102. lexmode( CurrentLexClass ); /* reset ExprStr in case table moved */
  103. }
  104. /* note: we use the actual ExprStr/TokenStr array
  105.  * here as TokenInd doesn't exist yet
  106.  */
  107. if ( *t == '"' ) ExprStr[TokenNum] = t;
  108. else TokenStr[TokenNum] = t;
  109. }
  110. static Expr *
  111. #ifdef __STDC__
  112. newExpr( char *e )
  113. #else
  114. newExpr( e )
  115. char *e;
  116. #endif
  117. {
  118. Expr *p = (Expr *) calloc(1, sizeof(Expr));
  119. require(p!=NULL, "newExpr: cannot alloc Expr node");
  120. p->expr = e;
  121. p->lclass = CurrentLexClass;
  122. return p;
  123. }
  124. /* switch to lexical class/mode m.  This amounts to creating a new
  125.  * lex mode if one does not already exist and making ExprStr point
  126.  * to the correct char string array.  We must also switch Texpr tables.
  127.  *
  128.  * BTW, we need multiple ExprStr arrays because more than one automaton
  129.  * may have the same label for a token, but with different expressions.
  130.  * We need to track an expr for each automaton.  If we disallowed this
  131.  * feature, only one ExprStr would be required.
  132.  */
  133. void
  134. #ifdef __STDC__
  135. lexclass( char *m )
  136. #else
  137. lexclass( m )
  138. char *m;
  139. #endif
  140. {
  141. int i;
  142. TermEntry *p;
  143. static char EOFSTR[] = ""@"";
  144. if ( hash_get(Tname, m) != NULL )
  145. {
  146. warn(eMsg1("lexclass name conflicts with token/errclass label '%s'",m));
  147. }
  148. /* does m already exist? */
  149. i = LexClassIndex(m);
  150. if ( i != -1 ) {lexmode(i); return;}
  151. /* must make new one */
  152. NumLexClasses++;
  153. CurrentLexClass = NumLexClasses-1;
  154. require(NumLexClasses<=MaxLexClasses, "number of allowable lexclasses exceedednIncrease MaxLexClasses in generic.h and recompile all C files");
  155. lclass[CurrentLexClass].classnum = m;
  156. lclass[CurrentLexClass].exprs = (char **) calloc(tsize, sizeof(char *));
  157. require(lclass[CurrentLexClass].exprs!=NULL,
  158. "lexclass: cannot allocate ExprStr");
  159. lclass[CurrentLexClass].htable = newHashTable();
  160. ExprStr = lclass[CurrentLexClass].exprs;
  161. Texpr = lclass[CurrentLexClass].htable;
  162. /* define EOF for each automaton */
  163. p = newTermEntry( EOFSTR );
  164. p->token = EofToken; /* couldn't have remapped tokens yet, use EofToken */
  165. hash_add(Texpr, EOFSTR, (Entry *)p);
  166. list_add(&ExprOrder, (void *)newExpr(EOFSTR));
  167. /* note: we use the actual ExprStr array
  168.  * here as TokenInd doesn't exist yet
  169.  */
  170. ExprStr[EofToken] = EOFSTR;
  171. }
  172. void
  173. #ifdef __STDC__
  174. lexmode( int i )
  175. #else
  176. lexmode( i )
  177. int i;
  178. #endif
  179. {
  180. require(i<NumLexClasses, "lexmode: invalid mode");
  181. ExprStr = lclass[i].exprs;
  182. Texpr = lclass[i].htable;
  183. CurrentLexClass = i;
  184. }
  185. /* return index into lclass array of lexical class. return -1 if nonexistent */
  186. int
  187. #ifdef __STDC__
  188. LexClassIndex( char *cl )
  189. #else
  190. LexClassIndex( cl )
  191. char *cl;
  192. #endif
  193. {
  194. int i;
  195. for (i=0; i<NumLexClasses; i++)
  196. {
  197. if ( strcmp(lclass[i].classnum, cl) == 0 ) return i;
  198. }
  199. return -1;
  200. }
  201. int
  202. #ifdef __STDC__
  203. hasAction( char *expr )
  204. #else
  205. hasAction( expr )
  206. char *expr;
  207. #endif
  208. {
  209. TermEntry *p;
  210. require(expr!=NULL, "hasAction: invalid expr");
  211. p = (TermEntry *) hash_get(Texpr, expr);
  212. require(p!=NULL, eMsg1("hasAction: expr '%s' doesn't exist",expr));
  213. return (p->action!=NULL);
  214. }
  215. void
  216. #ifdef __STDC__
  217. setHasAction( char *expr, char *action )
  218. #else
  219. setHasAction( expr, action )
  220. char *expr;
  221. char *action;
  222. #endif
  223. {
  224. TermEntry *p;
  225. require(expr!=NULL, "setHasAction: invalid expr");
  226. p = (TermEntry *) hash_get(Texpr, expr);
  227. require(p!=NULL, eMsg1("setHasAction: expr '%s' doesn't exist",expr));
  228. p->action = action;
  229. }
  230. ForcedToken *
  231. #ifdef __STDC__
  232. newForcedToken(char *token, int tnum)
  233. #else
  234. newForcedToken(token, tnum)
  235. char *token;
  236. int tnum;
  237. #endif
  238. {
  239. ForcedToken *ft = (ForcedToken *) calloc(1, sizeof(ForcedToken));
  240. require(ft!=NULL, "out of memory");
  241. ft->token = token;
  242. ft->tnum = tnum;
  243. return ft;
  244. }
  245. /*
  246.  * Make a token indirection array that remaps token numbers and then walk
  247.  * the appropriate symbol tables and SynDiag to change token numbers
  248.  */
  249. void
  250. #ifdef __STDC__
  251. RemapForcedTokens(void)
  252. #else
  253. RemapForcedTokens()
  254. #endif
  255. {
  256. ListNode *p;
  257. ForcedToken *q;
  258. int max_token_number=0;     /* MR9 23-Sep-97 Removed "unsigned" */
  259. int i;
  260. if ( ForcedTokens == NULL ) return;
  261. /* find max token num */
  262. for (p = ForcedTokens->next; p!=NULL; p=p->next)
  263. {
  264. q = (ForcedToken *) p->elem;
  265. if ( q->tnum > max_token_number ) max_token_number = q->tnum;
  266. }
  267. fprintf(stderr, "max token number is %dn", max_token_number);
  268. /* make token indirection array */
  269. TokenInd = (int *) calloc(max_token_number+1, sizeof(int));
  270. LastTokenCounted = TokenNum;
  271. TokenNum = max_token_number+1;
  272. require(TokenInd!=NULL, "RemapForcedTokens: cannot allocate TokenInd");
  273. /* fill token indirection array and change token id htable ; swap token indices */
  274. for (i=1; i<TokenNum; i++) TokenInd[i] = i;
  275. for (p = ForcedTokens->next; p!=NULL; p=p->next)
  276. {
  277. TermEntry *te;
  278. int old_pos, t;
  279. q = (ForcedToken *) p->elem;
  280. fprintf(stderr, "%s forced to %dn", q->token, q->tnum);
  281. te = (TermEntry *) hash_get(Tname, q->token);
  282. require(te!=NULL, "RemapForcedTokens: token not in hash table");
  283. old_pos = te->token;
  284. fprintf(stderr, "Before: TokenInd[old_pos==%d] is %dn", old_pos, TokenInd[old_pos]);
  285. fprintf(stderr, "Before: TokenInd[target==%d] is %dn", q->tnum, TokenInd[q->tnum]);
  286. q = (ForcedToken *) p->elem;
  287. t = TokenInd[old_pos];
  288. TokenInd[old_pos] = q->tnum;
  289. TokenInd[q->tnum] = t;
  290. te->token = q->tnum; /* update token type id symbol table */
  291. fprintf(stderr, "After: TokenInd[old_pos==%d] is %dn", old_pos, TokenInd[old_pos]);
  292. fprintf(stderr, "After: TokenInd[target==%d] is %dn", q->tnum, TokenInd[q->tnum]);
  293. /* Change the token number in the sym tab entry for the exprs
  294.  * at the old position of the token id and the target position
  295.  */
  296. /* update expr at target (if any) of forced token id */
  297. if ( q->tnum < TokenNum ) /* is it a valid position? */
  298. {
  299. for (i=0; i<NumLexClasses; i++)
  300. {
  301. if ( lclass[i].exprs[q->tnum]!=NULL )
  302. {
  303. /* update the symbol table for this expr */
  304. TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[q->tnum]);
  305. require(e!=NULL, "RemapForcedTokens: expr not in hash table");
  306. e->token = old_pos;
  307. fprintf(stderr, "found expr '%s' at target %d in lclass[%d]; changed to %dn",
  308. lclass[i].exprs[q->tnum], q->tnum, i, old_pos);
  309. }
  310. }
  311. }
  312. /* update expr at old position (if any) of forced token id */
  313. for (i=0; i<NumLexClasses; i++)
  314. {
  315. if ( lclass[i].exprs[old_pos]!=NULL )
  316. {
  317. /* update the symbol table for this expr */
  318. TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[old_pos]);
  319. require(e!=NULL, "RemapForcedTokens: expr not in hash table");
  320. e->token = q->tnum;
  321. fprintf(stderr, "found expr '%s' for id %s in lclass[%d]; changed to %dn",
  322. lclass[i].exprs[old_pos], q->token, i, q->tnum);
  323. }
  324. }
  325. }
  326. /* Update SynDiag */
  327. RemapForcedTokensInSyntaxDiagram((Node *)SynDiag);
  328. }
  329. static void
  330. #ifdef __STDC__
  331. RemapForcedTokensInSyntaxDiagram(Node *p)
  332. #else
  333. RemapForcedTokensInSyntaxDiagram(p)
  334. Node *p;
  335. #endif
  336. {
  337. Junction *j = (Junction *) p;
  338. RuleRefNode *r = (RuleRefNode *) p;
  339. TokNode *t = (TokNode *)p;
  340. if ( p==NULL ) return;
  341. require(p->ntype>=1 && p->ntype<=NumNodeTypes, "Remap...: invalid diagram node");
  342. switch ( p->ntype )
  343. {
  344. case nJunction :
  345. if ( j->visited ) return;
  346. if ( j->jtype == EndRule ) return;
  347. j->visited = TRUE;
  348. RemapForcedTokensInSyntaxDiagram( j->p1 );
  349. RemapForcedTokensInSyntaxDiagram( j->p2 );
  350. j->visited = FALSE;
  351. return;
  352. case nRuleRef :
  353. RemapForcedTokensInSyntaxDiagram( r->next );
  354. return;
  355. case nToken :
  356. if ( t->remapped ) return; /* we've been here before */
  357. t->remapped = 1;
  358. fprintf(stderr, "remapping %d to %dn", t->token, TokenInd[t->token]);
  359. t->token = TokenInd[t->token];
  360. RemapForcedTokensInSyntaxDiagram( t->next );
  361. return;
  362. case nAction :
  363. RemapForcedTokensInSyntaxDiagram( ((ActionNode *)p)->next );
  364. return;
  365. default :
  366. fatal_internal("invalid node type");
  367. }
  368. }
  369. /*
  370.  * Add a token name.  Return the token number associated with it.  If it already
  371.  * exists, then return the token number assigned to it.
  372.  *
  373.  * Track the order in which tokens are found so that the DLG output maintains
  374.  * that order.  It also lets us map token numbers to strings.
  375.  */
  376. int
  377. #ifdef __STDC__
  378. addTname( char *token )
  379. #else
  380. addTname( token )
  381. char *token;
  382. #endif
  383. {
  384. TermEntry *p;
  385. require(token!=NULL, "addTname: invalid token name");
  386. if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token;
  387. p = newTermEntry( token );
  388. Ttrack( p->str );
  389. p->token = TokenNum++;
  390. hash_add(Tname, token, (Entry *)p);
  391. return p->token;
  392. }
  393. /* This is the same as addTname except we force the TokenNum to be tnum.
  394.  * We don't have to use the Forced token stuff as no tokens will have
  395.  * been defined with #tokens when this is called.  This is only called
  396.  * when a #tokdefs meta-op is used.
  397.  */
  398. int
  399. #ifdef __STDC__
  400. addForcedTname( char *token, int tnum )
  401. #else
  402. addForcedTname( token, tnum )
  403. char *token;
  404. int tnum;
  405. #endif
  406. {
  407. TermEntry *p;
  408. require(token!=NULL, "addTname: invalid token name");
  409. if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token;
  410. p = newTermEntry( token );
  411. Ttrack( p->str );
  412. p->token = tnum;
  413. hash_add(Tname, token, (Entry *)p);
  414. return p->token;
  415. }
  416. /*
  417.  * Add a token expr.  Return the token number associated with it.  If it already
  418.  * exists, then return the token number assigned to it.
  419.  */
  420. int
  421. #ifdef __STDC__
  422. addTexpr( char *expr )
  423. #else
  424. addTexpr( expr )
  425. char *expr;
  426. #endif
  427. {
  428. TermEntry *p;
  429. require(expr!=NULL, "addTexpr: invalid regular expression");
  430. if ( (p=(TermEntry *)hash_get(Texpr, expr)) != NULL ) return p->token;
  431. p = newTermEntry( expr );
  432. Ttrack( p->str );
  433. /* track the order in which they occur */
  434. list_add(&ExprOrder, (void *)newExpr(p->str));
  435. p->token = TokenNum++;
  436. hash_add(Texpr, expr, (Entry *)p);
  437. return p->token;
  438. }
  439. /* return the token number of 'term'.  Return 0 if no 'term' exists */
  440. int
  441. #ifdef __STDC__
  442. Tnum( char *term )
  443. #else
  444. Tnum( term )
  445. char *term;
  446. #endif
  447. {
  448. TermEntry *p;
  449. require(term!=NULL, "Tnum: invalid terminal");
  450. if ( *term=='"' ) p = (TermEntry *) hash_get(Texpr, term);
  451. else p = (TermEntry *) hash_get(Tname, term);
  452. if ( p == NULL ) return 0;
  453. else return p->token;
  454. }
  455. /* associate a Name with an expr.  If both have been already assigned
  456.  * token numbers, then an error is reported.  Add the token or expr
  457.  * that has not been added if no error.  This 'represents' the #token
  458.  * ANTLR pseudo-op.  If both have not been defined, define them both
  459.  * linked to same token number.
  460.  */
  461. void
  462. #ifdef __STDC__
  463. Tklink( char *token, char *expr )
  464. #else
  465. Tklink( token, expr )
  466. char *token;
  467. char *expr;
  468. #endif
  469. {
  470. TermEntry *p, *q;
  471. require(token!=NULL && expr!=NULL, "Tklink: invalid token name and/or expr");
  472. p = (TermEntry *) hash_get(Tname, token);
  473. q = (TermEntry *) hash_get(Texpr, expr);
  474. if ( p != NULL && q != NULL ) /* both defined */
  475. {
  476. warn( eMsg2("token name %s and rexpr %s already defined; ignored",
  477. token, expr) );
  478. return;
  479. }
  480. if ( p==NULL && q==NULL ) /* both not defined */
  481. {
  482. int t = addTname( token );
  483. q = newTermEntry( expr );
  484. hash_add(Texpr, expr, (Entry *)q);
  485. q->token = t;
  486. /* note: we use the actual ExprStr array
  487.  * here as TokenInd doesn't exist yet
  488.  */
  489. ExprStr[t] = q->str;
  490. /* track the order in which they occur */
  491. list_add(&ExprOrder, (void *)newExpr(q->str));
  492. return;
  493. }
  494. if ( p != NULL ) /* one is defined, one is not */
  495. {
  496. q = newTermEntry( expr );
  497. hash_add(Texpr, expr, (Entry *)q);
  498. q->token = p->token;
  499. ExprStr[p->token] = q->str; /* both expr and token str defined now */
  500. list_add(&ExprOrder, (void *)newExpr(q->str));
  501. }
  502. else /* trying to associate name with expr here*/
  503. {
  504. p = newTermEntry( token );
  505. hash_add(Tname, token, (Entry *)p);
  506. p->token = q->token;
  507. TokenStr[p->token] = p->str;/* both expr and token str defined now */
  508. }
  509. }
  510. /*
  511.  * Given a string, this function allocates and returns a pointer to a
  512.  * hash table record of size 'sz' whose "str" pointer is reset to a position
  513.  * in the string table.
  514.  */
  515. Entry *
  516. #ifdef __STDC__
  517. newEntry( char *text, int sz )
  518. #else
  519. newEntry( text, sz )
  520. char *text;
  521. int sz;
  522. #endif
  523. {
  524. Entry *p;
  525. require(text!=NULL, "new: NULL terminal");
  526. if ( (p = (Entry *) calloc(1,sz)) == 0 )
  527. {
  528. fatal_internal("newEntry: out of memory for terminalsn");
  529. exit(PCCTS_EXIT_FAILURE);
  530. }
  531. p->str = mystrdup(text);
  532. return(p);
  533. }
  534. /*
  535.  * add an element to a list.
  536.  *
  537.  * Any non-empty list has a sentinel node whose 'elem' pointer is really
  538.  * a pointer to the last element.  (i.e. length(list) = #elemIn(list)+1).
  539.  * Elements are appended to the list.
  540.  */
  541. void
  542. #ifdef __STDC__
  543. list_add( ListNode **list, void *e )
  544. #else
  545. list_add( list, e )
  546. ListNode **list;
  547. void *e;
  548. #endif
  549. {
  550. ListNode *p, *tail;
  551. require(e!=NULL, "list_add: attempting to add NULL list element");
  552. p = newListNode;
  553. require(p!=NULL, "list_add: cannot alloc new list node");
  554. p->elem = e;
  555. if ( *list == NULL )
  556. {
  557. ListNode *sentinel = newListNode;
  558. require(sentinel!=NULL, "list_add: cannot alloc sentinel node");
  559. *list=sentinel;
  560. sentinel->next = p;
  561. sentinel->elem = (char *)p; /* set tail pointer */
  562. }
  563. else /* find end of list */
  564. {
  565. tail = (ListNode *) (*list)->elem; /* get tail pointer */
  566. tail->next = p;
  567. (*list)->elem = (char *) p; /* reset tail */
  568. }
  569. }
  570. /* MR10 list_free() frees the ListNode elements in the list       */
  571. /* MR10   if freeData then free the data elements of the list too */
  572. void
  573. #ifdef __STDC__
  574. list_free(ListNode **list,int freeData)
  575. #else
  576. list_free(list,freeData)
  577.   ListNode      **list;
  578.   int           freeData;
  579. #endif
  580. {
  581. ListNode *p;
  582.     ListNode *next;
  583. if (list == NULL) return;
  584.     if (*list == NULL) return;
  585. for (p=*list; p != NULL; p=next) {
  586.       next=p->next;
  587.       if (freeData && p->elem != NULL) {
  588.         free( (char *) p->elem);
  589.       };
  590.       free( (char *) p);
  591.     };
  592.     *list=NULL;
  593. }
  594. void
  595. #ifdef __STDC__
  596. list_apply( ListNode *list, void (*f)(void *) )
  597. #else
  598. list_apply( list, f )
  599. ListNode *list;
  600. void (*f)();
  601. #endif
  602. {
  603. ListNode *p;
  604. require(f!=NULL, "list_apply: NULL function to apply");
  605. if ( list == NULL ) return;
  606. for (p = list->next; p!=NULL; p=p->next) (*f)( p->elem );
  607. }
  608. /* F O L L O W  C y c l e  S t u f f */
  609. /* make a key based upon (rulename, computation, k value).
  610.  * Computation values are 'i'==FIRST, 'o'==FOLLOW.
  611.  */
  612. /* MR10  Make the key all characters so it can be read easily   */
  613. /* MR10    by a simple dump program.  Also, separates           */
  614. /* MR10   'o' and 'i' from rule name                            */
  615. char *
  616. #ifdef __STDC__
  617. Fkey( char *rule, int computation, int k )
  618. #else
  619. Fkey( rule, computation, k )
  620. char *rule;
  621. int computation;
  622. int k;
  623. #endif
  624. {
  625. static char key[MaxRuleName+2+2+1];                                 /* MR10 */
  626. int i;
  627. if ( k > 99 )                                                       /* MR10 */
  628. fatal("k>99 is too big for this implementation of ANTLR!n");   /* MR10 */
  629. if ( (i=strlen(rule)) > MaxRuleName )                               /* MR10 */
  630. fatal( eMsgd("rule name > max of %dn", MaxRuleName) );         /* MR10 */
  631. strcpy(key,rule);
  632. /* MR10 */     key[i]='*';
  633. /* MR10 */     key[i+1] = (int) computation;
  634. /* MR10 */     if (k < 10) {
  635. /* MR10 */       key[i+2] = (char) ( '0' + k);
  636. /* MR10 */    key[i+3] = '';
  637. /* MR10 */     } else {
  638. /* MR10 */       key[i+2] = (char) ( '0' + k/10);
  639. /* MR10 */       key[i+3] = (char) ( '0' + k % 10);
  640. /* MR10 */       key[i+4] = '';
  641. /* MR10 */     };
  642. return key;
  643. }
  644. /* Push a rule onto the kth FOLLOW stack */
  645. void
  646. #ifdef __STDC__
  647. FoPush( char *rule, int k )
  648. #else
  649. FoPush( rule, k )
  650. char *rule;
  651. int k;
  652. #endif
  653. {
  654. RuleEntry *r;
  655. require(rule!=NULL, "FoPush: tried to push NULL rule");
  656. require(k<=CLL_k, "FoPush: tried to access non-existent stack");
  657. /*fprintf(stderr, "FoPush(%s)n", rule);*/
  658. r = (RuleEntry *) hash_get(Rname, rule);
  659. if ( r == NULL ) {fatal_internal( eMsg1("rule %s must be defined but isn't", rule) );}
  660. if ( FoStack[k] == NULL ) /* Does the kth stack exist yet? */
  661. {
  662. /*fprintf(stderr, "allocating FoStackn");*/
  663. FoStack[k] = (int *) calloc(FoStackSize, sizeof(int));
  664. require(FoStack[k]!=NULL, "FoPush: cannot allocate FOLLOW stackn");
  665. }
  666. if ( FoTOS[k] == NULL )
  667. {
  668. FoTOS[k]=FoStack[k];
  669. *(FoTOS[k]) = r->rulenum;
  670. }
  671. else
  672. {
  673. #ifdef MEMCHK
  674. require(valid(FoStack[k]), "FoPush: invalid FoStack");
  675. #endif
  676. if ( FoTOS[k] >= &(FoStack[k][FoStackSize-1]) )
  677. fatal( eMsgd("exceeded max depth of FOLLOW recursion (%d)n",
  678. FoStackSize) );
  679. require(FoTOS[k]>=FoStack[k],
  680. eMsg1("FoPush: FoStack stack-ptr is playing out of its sandbox",
  681.   rule));
  682. ++(FoTOS[k]);
  683. *(FoTOS[k]) = r->rulenum;
  684. }
  685. {
  686. /*
  687. **** int *p;
  688. **** fprintf(stderr, "FoStack[k=%d]:n", k);
  689. **** for (p=FoStack[k]; p<=FoTOS[k]; p++)
  690. **** {
  691. **** fprintf(stderr, "t%sn", RulePtr[*p]->rname);
  692. **** }
  693. */
  694. }
  695. }
  696. /* Pop one rule off of the FOLLOW stack.  TOS ptr is NULL if empty. */
  697. void
  698. #ifdef __STDC__
  699. FoPop( int k )
  700. #else
  701. FoPop( k )
  702. int k;
  703. #endif
  704. {
  705. require(k<=CLL_k, "FoPop: tried to access non-existent stack");
  706. /*fprintf(stderr, "FoPopn");*/
  707. require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]),
  708. "FoPop: FoStack stack-ptr is playing out of its sandbox");
  709. if ( FoTOS[k] == FoStack[k] ) FoTOS[k] = NULL;
  710. else (FoTOS[k])--;
  711. }
  712. /* Compute FOLLOW cycle.
  713.  * Mark all FOLLOW sets for rules in cycle as incomplete.
  714.  * Then, save cycle on the cycle list (Cycles) for later resolution.
  715.  * The Cycle is stored in the form:
  716.  * (head of cycle==croot, rest of rules in cycle==cyclicDep)
  717.  *
  718.  * e.g. (Fo means "FOLLOW of", "-->" means requires or depends on)
  719.  *
  720.  * Fo(x)-->Fo(a)-->Fo(b)-->Fo(c)-->Fo(x)
  721.  *    ^----Infinite recursion (cycle)
  722.  *
  723.  * the cycle would be: x -> {a,b,c} or stored as (x,{a,b,c}).  Fo(x) depends
  724.  * on the FOLLOW of a,b, and c.  The root of a cycle is always complete after
  725.  * Fo(x) finishes.  Fo(a,b,c) however are not.  It turns out that all rules
  726.  * in a FOLLOW cycle have the same FOLLOW set.
  727.  */
  728. void
  729. #ifdef __STDC__
  730. RegisterCycle( char *rule, int k )
  731. #else
  732. RegisterCycle( rule, k )
  733. char *rule;
  734. int k;
  735. #endif
  736. {
  737. CacheEntry *f;
  738. Cycle *c;
  739. int *p;
  740. RuleEntry *r;
  741. require(rule!=NULL, "RegisterCycle: tried to register NULL rule");
  742. require(k<=CLL_k, "RegisterCycle: tried to access non-existent stack");
  743. /*fprintf(stderr, "RegisterCycle(%s)n", rule);*/
  744. /* Find cycle start */
  745. r = (RuleEntry *) hash_get(Rname, rule);
  746. require(r!=NULL,eMsg1("rule %s must be defined but isn't", rule));
  747. require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]),
  748. eMsg1("RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox",
  749.   rule));
  750. /*** if ( FoTOS[k]<FoStack[k]||FoTOS[k]>&(FoStack[k][FoStackSize-1]) )
  751. **** {
  752. **** fprintf(stderr, "RegisterCycle(%s): FoStack stack-ptr is playing out of its sandboxn",
  753. **** rule);
  754. **** fprintf(stderr, "RegisterCycle: sp==0x%x out of bounds 0x%x...0x%xn",
  755. **** FoTOS[k], FoStack[k], &(FoStack[k][FoStackSize-1]));
  756. **** exit(PCCTS_EXIT_FAILURE);
  757. **** }
  758. ****/
  759. #ifdef MEMCHK
  760. require(valid(FoStack[k]), "RegisterCycle: invalid FoStack");
  761. #endif
  762. for (p=FoTOS[k]; *p != r->rulenum && p >= FoStack[k]; --p) {;}
  763. require(p>=FoStack[k], "RegisterCycle: FoStack is screwed up beyond belief");
  764. if ( p == FoTOS[k] ) return; /* don't worry about cycles to oneself */
  765. /* compute cyclic dependents (rules in cycle except head) */
  766. c = newCycle;
  767. require(c!=NULL, "RegisterCycle: couldn't alloc new cycle");
  768. c->cyclicDep = empty;
  769. c->croot = *p++; /* record root of cycle */
  770. for (; p<=FoTOS[k]; p++)
  771. {
  772. /* Mark all dependent rules as incomplete */
  773. f = (CacheEntry *) hash_get(Fcache, Fkey(RulePtr[*p]->rname,'o',k));
  774. if ( f==NULL )
  775. {
  776. f = newCacheEntry( Fkey(RulePtr[*p]->rname,'o',k) );
  777. hash_add(Fcache, Fkey(RulePtr[*p]->rname,'o',k), (Entry *)f);
  778. }
  779. f->incomplete = TRUE;
  780. set_orel(*p, &(c->cyclicDep)); /* mark rule as dependent of croot */
  781. }
  782. list_add(&(Cycles[k]), (void *)c);
  783. }
  784. /* make all rules in cycle complete
  785.  *
  786.  * while ( some set has changed ) do
  787.  * for each cycle do
  788.  * if degree of FOLLOW set for croot > old degree then
  789.  * update all FOLLOW sets for rules in cyclic dependency
  790.  * change = TRUE
  791.  * endif
  792.  * endfor
  793.  * endwhile
  794.  */
  795. void
  796. #ifdef __STDC__
  797. ResolveFoCycles( int k )
  798. #else
  799. ResolveFoCycles( k )
  800. int k;
  801. #endif
  802. {
  803. ListNode *p, *q;
  804. Cycle *c;
  805. int changed = 1;
  806. CacheEntry *f,*g;
  807. int r;
  808. /*  int i;  */  /* MR10 not useful */
  809. unsigned d;
  810.     unsigned    *cursor;        /* MR10 */
  811.     unsigned    *origin;        /* MR10 */
  812. /*fprintf(stderr, "Resolving following cycles for %dn", k);*/
  813. while ( changed )
  814. {
  815. changed = 0;
  816. /* MR10 i = 0;  */
  817. for (p = Cycles[k]->next; p!=NULL; p=p->next)
  818. {
  819. c = (Cycle *) p->elem;
  820. /*fprintf(stderr, "cycle %d: %s -->", i++, RulePtr[c->croot]->rname);*/
  821. /*s_fprT(stderr, c->cyclicDep);*/
  822. /*fprintf(stderr, "n");*/
  823. f = (CacheEntry *)
  824. hash_get(Fcache, Fkey(RulePtr[c->croot]->rname,'o',k));
  825. require(f!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[c->croot]->rname) );
  826. if ( (d=set_deg(f->fset)) > c->deg )
  827. {
  828. /*fprintf(stderr, "Fo(%s) has changedn", RulePtr[c->croot]->rname);*/
  829. changed = 1;
  830. c->deg = d; /* update cycle FOLLOW set degree */
  831. /* MR10 */      origin=set_pdq(c->cyclicDep);
  832. /* MR10 */      for (cursor=origin; *cursor != nil; cursor++) {
  833. /* MR10 */         r=*cursor;
  834. /******** while ( !set_nil(c->cyclicDep) ) {      *****/
  835. /******** r = set_int(c->cyclicDep);  *****/
  836. /******** set_rm(r, c->cyclicDep);    *****/
  837. /*fprintf(stderr, "updating Fo(%s)n", RulePtr[r]->rname);*/
  838. g = (CacheEntry *)
  839. hash_get(Fcache, Fkey(RulePtr[r]->rname,'o',k));
  840. require(g!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[r]->rname) );
  841. set_orin(&(g->fset), f->fset);
  842. g->incomplete = FALSE;
  843. }
  844. /* MR10 */      free( (char *) origin);
  845. /* MR10 */      origin=NULL;
  846. }
  847. }
  848. /* MR10 - this if statement appears to be meaningless since i is always 0 */
  849. /* MR10 if ( i == 1 ) changed = 0; */ /* if only 1 cycle, no need to repeat */
  850. }
  851. /* kill Cycle list */
  852. for (q = Cycles[k]->next; q != NULL; q=p)
  853. {
  854. p = q->next;
  855. set_free( ((Cycle *)q->elem)->cyclicDep );
  856. free((char *)q);
  857. }
  858. free( (char *)Cycles[k] );
  859. Cycles[k] = NULL;
  860. }
  861. /* P r i n t i n g  S y n t a x  D i a g r a m s */
  862. static void
  863. #ifdef __STDC__
  864. pBlk( Junction *q, int btype )
  865. #else
  866. pBlk( q, btype )
  867. Junction *q;
  868. int btype;
  869. #endif
  870. {
  871. int k,a;
  872. Junction *alt, *p;
  873. q->end->pvisited = TRUE;
  874. if ( btype == aLoopBegin )
  875. {
  876. require(q->p2!=NULL, "pBlk: invalid ()* block");
  877. PRINT(q->p1);
  878. alt = (Junction *)q->p2;
  879. PRINT(alt->p1);
  880. if ( PrintAnnotate )
  881. {
  882. printf(" /* Opt ");
  883. k = 1;
  884. while ( !set_nil(alt->fset[k]) )
  885. {
  886. s_fprT(stdout, alt->fset[k]);
  887. if ( k++ == CLL_k ) break;
  888. if ( !set_nil(alt->fset[k]) ) printf(", ");
  889. }
  890. printf(" */n");
  891. }
  892. return;
  893. }
  894. for (a=1,alt=q; alt != NULL; alt= (Junction *) alt->p2, a++)
  895. {
  896. if ( alt->p1 != NULL ) PRINT(alt->p1);
  897. if ( PrintAnnotate )
  898. {
  899. printf( " /* [%d] ", alt->altnum);
  900. k = 1;
  901. while ( !set_nil(alt->fset[k]) )
  902. {
  903. s_fprT(stdout, alt->fset[k]);
  904. if ( k++ == CLL_k ) break;
  905. if ( !set_nil(alt->fset[k]) ) printf(", ");
  906. }
  907. if ( alt->p2 == NULL && btype == aOptBlk )
  908. printf( " (optional branch) */n");
  909. else printf( " */n");
  910. }
  911. /* ignore implied empty alt of Plus blocks */
  912. if ( alt->p2 != NULL && ((Junction *)alt->p2)->ignore ) break;
  913. if ( alt->p2 != NULL && !(((Junction *)alt->p2)->p2==NULL && btype == aOptBlk) )
  914. {
  915. if ( pLevel == 1 )
  916. {
  917. printf("n");
  918. if ( a+1==pAlt1 || a+1==pAlt2 ) printf("=>");
  919. printf("t");
  920. }
  921. else printf(" ");
  922. printf("|");
  923. if ( pLevel == 1 )
  924. {
  925. p = (Junction *) ((Junction *)alt->p2)->p1;
  926. while ( p!=NULL )
  927. {
  928. if ( p->ntype==nAction )
  929. {
  930. p=(Junction *)((ActionNode *)p)->next;
  931. continue;
  932. }
  933. if ( p->ntype!=nJunction )
  934. {
  935. break;
  936. }
  937. if ( p->jtype==EndBlk || p->jtype==EndRule )
  938. {
  939. p = NULL;
  940. break;
  941. }
  942. p = (Junction *)p->p1;
  943. }
  944. if ( p==NULL ) printf("nt"); /* Empty alt? */
  945. }
  946. }
  947. }
  948. q->end->pvisited = FALSE;
  949. }
  950. /* How to print out a junction */
  951. void
  952. #ifdef __STDC__
  953. pJunc( Junction *q )
  954. #else
  955. pJunc( q )
  956. Junction *q;
  957. #endif
  958. {
  959. int dum_k;
  960. int doing_rule;
  961. require(q!=NULL, "pJunc: NULL node");
  962. require(q->ntype==nJunction, "pJunc: not junction");
  963. if ( q->pvisited == TRUE ) return;
  964. q->pvisited = TRUE;
  965. switch ( q->jtype )
  966. {
  967. case aSubBlk :
  968. if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
  969. if ( q->end->p1 != NULL && ((Junction *)q->end->p1)->ntype==nJunction &&
  970.  ((Junction *)q->end->p1)->jtype == EndRule ) doing_rule = 1;
  971. else doing_rule = 0;
  972. pLevel++;
  973. if ( pLevel==1 )
  974. {
  975. if ( pAlt1==1 ) printf("=>");
  976. printf("t");
  977. }
  978. else printf(" ");
  979. if ( doing_rule )
  980. {
  981. if ( pLevel==1 ) printf(" ");
  982. pBlk(q,q->jtype);
  983. }
  984. else {
  985. printf("(");
  986. if ( pLevel==1 ) printf(" ");
  987. pBlk(q,q->jtype);
  988. if ( pLevel>1 ) printf(" ");
  989. printf(")");
  990. }
  991. if ( q->guess ) printf("?");
  992. pLevel--;
  993. if ( PrintAnnotate ) freeBlkFsets(q);
  994. if ( q->end->p1 != NULL ) PRINT(q->end->p1);
  995. break;
  996. case aOptBlk :
  997. if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
  998. pLevel++;
  999. if ( pLevel==1 )
  1000. {
  1001. if ( pAlt1==1 ) printf("=>");
  1002. printf("t");
  1003. }
  1004. else printf(" ");
  1005. printf("{");
  1006. if ( pLevel==1 ) printf(" ");
  1007. pBlk(q,q->jtype);
  1008. if ( pLevel>1 ) printf(" ");
  1009. else printf("nt");
  1010. printf("}");
  1011. pLevel--;
  1012. if ( PrintAnnotate ) freeBlkFsets(q);
  1013. if ( q->end->p1 != NULL ) PRINT(q->end->p1);
  1014. break;
  1015. case aLoopBegin :
  1016. if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
  1017. pLevel++;
  1018. if ( pLevel==1 )
  1019. {
  1020. if ( pAlt1==1 ) printf("=>");
  1021. printf("t");
  1022. }
  1023. else printf(" ");
  1024. printf("(");
  1025. if ( pLevel==1 ) printf(" ");
  1026. pBlk(q,q->jtype);
  1027. if ( pLevel>1 ) printf(" ");
  1028. else printf("nt");
  1029. printf(")*");
  1030. pLevel--;
  1031. if ( PrintAnnotate ) freeBlkFsets(q);
  1032. if ( q->end->p1 != NULL ) PRINT(q->end->p1);
  1033. break;
  1034. case aLoopBlk :
  1035. if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
  1036. pBlk(q,q->jtype);
  1037. if ( PrintAnnotate ) freeBlkFsets(q);
  1038. break;
  1039. case aPlusBlk :
  1040. if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
  1041. pLevel++;
  1042. if ( pLevel==1 )
  1043. {
  1044. if ( pAlt1==1 ) printf("=>");
  1045. printf("t");
  1046. }
  1047. else printf(" ");
  1048. printf("(");
  1049. if ( pLevel==1 ) printf(" ");
  1050. pBlk(q,q->jtype);
  1051. if ( pLevel>1 ) printf(" ");
  1052. printf(")+");
  1053. pLevel--;
  1054. if ( PrintAnnotate ) freeBlkFsets(q);
  1055. if ( q->end->p1 != NULL ) PRINT(q->end->p1);
  1056. break;
  1057. case EndBlk :
  1058. break;
  1059. case RuleBlk :
  1060. printf( "n%s :n", q->rname);
  1061. PRINT(q->p1);
  1062. if ( q->p2 != NULL ) PRINT(q->p2);
  1063. break;
  1064. case Generic :
  1065. if ( q->p1 != NULL ) PRINT(q->p1);
  1066. q->pvisited = FALSE;
  1067. if ( q->p2 != NULL ) PRINT(q->p2);
  1068. break;
  1069. case EndRule :
  1070. printf( "nt;n");
  1071. break;
  1072. }
  1073. q->pvisited = FALSE;
  1074. }
  1075. /* How to print out a rule reference node */
  1076. void
  1077. #ifdef __STDC__
  1078. pRuleRef( RuleRefNode *p )
  1079. #else
  1080. pRuleRef( p )
  1081. RuleRefNode *p;
  1082. #endif
  1083. {
  1084. require(p!=NULL, "pRuleRef: NULL node");
  1085. require(p->ntype==nRuleRef, "pRuleRef: not rule ref node");
  1086. printf( " %s", p->text);
  1087. PRINT(p->next);
  1088. }
  1089. /* How to print out a terminal node */
  1090. void
  1091. #ifdef __STDC__
  1092. pToken( TokNode *p )
  1093. #else
  1094. pToken( p )
  1095. TokNode *p;
  1096. #endif
  1097. {
  1098. require(p!=NULL, "pToken: NULL node");
  1099. require(p->ntype==nToken, "pToken: not token node");
  1100. if ( p->wild_card ) printf(" .");
  1101. printf( " %s", TerminalString(p->token));
  1102. PRINT(p->next);
  1103. }
  1104. /* How to print out a terminal node */
  1105. void
  1106. #ifdef __STDC__
  1107. pAction( ActionNode *p )
  1108. #else
  1109. pAction( p )
  1110. ActionNode *p;
  1111. #endif
  1112. {
  1113. require(p!=NULL, "pAction: NULL node");
  1114. require(p->ntype==nAction, "pAction: not action node");
  1115. PRINT(p->next);
  1116. }
  1117. /* F i l l  F o l l o w  L i s t s */
  1118. /*
  1119.  * Search all rules for all rule reference nodes, q to rule, r.
  1120.  * Add q->next to follow list dangling off of rule r.
  1121.  * i.e.
  1122.  *
  1123.  * r: -o-R-o-->o--> Ptr to node following rule r in another rule
  1124.  * |
  1125.  * o--> Ptr to node following another reference to r.
  1126.  *
  1127.  * This is the data structure employed to avoid FOLLOW set computation.  We
  1128.  * simply compute the FIRST (reach) of the EndRule Node which follows the
  1129.  * list found at the end of all rules which are referenced elsewhere.  Rules
  1130.  * not invoked by other rules have no follow list (r->end->p1==NULL).
  1131.  * Generally, only start symbols are not invoked by another rule.
  1132.  *
  1133.  * Note that this mechanism also gives a free cross-reference mechanism.
  1134.  *
  1135.  * The entire syntax diagram is layed out like this:
  1136.  *
  1137.  * SynDiag
  1138.  * |
  1139.  * v
  1140.  * o-->R1--o
  1141.  * |
  1142.  * o-->R2--o
  1143.  * |
  1144.  * ...
  1145.  * |
  1146.  * o-->Rn--o
  1147.  *
  1148.  */
  1149. void
  1150. #ifdef __STDC__
  1151. FoLink( Node *p )
  1152. #else
  1153. FoLink( p )
  1154. Node *p;
  1155. #endif
  1156. {
  1157. RuleEntry *q;
  1158. Junction *j = (Junction *) p;
  1159. RuleRefNode *r = (RuleRefNode *) p;
  1160. if ( p==NULL ) return;
  1161. require(p->ntype>=1 && p->ntype<=NumNodeTypes,
  1162. eMsgd("FoLink: invalid diagram node: ntype==%d",p->ntype));
  1163. switch ( p->ntype )
  1164. {
  1165. case nJunction :
  1166. if ( j->fvisited ) return;
  1167. if ( j->jtype == EndRule ) return;
  1168. j->fvisited = TRUE;
  1169. FoLink( j->p1 );
  1170. FoLink( j->p2 );
  1171. /* MR14 */
  1172. /* MR14 */  /* Need to determine whether the guess block is an         */
  1173. /* MR14 */  /* of the form (alpha)? beta before follow sets are        */
  1174. /* MR14 */  /* computed.  This is necessary to solve problem           */
  1175. /* MR14 */  /* of doing follow on the alpha of an (alpha)? beta block. */
  1176. /* MR14 */
  1177. /* MR14 */  /* This is performed by analysis_point as a side-effect.   */
  1178. /* MR14 */
  1179. /* MR14 */
  1180. /* MR14 */  if (j->jtype == aSubBlk && j->guess) {
  1181. /* MR14 */    Junction *ignore;
  1182. /* MR14 */    ignore=analysis_point(j);
  1183. /* MR14 */  }
  1184. /* MR14 */
  1185. return;
  1186. case nRuleRef :
  1187. if ( r->linked ) return;
  1188. q = (RuleEntry *) hash_get(Rname, r->text);
  1189. if ( q == NULL )
  1190. {
  1191. warnFL( eMsg1("rule %s not defined",r->text), FileStr[r->file], r->line );
  1192. }
  1193. else
  1194. {
  1195. if ( r->parms!=NULL && RulePtr[q->rulenum]->pdecl==NULL )
  1196. {
  1197. warnFL( eMsg1("rule %s accepts no parameter(s)", r->text),
  1198. FileStr[r->file], r->line );
  1199. }
  1200. if ( r->parms==NULL && RulePtr[q->rulenum]->pdecl!=NULL )
  1201. {
  1202. warnFL( eMsg1("rule %s requires parameter(s)", r->text),
  1203. FileStr[r->file], r->line );
  1204. }
  1205. if ( r->assign!=NULL && RulePtr[q->rulenum]->ret==NULL )
  1206. {
  1207. warnFL( eMsg1("rule %s yields no return value(s)", r->text),
  1208. FileStr[r->file], r->line );
  1209. }
  1210. if ( r->assign==NULL && RulePtr[q->rulenum]->ret!=NULL )
  1211. {
  1212. warnFL( eMsg1("rule %s returns a value(s)", r->text),
  1213. FileStr[r->file], r->line );
  1214. }
  1215. if ( !r->linked )
  1216. {
  1217. addFoLink( r->next, r->rname, RulePtr[q->rulenum] );
  1218. r->linked = TRUE;
  1219. }
  1220. }
  1221. FoLink( r->next );
  1222. return;
  1223. case nToken :
  1224. FoLink( ((TokNode *)p)->next );
  1225. return;
  1226. case nAction :
  1227. FoLink( ((ActionNode *)p)->next );
  1228. return;
  1229. default :
  1230. fatal_internal("invalid node type");
  1231. }
  1232. }
  1233. /*
  1234.  * Add a reference to the end of a rule.
  1235.  *
  1236.  * 'r' points to the RuleBlk node in a rule.  r->end points to the last node
  1237.  * (EndRule jtype) in a rule.
  1238.  *
  1239.  * Initial:
  1240.  * r->end -->  o
  1241.  *
  1242.  * After:
  1243.  * r->end -->  o-->o--> Ptr to node following rule r in another rule
  1244.  * |
  1245.  * o--> Ptr to node following another reference to r.
  1246.  *
  1247.  * Note that the links are added to the head of the list so that r->end->p1
  1248.  * always points to the most recently added follow-link.  At the end, it should
  1249.  * point to the last reference found in the grammar (starting from the 1st rule).
  1250.  */
  1251. void
  1252. #ifdef __STDC__
  1253. addFoLink( Node *p, char *rname, Junction *r )
  1254. #else
  1255. addFoLink( p, rname, r )
  1256. Node *p;
  1257. char *rname;
  1258. Junction *r;
  1259. #endif
  1260. {
  1261. Junction *j;
  1262. require(r!=NULL, "addFoLink: incorrect rule graph");
  1263. require(r->end!=NULL, "addFoLink: incorrect rule graph");
  1264. require(r->end->jtype==EndRule, "addFoLink: incorrect rule graph");
  1265. require(p!=NULL, "addFoLink: NULL FOLLOW link");
  1266. j = newJunction();
  1267. j->rname = rname; /* rname on follow links point to target rule */
  1268. j->p1 = p; /* link to other rule */
  1269. j->p2 = (Node *) r->end->p1;/* point to head of list */
  1270. r->end->p1 = (Node *) j; /* reset head to point to new node */
  1271. }
  1272. void
  1273. #ifdef __STDC__
  1274. GenCrossRef( Junction *p )
  1275. #else
  1276. GenCrossRef( p )
  1277. Junction *p;
  1278. #endif
  1279. {
  1280. set a;
  1281. Junction *j;
  1282. RuleEntry *q;
  1283. unsigned e;
  1284. require(p!=NULL, "GenCrossRef: why are you passing me a null grammar?");
  1285. printf("Cross Reference:nn");
  1286. a = empty;
  1287. for (; p!=NULL; p = (Junction *)p->p2)
  1288. {
  1289. printf("Rule %20s referenced by {", p->rname);
  1290. /* make a set of rules for uniqueness */
  1291. for (j = (Junction *)(p->end)->p1; j!=NULL; j = (Junction *)j->p2)
  1292. {
  1293. q = (RuleEntry *) hash_get(Rname, j->rname);
  1294. require(q!=NULL, "GenCrossRef: FoLinks are screwed up");
  1295. set_orel(q->rulenum, &a);
  1296. }
  1297. for (; !set_nil(a); set_rm(e, a))
  1298. {
  1299. e = set_int(a);
  1300. printf(" %s", RulePtr[e]->rname);
  1301. }
  1302. printf(" }n");
  1303. }
  1304. set_free( a );
  1305. }