1 /*
2 ** This file contains all sources (including headers) to the LEMON
3 ** LALR(1) parser generator.  The sources have been combined into a
4 ** single file to make it easy to include LEMON in the source tree
5 ** and Makefile of another program.
6 **
7 ** The author of this program disclaims copyright.
8 */
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <stdlib.h>
14 #include <assert.h>
15 
16 #define ISSPACE(X) isspace((unsigned char)(X))
17 #define ISDIGIT(X) isdigit((unsigned char)(X))
18 #define ISALNUM(X) isalnum((unsigned char)(X))
19 #define ISALPHA(X) isalpha((unsigned char)(X))
20 #define ISUPPER(X) isupper((unsigned char)(X))
21 #define ISLOWER(X) islower((unsigned char)(X))
22 
23 
24 #ifndef __WIN32__
25 #   if defined(_WIN32) || defined(WIN32)
26 #       define __WIN32__
27 #   endif
28 #endif
29 
30 #ifdef __WIN32__
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 extern int access(const char *path, int mode);
35 #ifdef __cplusplus
36 }
37 #endif
38 #else
39 #include <unistd.h>
40 #endif
41 
42 /* #define PRIVATE static */
43 #define PRIVATE
44 
45 #ifdef TEST
46 #define MAXRHS 5       /* Set low to exercise exception code */
47 #else
48 #define MAXRHS 1000
49 #endif
50 
51 static int showPrecedenceConflict = 0;
52 static char *msort(char*,char**,int(*)(const char*,const char*));
53 
54 /*
55 ** Compilers are getting increasingly pedantic about type conversions
56 ** as C evolves ever closer to Ada....  To work around the latest problems
57 ** we have to define the following variant of strlen().
58 */
59 #define lemonStrlen(X)   ((int)strlen(X))
60 
61 /*
62 ** Compilers are starting to complain about the use of sprintf() and strcpy(),
63 ** saying they are unsafe.  So we define our own versions of those routines too.
64 **
65 ** There are three routines here:  lemon_sprintf(), lemon_vsprintf(), and
66 ** lemon_addtext(). The first two are replacements for sprintf() and vsprintf().
67 ** The third is a helper routine for vsnprintf() that adds texts to the end of a
68 ** buffer, making sure the buffer is always zero-terminated.
69 **
70 ** The string formatter is a minimal subset of stdlib sprintf() supporting only
71 ** a few simply conversions:
72 **
73 **   %d
74 **   %s
75 **   %.*s
76 **
77 */
lemon_addtext(char * zBuf,int * pnUsed,const char * zIn,int nIn,int iWidth)78 static void lemon_addtext(
79   char *zBuf,           /* The buffer to which text is added */
80   int *pnUsed,          /* Slots of the buffer used so far */
81   const char *zIn,      /* Text to add */
82   int nIn,              /* Bytes of text to add.  -1 to use strlen() */
83   int iWidth            /* Field width.  Negative to left justify */
84 ){
85   if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){}
86   while( iWidth>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth--; }
87   if( nIn==0 ) return;
88   memcpy(&zBuf[*pnUsed], zIn, nIn);
89   *pnUsed += nIn;
90   while( (-iWidth)>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth++; }
91   zBuf[*pnUsed] = 0;
92 }
lemon_vsprintf(char * str,const char * zFormat,va_list ap)93 static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){
94   int i, j, k, c;
95   int nUsed = 0;
96   const char *z;
97   char zTemp[50];
98   str[0] = 0;
99   for(i=j=0; (c = zFormat[i])!=0; i++){
100     if( c=='%' ){
101       int iWidth = 0;
102       lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
103       c = zFormat[++i];
104       if( ISDIGIT(c) || (c=='-' && ISDIGIT(zFormat[i+1])) ){
105         if( c=='-' ) i++;
106         while( ISDIGIT(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0';
107         if( c=='-' ) iWidth = -iWidth;
108         c = zFormat[i];
109       }
110       if( c=='d' ){
111         int v = va_arg(ap, int);
112         if( v<0 ){
113           lemon_addtext(str, &nUsed, "-", 1, iWidth);
114           v = -v;
115         }else if( v==0 ){
116           lemon_addtext(str, &nUsed, "0", 1, iWidth);
117         }
118         k = 0;
119         while( v>0 ){
120           k++;
121           zTemp[sizeof(zTemp)-k] = (v%10) + '0';
122           v /= 10;
123         }
124         lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k, iWidth);
125       }else if( c=='s' ){
126         z = va_arg(ap, const char*);
127         lemon_addtext(str, &nUsed, z, -1, iWidth);
128       }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){
129         i += 2;
130         k = va_arg(ap, int);
131         z = va_arg(ap, const char*);
132         lemon_addtext(str, &nUsed, z, k, iWidth);
133       }else if( c=='%' ){
134         lemon_addtext(str, &nUsed, "%", 1, 0);
135       }else{
136         fprintf(stderr, "illegal format\n");
137         exit(1);
138       }
139       j = i+1;
140     }
141   }
142   lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0);
143   return nUsed;
144 }
lemon_sprintf(char * str,const char * format,...)145 static int lemon_sprintf(char *str, const char *format, ...){
146   va_list ap;
147   int rc;
148   va_start(ap, format);
149   rc = lemon_vsprintf(str, format, ap);
150   va_end(ap);
151   return rc;
152 }
lemon_strcpy(char * dest,const char * src)153 static void lemon_strcpy(char *dest, const char *src){
154   while( (*(dest++) = *(src++))!=0 ){}
155 }
lemon_strcat(char * dest,const char * src)156 static void lemon_strcat(char *dest, const char *src){
157   while( *dest ) dest++;
158   lemon_strcpy(dest, src);
159 }
160 
161 
162 /* a few forward declarations... */
163 struct rule;
164 struct lemon;
165 struct action;
166 
167 static struct action *Action_new(void);
168 static struct action *Action_sort(struct action *);
169 
170 /********** From the file "build.h" ************************************/
171 void FindRulePrecedences(struct lemon*);
172 void FindFirstSets(struct lemon*);
173 void FindStates(struct lemon*);
174 void FindLinks(struct lemon*);
175 void FindFollowSets(struct lemon*);
176 void FindActions(struct lemon*);
177 
178 /********* From the file "configlist.h" *********************************/
179 void Configlist_init(void);
180 struct config *Configlist_add(struct rule *, int);
181 struct config *Configlist_addbasis(struct rule *, int);
182 void Configlist_closure(struct lemon *);
183 void Configlist_sort(void);
184 void Configlist_sortbasis(void);
185 struct config *Configlist_return(void);
186 struct config *Configlist_basis(void);
187 void Configlist_eat(struct config *);
188 void Configlist_reset(void);
189 
190 /********* From the file "error.h" ***************************************/
191 void ErrorMsg(const char *, int,const char *, ...);
192 
193 /****** From the file "option.h" ******************************************/
194 enum option_type { OPT_FLAG=1,  OPT_INT,  OPT_DBL,  OPT_STR,
195          OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR};
196 struct s_options {
197   enum option_type type;
198   const char *label;
199   char *arg;
200   const char *message;
201 };
202 int    OptInit(char**,struct s_options*,FILE*);
203 int    OptNArgs(void);
204 char  *OptArg(int);
205 void   OptErr(int);
206 void   OptPrint(void);
207 
208 /******** From the file "parse.h" *****************************************/
209 void Parse(struct lemon *lemp);
210 
211 /********* From the file "plink.h" ***************************************/
212 struct plink *Plink_new(void);
213 void Plink_add(struct plink **, struct config *);
214 void Plink_copy(struct plink **, struct plink *);
215 void Plink_delete(struct plink *);
216 
217 /********** From the file "report.h" *************************************/
218 void Reprint(struct lemon *);
219 void ReportOutput(struct lemon *);
220 void ReportTable(struct lemon *, int);
221 void ReportHeader(struct lemon *);
222 void CompressTables(struct lemon *);
223 void ResortStates(struct lemon *);
224 
225 /********** From the file "set.h" ****************************************/
226 void  SetSize(int);             /* All sets will be of size N */
227 char *SetNew(void);               /* A new set for element 0..N */
228 void  SetFree(char*);             /* Deallocate a set */
229 int SetAdd(char*,int);            /* Add element to a set */
230 int SetUnion(char *,char *);    /* A <- A U B, thru element N */
231 #define SetFind(X,Y) (X[Y])       /* True if Y is in set X */
232 
233 /********** From the file "struct.h" *************************************/
234 /*
235 ** Principal data structures for the LEMON parser generator.
236 */
237 
238 typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean;
239 
240 /* Symbols (terminals and nonterminals) of the grammar are stored
241 ** in the following: */
242 enum symbol_type {
243   TERMINAL,
244   NONTERMINAL,
245   MULTITERMINAL
246 };
247 enum e_assoc {
248     LEFT,
249     RIGHT,
250     NONE,
251     UNK
252 };
253 struct symbol {
254   const char *name;        /* Name of the symbol */
255   int index;               /* Index number for this symbol */
256   enum symbol_type type;   /* Symbols are all either TERMINALS or NTs */
257   struct rule *rule;       /* Linked list of rules of this (if an NT) */
258   struct symbol *fallback; /* fallback token in case this token doesn't parse */
259   int prec;                /* Precedence if defined (-1 otherwise) */
260   enum e_assoc assoc;      /* Associativity if precedence is defined */
261   char *firstset;          /* First-set for all rules of this symbol */
262   Boolean lambda;          /* True if NT and can generate an empty string */
263   int useCnt;              /* Number of times used */
264   char *destructor;        /* Code which executes whenever this symbol is
265                            ** popped from the stack during error processing */
266   int destLineno;          /* Line number for start of destructor.  Set to
267                            ** -1 for duplicate destructors. */
268   char *datatype;          /* The data type of information held by this
269                            ** object. Only used if type==NONTERMINAL */
270   int dtnum;               /* The data type number.  In the parser, the value
271                            ** stack is a union.  The .yy%d element of this
272                            ** union is the correct data type for this object */
273   /* The following fields are used by MULTITERMINALs only */
274   int nsubsym;             /* Number of constituent symbols in the MULTI */
275   struct symbol **subsym;  /* Array of constituent symbols */
276 };
277 
278 /* Each production rule in the grammar is stored in the following
279 ** structure.  */
280 struct rule {
281   struct symbol *lhs;      /* Left-hand side of the rule */
282   const char *lhsalias;    /* Alias for the LHS (NULL if none) */
283   int lhsStart;            /* True if left-hand side is the start symbol */
284   int ruleline;            /* Line number for the rule */
285   int nrhs;                /* Number of RHS symbols */
286   struct symbol **rhs;     /* The RHS symbols */
287   const char **rhsalias;   /* An alias for each RHS symbol (NULL if none) */
288   int line;                /* Line number at which code begins */
289   const char *code;        /* The code executed when this rule is reduced */
290   const char *codePrefix;  /* Setup code before code[] above */
291   const char *codeSuffix;  /* Breakdown code after code[] above */
292   int noCode;              /* True if this rule has no associated C code */
293   int codeEmitted;         /* True if the code has been emitted already */
294   struct symbol *precsym;  /* Precedence symbol for this rule */
295   int index;               /* An index number for this rule */
296   int iRule;               /* Rule number as used in the generated tables */
297   Boolean canReduce;       /* True if this rule is ever reduced */
298   Boolean doesReduce;      /* Reduce actions occur after optimization */
299   struct rule *nextlhs;    /* Next rule with the same LHS */
300   struct rule *next;       /* Next rule in the global list */
301 };
302 
303 /* A configuration is a production rule of the grammar together with
304 ** a mark (dot) showing how much of that rule has been processed so far.
305 ** Configurations also contain a follow-set which is a list of terminal
306 ** symbols which are allowed to immediately follow the end of the rule.
307 ** Every configuration is recorded as an instance of the following: */
308 enum cfgstatus {
309   COMPLETE,
310   INCOMPLETE
311 };
312 struct config {
313   struct rule *rp;         /* The rule upon which the configuration is based */
314   int dot;                 /* The parse point */
315   char *fws;               /* Follow-set for this configuration only */
316   struct plink *fplp;      /* Follow-set forward propagation links */
317   struct plink *bplp;      /* Follow-set backwards propagation links */
318   struct state *stp;       /* Pointer to state which contains this */
319   enum cfgstatus status;   /* used during followset and shift computations */
320   struct config *next;     /* Next configuration in the state */
321   struct config *bp;       /* The next basis configuration */
322 };
323 
324 enum e_action {
325   SHIFT,
326   ACCEPT,
327   REDUCE,
328   ERROR,
329   SSCONFLICT,              /* A shift/shift conflict */
330   SRCONFLICT,              /* Was a reduce, but part of a conflict */
331   RRCONFLICT,              /* Was a reduce, but part of a conflict */
332   SH_RESOLVED,             /* Was a shift.  Precedence resolved conflict */
333   RD_RESOLVED,             /* Was reduce.  Precedence resolved conflict */
334   NOT_USED,                /* Deleted by compression */
335   SHIFTREDUCE              /* Shift first, then reduce */
336 };
337 
338 /* Every shift or reduce operation is stored as one of the following */
339 struct action {
340   struct symbol *sp;       /* The look-ahead symbol */
341   enum e_action type;
342   union {
343     struct state *stp;     /* The new state, if a shift */
344     struct rule *rp;       /* The rule, if a reduce */
345   } x;
346   struct symbol *spOpt;    /* SHIFTREDUCE optimization to this symbol */
347   struct action *next;     /* Next action for this state */
348   struct action *collide;  /* Next action with the same hash */
349 };
350 
351 /* Each state of the generated parser's finite state machine
352 ** is encoded as an instance of the following structure. */
353 struct state {
354   struct config *bp;       /* The basis configurations for this state */
355   struct config *cfp;      /* All configurations in this set */
356   int statenum;            /* Sequential number for this state */
357   struct action *ap;       /* List of actions for this state */
358   int nTknAct, nNtAct;     /* Number of actions on terminals and nonterminals */
359   int iTknOfst, iNtOfst;   /* yy_action[] offset for terminals and nonterms */
360   int iDfltReduce;         /* Default action is to REDUCE by this rule */
361   struct rule *pDfltReduce;/* The default REDUCE rule. */
362   int autoReduce;          /* True if this is an auto-reduce state */
363 };
364 #define NO_OFFSET (-2147483647)
365 
366 /* A followset propagation link indicates that the contents of one
367 ** configuration followset should be propagated to another whenever
368 ** the first changes. */
369 struct plink {
370   struct config *cfp;      /* The configuration to which linked */
371   struct plink *next;      /* The next propagate link */
372 };
373 
374 /* The state vector for the entire parser generator is recorded as
375 ** follows.  (LEMON uses no global variables and makes little use of
376 ** static variables.  Fields in the following structure can be thought
377 ** of as begin global variables in the program.) */
378 struct lemon {
379   struct state **sorted;   /* Table of states sorted by state number */
380   struct rule *rule;       /* List of all rules */
381   struct rule *startRule;  /* First rule */
382   int nstate;              /* Number of states */
383   int nxstate;             /* nstate with tail degenerate states removed */
384   int nrule;               /* Number of rules */
385   int nsymbol;             /* Number of terminal and nonterminal symbols */
386   int nterminal;           /* Number of terminal symbols */
387   struct symbol **symbols; /* Sorted array of pointers to symbols */
388   int errorcnt;            /* Number of errors */
389   struct symbol *errsym;   /* The error symbol */
390   struct symbol *wildcard; /* Token that matches anything */
391   char *name;              /* Name of the generated parser */
392   char *arg;               /* Declaration of the 3th argument to parser */
393   char *tokentype;         /* Type of terminal symbols in the parser stack */
394   char *vartype;           /* The default type of non-terminal symbols */
395   char *start;             /* Name of the start symbol for the grammar */
396   char *stacksize;         /* Size of the parser stack */
397   char *include;           /* Code to put at the start of the C file */
398   char *error;             /* Code to execute when an error is seen */
399   char *overflow;          /* Code to execute on a stack overflow */
400   char *failure;           /* Code to execute on parser failure */
401   char *accept;            /* Code to execute when the parser excepts */
402   char *extracode;         /* Code appended to the generated file */
403   char *tokendest;         /* Code to execute to destroy token data */
404   char *vardest;           /* Code for the default non-terminal destructor */
405   char *filename;          /* Name of the input file */
406   char *outname;           /* Name of the current output file */
407   char *tokenprefix;       /* A prefix added to token names in the .h file */
408   int nconflict;           /* Number of parsing conflicts */
409   int nactiontab;          /* Number of entries in the yy_action[] table */
410   int tablesize;           /* Total table size of all tables in bytes */
411   int basisflag;           /* Print only basis configurations */
412   int has_fallback;        /* True if any %fallback is seen in the grammar */
413   int nolinenosflag;       /* True if #line statements should not be printed */
414   char *argv0;             /* Name of the program */
415 };
416 
417 #define MemoryCheck(X) if((X)==0){ \
418   extern void memory_error(); \
419   memory_error(); \
420 }
421 
422 /**************** From the file "table.h" *********************************/
423 /*
424 ** All code in this file has been automatically generated
425 ** from a specification in the file
426 **              "table.q"
427 ** by the associative array code building program "aagen".
428 ** Do not edit this file!  Instead, edit the specification
429 ** file, then rerun aagen.
430 */
431 /*
432 ** Code for processing tables in the LEMON parser generator.
433 */
434 /* Routines for handling a strings */
435 
436 const char *Strsafe(const char *);
437 
438 void Strsafe_init(void);
439 int Strsafe_insert(const char *);
440 const char *Strsafe_find(const char *);
441 
442 /* Routines for handling symbols of the grammar */
443 
444 struct symbol *Symbol_new(const char *);
445 int Symbolcmpp(const void *, const void *);
446 void Symbol_init(void);
447 int Symbol_insert(struct symbol *, const char *);
448 struct symbol *Symbol_find(const char *);
449 struct symbol *Symbol_Nth(int);
450 int Symbol_count(void);
451 struct symbol **Symbol_arrayof(void);
452 
453 /* Routines to manage the state table */
454 
455 int Configcmp(const char *, const char *);
456 struct state *State_new(void);
457 void State_init(void);
458 int State_insert(struct state *, struct config *);
459 struct state *State_find(struct config *);
460 struct state **State_arrayof(void);
461 
462 /* Routines used for efficiency in Configlist_add */
463 
464 void Configtable_init(void);
465 int Configtable_insert(struct config *);
466 struct config *Configtable_find(struct config *);
467 void Configtable_clear(int(*)(struct config *));
468 
469 /****************** From the file "action.c" *******************************/
470 /*
471 ** Routines processing parser actions in the LEMON parser generator.
472 */
473 
474 /* Allocate a new parser action */
Action_new(void)475 static struct action *Action_new(void){
476   static struct action *freelist = 0;
477   struct action *newaction;
478 
479   if( freelist==0 ){
480     int i;
481     int amt = 100;
482     freelist = (struct action *)calloc(amt, sizeof(struct action));
483     if( freelist==0 ){
484       fprintf(stderr,"Unable to allocate memory for a new parser action.");
485       exit(1);
486     }
487     for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
488     freelist[amt-1].next = 0;
489   }
490   newaction = freelist;
491   freelist = freelist->next;
492   return newaction;
493 }
494 
495 /* Compare two actions for sorting purposes.  Return negative, zero, or
496 ** positive if the first action is less than, equal to, or greater than
497 ** the first
498 */
actioncmp(struct action * ap1,struct action * ap2)499 static int actioncmp(
500   struct action *ap1,
501   struct action *ap2
502 ){
503   int rc;
504   rc = ap1->sp->index - ap2->sp->index;
505   if( rc==0 ){
506     rc = (int)ap1->type - (int)ap2->type;
507   }
508   if( rc==0 && (ap1->type==REDUCE || ap1->type==SHIFTREDUCE) ){
509     rc = ap1->x.rp->index - ap2->x.rp->index;
510   }
511   if( rc==0 ){
512     rc = (int) (ap2 - ap1);
513   }
514   return rc;
515 }
516 
517 /* Sort parser actions */
Action_sort(struct action * ap)518 static struct action *Action_sort(
519   struct action *ap
520 ){
521   ap = (struct action *)msort((char *)ap,(char **)&ap->next,
522                               (int(*)(const char*,const char*))actioncmp);
523   return ap;
524 }
525 
Action_add(struct action ** app,enum e_action type,struct symbol * sp,char * arg)526 void Action_add(
527   struct action **app,
528   enum e_action type,
529   struct symbol *sp,
530   char *arg
531 ){
532   struct action *newaction;
533   newaction = Action_new();
534   newaction->next = *app;
535   *app = newaction;
536   newaction->type = type;
537   newaction->sp = sp;
538   newaction->spOpt = 0;
539   if( type==SHIFT ){
540     newaction->x.stp = (struct state *)arg;
541   }else{
542     newaction->x.rp = (struct rule *)arg;
543   }
544 }
545 /********************** New code to implement the "acttab" module ***********/
546 /*
547 ** This module implements routines use to construct the yy_action[] table.
548 */
549 
550 /*
551 ** The state of the yy_action table under construction is an instance of
552 ** the following structure.
553 **
554 ** The yy_action table maps the pair (state_number, lookahead) into an
555 ** action_number.  The table is an array of integers pairs.  The state_number
556 ** determines an initial offset into the yy_action array.  The lookahead
557 ** value is then added to this initial offset to get an index X into the
558 ** yy_action array. If the aAction[X].lookahead equals the value of the
559 ** of the lookahead input, then the value of the action_number output is
560 ** aAction[X].action.  If the lookaheads do not match then the
561 ** default action for the state_number is returned.
562 **
563 ** All actions associated with a single state_number are first entered
564 ** into aLookahead[] using multiple calls to acttab_action().  Then the
565 ** actions for that single state_number are placed into the aAction[]
566 ** array with a single call to acttab_insert().  The acttab_insert() call
567 ** also resets the aLookahead[] array in preparation for the next
568 ** state number.
569 */
570 struct lookahead_action {
571   int lookahead;             /* Value of the lookahead token */
572   int action;                /* Action to take on the given lookahead */
573 };
574 typedef struct acttab acttab;
575 struct acttab {
576   int nAction;                 /* Number of used slots in aAction[] */
577   int nActionAlloc;            /* Slots allocated for aAction[] */
578   struct lookahead_action
579     *aAction,                  /* The yy_action[] table under construction */
580     *aLookahead;               /* A single new transaction set */
581   int mnLookahead;             /* Minimum aLookahead[].lookahead */
582   int mnAction;                /* Action associated with mnLookahead */
583   int mxLookahead;             /* Maximum aLookahead[].lookahead */
584   int nLookahead;              /* Used slots in aLookahead[] */
585   int nLookaheadAlloc;         /* Slots allocated in aLookahead[] */
586 };
587 
588 /* Return the number of entries in the yy_action table */
589 #define acttab_size(X) ((X)->nAction)
590 
591 /* The value for the N-th entry in yy_action */
592 #define acttab_yyaction(X,N)  ((X)->aAction[N].action)
593 
594 /* The value for the N-th entry in yy_lookahead */
595 #define acttab_yylookahead(X,N)  ((X)->aAction[N].lookahead)
596 
597 /* Free all memory associated with the given acttab */
acttab_free(acttab * p)598 void acttab_free(acttab *p){
599   free( p->aAction );
600   free( p->aLookahead );
601   free( p );
602 }
603 
604 /* Allocate a new acttab structure */
acttab_alloc(void)605 acttab *acttab_alloc(void){
606   acttab *p = (acttab *) calloc( 1, sizeof(*p) );
607   if( p==0 ){
608     fprintf(stderr,"Unable to allocate memory for a new acttab.");
609     exit(1);
610   }
611   memset(p, 0, sizeof(*p));
612   return p;
613 }
614 
615 /* Add a new action to the current transaction set.
616 **
617 ** This routine is called once for each lookahead for a particular
618 ** state.
619 */
acttab_action(acttab * p,int lookahead,int action)620 void acttab_action(acttab *p, int lookahead, int action){
621   if( p->nLookahead>=p->nLookaheadAlloc ){
622     p->nLookaheadAlloc += 25;
623     p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead,
624                              sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
625     if( p->aLookahead==0 ){
626       fprintf(stderr,"malloc failed\n");
627       exit(1);
628     }
629   }
630   if( p->nLookahead==0 ){
631     p->mxLookahead = lookahead;
632     p->mnLookahead = lookahead;
633     p->mnAction = action;
634   }else{
635     if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
636     if( p->mnLookahead>lookahead ){
637       p->mnLookahead = lookahead;
638       p->mnAction = action;
639     }
640   }
641   p->aLookahead[p->nLookahead].lookahead = lookahead;
642   p->aLookahead[p->nLookahead].action = action;
643   p->nLookahead++;
644 }
645 
646 /*
647 ** Add the transaction set built up with prior calls to acttab_action()
648 ** into the current action table.  Then reset the transaction set back
649 ** to an empty set in preparation for a new round of acttab_action() calls.
650 **
651 ** Return the offset into the action table of the new transaction.
652 */
acttab_insert(acttab * p)653 int acttab_insert(acttab *p){
654   int i, j, k, n;
655   assert( p->nLookahead>0 );
656 
657   /* Make sure we have enough space to hold the expanded action table
658   ** in the worst case.  The worst case occurs if the transaction set
659   ** must be appended to the current action table
660   */
661   n = p->mxLookahead + 1;
662   if( p->nAction + n >= p->nActionAlloc ){
663     int oldAlloc = p->nActionAlloc;
664     p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
665     p->aAction = (struct lookahead_action *) realloc( p->aAction,
666                           sizeof(p->aAction[0])*p->nActionAlloc);
667     if( p->aAction==0 ){
668       fprintf(stderr,"malloc failed\n");
669       exit(1);
670     }
671     for(i=oldAlloc; i<p->nActionAlloc; i++){
672       p->aAction[i].lookahead = -1;
673       p->aAction[i].action = -1;
674     }
675   }
676 
677   /* Scan the existing action table looking for an offset that is a
678   ** duplicate of the current transaction set.  Fall out of the loop
679   ** if and when the duplicate is found.
680   **
681   ** i is the index in p->aAction[] where p->mnLookahead is inserted.
682   */
683   for(i=p->nAction-1; i>=0; i--){
684     if( p->aAction[i].lookahead==p->mnLookahead ){
685       /* All lookaheads and actions in the aLookahead[] transaction
686       ** must match against the candidate aAction[i] entry. */
687       if( p->aAction[i].action!=p->mnAction ) continue;
688       for(j=0; j<p->nLookahead; j++){
689         k = p->aLookahead[j].lookahead - p->mnLookahead + i;
690         if( k<0 || k>=p->nAction ) break;
691         if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
692         if( p->aLookahead[j].action!=p->aAction[k].action ) break;
693       }
694       if( j<p->nLookahead ) continue;
695 
696       /* No possible lookahead value that is not in the aLookahead[]
697       ** transaction is allowed to match aAction[i] */
698       n = 0;
699       for(j=0; j<p->nAction; j++){
700         if( p->aAction[j].lookahead<0 ) continue;
701         if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
702       }
703       if( n==p->nLookahead ){
704         break;  /* An exact match is found at offset i */
705       }
706     }
707   }
708 
709   /* If no existing offsets exactly match the current transaction, find an
710   ** an empty offset in the aAction[] table in which we can add the
711   ** aLookahead[] transaction.
712   */
713   if( i<0 ){
714     /* Look for holes in the aAction[] table that fit the current
715     ** aLookahead[] transaction.  Leave i set to the offset of the hole.
716     ** If no holes are found, i is left at p->nAction, which means the
717     ** transaction will be appended. */
718     for(i=0; i<p->nActionAlloc - p->mxLookahead; i++){
719       if( p->aAction[i].lookahead<0 ){
720         for(j=0; j<p->nLookahead; j++){
721           k = p->aLookahead[j].lookahead - p->mnLookahead + i;
722           if( k<0 ) break;
723           if( p->aAction[k].lookahead>=0 ) break;
724         }
725         if( j<p->nLookahead ) continue;
726         for(j=0; j<p->nAction; j++){
727           if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
728         }
729         if( j==p->nAction ){
730           break;  /* Fits in empty slots */
731         }
732       }
733     }
734   }
735   /* Insert transaction set at index i. */
736   for(j=0; j<p->nLookahead; j++){
737     k = p->aLookahead[j].lookahead - p->mnLookahead + i;
738     p->aAction[k] = p->aLookahead[j];
739     if( k>=p->nAction ) p->nAction = k+1;
740   }
741   p->nLookahead = 0;
742 
743   /* Return the offset that is added to the lookahead in order to get the
744   ** index into yy_action of the action */
745   return i - p->mnLookahead;
746 }
747 
748 /********************** From the file "build.c" *****************************/
749 /*
750 ** Routines to construction the finite state machine for the LEMON
751 ** parser generator.
752 */
753 
754 /* Find a precedence symbol of every rule in the grammar.
755 **
756 ** Those rules which have a precedence symbol coded in the input
757 ** grammar using the "[symbol]" construct will already have the
758 ** rp->precsym field filled.  Other rules take as their precedence
759 ** symbol the first RHS symbol with a defined precedence.  If there
760 ** are not RHS symbols with a defined precedence, the precedence
761 ** symbol field is left blank.
762 */
FindRulePrecedences(struct lemon * xp)763 void FindRulePrecedences(struct lemon *xp)
764 {
765   struct rule *rp;
766   for(rp=xp->rule; rp; rp=rp->next){
767     if( rp->precsym==0 ){
768       int i, j;
769       for(i=0; i<rp->nrhs && rp->precsym==0; i++){
770         struct symbol *sp = rp->rhs[i];
771         if( sp->type==MULTITERMINAL ){
772           for(j=0; j<sp->nsubsym; j++){
773             if( sp->subsym[j]->prec>=0 ){
774               rp->precsym = sp->subsym[j];
775               break;
776             }
777           }
778         }else if( sp->prec>=0 ){
779           rp->precsym = rp->rhs[i];
780         }
781       }
782     }
783   }
784   return;
785 }
786 
787 /* Find all nonterminals which will generate the empty string.
788 ** Then go back and compute the first sets of every nonterminal.
789 ** The first set is the set of all terminal symbols which can begin
790 ** a string generated by that nonterminal.
791 */
FindFirstSets(struct lemon * lemp)792 void FindFirstSets(struct lemon *lemp)
793 {
794   int i, j;
795   struct rule *rp;
796   int progress;
797 
798   for(i=0; i<lemp->nsymbol; i++){
799     lemp->symbols[i]->lambda = LEMON_FALSE;
800   }
801   for(i=lemp->nterminal; i<lemp->nsymbol; i++){
802     lemp->symbols[i]->firstset = SetNew();
803   }
804 
805   /* First compute all lambdas */
806   do{
807     progress = 0;
808     for(rp=lemp->rule; rp; rp=rp->next){
809       if( rp->lhs->lambda ) continue;
810       for(i=0; i<rp->nrhs; i++){
811         struct symbol *sp = rp->rhs[i];
812         assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE );
813         if( sp->lambda==LEMON_FALSE ) break;
814       }
815       if( i==rp->nrhs ){
816         rp->lhs->lambda = LEMON_TRUE;
817         progress = 1;
818       }
819     }
820   }while( progress );
821 
822   /* Now compute all first sets */
823   do{
824     struct symbol *s1, *s2;
825     progress = 0;
826     for(rp=lemp->rule; rp; rp=rp->next){
827       s1 = rp->lhs;
828       for(i=0; i<rp->nrhs; i++){
829         s2 = rp->rhs[i];
830         if( s2->type==TERMINAL ){
831           progress += SetAdd(s1->firstset,s2->index);
832           break;
833         }else if( s2->type==MULTITERMINAL ){
834           for(j=0; j<s2->nsubsym; j++){
835             progress += SetAdd(s1->firstset,s2->subsym[j]->index);
836           }
837           break;
838         }else if( s1==s2 ){
839           if( s1->lambda==LEMON_FALSE ) break;
840         }else{
841           progress += SetUnion(s1->firstset,s2->firstset);
842           if( s2->lambda==LEMON_FALSE ) break;
843         }
844       }
845     }
846   }while( progress );
847   return;
848 }
849 
850 /* Compute all LR(0) states for the grammar.  Links
851 ** are added to between some states so that the LR(1) follow sets
852 ** can be computed later.
853 */
854 PRIVATE struct state *getstate(struct lemon *);  /* forward reference */
FindStates(struct lemon * lemp)855 void FindStates(struct lemon *lemp)
856 {
857   struct symbol *sp;
858   struct rule *rp;
859 
860   Configlist_init();
861 
862   /* Find the start symbol */
863   if( lemp->start ){
864     sp = Symbol_find(lemp->start);
865     if( sp==0 ){
866       ErrorMsg(lemp->filename,0,
867 "The specified start symbol \"%s\" is not \
868 in a nonterminal of the grammar.  \"%s\" will be used as the start \
869 symbol instead.",lemp->start,lemp->startRule->lhs->name);
870       lemp->errorcnt++;
871       sp = lemp->startRule->lhs;
872     }
873   }else{
874     sp = lemp->startRule->lhs;
875   }
876 
877   /* Make sure the start symbol doesn't occur on the right-hand side of
878   ** any rule.  Report an error if it does.  (YACC would generate a new
879   ** start symbol in this case.) */
880   for(rp=lemp->rule; rp; rp=rp->next){
881     int i;
882     for(i=0; i<rp->nrhs; i++){
883       if( rp->rhs[i]==sp ){   /* FIX ME:  Deal with multiterminals */
884         ErrorMsg(lemp->filename,0,
885 "The start symbol \"%s\" occurs on the \
886 right-hand side of a rule. This will result in a parser which \
887 does not work properly.",sp->name);
888         lemp->errorcnt++;
889       }
890     }
891   }
892 
893   /* The basis configuration set for the first state
894   ** is all rules which have the start symbol as their
895   ** left-hand side */
896   for(rp=sp->rule; rp; rp=rp->nextlhs){
897     struct config *newcfp;
898     rp->lhsStart = 1;
899     newcfp = Configlist_addbasis(rp,0);
900     SetAdd(newcfp->fws,0);
901   }
902 
903   /* Compute the first state.  All other states will be
904   ** computed automatically during the computation of the first one.
905   ** The returned pointer to the first state is not used. */
906   (void)getstate(lemp);
907   return;
908 }
909 
910 /* Return a pointer to a state which is described by the configuration
911 ** list which has been built from calls to Configlist_add.
912 */
913 PRIVATE void buildshifts(struct lemon *, struct state *); /* Forwd ref */
getstate(struct lemon * lemp)914 PRIVATE struct state *getstate(struct lemon *lemp)
915 {
916   struct config *cfp, *bp;
917   struct state *stp;
918 
919   /* Extract the sorted basis of the new state.  The basis was constructed
920   ** by prior calls to "Configlist_addbasis()". */
921   Configlist_sortbasis();
922   bp = Configlist_basis();
923 
924   /* Get a state with the same basis */
925   stp = State_find(bp);
926   if( stp ){
927     /* A state with the same basis already exists!  Copy all the follow-set
928     ** propagation links from the state under construction into the
929     ** preexisting state, then return a pointer to the preexisting state */
930     struct config *x, *y;
931     for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
932       Plink_copy(&y->bplp,x->bplp);
933       Plink_delete(x->fplp);
934       x->fplp = x->bplp = 0;
935     }
936     cfp = Configlist_return();
937     Configlist_eat(cfp);
938   }else{
939     /* This really is a new state.  Construct all the details */
940     Configlist_closure(lemp);    /* Compute the configuration closure */
941     Configlist_sort();           /* Sort the configuration closure */
942     cfp = Configlist_return();   /* Get a pointer to the config list */
943     stp = State_new();           /* A new state structure */
944     MemoryCheck(stp);
945     stp->bp = bp;                /* Remember the configuration basis */
946     stp->cfp = cfp;              /* Remember the configuration closure */
947     stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
948     stp->ap = 0;                 /* No actions, yet. */
949     State_insert(stp,stp->bp);   /* Add to the state table */
950     buildshifts(lemp,stp);       /* Recursively compute successor states */
951   }
952   return stp;
953 }
954 
955 /*
956 ** Return true if two symbols are the same.
957 */
same_symbol(struct symbol * a,struct symbol * b)958 int same_symbol(struct symbol *a, struct symbol *b)
959 {
960   int i;
961   if( a==b ) return 1;
962   if( a->type!=MULTITERMINAL ) return 0;
963   if( b->type!=MULTITERMINAL ) return 0;
964   if( a->nsubsym!=b->nsubsym ) return 0;
965   for(i=0; i<a->nsubsym; i++){
966     if( a->subsym[i]!=b->subsym[i] ) return 0;
967   }
968   return 1;
969 }
970 
971 /* Construct all successor states to the given state.  A "successor"
972 ** state is any state which can be reached by a shift action.
973 */
buildshifts(struct lemon * lemp,struct state * stp)974 PRIVATE void buildshifts(struct lemon *lemp, struct state *stp)
975 {
976   struct config *cfp;  /* For looping thru the config closure of "stp" */
977   struct config *bcfp; /* For the inner loop on config closure of "stp" */
978   struct config *newcfg;  /* */
979   struct symbol *sp;   /* Symbol following the dot in configuration "cfp" */
980   struct symbol *bsp;  /* Symbol following the dot in configuration "bcfp" */
981   struct state *newstp; /* A pointer to a successor state */
982 
983   /* Each configuration becomes complete after it contibutes to a successor
984   ** state.  Initially, all configurations are incomplete */
985   for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
986 
987   /* Loop through all configurations of the state "stp" */
988   for(cfp=stp->cfp; cfp; cfp=cfp->next){
989     if( cfp->status==COMPLETE ) continue;    /* Already used by inner loop */
990     if( cfp->dot>=cfp->rp->nrhs ) continue;  /* Can't shift this config */
991     Configlist_reset();                      /* Reset the new config set */
992     sp = cfp->rp->rhs[cfp->dot];             /* Symbol after the dot */
993 
994     /* For every configuration in the state "stp" which has the symbol "sp"
995     ** following its dot, add the same configuration to the basis set under
996     ** construction but with the dot shifted one symbol to the right. */
997     for(bcfp=cfp; bcfp; bcfp=bcfp->next){
998       if( bcfp->status==COMPLETE ) continue;    /* Already used */
999       if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
1000       bsp = bcfp->rp->rhs[bcfp->dot];           /* Get symbol after dot */
1001       if( !same_symbol(bsp,sp) ) continue;      /* Must be same as for "cfp" */
1002       bcfp->status = COMPLETE;                  /* Mark this config as used */
1003       newcfg = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
1004       Plink_add(&newcfg->bplp,bcfp);
1005     }
1006 
1007     /* Get a pointer to the state described by the basis configuration set
1008     ** constructed in the preceding loop */
1009     newstp = getstate(lemp);
1010 
1011     /* The state "newstp" is reached from the state "stp" by a shift action
1012     ** on the symbol "sp" */
1013     if( sp->type==MULTITERMINAL ){
1014       int i;
1015       for(i=0; i<sp->nsubsym; i++){
1016         Action_add(&stp->ap,SHIFT,sp->subsym[i],(char*)newstp);
1017       }
1018     }else{
1019       Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
1020     }
1021   }
1022 }
1023 
1024 /*
1025 ** Construct the propagation links
1026 */
FindLinks(struct lemon * lemp)1027 void FindLinks(struct lemon *lemp)
1028 {
1029   int i;
1030   struct config *cfp, *other;
1031   struct state *stp;
1032   struct plink *plp;
1033 
1034   /* Housekeeping detail:
1035   ** Add to every propagate link a pointer back to the state to
1036   ** which the link is attached. */
1037   for(i=0; i<lemp->nstate; i++){
1038     stp = lemp->sorted[i];
1039     for(cfp=stp->cfp; cfp; cfp=cfp->next){
1040       cfp->stp = stp;
1041     }
1042   }
1043 
1044   /* Convert all backlinks into forward links.  Only the forward
1045   ** links are used in the follow-set computation. */
1046   for(i=0; i<lemp->nstate; i++){
1047     stp = lemp->sorted[i];
1048     for(cfp=stp->cfp; cfp; cfp=cfp->next){
1049       for(plp=cfp->bplp; plp; plp=plp->next){
1050         other = plp->cfp;
1051         Plink_add(&other->fplp,cfp);
1052       }
1053     }
1054   }
1055 }
1056 
1057 /* Compute all followsets.
1058 **
1059 ** A followset is the set of all symbols which can come immediately
1060 ** after a configuration.
1061 */
FindFollowSets(struct lemon * lemp)1062 void FindFollowSets(struct lemon *lemp)
1063 {
1064   int i;
1065   struct config *cfp;
1066   struct plink *plp;
1067   int progress;
1068   int change;
1069 
1070   for(i=0; i<lemp->nstate; i++){
1071     for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
1072       cfp->status = INCOMPLETE;
1073     }
1074   }
1075 
1076   do{
1077     progress = 0;
1078     for(i=0; i<lemp->nstate; i++){
1079       for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
1080         if( cfp->status==COMPLETE ) continue;
1081         for(plp=cfp->fplp; plp; plp=plp->next){
1082           change = SetUnion(plp->cfp->fws,cfp->fws);
1083           if( change ){
1084             plp->cfp->status = INCOMPLETE;
1085             progress = 1;
1086           }
1087         }
1088         cfp->status = COMPLETE;
1089       }
1090     }
1091   }while( progress );
1092 }
1093 
1094 static int resolve_conflict(struct action *,struct action *);
1095 
1096 /* Compute the reduce actions, and resolve conflicts.
1097 */
FindActions(struct lemon * lemp)1098 void FindActions(struct lemon *lemp)
1099 {
1100   int i,j;
1101   struct config *cfp;
1102   struct state *stp;
1103   struct symbol *sp;
1104   struct rule *rp;
1105 
1106   /* Add all of the reduce actions
1107   ** A reduce action is added for each element of the followset of
1108   ** a configuration which has its dot at the extreme right.
1109   */
1110   for(i=0; i<lemp->nstate; i++){   /* Loop over all states */
1111     stp = lemp->sorted[i];
1112     for(cfp=stp->cfp; cfp; cfp=cfp->next){  /* Loop over all configurations */
1113       if( cfp->rp->nrhs==cfp->dot ){        /* Is dot at extreme right? */
1114         for(j=0; j<lemp->nterminal; j++){
1115           if( SetFind(cfp->fws,j) ){
1116             /* Add a reduce action to the state "stp" which will reduce by the
1117             ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
1118             Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
1119           }
1120         }
1121       }
1122     }
1123   }
1124 
1125   /* Add the accepting token */
1126   if( lemp->start ){
1127     sp = Symbol_find(lemp->start);
1128     if( sp==0 ) sp = lemp->startRule->lhs;
1129   }else{
1130     sp = lemp->startRule->lhs;
1131   }
1132   /* Add to the first state (which is always the starting state of the
1133   ** finite state machine) an action to ACCEPT if the lookahead is the
1134   ** start nonterminal.  */
1135   Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
1136 
1137   /* Resolve conflicts */
1138   for(i=0; i<lemp->nstate; i++){
1139     struct action *ap, *nap;
1140     stp = lemp->sorted[i];
1141     /* assert( stp->ap ); */
1142     stp->ap = Action_sort(stp->ap);
1143     for(ap=stp->ap; ap && ap->next; ap=ap->next){
1144       for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
1145          /* The two actions "ap" and "nap" have the same lookahead.
1146          ** Figure out which one should be used */
1147          lemp->nconflict += resolve_conflict(ap,nap);
1148       }
1149     }
1150   }
1151 
1152   /* Report an error for each rule that can never be reduced. */
1153   for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE;
1154   for(i=0; i<lemp->nstate; i++){
1155     struct action *ap;
1156     for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
1157       if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE;
1158     }
1159   }
1160   for(rp=lemp->rule; rp; rp=rp->next){
1161     if( rp->canReduce ) continue;
1162     ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
1163     lemp->errorcnt++;
1164   }
1165 }
1166 
1167 /* Resolve a conflict between the two given actions.  If the
1168 ** conflict can't be resolved, return non-zero.
1169 **
1170 ** NO LONGER TRUE:
1171 **   To resolve a conflict, first look to see if either action
1172 **   is on an error rule.  In that case, take the action which
1173 **   is not associated with the error rule.  If neither or both
1174 **   actions are associated with an error rule, then try to
1175 **   use precedence to resolve the conflict.
1176 **
1177 ** If either action is a SHIFT, then it must be apx.  This
1178 ** function won't work if apx->type==REDUCE and apy->type==SHIFT.
1179 */
resolve_conflict(struct action * apx,struct action * apy)1180 static int resolve_conflict(
1181   struct action *apx,
1182   struct action *apy
1183 ){
1184   struct symbol *spx, *spy;
1185   int errcnt = 0;
1186   assert( apx->sp==apy->sp );  /* Otherwise there would be no conflict */
1187   if( apx->type==SHIFT && apy->type==SHIFT ){
1188     apy->type = SSCONFLICT;
1189     errcnt++;
1190   }
1191   if( apx->type==SHIFT && apy->type==REDUCE ){
1192     spx = apx->sp;
1193     spy = apy->x.rp->precsym;
1194     if( spy==0 || spx->prec<0 || spy->prec<0 ){
1195       /* Not enough precedence information. */
1196       apy->type = SRCONFLICT;
1197       errcnt++;
1198     }else if( spx->prec>spy->prec ){    /* higher precedence wins */
1199       apy->type = RD_RESOLVED;
1200     }else if( spx->prec<spy->prec ){
1201       apx->type = SH_RESOLVED;
1202     }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
1203       apy->type = RD_RESOLVED;                             /* associativity */
1204     }else if( spx->prec==spy->prec && spx->assoc==LEFT ){  /* to break tie */
1205       apx->type = SH_RESOLVED;
1206     }else{
1207       assert( spx->prec==spy->prec && spx->assoc==NONE );
1208       apx->type = ERROR;
1209     }
1210   }else if( apx->type==REDUCE && apy->type==REDUCE ){
1211     spx = apx->x.rp->precsym;
1212     spy = apy->x.rp->precsym;
1213     if( spx==0 || spy==0 || spx->prec<0 ||
1214     spy->prec<0 || spx->prec==spy->prec ){
1215       apy->type = RRCONFLICT;
1216       errcnt++;
1217     }else if( spx->prec>spy->prec ){
1218       apy->type = RD_RESOLVED;
1219     }else if( spx->prec<spy->prec ){
1220       apx->type = RD_RESOLVED;
1221     }
1222   }else{
1223     assert(
1224       apx->type==SH_RESOLVED ||
1225       apx->type==RD_RESOLVED ||
1226       apx->type==SSCONFLICT ||
1227       apx->type==SRCONFLICT ||
1228       apx->type==RRCONFLICT ||
1229       apy->type==SH_RESOLVED ||
1230       apy->type==RD_RESOLVED ||
1231       apy->type==SSCONFLICT ||
1232       apy->type==SRCONFLICT ||
1233       apy->type==RRCONFLICT
1234     );
1235     /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
1236     ** REDUCEs on the list.  If we reach this point it must be because
1237     ** the parser conflict had already been resolved. */
1238   }
1239   return errcnt;
1240 }
1241 /********************* From the file "configlist.c" *************************/
1242 /*
1243 ** Routines to processing a configuration list and building a state
1244 ** in the LEMON parser generator.
1245 */
1246 
1247 static struct config *freelist = 0;      /* List of free configurations */
1248 static struct config *current = 0;       /* Top of list of configurations */
1249 static struct config **currentend = 0;   /* Last on list of configs */
1250 static struct config *basis = 0;         /* Top of list of basis configs */
1251 static struct config **basisend = 0;     /* End of list of basis configs */
1252 
1253 /* Return a pointer to a new configuration */
newconfig(void)1254 PRIVATE struct config *newconfig(void){
1255   struct config *newcfg;
1256   if( freelist==0 ){
1257     int i;
1258     int amt = 3;
1259     freelist = (struct config *)calloc( amt, sizeof(struct config) );
1260     if( freelist==0 ){
1261       fprintf(stderr,"Unable to allocate memory for a new configuration.");
1262       exit(1);
1263     }
1264     for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
1265     freelist[amt-1].next = 0;
1266   }
1267   newcfg = freelist;
1268   freelist = freelist->next;
1269   return newcfg;
1270 }
1271 
1272 /* The configuration "old" is no longer used */
deleteconfig(struct config * old)1273 PRIVATE void deleteconfig(struct config *old)
1274 {
1275   old->next = freelist;
1276   freelist = old;
1277 }
1278 
1279 /* Initialized the configuration list builder */
Configlist_init(void)1280 void Configlist_init(void){
1281   current = 0;
1282   currentend = &current;
1283   basis = 0;
1284   basisend = &basis;
1285   Configtable_init();
1286   return;
1287 }
1288 
1289 /* Initialized the configuration list builder */
Configlist_reset(void)1290 void Configlist_reset(void){
1291   current = 0;
1292   currentend = &current;
1293   basis = 0;
1294   basisend = &basis;
1295   Configtable_clear(0);
1296   return;
1297 }
1298 
1299 /* Add another configuration to the configuration list */
Configlist_add(struct rule * rp,int dot)1300 struct config *Configlist_add(
1301   struct rule *rp,    /* The rule */
1302   int dot             /* Index into the RHS of the rule where the dot goes */
1303 ){
1304   struct config *cfp, model;
1305 
1306   assert( currentend!=0 );
1307   model.rp = rp;
1308   model.dot = dot;
1309   cfp = Configtable_find(&model);
1310   if( cfp==0 ){
1311     cfp = newconfig();
1312     cfp->rp = rp;
1313     cfp->dot = dot;
1314     cfp->fws = SetNew();
1315     cfp->stp = 0;
1316     cfp->fplp = cfp->bplp = 0;
1317     cfp->next = 0;
1318     cfp->bp = 0;
1319     *currentend = cfp;
1320     currentend = &cfp->next;
1321     Configtable_insert(cfp);
1322   }
1323   return cfp;
1324 }
1325 
1326 /* Add a basis configuration to the configuration list */
Configlist_addbasis(struct rule * rp,int dot)1327 struct config *Configlist_addbasis(struct rule *rp, int dot)
1328 {
1329   struct config *cfp, model;
1330 
1331   assert( basisend!=0 );
1332   assert( currentend!=0 );
1333   model.rp = rp;
1334   model.dot = dot;
1335   cfp = Configtable_find(&model);
1336   if( cfp==0 ){
1337     cfp = newconfig();
1338     cfp->rp = rp;
1339     cfp->dot = dot;
1340     cfp->fws = SetNew();
1341     cfp->stp = 0;
1342     cfp->fplp = cfp->bplp = 0;
1343     cfp->next = 0;
1344     cfp->bp = 0;
1345     *currentend = cfp;
1346     currentend = &cfp->next;
1347     *basisend = cfp;
1348     basisend = &cfp->bp;
1349     Configtable_insert(cfp);
1350   }
1351   return cfp;
1352 }
1353 
1354 /* Compute the closure of the configuration list */
Configlist_closure(struct lemon * lemp)1355 void Configlist_closure(struct lemon *lemp)
1356 {
1357   struct config *cfp, *newcfp;
1358   struct rule *rp, *newrp;
1359   struct symbol *sp, *xsp;
1360   int i, dot;
1361 
1362   assert( currentend!=0 );
1363   for(cfp=current; cfp; cfp=cfp->next){
1364     rp = cfp->rp;
1365     dot = cfp->dot;
1366     if( dot>=rp->nrhs ) continue;
1367     sp = rp->rhs[dot];
1368     if( sp->type==NONTERMINAL ){
1369       if( sp->rule==0 && sp!=lemp->errsym ){
1370         ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
1371           sp->name);
1372         lemp->errorcnt++;
1373       }
1374       for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
1375         newcfp = Configlist_add(newrp,0);
1376         for(i=dot+1; i<rp->nrhs; i++){
1377           xsp = rp->rhs[i];
1378           if( xsp->type==TERMINAL ){
1379             SetAdd(newcfp->fws,xsp->index);
1380             break;
1381           }else if( xsp->type==MULTITERMINAL ){
1382             int k;
1383             for(k=0; k<xsp->nsubsym; k++){
1384               SetAdd(newcfp->fws, xsp->subsym[k]->index);
1385             }
1386             break;
1387           }else{
1388             SetUnion(newcfp->fws,xsp->firstset);
1389             if( xsp->lambda==LEMON_FALSE ) break;
1390           }
1391         }
1392         if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
1393       }
1394     }
1395   }
1396   return;
1397 }
1398 
1399 /* Sort the configuration list */
Configlist_sort(void)1400 void Configlist_sort(void){
1401   current = (struct config*)msort((char*)current,(char**)&(current->next),
1402                                   Configcmp);
1403   currentend = 0;
1404   return;
1405 }
1406 
1407 /* Sort the basis configuration list */
Configlist_sortbasis(void)1408 void Configlist_sortbasis(void){
1409   basis = (struct config*)msort((char*)current,(char**)&(current->bp),
1410                                 Configcmp);
1411   basisend = 0;
1412   return;
1413 }
1414 
1415 /* Return a pointer to the head of the configuration list and
1416 ** reset the list */
Configlist_return(void)1417 struct config *Configlist_return(void){
1418   struct config *old;
1419   old = current;
1420   current = 0;
1421   currentend = 0;
1422   return old;
1423 }
1424 
1425 /* Return a pointer to the head of the configuration list and
1426 ** reset the list */
Configlist_basis(void)1427 struct config *Configlist_basis(void){
1428   struct config *old;
1429   old = basis;
1430   basis = 0;
1431   basisend = 0;
1432   return old;
1433 }
1434 
1435 /* Free all elements of the given configuration list */
Configlist_eat(struct config * cfp)1436 void Configlist_eat(struct config *cfp)
1437 {
1438   struct config *nextcfp;
1439   for(; cfp; cfp=nextcfp){
1440     nextcfp = cfp->next;
1441     assert( cfp->fplp==0 );
1442     assert( cfp->bplp==0 );
1443     if( cfp->fws ) SetFree(cfp->fws);
1444     deleteconfig(cfp);
1445   }
1446   return;
1447 }
1448 /***************** From the file "error.c" *********************************/
1449 /*
1450 ** Code for printing error message.
1451 */
1452 
ErrorMsg(const char * filename,int lineno,const char * format,...)1453 void ErrorMsg(const char *filename, int lineno, const char *format, ...){
1454   va_list ap;
1455   fprintf(stderr, "%s:%d: ", filename, lineno);
1456   va_start(ap, format);
1457   vfprintf(stderr,format,ap);
1458   va_end(ap);
1459   fprintf(stderr, "\n");
1460 }
1461 /**************** From the file "main.c" ************************************/
1462 /*
1463 ** Main program file for the LEMON parser generator.
1464 */
1465 
1466 /* Report an out-of-memory condition and abort.  This function
1467 ** is used mostly by the "MemoryCheck" macro in struct.h
1468 */
memory_error(void)1469 void memory_error(void){
1470   fprintf(stderr,"Out of memory.  Aborting...\n");
1471   exit(1);
1472 }
1473 
1474 static int nDefine = 0;      /* Number of -D options on the command line */
1475 static char **azDefine = 0;  /* Name of the -D macros */
1476 
1477 /* This routine is called with the argument to each -D command-line option.
1478 ** Add the macro defined to the azDefine array.
1479 */
handle_D_option(char * z)1480 static void handle_D_option(char *z){
1481   char **paz;
1482   nDefine++;
1483   azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine);
1484   if( azDefine==0 ){
1485     fprintf(stderr,"out of memory\n");
1486     exit(1);
1487   }
1488   paz = &azDefine[nDefine-1];
1489   *paz = (char *) malloc( lemonStrlen(z)+1 );
1490   if( *paz==0 ){
1491     fprintf(stderr,"out of memory\n");
1492     exit(1);
1493   }
1494   lemon_strcpy(*paz, z);
1495   for(z=*paz; *z && *z!='='; z++){}
1496   *z = 0;
1497 }
1498 
1499 static char *user_templatename = NULL;
handle_T_option(char * z)1500 static void handle_T_option(char *z){
1501   user_templatename = (char *) malloc( lemonStrlen(z)+1 );
1502   if( user_templatename==0 ){
1503     memory_error();
1504   }
1505   lemon_strcpy(user_templatename, z);
1506 }
1507 
1508 /* Merge together to lists of rules ordered by rule.iRule */
Rule_merge(struct rule * pA,struct rule * pB)1509 static struct rule *Rule_merge(struct rule *pA, struct rule *pB){
1510   struct rule *pFirst = 0;
1511   struct rule **ppPrev = &pFirst;
1512   while( pA && pB ){
1513     if( pA->iRule<pB->iRule ){
1514       *ppPrev = pA;
1515       ppPrev = &pA->next;
1516       pA = pA->next;
1517     }else{
1518       *ppPrev = pB;
1519       ppPrev = &pB->next;
1520       pB = pB->next;
1521     }
1522   }
1523   if( pA ){
1524     *ppPrev = pA;
1525   }else{
1526     *ppPrev = pB;
1527   }
1528   return pFirst;
1529 }
1530 
1531 /*
1532 ** Sort a list of rules in order of increasing iRule value
1533 */
Rule_sort(struct rule * rp)1534 static struct rule *Rule_sort(struct rule *rp){
1535   int i;
1536   struct rule *pNext;
1537   struct rule *x[32];
1538   memset(x, 0, sizeof(x));
1539   while( rp ){
1540     pNext = rp->next;
1541     rp->next = 0;
1542     for(i=0; i<sizeof(x)/sizeof(x[0]) && x[i]; i++){
1543       rp = Rule_merge(x[i], rp);
1544       x[i] = 0;
1545     }
1546     x[i] = rp;
1547     rp = pNext;
1548   }
1549   rp = 0;
1550   for(i=0; i<sizeof(x)/sizeof(x[0]); i++){
1551     rp = Rule_merge(x[i], rp);
1552   }
1553   return rp;
1554 }
1555 
1556 /* forward reference */
1557 static const char *minimum_size_type(int lwr, int upr, int *pnByte);
1558 
1559 /* Print a single line of the "Parser Stats" output
1560 */
stats_line(const char * zLabel,int iValue)1561 static void stats_line(const char *zLabel, int iValue){
1562   int nLabel = lemonStrlen(zLabel);
1563   printf("  %s%.*s %5d\n", zLabel,
1564          35-nLabel, "................................",
1565          iValue);
1566 }
1567 
1568 /* The main program.  Parse the command line and do it... */
main(int argc,char ** argv)1569 int main(int argc, char **argv)
1570 {
1571   static int version = 0;
1572   static int rpflag = 0;
1573   static int basisflag = 0;
1574   static int compress = 0;
1575   static int quiet = 0;
1576   static int statistics = 0;
1577   static int mhflag = 0;
1578   static int nolinenosflag = 0;
1579   static int noResort = 0;
1580   static struct s_options options[] = {
1581     {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
1582     {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
1583     {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
1584     {OPT_FSTR, "f", 0, "Ignored.  (Placeholder for -f compiler options.)"},
1585     {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
1586     {OPT_FSTR, "I", 0, "Ignored.  (Placeholder for '-I' compiler options.)"},
1587     {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."},
1588     {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."},
1589     {OPT_FSTR, "O", 0, "Ignored.  (Placeholder for '-O' compiler options.)"},
1590     {OPT_FLAG, "p", (char*)&showPrecedenceConflict,
1591                     "Show conflicts resolved by precedence rules"},
1592     {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
1593     {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
1594     {OPT_FLAG, "s", (char*)&statistics,
1595                                    "Print parser stats to standard output."},
1596     {OPT_FLAG, "x", (char*)&version, "Print the version number."},
1597     {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
1598     {OPT_FSTR, "W", 0, "Ignored.  (Placeholder for '-W' compiler options.)"},
1599     {OPT_FLAG,0,0,0}
1600   };
1601   int i;
1602   int exitcode;
1603   struct lemon lem;
1604   struct rule *rp;
1605 
1606   OptInit(argv,options,stderr);
1607   if( version ){
1608      printf("Lemon version 1.0\n");
1609      exit(0);
1610   }
1611   if( OptNArgs()!=1 ){
1612     fprintf(stderr,"Exactly one filename argument is required.\n");
1613     exit(1);
1614   }
1615   memset(&lem, 0, sizeof(lem));
1616   lem.errorcnt = 0;
1617 
1618   /* Initialize the machine */
1619   Strsafe_init();
1620   Symbol_init();
1621   State_init();
1622   lem.argv0 = argv[0];
1623   lem.filename = OptArg(0);
1624   lem.basisflag = basisflag;
1625   lem.nolinenosflag = nolinenosflag;
1626   Symbol_new("$");
1627   lem.errsym = Symbol_new("error");
1628   lem.errsym->useCnt = 0;
1629 
1630   /* Parse the input file */
1631   Parse(&lem);
1632   if( lem.errorcnt ) exit(lem.errorcnt);
1633   if( lem.nrule==0 ){
1634     fprintf(stderr,"Empty grammar.\n");
1635     exit(1);
1636   }
1637 
1638   /* Count and index the symbols of the grammar */
1639   Symbol_new("{default}");
1640   lem.nsymbol = Symbol_count();
1641   lem.symbols = Symbol_arrayof();
1642   for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
1643   qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp);
1644   for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
1645   while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; }
1646   assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 );
1647   lem.nsymbol = i - 1;
1648   for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++);
1649   lem.nterminal = i;
1650 
1651   /* Assign sequential rule numbers.  Start with 0.  Put rules that have no
1652   ** reduce action C-code associated with them last, so that the switch()
1653   ** statement that selects reduction actions will have a smaller jump table.
1654   */
1655   for(i=0, rp=lem.rule; rp; rp=rp->next){
1656     rp->iRule = rp->code ? i++ : -1;
1657   }
1658   for(rp=lem.rule; rp; rp=rp->next){
1659     if( rp->iRule<0 ) rp->iRule = i++;
1660   }
1661   lem.startRule = lem.rule;
1662   lem.rule = Rule_sort(lem.rule);
1663 
1664   /* Generate a reprint of the grammar, if requested on the command line */
1665   if( rpflag ){
1666     Reprint(&lem);
1667   }else{
1668     /* Initialize the size for all follow and first sets */
1669     SetSize(lem.nterminal+1);
1670 
1671     /* Find the precedence for every production rule (that has one) */
1672     FindRulePrecedences(&lem);
1673 
1674     /* Compute the lambda-nonterminals and the first-sets for every
1675     ** nonterminal */
1676     FindFirstSets(&lem);
1677 
1678     /* Compute all LR(0) states.  Also record follow-set propagation
1679     ** links so that the follow-set can be computed later */
1680     lem.nstate = 0;
1681     FindStates(&lem);
1682     lem.sorted = State_arrayof();
1683 
1684     /* Tie up loose ends on the propagation links */
1685     FindLinks(&lem);
1686 
1687     /* Compute the follow set of every reducible configuration */
1688     FindFollowSets(&lem);
1689 
1690     /* Compute the action tables */
1691     FindActions(&lem);
1692 
1693     /* Compress the action tables */
1694     if( compress==0 ) CompressTables(&lem);
1695 
1696     /* Reorder and renumber the states so that states with fewer choices
1697     ** occur at the end.  This is an optimization that helps make the
1698     ** generated parser tables smaller. */
1699     if( noResort==0 ) ResortStates(&lem);
1700 
1701     /* Generate a report of the parser generated.  (the "y.output" file) */
1702     if( !quiet ) ReportOutput(&lem);
1703 
1704     /* Generate the source code for the parser */
1705     ReportTable(&lem, mhflag);
1706 
1707     /* Produce a header file for use by the scanner.  (This step is
1708     ** omitted if the "-m" option is used because makeheaders will
1709     ** generate the file for us.) */
1710     if( !mhflag ) ReportHeader(&lem);
1711   }
1712   if( statistics ){
1713     printf("Parser statistics:\n");
1714     stats_line("terminal symbols", lem.nterminal);
1715     stats_line("non-terminal symbols", lem.nsymbol - lem.nterminal);
1716     stats_line("total symbols", lem.nsymbol);
1717     stats_line("rules", lem.nrule);
1718     stats_line("states", lem.nxstate);
1719     stats_line("conflicts", lem.nconflict);
1720     stats_line("action table entries", lem.nactiontab);
1721     stats_line("total table size (bytes)", lem.tablesize);
1722   }
1723   if( lem.nconflict > 0 ){
1724     fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
1725   }
1726 
1727   /* return 0 on success, 1 on failure. */
1728   exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
1729   exit(exitcode);
1730   return (exitcode);
1731 }
1732 /******************** From the file "msort.c" *******************************/
1733 /*
1734 ** A generic merge-sort program.
1735 **
1736 ** USAGE:
1737 ** Let "ptr" be a pointer to some structure which is at the head of
1738 ** a null-terminated list.  Then to sort the list call:
1739 **
1740 **     ptr = msort(ptr,&(ptr->next),cmpfnc);
1741 **
1742 ** In the above, "cmpfnc" is a pointer to a function which compares
1743 ** two instances of the structure and returns an integer, as in
1744 ** strcmp.  The second argument is a pointer to the pointer to the
1745 ** second element of the linked list.  This address is used to compute
1746 ** the offset to the "next" field within the structure.  The offset to
1747 ** the "next" field must be constant for all structures in the list.
1748 **
1749 ** The function returns a new pointer which is the head of the list
1750 ** after sorting.
1751 **
1752 ** ALGORITHM:
1753 ** Merge-sort.
1754 */
1755 
1756 /*
1757 ** Return a pointer to the next structure in the linked list.
1758 */
1759 #define NEXT(A) (*(char**)(((char*)A)+offset))
1760 
1761 /*
1762 ** Inputs:
1763 **   a:       A sorted, null-terminated linked list.  (May be null).
1764 **   b:       A sorted, null-terminated linked list.  (May be null).
1765 **   cmp:     A pointer to the comparison function.
1766 **   offset:  Offset in the structure to the "next" field.
1767 **
1768 ** Return Value:
1769 **   A pointer to the head of a sorted list containing the elements
1770 **   of both a and b.
1771 **
1772 ** Side effects:
1773 **   The "next" pointers for elements in the lists a and b are
1774 **   changed.
1775 */
merge(char * a,char * b,int (* cmp)(const char *,const char *),int offset)1776 static char *merge(
1777   char *a,
1778   char *b,
1779   int (*cmp)(const char*,const char*),
1780   int offset
1781 ){
1782   char *ptr, *head;
1783 
1784   if( a==0 ){
1785     head = b;
1786   }else if( b==0 ){
1787     head = a;
1788   }else{
1789     if( (*cmp)(a,b)<=0 ){
1790       ptr = a;
1791       a = NEXT(a);
1792     }else{
1793       ptr = b;
1794       b = NEXT(b);
1795     }
1796     head = ptr;
1797     while( a && b ){
1798       if( (*cmp)(a,b)<=0 ){
1799         NEXT(ptr) = a;
1800         ptr = a;
1801         a = NEXT(a);
1802       }else{
1803         NEXT(ptr) = b;
1804         ptr = b;
1805         b = NEXT(b);
1806       }
1807     }
1808     if( a ) NEXT(ptr) = a;
1809     else    NEXT(ptr) = b;
1810   }
1811   return head;
1812 }
1813 
1814 /*
1815 ** Inputs:
1816 **   list:      Pointer to a singly-linked list of structures.
1817 **   next:      Pointer to pointer to the second element of the list.
1818 **   cmp:       A comparison function.
1819 **
1820 ** Return Value:
1821 **   A pointer to the head of a sorted list containing the elements
1822 **   orginally in list.
1823 **
1824 ** Side effects:
1825 **   The "next" pointers for elements in list are changed.
1826 */
1827 #define LISTSIZE 30
msort(char * list,char ** next,int (* cmp)(const char *,const char *))1828 static char *msort(
1829   char *list,
1830   char **next,
1831   int (*cmp)(const char*,const char*)
1832 ){
1833   unsigned long offset;
1834   char *ep;
1835   char *set[LISTSIZE];
1836   int i;
1837   offset = (unsigned long)((char*)next - (char*)list);
1838   for(i=0; i<LISTSIZE; i++) set[i] = 0;
1839   while( list ){
1840     ep = list;
1841     list = NEXT(list);
1842     NEXT(ep) = 0;
1843     for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
1844       ep = merge(ep,set[i],cmp,offset);
1845       set[i] = 0;
1846     }
1847     set[i] = ep;
1848   }
1849   ep = 0;
1850   for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset);
1851   return ep;
1852 }
1853 /************************ From the file "option.c" **************************/
1854 static char **argv;
1855 static struct s_options *op;
1856 static FILE *errstream;
1857 
1858 #define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
1859 
1860 /*
1861 ** Print the command line with a carrot pointing to the k-th character
1862 ** of the n-th field.
1863 */
errline(int n,int k,FILE * err)1864 static void errline(int n, int k, FILE *err)
1865 {
1866   int spcnt, i;
1867   if( argv[0] ) fprintf(err,"%s",argv[0]);
1868   spcnt = lemonStrlen(argv[0]) + 1;
1869   for(i=1; i<n && argv[i]; i++){
1870     fprintf(err," %s",argv[i]);
1871     spcnt += lemonStrlen(argv[i])+1;
1872   }
1873   spcnt += k;
1874   for(; argv[i]; i++) fprintf(err," %s",argv[i]);
1875   if( spcnt<20 ){
1876     fprintf(err,"\n%*s^-- here\n",spcnt,"");
1877   }else{
1878     fprintf(err,"\n%*shere --^\n",spcnt-7,"");
1879   }
1880 }
1881 
1882 /*
1883 ** Return the index of the N-th non-switch argument.  Return -1
1884 ** if N is out of range.
1885 */
argindex(int n)1886 static int argindex(int n)
1887 {
1888   int i;
1889   int dashdash = 0;
1890   if( argv!=0 && *argv!=0 ){
1891     for(i=1; argv[i]; i++){
1892       if( dashdash || !ISOPT(argv[i]) ){
1893         if( n==0 ) return i;
1894         n--;
1895       }
1896       if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1897     }
1898   }
1899   return -1;
1900 }
1901 
1902 static char emsg[] = "Command line syntax error: ";
1903 
1904 /*
1905 ** Process a flag command line argument.
1906 */
handleflags(int i,FILE * err)1907 static int handleflags(int i, FILE *err)
1908 {
1909   int v;
1910   int errcnt = 0;
1911   int j;
1912   for(j=0; op[j].label; j++){
1913     if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
1914   }
1915   v = argv[i][0]=='-' ? 1 : 0;
1916   if( op[j].label==0 ){
1917     if( err ){
1918       fprintf(err,"%sundefined option.\n",emsg);
1919       errline(i,1,err);
1920     }
1921     errcnt++;
1922   }else if( op[j].arg==0 ){
1923     /* Ignore this option */
1924   }else if( op[j].type==OPT_FLAG ){
1925     *((int*)op[j].arg) = v;
1926   }else if( op[j].type==OPT_FFLAG ){
1927     (*(void(*)(int))(op[j].arg))(v);
1928   }else if( op[j].type==OPT_FSTR ){
1929     (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
1930   }else{
1931     if( err ){
1932       fprintf(err,"%smissing argument on switch.\n",emsg);
1933       errline(i,1,err);
1934     }
1935     errcnt++;
1936   }
1937   return errcnt;
1938 }
1939 
1940 /*
1941 ** Process a command line switch which has an argument.
1942 */
handleswitch(int i,FILE * err)1943 static int handleswitch(int i, FILE *err)
1944 {
1945   int lv = 0;
1946   double dv = 0.0;
1947   char *sv = 0, *end;
1948   char *cp;
1949   int j;
1950   int errcnt = 0;
1951   cp = strchr(argv[i],'=');
1952   assert( cp!=0 );
1953   *cp = 0;
1954   for(j=0; op[j].label; j++){
1955     if( strcmp(argv[i],op[j].label)==0 ) break;
1956   }
1957   *cp = '=';
1958   if( op[j].label==0 ){
1959     if( err ){
1960       fprintf(err,"%sundefined option.\n",emsg);
1961       errline(i,0,err);
1962     }
1963     errcnt++;
1964   }else{
1965     cp++;
1966     switch( op[j].type ){
1967       case OPT_FLAG:
1968       case OPT_FFLAG:
1969         if( err ){
1970           fprintf(err,"%soption requires an argument.\n",emsg);
1971           errline(i,0,err);
1972         }
1973         errcnt++;
1974         break;
1975       case OPT_DBL:
1976       case OPT_FDBL:
1977         dv = strtod(cp,&end);
1978         if( *end ){
1979           if( err ){
1980             fprintf(err,
1981                "%sillegal character in floating-point argument.\n",emsg);
1982             errline(i,(int)((char*)end-(char*)argv[i]),err);
1983           }
1984           errcnt++;
1985         }
1986         break;
1987       case OPT_INT:
1988       case OPT_FINT:
1989         lv = strtol(cp,&end,0);
1990         if( *end ){
1991           if( err ){
1992             fprintf(err,"%sillegal character in integer argument.\n",emsg);
1993             errline(i,(int)((char*)end-(char*)argv[i]),err);
1994           }
1995           errcnt++;
1996         }
1997         break;
1998       case OPT_STR:
1999       case OPT_FSTR:
2000         sv = cp;
2001         break;
2002     }
2003     switch( op[j].type ){
2004       case OPT_FLAG:
2005       case OPT_FFLAG:
2006         break;
2007       case OPT_DBL:
2008         *(double*)(op[j].arg) = dv;
2009         break;
2010       case OPT_FDBL:
2011         (*(void(*)(double))(op[j].arg))(dv);
2012         break;
2013       case OPT_INT:
2014         *(int*)(op[j].arg) = lv;
2015         break;
2016       case OPT_FINT:
2017         (*(void(*)(int))(op[j].arg))((int)lv);
2018         break;
2019       case OPT_STR:
2020         *(char**)(op[j].arg) = sv;
2021         break;
2022       case OPT_FSTR:
2023         (*(void(*)(char *))(op[j].arg))(sv);
2024         break;
2025     }
2026   }
2027   return errcnt;
2028 }
2029 
OptInit(char ** a,struct s_options * o,FILE * err)2030 int OptInit(char **a, struct s_options *o, FILE *err)
2031 {
2032   int errcnt = 0;
2033   argv = a;
2034   op = o;
2035   errstream = err;
2036   if( argv && *argv && op ){
2037     int i;
2038     for(i=1; argv[i]; i++){
2039       if( argv[i][0]=='+' || argv[i][0]=='-' ){
2040         errcnt += handleflags(i,err);
2041       }else if( strchr(argv[i],'=') ){
2042         errcnt += handleswitch(i,err);
2043       }
2044     }
2045   }
2046   if( errcnt>0 ){
2047     fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
2048     OptPrint();
2049     exit(1);
2050   }
2051   return 0;
2052 }
2053 
OptNArgs(void)2054 int OptNArgs(void){
2055   int cnt = 0;
2056   int dashdash = 0;
2057   int i;
2058   if( argv!=0 && argv[0]!=0 ){
2059     for(i=1; argv[i]; i++){
2060       if( dashdash || !ISOPT(argv[i]) ) cnt++;
2061       if( strcmp(argv[i],"--")==0 ) dashdash = 1;
2062     }
2063   }
2064   return cnt;
2065 }
2066 
OptArg(int n)2067 char *OptArg(int n)
2068 {
2069   int i;
2070   i = argindex(n);
2071   return i>=0 ? argv[i] : 0;
2072 }
2073 
OptErr(int n)2074 void OptErr(int n)
2075 {
2076   int i;
2077   i = argindex(n);
2078   if( i>=0 ) errline(i,0,errstream);
2079 }
2080 
OptPrint(void)2081 void OptPrint(void){
2082   int i;
2083   int max, len;
2084   max = 0;
2085   for(i=0; op[i].label; i++){
2086     len = lemonStrlen(op[i].label) + 1;
2087     switch( op[i].type ){
2088       case OPT_FLAG:
2089       case OPT_FFLAG:
2090         break;
2091       case OPT_INT:
2092       case OPT_FINT:
2093         len += 9;       /* length of "<integer>" */
2094         break;
2095       case OPT_DBL:
2096       case OPT_FDBL:
2097         len += 6;       /* length of "<real>" */
2098         break;
2099       case OPT_STR:
2100       case OPT_FSTR:
2101         len += 8;       /* length of "<string>" */
2102         break;
2103     }
2104     if( len>max ) max = len;
2105   }
2106   for(i=0; op[i].label; i++){
2107     switch( op[i].type ){
2108       case OPT_FLAG:
2109       case OPT_FFLAG:
2110         fprintf(errstream,"  -%-*s  %s\n",max,op[i].label,op[i].message);
2111         break;
2112       case OPT_INT:
2113       case OPT_FINT:
2114         fprintf(errstream,"  -%s<integer>%*s  %s\n",op[i].label,
2115           (int)(max-lemonStrlen(op[i].label)-9),"",op[i].message);
2116         break;
2117       case OPT_DBL:
2118       case OPT_FDBL:
2119         fprintf(errstream,"  -%s<real>%*s  %s\n",op[i].label,
2120           (int)(max-lemonStrlen(op[i].label)-6),"",op[i].message);
2121         break;
2122       case OPT_STR:
2123       case OPT_FSTR:
2124         fprintf(errstream,"  -%s<string>%*s  %s\n",op[i].label,
2125           (int)(max-lemonStrlen(op[i].label)-8),"",op[i].message);
2126         break;
2127     }
2128   }
2129 }
2130 /*********************** From the file "parse.c" ****************************/
2131 /*
2132 ** Input file parser for the LEMON parser generator.
2133 */
2134 
2135 /* The state of the parser */
2136 enum e_state {
2137   INITIALIZE,
2138   WAITING_FOR_DECL_OR_RULE,
2139   WAITING_FOR_DECL_KEYWORD,
2140   WAITING_FOR_DECL_ARG,
2141   WAITING_FOR_PRECEDENCE_SYMBOL,
2142   WAITING_FOR_ARROW,
2143   IN_RHS,
2144   LHS_ALIAS_1,
2145   LHS_ALIAS_2,
2146   LHS_ALIAS_3,
2147   RHS_ALIAS_1,
2148   RHS_ALIAS_2,
2149   PRECEDENCE_MARK_1,
2150   PRECEDENCE_MARK_2,
2151   RESYNC_AFTER_RULE_ERROR,
2152   RESYNC_AFTER_DECL_ERROR,
2153   WAITING_FOR_DESTRUCTOR_SYMBOL,
2154   WAITING_FOR_DATATYPE_SYMBOL,
2155   WAITING_FOR_FALLBACK_ID,
2156   WAITING_FOR_WILDCARD_ID,
2157   WAITING_FOR_CLASS_ID,
2158   WAITING_FOR_CLASS_TOKEN,
2159   WAITING_FOR_TOKEN_NAME
2160 };
2161 struct pstate {
2162   char *filename;       /* Name of the input file */
2163   int tokenlineno;      /* Linenumber at which current token starts */
2164   int errorcnt;         /* Number of errors so far */
2165   char *tokenstart;     /* Text of current token */
2166   struct lemon *gp;     /* Global state vector */
2167   enum e_state state;        /* The state of the parser */
2168   struct symbol *fallback;   /* The fallback token */
2169   struct symbol *tkclass;    /* Token class symbol */
2170   struct symbol *lhs;        /* Left-hand side of current rule */
2171   const char *lhsalias;      /* Alias for the LHS */
2172   int nrhs;                  /* Number of right-hand side symbols seen */
2173   struct symbol *rhs[MAXRHS];  /* RHS symbols */
2174   const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
2175   struct rule *prevrule;     /* Previous rule parsed */
2176   const char *declkeyword;   /* Keyword of a declaration */
2177   char **declargslot;        /* Where the declaration argument should be put */
2178   int insertLineMacro;       /* Add #line before declaration insert */
2179   int *decllinenoslot;       /* Where to write declaration line number */
2180   enum e_assoc declassoc;    /* Assign this association to decl arguments */
2181   int preccounter;           /* Assign this precedence to decl arguments */
2182   struct rule *firstrule;    /* Pointer to first rule in the grammar */
2183   struct rule *lastrule;     /* Pointer to the most recently parsed rule */
2184 };
2185 
2186 /* Parse a single token */
parseonetoken(struct pstate * psp)2187 static void parseonetoken(struct pstate *psp)
2188 {
2189   const char *x;
2190   x = Strsafe(psp->tokenstart);     /* Save the token permanently */
2191 #if 0
2192   printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
2193     x,psp->state);
2194 #endif
2195   switch( psp->state ){
2196     case INITIALIZE:
2197       psp->prevrule = 0;
2198       psp->preccounter = 0;
2199       psp->firstrule = psp->lastrule = 0;
2200       psp->gp->nrule = 0;
2201       /* Fall thru to next case */
2202     case WAITING_FOR_DECL_OR_RULE:
2203       if( x[0]=='%' ){
2204         psp->state = WAITING_FOR_DECL_KEYWORD;
2205       }else if( ISLOWER(x[0]) ){
2206         psp->lhs = Symbol_new(x);
2207         psp->nrhs = 0;
2208         psp->lhsalias = 0;
2209         psp->state = WAITING_FOR_ARROW;
2210       }else if( x[0]=='{' ){
2211         if( psp->prevrule==0 ){
2212           ErrorMsg(psp->filename,psp->tokenlineno,
2213 "There is no prior rule upon which to attach the code \
2214 fragment which begins on this line.");
2215           psp->errorcnt++;
2216         }else if( psp->prevrule->code!=0 ){
2217           ErrorMsg(psp->filename,psp->tokenlineno,
2218 "Code fragment beginning on this line is not the first \
2219 to follow the previous rule.");
2220           psp->errorcnt++;
2221         }else{
2222           psp->prevrule->line = psp->tokenlineno;
2223           psp->prevrule->code = &x[1];
2224           psp->prevrule->noCode = 0;
2225         }
2226       }else if( x[0]=='[' ){
2227         psp->state = PRECEDENCE_MARK_1;
2228       }else{
2229         ErrorMsg(psp->filename,psp->tokenlineno,
2230           "Token \"%s\" should be either \"%%\" or a nonterminal name.",
2231           x);
2232         psp->errorcnt++;
2233       }
2234       break;
2235     case PRECEDENCE_MARK_1:
2236       if( !ISUPPER(x[0]) ){
2237         ErrorMsg(psp->filename,psp->tokenlineno,
2238           "The precedence symbol must be a terminal.");
2239         psp->errorcnt++;
2240       }else if( psp->prevrule==0 ){
2241         ErrorMsg(psp->filename,psp->tokenlineno,
2242           "There is no prior rule to assign precedence \"[%s]\".",x);
2243         psp->errorcnt++;
2244       }else if( psp->prevrule->precsym!=0 ){
2245         ErrorMsg(psp->filename,psp->tokenlineno,
2246 "Precedence mark on this line is not the first \
2247 to follow the previous rule.");
2248         psp->errorcnt++;
2249       }else{
2250         psp->prevrule->precsym = Symbol_new(x);
2251       }
2252       psp->state = PRECEDENCE_MARK_2;
2253       break;
2254     case PRECEDENCE_MARK_2:
2255       if( x[0]!=']' ){
2256         ErrorMsg(psp->filename,psp->tokenlineno,
2257           "Missing \"]\" on precedence mark.");
2258         psp->errorcnt++;
2259       }
2260       psp->state = WAITING_FOR_DECL_OR_RULE;
2261       break;
2262     case WAITING_FOR_ARROW:
2263       if( x[0]==':' && x[1]==':' && x[2]=='=' ){
2264         psp->state = IN_RHS;
2265       }else if( x[0]=='(' ){
2266         psp->state = LHS_ALIAS_1;
2267       }else{
2268         ErrorMsg(psp->filename,psp->tokenlineno,
2269           "Expected to see a \":\" following the LHS symbol \"%s\".",
2270           psp->lhs->name);
2271         psp->errorcnt++;
2272         psp->state = RESYNC_AFTER_RULE_ERROR;
2273       }
2274       break;
2275     case LHS_ALIAS_1:
2276       if( ISALPHA(x[0]) ){
2277         psp->lhsalias = x;
2278         psp->state = LHS_ALIAS_2;
2279       }else{
2280         ErrorMsg(psp->filename,psp->tokenlineno,
2281           "\"%s\" is not a valid alias for the LHS \"%s\"\n",
2282           x,psp->lhs->name);
2283         psp->errorcnt++;
2284         psp->state = RESYNC_AFTER_RULE_ERROR;
2285       }
2286       break;
2287     case LHS_ALIAS_2:
2288       if( x[0]==')' ){
2289         psp->state = LHS_ALIAS_3;
2290       }else{
2291         ErrorMsg(psp->filename,psp->tokenlineno,
2292           "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
2293         psp->errorcnt++;
2294         psp->state = RESYNC_AFTER_RULE_ERROR;
2295       }
2296       break;
2297     case LHS_ALIAS_3:
2298       if( x[0]==':' && x[1]==':' && x[2]=='=' ){
2299         psp->state = IN_RHS;
2300       }else{
2301         ErrorMsg(psp->filename,psp->tokenlineno,
2302           "Missing \"->\" following: \"%s(%s)\".",
2303            psp->lhs->name,psp->lhsalias);
2304         psp->errorcnt++;
2305         psp->state = RESYNC_AFTER_RULE_ERROR;
2306       }
2307       break;
2308     case IN_RHS:
2309       if( x[0]=='.' ){
2310         struct rule *rp;
2311         rp = (struct rule *)calloc( sizeof(struct rule) +
2312              sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1);
2313         if( rp==0 ){
2314           ErrorMsg(psp->filename,psp->tokenlineno,
2315             "Can't allocate enough memory for this rule.");
2316           psp->errorcnt++;
2317           psp->prevrule = 0;
2318         }else{
2319           int i;
2320           rp->ruleline = psp->tokenlineno;
2321           rp->rhs = (struct symbol**)&rp[1];
2322           rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]);
2323           for(i=0; i<psp->nrhs; i++){
2324             rp->rhs[i] = psp->rhs[i];
2325             rp->rhsalias[i] = psp->alias[i];
2326           }
2327           rp->lhs = psp->lhs;
2328           rp->lhsalias = psp->lhsalias;
2329           rp->nrhs = psp->nrhs;
2330           rp->code = 0;
2331           rp->noCode = 1;
2332           rp->precsym = 0;
2333           rp->index = psp->gp->nrule++;
2334           rp->nextlhs = rp->lhs->rule;
2335           rp->lhs->rule = rp;
2336           rp->next = 0;
2337           if( psp->firstrule==0 ){
2338             psp->firstrule = psp->lastrule = rp;
2339           }else{
2340             psp->lastrule->next = rp;
2341             psp->lastrule = rp;
2342           }
2343           psp->prevrule = rp;
2344         }
2345         psp->state = WAITING_FOR_DECL_OR_RULE;
2346       }else if( ISALPHA(x[0]) ){
2347         if( psp->nrhs>=MAXRHS ){
2348           ErrorMsg(psp->filename,psp->tokenlineno,
2349             "Too many symbols on RHS of rule beginning at \"%s\".",
2350             x);
2351           psp->errorcnt++;
2352           psp->state = RESYNC_AFTER_RULE_ERROR;
2353         }else{
2354           psp->rhs[psp->nrhs] = Symbol_new(x);
2355           psp->alias[psp->nrhs] = 0;
2356           psp->nrhs++;
2357         }
2358       }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
2359         struct symbol *msp = psp->rhs[psp->nrhs-1];
2360         if( msp->type!=MULTITERMINAL ){
2361           struct symbol *origsp = msp;
2362           msp = (struct symbol *) calloc(1,sizeof(*msp));
2363           memset(msp, 0, sizeof(*msp));
2364           msp->type = MULTITERMINAL;
2365           msp->nsubsym = 1;
2366           msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*));
2367           msp->subsym[0] = origsp;
2368           msp->name = origsp->name;
2369           psp->rhs[psp->nrhs-1] = msp;
2370         }
2371         msp->nsubsym++;
2372         msp->subsym = (struct symbol **) realloc(msp->subsym,
2373           sizeof(struct symbol*)*msp->nsubsym);
2374         msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
2375         if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){
2376           ErrorMsg(psp->filename,psp->tokenlineno,
2377             "Cannot form a compound containing a non-terminal");
2378           psp->errorcnt++;
2379         }
2380       }else if( x[0]=='(' && psp->nrhs>0 ){
2381         psp->state = RHS_ALIAS_1;
2382       }else{
2383         ErrorMsg(psp->filename,psp->tokenlineno,
2384           "Illegal character on RHS of rule: \"%s\".",x);
2385         psp->errorcnt++;
2386         psp->state = RESYNC_AFTER_RULE_ERROR;
2387       }
2388       break;
2389     case RHS_ALIAS_1:
2390       if( ISALPHA(x[0]) ){
2391         psp->alias[psp->nrhs-1] = x;
2392         psp->state = RHS_ALIAS_2;
2393       }else{
2394         ErrorMsg(psp->filename,psp->tokenlineno,
2395           "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
2396           x,psp->rhs[psp->nrhs-1]->name);
2397         psp->errorcnt++;
2398         psp->state = RESYNC_AFTER_RULE_ERROR;
2399       }
2400       break;
2401     case RHS_ALIAS_2:
2402       if( x[0]==')' ){
2403         psp->state = IN_RHS;
2404       }else{
2405         ErrorMsg(psp->filename,psp->tokenlineno,
2406           "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
2407         psp->errorcnt++;
2408         psp->state = RESYNC_AFTER_RULE_ERROR;
2409       }
2410       break;
2411     case WAITING_FOR_DECL_KEYWORD:
2412       if( ISALPHA(x[0]) ){
2413         psp->declkeyword = x;
2414         psp->declargslot = 0;
2415         psp->decllinenoslot = 0;
2416         psp->insertLineMacro = 1;
2417         psp->state = WAITING_FOR_DECL_ARG;
2418         if( strcmp(x,"name")==0 ){
2419           psp->declargslot = &(psp->gp->name);
2420           psp->insertLineMacro = 0;
2421         }else if( strcmp(x,"include")==0 ){
2422           psp->declargslot = &(psp->gp->include);
2423         }else if( strcmp(x,"code")==0 ){
2424           psp->declargslot = &(psp->gp->extracode);
2425         }else if( strcmp(x,"token_destructor")==0 ){
2426           psp->declargslot = &psp->gp->tokendest;
2427         }else if( strcmp(x,"default_destructor")==0 ){
2428           psp->declargslot = &psp->gp->vardest;
2429         }else if( strcmp(x,"token_prefix")==0 ){
2430           psp->declargslot = &psp->gp->tokenprefix;
2431           psp->insertLineMacro = 0;
2432         }else if( strcmp(x,"syntax_error")==0 ){
2433           psp->declargslot = &(psp->gp->error);
2434         }else if( strcmp(x,"parse_accept")==0 ){
2435           psp->declargslot = &(psp->gp->accept);
2436         }else if( strcmp(x,"parse_failure")==0 ){
2437           psp->declargslot = &(psp->gp->failure);
2438         }else if( strcmp(x,"stack_overflow")==0 ){
2439           psp->declargslot = &(psp->gp->overflow);
2440         }else if( strcmp(x,"extra_argument")==0 ){
2441           psp->declargslot = &(psp->gp->arg);
2442           psp->insertLineMacro = 0;
2443         }else if( strcmp(x,"token_type")==0 ){
2444           psp->declargslot = &(psp->gp->tokentype);
2445           psp->insertLineMacro = 0;
2446         }else if( strcmp(x,"default_type")==0 ){
2447           psp->declargslot = &(psp->gp->vartype);
2448           psp->insertLineMacro = 0;
2449         }else if( strcmp(x,"stack_size")==0 ){
2450           psp->declargslot = &(psp->gp->stacksize);
2451           psp->insertLineMacro = 0;
2452         }else if( strcmp(x,"start_symbol")==0 ){
2453           psp->declargslot = &(psp->gp->start);
2454           psp->insertLineMacro = 0;
2455         }else if( strcmp(x,"left")==0 ){
2456           psp->preccounter++;
2457           psp->declassoc = LEFT;
2458           psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2459         }else if( strcmp(x,"right")==0 ){
2460           psp->preccounter++;
2461           psp->declassoc = RIGHT;
2462           psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2463         }else if( strcmp(x,"nonassoc")==0 ){
2464           psp->preccounter++;
2465           psp->declassoc = NONE;
2466           psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2467         }else if( strcmp(x,"destructor")==0 ){
2468           psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
2469         }else if( strcmp(x,"type")==0 ){
2470           psp->state = WAITING_FOR_DATATYPE_SYMBOL;
2471         }else if( strcmp(x,"fallback")==0 ){
2472           psp->fallback = 0;
2473           psp->state = WAITING_FOR_FALLBACK_ID;
2474         }else if( strcmp(x,"token")==0 ){
2475           psp->state = WAITING_FOR_TOKEN_NAME;
2476         }else if( strcmp(x,"wildcard")==0 ){
2477           psp->state = WAITING_FOR_WILDCARD_ID;
2478         }else if( strcmp(x,"token_class")==0 ){
2479           psp->state = WAITING_FOR_CLASS_ID;
2480         }else{
2481           ErrorMsg(psp->filename,psp->tokenlineno,
2482             "Unknown declaration keyword: \"%%%s\".",x);
2483           psp->errorcnt++;
2484           psp->state = RESYNC_AFTER_DECL_ERROR;
2485         }
2486       }else{
2487         ErrorMsg(psp->filename,psp->tokenlineno,
2488           "Illegal declaration keyword: \"%s\".",x);
2489         psp->errorcnt++;
2490         psp->state = RESYNC_AFTER_DECL_ERROR;
2491       }
2492       break;
2493     case WAITING_FOR_DESTRUCTOR_SYMBOL:
2494       if( !ISALPHA(x[0]) ){
2495         ErrorMsg(psp->filename,psp->tokenlineno,
2496           "Symbol name missing after %%destructor keyword");
2497         psp->errorcnt++;
2498         psp->state = RESYNC_AFTER_DECL_ERROR;
2499       }else{
2500         struct symbol *sp = Symbol_new(x);
2501         psp->declargslot = &sp->destructor;
2502         psp->decllinenoslot = &sp->destLineno;
2503         psp->insertLineMacro = 1;
2504         psp->state = WAITING_FOR_DECL_ARG;
2505       }
2506       break;
2507     case WAITING_FOR_DATATYPE_SYMBOL:
2508       if( !ISALPHA(x[0]) ){
2509         ErrorMsg(psp->filename,psp->tokenlineno,
2510           "Symbol name missing after %%type keyword");
2511         psp->errorcnt++;
2512         psp->state = RESYNC_AFTER_DECL_ERROR;
2513       }else{
2514         struct symbol *sp = Symbol_find(x);
2515         if((sp) && (sp->datatype)){
2516           ErrorMsg(psp->filename,psp->tokenlineno,
2517             "Symbol %%type \"%s\" already defined", x);
2518           psp->errorcnt++;
2519           psp->state = RESYNC_AFTER_DECL_ERROR;
2520         }else{
2521           if (!sp){
2522             sp = Symbol_new(x);
2523           }
2524           psp->declargslot = &sp->datatype;
2525           psp->insertLineMacro = 0;
2526           psp->state = WAITING_FOR_DECL_ARG;
2527         }
2528       }
2529       break;
2530     case WAITING_FOR_PRECEDENCE_SYMBOL:
2531       if( x[0]=='.' ){
2532         psp->state = WAITING_FOR_DECL_OR_RULE;
2533       }else if( ISUPPER(x[0]) ){
2534         struct symbol *sp;
2535         sp = Symbol_new(x);
2536         if( sp->prec>=0 ){
2537           ErrorMsg(psp->filename,psp->tokenlineno,
2538             "Symbol \"%s\" has already be given a precedence.",x);
2539           psp->errorcnt++;
2540         }else{
2541           sp->prec = psp->preccounter;
2542           sp->assoc = psp->declassoc;
2543         }
2544       }else{
2545         ErrorMsg(psp->filename,psp->tokenlineno,
2546           "Can't assign a precedence to \"%s\".",x);
2547         psp->errorcnt++;
2548       }
2549       break;
2550     case WAITING_FOR_DECL_ARG:
2551       if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) ){
2552         const char *zOld, *zNew;
2553         char *zBuf, *z;
2554         int nOld, n, nLine = 0, nNew, nBack;
2555         int addLineMacro;
2556         char zLine[50];
2557         zNew = x;
2558         if( zNew[0]=='"' || zNew[0]=='{' ) zNew++;
2559         nNew = lemonStrlen(zNew);
2560         if( *psp->declargslot ){
2561           zOld = *psp->declargslot;
2562         }else{
2563           zOld = "";
2564         }
2565         nOld = lemonStrlen(zOld);
2566         n = nOld + nNew + 20;
2567         addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro &&
2568                         (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
2569         if( addLineMacro ){
2570           for(z=psp->filename, nBack=0; *z; z++){
2571             if( *z=='\\' ) nBack++;
2572           }
2573           lemon_sprintf(zLine, "#line %d ", psp->tokenlineno);
2574           nLine = lemonStrlen(zLine);
2575           n += nLine + lemonStrlen(psp->filename) + nBack;
2576         }
2577         *psp->declargslot = (char *) realloc(*psp->declargslot, n);
2578         zBuf = *psp->declargslot + nOld;
2579         if( addLineMacro ){
2580           if( nOld && zBuf[-1]!='\n' ){
2581             *(zBuf++) = '\n';
2582           }
2583           memcpy(zBuf, zLine, nLine);
2584           zBuf += nLine;
2585           *(zBuf++) = '"';
2586           for(z=psp->filename; *z; z++){
2587             if( *z=='\\' ){
2588               *(zBuf++) = '\\';
2589             }
2590             *(zBuf++) = *z;
2591           }
2592           *(zBuf++) = '"';
2593           *(zBuf++) = '\n';
2594         }
2595         if( psp->decllinenoslot && psp->decllinenoslot[0]==0 ){
2596           psp->decllinenoslot[0] = psp->tokenlineno;
2597         }
2598         memcpy(zBuf, zNew, nNew);
2599         zBuf += nNew;
2600         *zBuf = 0;
2601         psp->state = WAITING_FOR_DECL_OR_RULE;
2602       }else{
2603         ErrorMsg(psp->filename,psp->tokenlineno,
2604           "Illegal argument to %%%s: %s",psp->declkeyword,x);
2605         psp->errorcnt++;
2606         psp->state = RESYNC_AFTER_DECL_ERROR;
2607       }
2608       break;
2609     case WAITING_FOR_FALLBACK_ID:
2610       if( x[0]=='.' ){
2611         psp->state = WAITING_FOR_DECL_OR_RULE;
2612       }else if( !ISUPPER(x[0]) ){
2613         ErrorMsg(psp->filename, psp->tokenlineno,
2614           "%%fallback argument \"%s\" should be a token", x);
2615         psp->errorcnt++;
2616       }else{
2617         struct symbol *sp = Symbol_new(x);
2618         if( psp->fallback==0 ){
2619           psp->fallback = sp;
2620         }else if( sp->fallback ){
2621           ErrorMsg(psp->filename, psp->tokenlineno,
2622             "More than one fallback assigned to token %s", x);
2623           psp->errorcnt++;
2624         }else{
2625           sp->fallback = psp->fallback;
2626           psp->gp->has_fallback = 1;
2627         }
2628       }
2629       break;
2630     case WAITING_FOR_TOKEN_NAME:
2631       /* Tokens do not have to be declared before use.  But they can be
2632       ** in order to control their assigned integer number.  The number for
2633       ** each token is assigned when it is first seen.  So by including
2634       **
2635       **     %token ONE TWO THREE
2636       **
2637       ** early in the grammar file, that assigns small consecutive values
2638       ** to each of the tokens ONE TWO and THREE.
2639       */
2640       if( x[0]=='.' ){
2641         psp->state = WAITING_FOR_DECL_OR_RULE;
2642       }else if( !ISUPPER(x[0]) ){
2643         ErrorMsg(psp->filename, psp->tokenlineno,
2644           "%%token argument \"%s\" should be a token", x);
2645         psp->errorcnt++;
2646       }else{
2647         (void)Symbol_new(x);
2648       }
2649       break;
2650     case WAITING_FOR_WILDCARD_ID:
2651       if( x[0]=='.' ){
2652         psp->state = WAITING_FOR_DECL_OR_RULE;
2653       }else if( !ISUPPER(x[0]) ){
2654         ErrorMsg(psp->filename, psp->tokenlineno,
2655           "%%wildcard argument \"%s\" should be a token", x);
2656         psp->errorcnt++;
2657       }else{
2658         struct symbol *sp = Symbol_new(x);
2659         if( psp->gp->wildcard==0 ){
2660           psp->gp->wildcard = sp;
2661         }else{
2662           ErrorMsg(psp->filename, psp->tokenlineno,
2663             "Extra wildcard to token: %s", x);
2664           psp->errorcnt++;
2665         }
2666       }
2667       break;
2668     case WAITING_FOR_CLASS_ID:
2669       if( !ISLOWER(x[0]) ){
2670         ErrorMsg(psp->filename, psp->tokenlineno,
2671           "%%token_class must be followed by an identifier: ", x);
2672         psp->errorcnt++;
2673         psp->state = RESYNC_AFTER_DECL_ERROR;
2674      }else if( Symbol_find(x) ){
2675         ErrorMsg(psp->filename, psp->tokenlineno,
2676           "Symbol \"%s\" already used", x);
2677         psp->errorcnt++;
2678         psp->state = RESYNC_AFTER_DECL_ERROR;
2679       }else{
2680         psp->tkclass = Symbol_new(x);
2681         psp->tkclass->type = MULTITERMINAL;
2682         psp->state = WAITING_FOR_CLASS_TOKEN;
2683       }
2684       break;
2685     case WAITING_FOR_CLASS_TOKEN:
2686       if( x[0]=='.' ){
2687         psp->state = WAITING_FOR_DECL_OR_RULE;
2688       }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){
2689         struct symbol *msp = psp->tkclass;
2690         msp->nsubsym++;
2691         msp->subsym = (struct symbol **) realloc(msp->subsym,
2692           sizeof(struct symbol*)*msp->nsubsym);
2693         if( !ISUPPER(x[0]) ) x++;
2694         msp->subsym[msp->nsubsym-1] = Symbol_new(x);
2695       }else{
2696         ErrorMsg(psp->filename, psp->tokenlineno,
2697           "%%token_class argument \"%s\" should be a token", x);
2698         psp->errorcnt++;
2699         psp->state = RESYNC_AFTER_DECL_ERROR;
2700       }
2701       break;
2702     case RESYNC_AFTER_RULE_ERROR:
2703 /*      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2704 **      break; */
2705     case RESYNC_AFTER_DECL_ERROR:
2706       if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2707       if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
2708       break;
2709   }
2710 }
2711 
2712 /* Run the preprocessor over the input file text.  The global variables
2713 ** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
2714 ** macros.  This routine looks for "%ifdef" and "%ifndef" and "%endif" and
2715 ** comments them out.  Text in between is also commented out as appropriate.
2716 */
preprocess_input(char * z)2717 static void preprocess_input(char *z){
2718   int i, j, k, n;
2719   int exclude = 0;
2720   int start = 0;
2721   int lineno = 1;
2722   int start_lineno = 1;
2723   for(i=0; z[i]; i++){
2724     if( z[i]=='\n' ) lineno++;
2725     if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue;
2726     if( strncmp(&z[i],"%endif",6)==0 && ISSPACE(z[i+6]) ){
2727       if( exclude ){
2728         exclude--;
2729         if( exclude==0 ){
2730           for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
2731         }
2732       }
2733       for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
2734     }else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6]))
2735           || (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){
2736       if( exclude ){
2737         exclude++;
2738       }else{
2739         for(j=i+7; ISSPACE(z[j]); j++){}
2740         for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){}
2741         exclude = 1;
2742         for(k=0; k<nDefine; k++){
2743           if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){
2744             exclude = 0;
2745             break;
2746           }
2747         }
2748         if( z[i+3]=='n' ) exclude = !exclude;
2749         if( exclude ){
2750           start = i;
2751           start_lineno = lineno;
2752         }
2753       }
2754       for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
2755     }
2756   }
2757   if( exclude ){
2758     fprintf(stderr,"unterminated %%ifdef starting on line %d\n", start_lineno);
2759     exit(1);
2760   }
2761 }
2762 
2763 /* In spite of its name, this function is really a scanner.  It read
2764 ** in the entire input file (all at once) then tokenizes it.  Each
2765 ** token is passed to the function "parseonetoken" which builds all
2766 ** the appropriate data structures in the global state vector "gp".
2767 */
Parse(struct lemon * gp)2768 void Parse(struct lemon *gp)
2769 {
2770   struct pstate ps;
2771   FILE *fp;
2772   char *filebuf;
2773   unsigned int filesize;
2774   int lineno;
2775   int c;
2776   char *cp, *nextcp;
2777   int startline = 0;
2778 
2779   memset(&ps, '\0', sizeof(ps));
2780   ps.gp = gp;
2781   ps.filename = gp->filename;
2782   ps.errorcnt = 0;
2783   ps.state = INITIALIZE;
2784 
2785   /* Begin by reading the input file */
2786   fp = fopen(ps.filename,"rb");
2787   if( fp==0 ){
2788     ErrorMsg(ps.filename,0,"Can't open this file for reading.");
2789     gp->errorcnt++;
2790     return;
2791   }
2792   fseek(fp,0,2);
2793   filesize = ftell(fp);
2794   rewind(fp);
2795   filebuf = (char *)malloc( filesize+1 );
2796   if( filesize>100000000 || filebuf==0 ){
2797     ErrorMsg(ps.filename,0,"Input file too large.");
2798     gp->errorcnt++;
2799     fclose(fp);
2800     return;
2801   }
2802   if( fread(filebuf,1,filesize,fp)!=filesize ){
2803     ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
2804       filesize);
2805     free(filebuf);
2806     gp->errorcnt++;
2807     fclose(fp);
2808     return;
2809   }
2810   fclose(fp);
2811   filebuf[filesize] = 0;
2812 
2813   /* Make an initial pass through the file to handle %ifdef and %ifndef */
2814   preprocess_input(filebuf);
2815 
2816   /* Now scan the text of the input file */
2817   lineno = 1;
2818   for(cp=filebuf; (c= *cp)!=0; ){
2819     if( c=='\n' ) lineno++;              /* Keep track of the line number */
2820     if( ISSPACE(c) ){ cp++; continue; }  /* Skip all white space */
2821     if( c=='/' && cp[1]=='/' ){          /* Skip C++ style comments */
2822       cp+=2;
2823       while( (c= *cp)!=0 && c!='\n' ) cp++;
2824       continue;
2825     }
2826     if( c=='/' && cp[1]=='*' ){          /* Skip C style comments */
2827       cp+=2;
2828       while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
2829         if( c=='\n' ) lineno++;
2830         cp++;
2831       }
2832       if( c ) cp++;
2833       continue;
2834     }
2835     ps.tokenstart = cp;                /* Mark the beginning of the token */
2836     ps.tokenlineno = lineno;           /* Linenumber on which token begins */
2837     if( c=='\"' ){                     /* String literals */
2838       cp++;
2839       while( (c= *cp)!=0 && c!='\"' ){
2840         if( c=='\n' ) lineno++;
2841         cp++;
2842       }
2843       if( c==0 ){
2844         ErrorMsg(ps.filename,startline,
2845 "String starting on this line is not terminated before the end of the file.");
2846         ps.errorcnt++;
2847         nextcp = cp;
2848       }else{
2849         nextcp = cp+1;
2850       }
2851     }else if( c=='{' ){               /* A block of C code */
2852       int level;
2853       cp++;
2854       for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
2855         if( c=='\n' ) lineno++;
2856         else if( c=='{' ) level++;
2857         else if( c=='}' ) level--;
2858         else if( c=='/' && cp[1]=='*' ){  /* Skip comments */
2859           int prevc;
2860           cp = &cp[2];
2861           prevc = 0;
2862           while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
2863             if( c=='\n' ) lineno++;
2864             prevc = c;
2865             cp++;
2866           }
2867         }else if( c=='/' && cp[1]=='/' ){  /* Skip C++ style comments too */
2868           cp = &cp[2];
2869           while( (c= *cp)!=0 && c!='\n' ) cp++;
2870           if( c ) lineno++;
2871         }else if( c=='\'' || c=='\"' ){    /* String a character literals */
2872           int startchar, prevc;
2873           startchar = c;
2874           prevc = 0;
2875           for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
2876             if( c=='\n' ) lineno++;
2877             if( prevc=='\\' ) prevc = 0;
2878             else              prevc = c;
2879           }
2880         }
2881       }
2882       if( c==0 ){
2883         ErrorMsg(ps.filename,ps.tokenlineno,
2884 "C code starting on this line is not terminated before the end of the file.");
2885         ps.errorcnt++;
2886         nextcp = cp;
2887       }else{
2888         nextcp = cp+1;
2889       }
2890     }else if( ISALNUM(c) ){          /* Identifiers */
2891       while( (c= *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++;
2892       nextcp = cp;
2893     }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
2894       cp += 3;
2895       nextcp = cp;
2896     }else if( (c=='/' || c=='|') && ISALPHA(cp[1]) ){
2897       cp += 2;
2898       while( (c = *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++;
2899       nextcp = cp;
2900     }else{                          /* All other (one character) operators */
2901       cp++;
2902       nextcp = cp;
2903     }
2904     c = *cp;
2905     *cp = 0;                        /* Null terminate the token */
2906     parseonetoken(&ps);             /* Parse the token */
2907     *cp = (char)c;                  /* Restore the buffer */
2908     cp = nextcp;
2909   }
2910   free(filebuf);                    /* Release the buffer after parsing */
2911   gp->rule = ps.firstrule;
2912   gp->errorcnt = ps.errorcnt;
2913 }
2914 /*************************** From the file "plink.c" *********************/
2915 /*
2916 ** Routines processing configuration follow-set propagation links
2917 ** in the LEMON parser generator.
2918 */
2919 static struct plink *plink_freelist = 0;
2920 
2921 /* Allocate a new plink */
Plink_new(void)2922 struct plink *Plink_new(void){
2923   struct plink *newlink;
2924 
2925   if( plink_freelist==0 ){
2926     int i;
2927     int amt = 100;
2928     plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) );
2929     if( plink_freelist==0 ){
2930       fprintf(stderr,
2931       "Unable to allocate memory for a new follow-set propagation link.\n");
2932       exit(1);
2933     }
2934     for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
2935     plink_freelist[amt-1].next = 0;
2936   }
2937   newlink = plink_freelist;
2938   plink_freelist = plink_freelist->next;
2939   return newlink;
2940 }
2941 
2942 /* Add a plink to a plink list */
Plink_add(struct plink ** plpp,struct config * cfp)2943 void Plink_add(struct plink **plpp, struct config *cfp)
2944 {
2945   struct plink *newlink;
2946   newlink = Plink_new();
2947   newlink->next = *plpp;
2948   *plpp = newlink;
2949   newlink->cfp = cfp;
2950 }
2951 
2952 /* Transfer every plink on the list "from" to the list "to" */
Plink_copy(struct plink ** to,struct plink * from)2953 void Plink_copy(struct plink **to, struct plink *from)
2954 {
2955   struct plink *nextpl;
2956   while( from ){
2957     nextpl = from->next;
2958     from->next = *to;
2959     *to = from;
2960     from = nextpl;
2961   }
2962 }
2963 
2964 /* Delete every plink on the list */
Plink_delete(struct plink * plp)2965 void Plink_delete(struct plink *plp)
2966 {
2967   struct plink *nextpl;
2968 
2969   while( plp ){
2970     nextpl = plp->next;
2971     plp->next = plink_freelist;
2972     plink_freelist = plp;
2973     plp = nextpl;
2974   }
2975 }
2976 /*********************** From the file "report.c" **************************/
2977 /*
2978 ** Procedures for generating reports and tables in the LEMON parser generator.
2979 */
2980 
2981 /* Generate a filename with the given suffix.  Space to hold the
2982 ** name comes from malloc() and must be freed by the calling
2983 ** function.
2984 */
file_makename(struct lemon * lemp,const char * suffix)2985 PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
2986 {
2987   char *name;
2988   char *cp;
2989 
2990   name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 );
2991   if( name==0 ){
2992     fprintf(stderr,"Can't allocate space for a filename.\n");
2993     exit(1);
2994   }
2995   lemon_strcpy(name,lemp->filename);
2996   cp = strrchr(name,'.');
2997   if( cp ) *cp = 0;
2998   lemon_strcat(name,suffix);
2999   return name;
3000 }
3001 
3002 /* Open a file with a name based on the name of the input file,
3003 ** but with a different (specified) suffix, and return a pointer
3004 ** to the stream */
file_open(struct lemon * lemp,const char * suffix,const char * mode)3005 PRIVATE FILE *file_open(
3006   struct lemon *lemp,
3007   const char *suffix,
3008   const char *mode
3009 ){
3010   FILE *fp;
3011 
3012   if( lemp->outname ) free(lemp->outname);
3013   lemp->outname = file_makename(lemp, suffix);
3014   fp = fopen(lemp->outname,mode);
3015   if( fp==0 && *mode=='w' ){
3016     fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
3017     lemp->errorcnt++;
3018     return 0;
3019   }
3020   return fp;
3021 }
3022 
3023 /* Duplicate the input file without comments and without actions
3024 ** on rules */
Reprint(struct lemon * lemp)3025 void Reprint(struct lemon *lemp)
3026 {
3027   struct rule *rp;
3028   struct symbol *sp;
3029   int i, j, maxlen, len, ncolumns, skip;
3030   printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
3031   maxlen = 10;
3032   for(i=0; i<lemp->nsymbol; i++){
3033     sp = lemp->symbols[i];
3034     len = lemonStrlen(sp->name);
3035     if( len>maxlen ) maxlen = len;
3036   }
3037   ncolumns = 76/(maxlen+5);
3038   if( ncolumns<1 ) ncolumns = 1;
3039   skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
3040   for(i=0; i<skip; i++){
3041     printf("//");
3042     for(j=i; j<lemp->nsymbol; j+=skip){
3043       sp = lemp->symbols[j];
3044       assert( sp->index==j );
3045       printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
3046     }
3047     printf("\n");
3048   }
3049   for(rp=lemp->rule; rp; rp=rp->next){
3050     printf("%s",rp->lhs->name);
3051     /*    if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
3052     printf(" ::=");
3053     for(i=0; i<rp->nrhs; i++){
3054       sp = rp->rhs[i];
3055       if( sp->type==MULTITERMINAL ){
3056         printf(" %s", sp->subsym[0]->name);
3057         for(j=1; j<sp->nsubsym; j++){
3058           printf("|%s", sp->subsym[j]->name);
3059         }
3060       }else{
3061         printf(" %s", sp->name);
3062       }
3063       /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
3064     }
3065     printf(".");
3066     if( rp->precsym ) printf(" [%s]",rp->precsym->name);
3067     /* if( rp->code ) printf("\n    %s",rp->code); */
3068     printf("\n");
3069   }
3070 }
3071 
3072 /* Print a single rule.
3073 */
RulePrint(FILE * fp,struct rule * rp,int iCursor)3074 void RulePrint(FILE *fp, struct rule *rp, int iCursor){
3075   struct symbol *sp;
3076   int i, j;
3077   fprintf(fp,"%s ::=",rp->lhs->name);
3078   for(i=0; i<=rp->nrhs; i++){
3079     if( i==iCursor ) fprintf(fp," *");
3080     if( i==rp->nrhs ) break;
3081     sp = rp->rhs[i];
3082     if( sp->type==MULTITERMINAL ){
3083       fprintf(fp," %s", sp->subsym[0]->name);
3084       for(j=1; j<sp->nsubsym; j++){
3085         fprintf(fp,"|%s",sp->subsym[j]->name);
3086       }
3087     }else{
3088       fprintf(fp," %s", sp->name);
3089     }
3090   }
3091 }
3092 
3093 /* Print the rule for a configuration.
3094 */
ConfigPrint(FILE * fp,struct config * cfp)3095 void ConfigPrint(FILE *fp, struct config *cfp){
3096   RulePrint(fp, cfp->rp, cfp->dot);
3097 }
3098 
3099 /* #define TEST */
3100 #if 0
3101 /* Print a set */
3102 PRIVATE void SetPrint(out,set,lemp)
3103 FILE *out;
3104 char *set;
3105 struct lemon *lemp;
3106 {
3107   int i;
3108   char *spacer;
3109   spacer = "";
3110   fprintf(out,"%12s[","");
3111   for(i=0; i<lemp->nterminal; i++){
3112     if( SetFind(set,i) ){
3113       fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
3114       spacer = " ";
3115     }
3116   }
3117   fprintf(out,"]\n");
3118 }
3119 
3120 /* Print a plink chain */
3121 PRIVATE void PlinkPrint(out,plp,tag)
3122 FILE *out;
3123 struct plink *plp;
3124 char *tag;
3125 {
3126   while( plp ){
3127     fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->statenum);
3128     ConfigPrint(out,plp->cfp);
3129     fprintf(out,"\n");
3130     plp = plp->next;
3131   }
3132 }
3133 #endif
3134 
3135 /* Print an action to the given file descriptor.  Return FALSE if
3136 ** nothing was actually printed.
3137 */
PrintAction(struct action * ap,FILE * fp,int indent)3138 int PrintAction(
3139   struct action *ap,          /* The action to print */
3140   FILE *fp,                   /* Print the action here */
3141   int indent                  /* Indent by this amount */
3142 ){
3143   int result = 1;
3144   switch( ap->type ){
3145     case SHIFT: {
3146       struct state *stp = ap->x.stp;
3147       fprintf(fp,"%*s shift        %-7d",indent,ap->sp->name,stp->statenum);
3148       break;
3149     }
3150     case REDUCE: {
3151       struct rule *rp = ap->x.rp;
3152       fprintf(fp,"%*s reduce       %-7d",indent,ap->sp->name,rp->iRule);
3153       RulePrint(fp, rp, -1);
3154       break;
3155     }
3156     case SHIFTREDUCE: {
3157       struct rule *rp = ap->x.rp;
3158       fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->iRule);
3159       RulePrint(fp, rp, -1);
3160       break;
3161     }
3162     case ACCEPT:
3163       fprintf(fp,"%*s accept",indent,ap->sp->name);
3164       break;
3165     case ERROR:
3166       fprintf(fp,"%*s error",indent,ap->sp->name);
3167       break;
3168     case SRCONFLICT:
3169     case RRCONFLICT:
3170       fprintf(fp,"%*s reduce       %-7d ** Parsing conflict **",
3171         indent,ap->sp->name,ap->x.rp->iRule);
3172       break;
3173     case SSCONFLICT:
3174       fprintf(fp,"%*s shift        %-7d ** Parsing conflict **",
3175         indent,ap->sp->name,ap->x.stp->statenum);
3176       break;
3177     case SH_RESOLVED:
3178       if( showPrecedenceConflict ){
3179         fprintf(fp,"%*s shift        %-7d -- dropped by precedence",
3180                 indent,ap->sp->name,ap->x.stp->statenum);
3181       }else{
3182         result = 0;
3183       }
3184       break;
3185     case RD_RESOLVED:
3186       if( showPrecedenceConflict ){
3187         fprintf(fp,"%*s reduce %-7d -- dropped by precedence",
3188                 indent,ap->sp->name,ap->x.rp->iRule);
3189       }else{
3190         result = 0;
3191       }
3192       break;
3193     case NOT_USED:
3194       result = 0;
3195       break;
3196   }
3197   if( result && ap->spOpt ){
3198     fprintf(fp,"  /* because %s==%s */", ap->sp->name, ap->spOpt->name);
3199   }
3200   return result;
3201 }
3202 
3203 /* Generate the "*.out" log file */
ReportOutput(struct lemon * lemp)3204 void ReportOutput(struct lemon *lemp)
3205 {
3206   int i;
3207   struct state *stp;
3208   struct config *cfp;
3209   struct action *ap;
3210   FILE *fp;
3211 
3212   fp = file_open(lemp,".out","wb");
3213   if( fp==0 ) return;
3214   for(i=0; i<lemp->nxstate; i++){
3215     stp = lemp->sorted[i];
3216     fprintf(fp,"State %d:\n",stp->statenum);
3217     if( lemp->basisflag ) cfp=stp->bp;
3218     else                  cfp=stp->cfp;
3219     while( cfp ){
3220       char buf[20];
3221       if( cfp->dot==cfp->rp->nrhs ){
3222         lemon_sprintf(buf,"(%d)",cfp->rp->iRule);
3223         fprintf(fp,"    %5s ",buf);
3224       }else{
3225         fprintf(fp,"          ");
3226       }
3227       ConfigPrint(fp,cfp);
3228       fprintf(fp,"\n");
3229 #if 0
3230       SetPrint(fp,cfp->fws,lemp);
3231       PlinkPrint(fp,cfp->fplp,"To  ");
3232       PlinkPrint(fp,cfp->bplp,"From");
3233 #endif
3234       if( lemp->basisflag ) cfp=cfp->bp;
3235       else                  cfp=cfp->next;
3236     }
3237     fprintf(fp,"\n");
3238     for(ap=stp->ap; ap; ap=ap->next){
3239       if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
3240     }
3241     fprintf(fp,"\n");
3242   }
3243   fprintf(fp, "----------------------------------------------------\n");
3244   fprintf(fp, "Symbols:\n");
3245   for(i=0; i<lemp->nsymbol; i++){
3246     int j;
3247     struct symbol *sp;
3248 
3249     sp = lemp->symbols[i];
3250     fprintf(fp, "  %3d: %s", i, sp->name);
3251     if( sp->type==NONTERMINAL ){
3252       fprintf(fp, ":");
3253       if( sp->lambda ){
3254         fprintf(fp, " <lambda>");
3255       }
3256       for(j=0; j<lemp->nterminal; j++){
3257         if( sp->firstset && SetFind(sp->firstset, j) ){
3258           fprintf(fp, " %s", lemp->symbols[j]->name);
3259         }
3260       }
3261     }
3262     fprintf(fp, "\n");
3263   }
3264   fclose(fp);
3265   return;
3266 }
3267 
3268 /* Search for the file "name" which is in the same directory as
3269 ** the exacutable */
pathsearch(char * argv0,char * name,int modemask)3270 PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
3271 {
3272   const char *pathlist;
3273   char *pathbufptr;
3274   char *pathbuf;
3275   char *path,*cp;
3276   char c;
3277 
3278 #ifdef __WIN32__
3279   cp = strrchr(argv0,'\\');
3280 #else
3281   cp = strrchr(argv0,'/');
3282 #endif
3283   if( cp ){
3284     c = *cp;
3285     *cp = 0;
3286     path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 );
3287     if( path ) lemon_sprintf(path,"%s/%s",argv0,name);
3288     *cp = c;
3289   }else{
3290     pathlist = getenv("PATH");
3291     if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
3292     pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
3293     path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
3294     if( (pathbuf != 0) && (path!=0) ){
3295       pathbufptr = pathbuf;
3296       lemon_strcpy(pathbuf, pathlist);
3297       while( *pathbuf ){
3298         cp = strchr(pathbuf,':');
3299         if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)];
3300         c = *cp;
3301         *cp = 0;
3302         lemon_sprintf(path,"%s/%s",pathbuf,name);
3303         *cp = c;
3304         if( c==0 ) pathbuf[0] = 0;
3305         else pathbuf = &cp[1];
3306         if( access(path,modemask)==0 ) break;
3307       }
3308       free(pathbufptr);
3309     }
3310   }
3311   return path;
3312 }
3313 
3314 /* Given an action, compute the integer value for that action
3315 ** which is to be put in the action table of the generated machine.
3316 ** Return negative if no action should be generated.
3317 */
compute_action(struct lemon * lemp,struct action * ap)3318 PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
3319 {
3320   int act;
3321   switch( ap->type ){
3322     case SHIFT:  act = ap->x.stp->statenum;                        break;
3323     case SHIFTREDUCE: {
3324       act = ap->x.rp->iRule + lemp->nstate;
3325       /* Since a SHIFT is inherient after a prior REDUCE, convert any
3326       ** SHIFTREDUCE action with a nonterminal on the LHS into a simple
3327       ** REDUCE action: */
3328       if( ap->sp->index>=lemp->nterminal ) act += lemp->nrule;
3329       break;
3330     }
3331     case REDUCE: act = ap->x.rp->iRule + lemp->nstate+lemp->nrule; break;
3332     case ERROR:  act = lemp->nstate + lemp->nrule*2;               break;
3333     case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1;           break;
3334     default:     act = -1; break;
3335   }
3336   return act;
3337 }
3338 
3339 #define LINESIZE 1000
3340 /* The next cluster of routines are for reading the template file
3341 ** and writing the results to the generated parser */
3342 /* The first function transfers data from "in" to "out" until
3343 ** a line is seen which begins with "%%".  The line number is
3344 ** tracked.
3345 **
3346 ** if name!=0, then any word that begin with "Parse" is changed to
3347 ** begin with *name instead.
3348 */
tplt_xfer(char * name,FILE * in,FILE * out,int * lineno)3349 PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
3350 {
3351   int i, iStart;
3352   char line[LINESIZE];
3353   while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
3354     (*lineno)++;
3355     iStart = 0;
3356     if( name ){
3357       for(i=0; line[i]; i++){
3358         if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
3359           && (i==0 || !ISALPHA(line[i-1]))
3360         ){
3361           if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
3362           fprintf(out,"%s",name);
3363           i += 4;
3364           iStart = i+1;
3365         }
3366       }
3367     }
3368     fprintf(out,"%s",&line[iStart]);
3369   }
3370 }
3371 
3372 /* The next function finds the template file and opens it, returning
3373 ** a pointer to the opened file. */
tplt_open(struct lemon * lemp)3374 PRIVATE FILE *tplt_open(struct lemon *lemp)
3375 {
3376   static char templatename[] = "lempar.c";
3377   char buf[1000];
3378   FILE *in;
3379   char *tpltname;
3380   char *cp;
3381 
3382   /* first, see if user specified a template filename on the command line. */
3383   if (user_templatename != 0) {
3384     if( access(user_templatename,004)==-1 ){
3385       fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
3386         user_templatename);
3387       lemp->errorcnt++;
3388       return 0;
3389     }
3390     in = fopen(user_templatename,"rb");
3391     if( in==0 ){
3392       fprintf(stderr,"Can't open the template file \"%s\".\n",
3393               user_templatename);
3394       lemp->errorcnt++;
3395       return 0;
3396     }
3397     return in;
3398   }
3399 
3400   cp = strrchr(lemp->filename,'.');
3401   if( cp ){
3402     lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
3403   }else{
3404     lemon_sprintf(buf,"%s.lt",lemp->filename);
3405   }
3406   if( access(buf,004)==0 ){
3407     tpltname = buf;
3408   }else if( access(templatename,004)==0 ){
3409     tpltname = templatename;
3410   }else{
3411     tpltname = pathsearch(lemp->argv0,templatename,0);
3412   }
3413   if( tpltname==0 ){
3414     fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
3415     templatename);
3416     lemp->errorcnt++;
3417     return 0;
3418   }
3419   in = fopen(tpltname,"rb");
3420   if( in==0 ){
3421     fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
3422     lemp->errorcnt++;
3423     return 0;
3424   }
3425   return in;
3426 }
3427 
3428 /* Print a #line directive line to the output file. */
tplt_linedir(FILE * out,int lineno,char * filename)3429 PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename)
3430 {
3431   fprintf(out,"#line %d \"",lineno);
3432   while( *filename ){
3433     if( *filename == '\\' ) putc('\\',out);
3434     putc(*filename,out);
3435     filename++;
3436   }
3437   fprintf(out,"\"\n");
3438 }
3439 
3440 /* Print a string to the file and keep the linenumber up to date */
tplt_print(FILE * out,struct lemon * lemp,char * str,int * lineno)3441 PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, int *lineno)
3442 {
3443   if( str==0 ) return;
3444   while( *str ){
3445     putc(*str,out);
3446     if( *str=='\n' ) (*lineno)++;
3447     str++;
3448   }
3449   if( str[-1]!='\n' ){
3450     putc('\n',out);
3451     (*lineno)++;
3452   }
3453   if (!lemp->nolinenosflag) {
3454     (*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
3455   }
3456   return;
3457 }
3458 
3459 /*
3460 ** The following routine emits code for the destructor for the
3461 ** symbol sp
3462 */
emit_destructor_code(FILE * out,struct symbol * sp,struct lemon * lemp,int * lineno)3463 void emit_destructor_code(
3464   FILE *out,
3465   struct symbol *sp,
3466   struct lemon *lemp,
3467   int *lineno
3468 ){
3469  char *cp = 0;
3470 
3471  if( sp->type==TERMINAL ){
3472    cp = lemp->tokendest;
3473    if( cp==0 ) return;
3474    fprintf(out,"{\n"); (*lineno)++;
3475  }else if( sp->destructor ){
3476    cp = sp->destructor;
3477    fprintf(out,"{\n"); (*lineno)++;
3478    if( !lemp->nolinenosflag ){
3479      (*lineno)++;
3480      tplt_linedir(out,sp->destLineno,lemp->filename);
3481    }
3482  }else if( lemp->vardest ){
3483    cp = lemp->vardest;
3484    if( cp==0 ) return;
3485    fprintf(out,"{\n"); (*lineno)++;
3486  }else{
3487    assert( 0 );  /* Cannot happen */
3488  }
3489  for(; *cp; cp++){
3490    if( *cp=='$' && cp[1]=='$' ){
3491      fprintf(out,"(yypminor->yy%d)",sp->dtnum);
3492      cp++;
3493      continue;
3494    }
3495    if( *cp=='\n' ) (*lineno)++;
3496    fputc(*cp,out);
3497  }
3498  fprintf(out,"\n"); (*lineno)++;
3499  if (!lemp->nolinenosflag) {
3500    (*lineno)++; tplt_linedir(out,*lineno,lemp->outname);
3501  }
3502  fprintf(out,"}\n"); (*lineno)++;
3503  return;
3504 }
3505 
3506 /*
3507 ** Return TRUE (non-zero) if the given symbol has a destructor.
3508 */
has_destructor(struct symbol * sp,struct lemon * lemp)3509 int has_destructor(struct symbol *sp, struct lemon *lemp)
3510 {
3511   int ret;
3512   if( sp->type==TERMINAL ){
3513     ret = lemp->tokendest!=0;
3514   }else{
3515     ret = lemp->vardest!=0 || sp->destructor!=0;
3516   }
3517   return ret;
3518 }
3519 
3520 /*
3521 ** Append text to a dynamically allocated string.  If zText is 0 then
3522 ** reset the string to be empty again.  Always return the complete text
3523 ** of the string (which is overwritten with each call).
3524 **
3525 ** n bytes of zText are stored.  If n==0 then all of zText up to the first
3526 ** \000 terminator is stored.  zText can contain up to two instances of
3527 ** %d.  The values of p1 and p2 are written into the first and second
3528 ** %d.
3529 **
3530 ** If n==-1, then the previous character is overwritten.
3531 */
append_str(const char * zText,int n,int p1,int p2)3532 PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
3533   static char empty[1] = { 0 };
3534   static char *z = 0;
3535   static int alloced = 0;
3536   static int used = 0;
3537   int c;
3538   char zInt[40];
3539   if( zText==0 ){
3540     if( used==0 && z!=0 ) z[0] = 0;
3541     used = 0;
3542     return z;
3543   }
3544   if( n<=0 ){
3545     if( n<0 ){
3546       used += n;
3547       assert( used>=0 );
3548     }
3549     n = lemonStrlen(zText);
3550   }
3551   if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
3552     alloced = n + sizeof(zInt)*2 + used + 200;
3553     z = (char *) realloc(z,  alloced);
3554   }
3555   if( z==0 ) return empty;
3556   while( n-- > 0 ){
3557     c = *(zText++);
3558     if( c=='%' && n>0 && zText[0]=='d' ){
3559       lemon_sprintf(zInt, "%d", p1);
3560       p1 = p2;
3561       lemon_strcpy(&z[used], zInt);
3562       used += lemonStrlen(&z[used]);
3563       zText++;
3564       n--;
3565     }else{
3566       z[used++] = (char)c;
3567     }
3568   }
3569   z[used] = 0;
3570   return z;
3571 }
3572 
3573 /*
3574 ** Write and transform the rp->code string so that symbols are expanded.
3575 ** Populate the rp->codePrefix and rp->codeSuffix strings, as appropriate.
3576 **
3577 ** Return 1 if the expanded code requires that "yylhsminor" local variable
3578 ** to be defined.
3579 */
translate_code(struct lemon * lemp,struct rule * rp)3580 PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
3581   char *cp, *xp;
3582   int i;
3583   int rc = 0;            /* True if yylhsminor is used */
3584   int dontUseRhs0 = 0;   /* If true, use of left-most RHS label is illegal */
3585   const char *zSkip = 0; /* The zOvwrt comment within rp->code, or NULL */
3586   char lhsused = 0;      /* True if the LHS element has been used */
3587   char lhsdirect;        /* True if LHS writes directly into stack */
3588   char used[MAXRHS];     /* True for each RHS element which is used */
3589   char zLhs[50];         /* Convert the LHS symbol into this string */
3590   char zOvwrt[900];      /* Comment that to allow LHS to overwrite RHS */
3591 
3592   for(i=0; i<rp->nrhs; i++) used[i] = 0;
3593   lhsused = 0;
3594 
3595   if( rp->code==0 ){
3596     static char newlinestr[2] = { '\n', '\0' };
3597     rp->code = newlinestr;
3598     rp->line = rp->ruleline;
3599     rp->noCode = 1;
3600   }else{
3601     rp->noCode = 0;
3602   }
3603 
3604 
3605   if( rp->nrhs==0 ){
3606     /* If there are no RHS symbols, then writing directly to the LHS is ok */
3607     lhsdirect = 1;
3608   }else if( rp->rhsalias[0]==0 ){
3609     /* The left-most RHS symbol has no value.  LHS direct is ok.  But
3610     ** we have to call the distructor on the RHS symbol first. */
3611     lhsdirect = 1;
3612     if( has_destructor(rp->rhs[0],lemp) ){
3613       append_str(0,0,0,0);
3614       append_str("  yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
3615                  rp->rhs[0]->index,1-rp->nrhs);
3616       rp->codePrefix = Strsafe(append_str(0,0,0,0));
3617       rp->noCode = 0;
3618     }
3619   }else if( rp->lhsalias==0 ){
3620     /* There is no LHS value symbol. */
3621     lhsdirect = 1;
3622   }else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){
3623     /* The LHS symbol and the left-most RHS symbol are the same, so
3624     ** direct writing is allowed */
3625     lhsdirect = 1;
3626     lhsused = 1;
3627     used[0] = 1;
3628     if( rp->lhs->dtnum!=rp->rhs[0]->dtnum ){
3629       ErrorMsg(lemp->filename,rp->ruleline,
3630         "%s(%s) and %s(%s) share the same label but have "
3631         "different datatypes.",
3632         rp->lhs->name, rp->lhsalias, rp->rhs[0]->name, rp->rhsalias[0]);
3633       lemp->errorcnt++;
3634     }
3635   }else{
3636     lemon_sprintf(zOvwrt, "/*%s-overwrites-%s*/",
3637                   rp->lhsalias, rp->rhsalias[0]);
3638     zSkip = strstr(rp->code, zOvwrt);
3639     if( zSkip!=0 ){
3640       /* The code contains a special comment that indicates that it is safe
3641       ** for the LHS label to overwrite left-most RHS label. */
3642       lhsdirect = 1;
3643     }else{
3644       lhsdirect = 0;
3645     }
3646   }
3647   if( lhsdirect ){
3648     sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
3649   }else{
3650     rc = 1;
3651     sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
3652   }
3653 
3654   append_str(0,0,0,0);
3655 
3656   /* This const cast is wrong but harmless, if we're careful. */
3657   for(cp=(char *)rp->code; *cp; cp++){
3658     if( cp==zSkip ){
3659       append_str(zOvwrt,0,0,0);
3660       cp += lemonStrlen(zOvwrt)-1;
3661       dontUseRhs0 = 1;
3662       continue;
3663     }
3664     if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){
3665       char saved;
3666       for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++);
3667       saved = *xp;
3668       *xp = 0;
3669       if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
3670         append_str(zLhs,0,0,0);
3671         cp = xp;
3672         lhsused = 1;
3673       }else{
3674         for(i=0; i<rp->nrhs; i++){
3675           if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
3676             if( i==0 && dontUseRhs0 ){
3677               ErrorMsg(lemp->filename,rp->ruleline,
3678                  "Label %s used after '%s'.",
3679                  rp->rhsalias[0], zOvwrt);
3680               lemp->errorcnt++;
3681             }else if( cp!=rp->code && cp[-1]=='@' ){
3682               /* If the argument is of the form @X then substituted
3683               ** the token number of X, not the value of X */
3684               append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0);
3685             }else{
3686               struct symbol *sp = rp->rhs[i];
3687               int dtnum;
3688               if( sp->type==MULTITERMINAL ){
3689                 dtnum = sp->subsym[0]->dtnum;
3690               }else{
3691                 dtnum = sp->dtnum;
3692               }
3693               append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum);
3694             }
3695             cp = xp;
3696             used[i] = 1;
3697             break;
3698           }
3699         }
3700       }
3701       *xp = saved;
3702     }
3703     append_str(cp, 1, 0, 0);
3704   } /* End loop */
3705 
3706   /* Main code generation completed */
3707   cp = append_str(0,0,0,0);
3708   if( cp && cp[0] ) rp->code = Strsafe(cp);
3709   append_str(0,0,0,0);
3710 
3711   /* Check to make sure the LHS has been used */
3712   if( rp->lhsalias && !lhsused ){
3713     ErrorMsg(lemp->filename,rp->ruleline,
3714       "Label \"%s\" for \"%s(%s)\" is never used.",
3715         rp->lhsalias,rp->lhs->name,rp->lhsalias);
3716     lemp->errorcnt++;
3717   }
3718 
3719   /* Generate destructor code for RHS minor values which are not referenced.
3720   ** Generate error messages for unused labels and duplicate labels.
3721   */
3722   for(i=0; i<rp->nrhs; i++){
3723     if( rp->rhsalias[i] ){
3724       if( i>0 ){
3725         int j;
3726         if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){
3727           ErrorMsg(lemp->filename,rp->ruleline,
3728             "%s(%s) has the same label as the LHS but is not the left-most "
3729             "symbol on the RHS.",
3730             rp->rhs[i]->name, rp->rhsalias);
3731           lemp->errorcnt++;
3732         }
3733         for(j=0; j<i; j++){
3734           if( rp->rhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){
3735             ErrorMsg(lemp->filename,rp->ruleline,
3736               "Label %s used for multiple symbols on the RHS of a rule.",
3737               rp->rhsalias[i]);
3738             lemp->errorcnt++;
3739             break;
3740           }
3741         }
3742       }
3743       if( !used[i] ){
3744         ErrorMsg(lemp->filename,rp->ruleline,
3745           "Label %s for \"%s(%s)\" is never used.",
3746           rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
3747         lemp->errorcnt++;
3748       }
3749     }else if( i>0 && has_destructor(rp->rhs[i],lemp) ){
3750       append_str("  yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
3751          rp->rhs[i]->index,i-rp->nrhs+1);
3752     }
3753   }
3754 
3755   /* If unable to write LHS values directly into the stack, write the
3756   ** saved LHS value now. */
3757   if( lhsdirect==0 ){
3758     append_str("  yymsp[%d].minor.yy%d = ", 0, 1-rp->nrhs, rp->lhs->dtnum);
3759     append_str(zLhs, 0, 0, 0);
3760     append_str(";\n", 0, 0, 0);
3761   }
3762 
3763   /* Suffix code generation complete */
3764   cp = append_str(0,0,0,0);
3765   if( cp && cp[0] ){
3766     rp->codeSuffix = Strsafe(cp);
3767     rp->noCode = 0;
3768   }
3769 
3770   return rc;
3771 }
3772 
3773 /*
3774 ** Generate code which executes when the rule "rp" is reduced.  Write
3775 ** the code to "out".  Make sure lineno stays up-to-date.
3776 */
emit_code(FILE * out,struct rule * rp,struct lemon * lemp,int * lineno)3777 PRIVATE void emit_code(
3778   FILE *out,
3779   struct rule *rp,
3780   struct lemon *lemp,
3781   int *lineno
3782 ){
3783  const char *cp;
3784 
3785  /* Setup code prior to the #line directive */
3786  if( rp->codePrefix && rp->codePrefix[0] ){
3787    fprintf(out, "{%s", rp->codePrefix);
3788    for(cp=rp->codePrefix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
3789  }
3790 
3791  /* Generate code to do the reduce action */
3792  if( rp->code ){
3793    if( !lemp->nolinenosflag ){
3794      (*lineno)++;
3795      tplt_linedir(out,rp->line,lemp->filename);
3796    }
3797    fprintf(out,"{%s",rp->code);
3798    for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
3799    fprintf(out,"}\n"); (*lineno)++;
3800    if( !lemp->nolinenosflag ){
3801      (*lineno)++;
3802      tplt_linedir(out,*lineno,lemp->outname);
3803    }
3804  }
3805 
3806  /* Generate breakdown code that occurs after the #line directive */
3807  if( rp->codeSuffix && rp->codeSuffix[0] ){
3808    fprintf(out, "%s", rp->codeSuffix);
3809    for(cp=rp->codeSuffix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
3810  }
3811 
3812  if( rp->codePrefix ){
3813    fprintf(out, "}\n"); (*lineno)++;
3814  }
3815 
3816  return;
3817 }
3818 
3819 /*
3820 ** Print the definition of the union used for the parser's data stack.
3821 ** This union contains fields for every possible data type for tokens
3822 ** and nonterminals.  In the process of computing and printing this
3823 ** union, also set the ".dtnum" field of every terminal and nonterminal
3824 ** symbol.
3825 */
print_stack_union(FILE * out,struct lemon * lemp,int * plineno,int mhflag)3826 void print_stack_union(
3827   FILE *out,                  /* The output stream */
3828   struct lemon *lemp,         /* The main info structure for this parser */
3829   int *plineno,               /* Pointer to the line number */
3830   int mhflag                  /* True if generating makeheaders output */
3831 ){
3832   int lineno = *plineno;    /* The line number of the output */
3833   char **types;             /* A hash table of datatypes */
3834   int arraysize;            /* Size of the "types" array */
3835   int maxdtlength;          /* Maximum length of any ".datatype" field. */
3836   char *stddt;              /* Standardized name for a datatype */
3837   int i,j;                  /* Loop counters */
3838   unsigned hash;            /* For hashing the name of a type */
3839   const char *name;         /* Name of the parser */
3840 
3841   /* Allocate and initialize types[] and allocate stddt[] */
3842   arraysize = lemp->nsymbol * 2;
3843   types = (char**)calloc( arraysize, sizeof(char*) );
3844   if( types==0 ){
3845     fprintf(stderr,"Out of memory.\n");
3846     exit(1);
3847   }
3848   for(i=0; i<arraysize; i++) types[i] = 0;
3849   maxdtlength = 0;
3850   if( lemp->vartype ){
3851     maxdtlength = lemonStrlen(lemp->vartype);
3852   }
3853   for(i=0; i<lemp->nsymbol; i++){
3854     int len;
3855     struct symbol *sp = lemp->symbols[i];
3856     if( sp->datatype==0 ) continue;
3857     len = lemonStrlen(sp->datatype);
3858     if( len>maxdtlength ) maxdtlength = len;
3859   }
3860   stddt = (char*)malloc( maxdtlength*2 + 1 );
3861   if( stddt==0 ){
3862     fprintf(stderr,"Out of memory.\n");
3863     exit(1);
3864   }
3865 
3866   /* Build a hash table of datatypes. The ".dtnum" field of each symbol
3867   ** is filled in with the hash index plus 1.  A ".dtnum" value of 0 is
3868   ** used for terminal symbols.  If there is no %default_type defined then
3869   ** 0 is also used as the .dtnum value for nonterminals which do not specify
3870   ** a datatype using the %type directive.
3871   */
3872   for(i=0; i<lemp->nsymbol; i++){
3873     struct symbol *sp = lemp->symbols[i];
3874     char *cp;
3875     if( sp==lemp->errsym ){
3876       sp->dtnum = arraysize+1;
3877       continue;
3878     }
3879     if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
3880       sp->dtnum = 0;
3881       continue;
3882     }
3883     cp = sp->datatype;
3884     if( cp==0 ) cp = lemp->vartype;
3885     j = 0;
3886     while( ISSPACE(*cp) ) cp++;
3887     while( *cp ) stddt[j++] = *cp++;
3888     while( j>0 && ISSPACE(stddt[j-1]) ) j--;
3889     stddt[j] = 0;
3890     if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){
3891       sp->dtnum = 0;
3892       continue;
3893     }
3894     hash = 0;
3895     for(j=0; stddt[j]; j++){
3896       hash = hash*53 + stddt[j];
3897     }
3898     hash = (hash & 0x7fffffff)%arraysize;
3899     while( types[hash] ){
3900       if( strcmp(types[hash],stddt)==0 ){
3901         sp->dtnum = hash + 1;
3902         break;
3903       }
3904       hash++;
3905       if( hash>=(unsigned)arraysize ) hash = 0;
3906     }
3907     if( types[hash]==0 ){
3908       sp->dtnum = hash + 1;
3909       types[hash] = (char*)malloc( lemonStrlen(stddt)+1 );
3910       if( types[hash]==0 ){
3911         fprintf(stderr,"Out of memory.\n");
3912         exit(1);
3913       }
3914       lemon_strcpy(types[hash],stddt);
3915     }
3916   }
3917 
3918   /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
3919   name = lemp->name ? lemp->name : "Parse";
3920   lineno = *plineno;
3921   if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
3922   fprintf(out,"#define %sTOKENTYPE %s\n",name,
3923     lemp->tokentype?lemp->tokentype:"void*");  lineno++;
3924   if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
3925   fprintf(out,"typedef union {\n"); lineno++;
3926   fprintf(out,"  int yyinit;\n"); lineno++;
3927   fprintf(out,"  %sTOKENTYPE yy0;\n",name); lineno++;
3928   for(i=0; i<arraysize; i++){
3929     if( types[i]==0 ) continue;
3930     fprintf(out,"  %s yy%d;\n",types[i],i+1); lineno++;
3931     free(types[i]);
3932   }
3933   if( lemp->errsym->useCnt ){
3934     fprintf(out,"  int yy%d;\n",lemp->errsym->dtnum); lineno++;
3935   }
3936   free(stddt);
3937   free(types);
3938   fprintf(out,"} YYMINORTYPE;\n"); lineno++;
3939   *plineno = lineno;
3940 }
3941 
3942 /*
3943 ** Return the name of a C datatype able to represent values between
3944 ** lwr and upr, inclusive.  If pnByte!=NULL then also write the sizeof
3945 ** for that type (1, 2, or 4) into *pnByte.
3946 */
minimum_size_type(int lwr,int upr,int * pnByte)3947 static const char *minimum_size_type(int lwr, int upr, int *pnByte){
3948   const char *zType = "int";
3949   int nByte = 4;
3950   if( lwr>=0 ){
3951     if( upr<=255 ){
3952       zType = "unsigned char";
3953       nByte = 1;
3954     }else if( upr<65535 ){
3955       zType = "unsigned short int";
3956       nByte = 2;
3957     }else{
3958       zType = "unsigned int";
3959       nByte = 4;
3960     }
3961   }else if( lwr>=-127 && upr<=127 ){
3962     zType = "signed char";
3963     nByte = 1;
3964   }else if( lwr>=-32767 && upr<32767 ){
3965     zType = "short";
3966     nByte = 2;
3967   }
3968   if( pnByte ) *pnByte = nByte;
3969   return zType;
3970 }
3971 
3972 /*
3973 ** Each state contains a set of token transaction and a set of
3974 ** nonterminal transactions.  Each of these sets makes an instance
3975 ** of the following structure.  An array of these structures is used
3976 ** to order the creation of entries in the yy_action[] table.
3977 */
3978 struct axset {
3979   struct state *stp;   /* A pointer to a state */
3980   int isTkn;           /* True to use tokens.  False for non-terminals */
3981   int nAction;         /* Number of actions */
3982   int iOrder;          /* Original order of action sets */
3983 };
3984 
3985 /*
3986 ** Compare to axset structures for sorting purposes
3987 */
axset_compare(const void * a,const void * b)3988 static int axset_compare(const void *a, const void *b){
3989   struct axset *p1 = (struct axset*)a;
3990   struct axset *p2 = (struct axset*)b;
3991   int c;
3992   c = p2->nAction - p1->nAction;
3993   if( c==0 ){
3994     c = p1->iOrder - p2->iOrder;
3995   }
3996   assert( c!=0 || p1==p2 );
3997   return c;
3998 }
3999 
4000 /*
4001 ** Write text on "out" that describes the rule "rp".
4002 */
writeRuleText(FILE * out,struct rule * rp)4003 static void writeRuleText(FILE *out, struct rule *rp){
4004   int j;
4005   fprintf(out,"%s ::=", rp->lhs->name);
4006   for(j=0; j<rp->nrhs; j++){
4007     struct symbol *sp = rp->rhs[j];
4008     if( sp->type!=MULTITERMINAL ){
4009       fprintf(out," %s", sp->name);
4010     }else{
4011       int k;
4012       fprintf(out," %s", sp->subsym[0]->name);
4013       for(k=1; k<sp->nsubsym; k++){
4014         fprintf(out,"|%s",sp->subsym[k]->name);
4015       }
4016     }
4017   }
4018 }
4019 
4020 
4021 /* Generate C source code for the parser */
ReportTable(struct lemon * lemp,int mhflag)4022 void ReportTable(
4023   struct lemon *lemp,
4024   int mhflag     /* Output in makeheaders format if true */
4025 ){
4026   FILE *out, *in;
4027   char line[LINESIZE];
4028   int  lineno;
4029   struct state *stp;
4030   struct action *ap;
4031   struct rule *rp;
4032   struct acttab *pActtab;
4033   int i, j, n, sz;
4034   int szActionType;     /* sizeof(YYACTIONTYPE) */
4035   int szCodeType;       /* sizeof(YYCODETYPE)   */
4036   const char *name;
4037   int mnTknOfst, mxTknOfst;
4038   int mnNtOfst, mxNtOfst;
4039   struct axset *ax;
4040 
4041   in = tplt_open(lemp);
4042   if( in==0 ) return;
4043   out = file_open(lemp,".c","wb");
4044   if( out==0 ){
4045     fclose(in);
4046     return;
4047   }
4048   lineno = 1;
4049   tplt_xfer(lemp->name,in,out,&lineno);
4050 
4051   /* Generate the include code, if any */
4052   tplt_print(out,lemp,lemp->include,&lineno);
4053   if( mhflag ){
4054     char *incName = file_makename(lemp, ".h");
4055     fprintf(out,"#include \"%s\"\n", incName); lineno++;
4056     free(incName);
4057   }
4058   tplt_xfer(lemp->name,in,out,&lineno);
4059 
4060   /* Generate #defines for all tokens */
4061   if( mhflag ){
4062     const char *prefix;
4063     fprintf(out,"#if INTERFACE\n"); lineno++;
4064     if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
4065     else                    prefix = "";
4066     for(i=1; i<lemp->nterminal; i++){
4067       fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
4068       lineno++;
4069     }
4070     fprintf(out,"#endif\n"); lineno++;
4071   }
4072   tplt_xfer(lemp->name,in,out,&lineno);
4073 
4074   /* Generate the defines */
4075   fprintf(out,"#define YYCODETYPE %s\n",
4076     minimum_size_type(0, lemp->nsymbol+1, &szCodeType)); lineno++;
4077   fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1);  lineno++;
4078   fprintf(out,"#define YYACTIONTYPE %s\n",
4079     minimum_size_type(0,lemp->nstate+lemp->nrule*2+5,&szActionType)); lineno++;
4080   if( lemp->wildcard ){
4081     fprintf(out,"#define YYWILDCARD %d\n",
4082        lemp->wildcard->index); lineno++;
4083   }
4084   print_stack_union(out,lemp,&lineno,mhflag);
4085   fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++;
4086   if( lemp->stacksize ){
4087     fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize);  lineno++;
4088   }else{
4089     fprintf(out,"#define YYSTACKDEPTH 100\n");  lineno++;
4090   }
4091   fprintf(out, "#endif\n"); lineno++;
4092   if( mhflag ){
4093     fprintf(out,"#if INTERFACE\n"); lineno++;
4094   }
4095   name = lemp->name ? lemp->name : "Parse";
4096   if( lemp->arg && lemp->arg[0] ){
4097     i = lemonStrlen(lemp->arg);
4098     while( i>=1 && ISSPACE(lemp->arg[i-1]) ) i--;
4099     while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
4100     fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg);  lineno++;
4101     fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg);  lineno++;
4102     fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
4103                  name,lemp->arg,&lemp->arg[i]);  lineno++;
4104     fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
4105                  name,&lemp->arg[i],&lemp->arg[i]);  lineno++;
4106   }else{
4107     fprintf(out,"#define %sARG_SDECL\n",name);  lineno++;
4108     fprintf(out,"#define %sARG_PDECL\n",name);  lineno++;
4109     fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
4110     fprintf(out,"#define %sARG_STORE\n",name); lineno++;
4111   }
4112   if( mhflag ){
4113     fprintf(out,"#endif\n"); lineno++;
4114   }
4115   if( lemp->errsym->useCnt ){
4116     fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
4117     fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
4118   }
4119   if( lemp->has_fallback ){
4120     fprintf(out,"#define YYFALLBACK 1\n");  lineno++;
4121   }
4122 
4123   /* Compute the action table, but do not output it yet.  The action
4124   ** table must be computed before generating the YYNSTATE macro because
4125   ** we need to know how many states can be eliminated.
4126   */
4127   ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
4128   if( ax==0 ){
4129     fprintf(stderr,"malloc failed\n");
4130     exit(1);
4131   }
4132   for(i=0; i<lemp->nxstate; i++){
4133     stp = lemp->sorted[i];
4134     ax[i*2].stp = stp;
4135     ax[i*2].isTkn = 1;
4136     ax[i*2].nAction = stp->nTknAct;
4137     ax[i*2+1].stp = stp;
4138     ax[i*2+1].isTkn = 0;
4139     ax[i*2+1].nAction = stp->nNtAct;
4140   }
4141   mxTknOfst = mnTknOfst = 0;
4142   mxNtOfst = mnNtOfst = 0;
4143   /* In an effort to minimize the action table size, use the heuristic
4144   ** of placing the largest action sets first */
4145   for(i=0; i<lemp->nxstate*2; i++) ax[i].iOrder = i;
4146   qsort(ax, lemp->nxstate*2, sizeof(ax[0]), axset_compare);
4147   pActtab = acttab_alloc();
4148   for(i=0; i<lemp->nxstate*2 && ax[i].nAction>0; i++){
4149     stp = ax[i].stp;
4150     if( ax[i].isTkn ){
4151       for(ap=stp->ap; ap; ap=ap->next){
4152         int action;
4153         if( ap->sp->index>=lemp->nterminal ) continue;
4154         action = compute_action(lemp, ap);
4155         if( action<0 ) continue;
4156         acttab_action(pActtab, ap->sp->index, action);
4157       }
4158       stp->iTknOfst = acttab_insert(pActtab);
4159       if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
4160       if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
4161     }else{
4162       for(ap=stp->ap; ap; ap=ap->next){
4163         int action;
4164         if( ap->sp->index<lemp->nterminal ) continue;
4165         if( ap->sp->index==lemp->nsymbol ) continue;
4166         action = compute_action(lemp, ap);
4167         if( action<0 ) continue;
4168         acttab_action(pActtab, ap->sp->index, action);
4169       }
4170       stp->iNtOfst = acttab_insert(pActtab);
4171       if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
4172       if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
4173     }
4174 #if 0  /* Uncomment for a trace of how the yy_action[] table fills out */
4175     { int jj, nn;
4176       for(jj=nn=0; jj<pActtab->nAction; jj++){
4177         if( pActtab->aAction[jj].action<0 ) nn++;
4178       }
4179       printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n",
4180              i, stp->statenum, ax[i].isTkn ? "Token" : "Var  ",
4181              ax[i].nAction, pActtab->nAction, nn);
4182     }
4183 #endif
4184   }
4185   free(ax);
4186 
4187   /* Mark rules that are actually used for reduce actions after all
4188   ** optimizations have been applied
4189   */
4190   for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE;
4191   for(i=0; i<lemp->nxstate; i++){
4192     for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
4193       if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){
4194         ap->x.rp->doesReduce = 1;
4195       }
4196     }
4197   }
4198 
4199   /* Finish rendering the constants now that the action table has
4200   ** been computed */
4201   fprintf(out,"#define YYNSTATE             %d\n",lemp->nxstate);  lineno++;
4202   fprintf(out,"#define YYNRULE              %d\n",lemp->nrule);  lineno++;
4203   fprintf(out,"#define YY_MAX_SHIFT         %d\n",lemp->nxstate-1); lineno++;
4204   fprintf(out,"#define YY_MIN_SHIFTREDUCE   %d\n",lemp->nstate); lineno++;
4205   i = lemp->nstate + lemp->nrule;
4206   fprintf(out,"#define YY_MAX_SHIFTREDUCE   %d\n", i-1); lineno++;
4207   fprintf(out,"#define YY_MIN_REDUCE        %d\n", i); lineno++;
4208   i = lemp->nstate + lemp->nrule*2;
4209   fprintf(out,"#define YY_MAX_REDUCE        %d\n", i-1); lineno++;
4210   fprintf(out,"#define YY_ERROR_ACTION      %d\n", i); lineno++;
4211   fprintf(out,"#define YY_ACCEPT_ACTION     %d\n", i+1); lineno++;
4212   fprintf(out,"#define YY_NO_ACTION         %d\n", i+2); lineno++;
4213   tplt_xfer(lemp->name,in,out,&lineno);
4214 
4215   /* Now output the action table and its associates:
4216   **
4217   **  yy_action[]        A single table containing all actions.
4218   **  yy_lookahead[]     A table containing the lookahead for each entry in
4219   **                     yy_action.  Used to detect hash collisions.
4220   **  yy_shift_ofst[]    For each state, the offset into yy_action for
4221   **                     shifting terminals.
4222   **  yy_reduce_ofst[]   For each state, the offset into yy_action for
4223   **                     shifting non-terminals after a reduce.
4224   **  yy_default[]       Default action for each state.
4225   */
4226 
4227   /* Output the yy_action table */
4228   lemp->nactiontab = n = acttab_size(pActtab);
4229   lemp->tablesize += n*szActionType;
4230   fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++;
4231   fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
4232   for(i=j=0; i<n; i++){
4233     int action = acttab_yyaction(pActtab, i);
4234     if( action<0 ) action = lemp->nstate + lemp->nrule + 2;
4235     if( j==0 ) fprintf(out," /* %5d */ ", i);
4236     fprintf(out, " %4d,", action);
4237     if( j==9 || i==n-1 ){
4238       fprintf(out, "\n"); lineno++;
4239       j = 0;
4240     }else{
4241       j++;
4242     }
4243   }
4244   fprintf(out, "};\n"); lineno++;
4245 
4246   /* Output the yy_lookahead table */
4247   lemp->tablesize += n*szCodeType;
4248   fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
4249   for(i=j=0; i<n; i++){
4250     int la = acttab_yylookahead(pActtab, i);
4251     if( la<0 ) la = lemp->nsymbol;
4252     if( j==0 ) fprintf(out," /* %5d */ ", i);
4253     fprintf(out, " %4d,", la);
4254     if( j==9 || i==n-1 ){
4255       fprintf(out, "\n"); lineno++;
4256       j = 0;
4257     }else{
4258       j++;
4259     }
4260   }
4261   fprintf(out, "};\n"); lineno++;
4262 
4263   /* Output the yy_shift_ofst[] table */
4264   n = lemp->nxstate;
4265   while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
4266   fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", lemp->nactiontab); lineno++;
4267   fprintf(out, "#define YY_SHIFT_COUNT    (%d)\n", n-1); lineno++;
4268   fprintf(out, "#define YY_SHIFT_MIN      (%d)\n", mnTknOfst); lineno++;
4269   fprintf(out, "#define YY_SHIFT_MAX      (%d)\n", mxTknOfst); lineno++;
4270   fprintf(out, "static const %s yy_shift_ofst[] = {\n",
4271        minimum_size_type(mnTknOfst, lemp->nterminal+lemp->nactiontab, &sz));
4272        lineno++;
4273   lemp->tablesize += n*sz;
4274   for(i=j=0; i<n; i++){
4275     int ofst;
4276     stp = lemp->sorted[i];
4277     ofst = stp->iTknOfst;
4278     if( ofst==NO_OFFSET ) ofst = lemp->nactiontab;
4279     if( j==0 ) fprintf(out," /* %5d */ ", i);
4280     fprintf(out, " %4d,", ofst);
4281     if( j==9 || i==n-1 ){
4282       fprintf(out, "\n"); lineno++;
4283       j = 0;
4284     }else{
4285       j++;
4286     }
4287   }
4288   fprintf(out, "};\n"); lineno++;
4289 
4290   /* Output the yy_reduce_ofst[] table */
4291   fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
4292   n = lemp->nxstate;
4293   while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
4294   fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++;
4295   fprintf(out, "#define YY_REDUCE_MIN   (%d)\n", mnNtOfst); lineno++;
4296   fprintf(out, "#define YY_REDUCE_MAX   (%d)\n", mxNtOfst); lineno++;
4297   fprintf(out, "static const %s yy_reduce_ofst[] = {\n",
4298           minimum_size_type(mnNtOfst-1, mxNtOfst, &sz)); lineno++;
4299   lemp->tablesize += n*sz;
4300   for(i=j=0; i<n; i++){
4301     int ofst;
4302     stp = lemp->sorted[i];
4303     ofst = stp->iNtOfst;
4304     if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
4305     if( j==0 ) fprintf(out," /* %5d */ ", i);
4306     fprintf(out, " %4d,", ofst);
4307     if( j==9 || i==n-1 ){
4308       fprintf(out, "\n"); lineno++;
4309       j = 0;
4310     }else{
4311       j++;
4312     }
4313   }
4314   fprintf(out, "};\n"); lineno++;
4315 
4316   /* Output the default action table */
4317   fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
4318   n = lemp->nxstate;
4319   lemp->tablesize += n*szActionType;
4320   for(i=j=0; i<n; i++){
4321     stp = lemp->sorted[i];
4322     if( j==0 ) fprintf(out," /* %5d */ ", i);
4323     fprintf(out, " %4d,", stp->iDfltReduce+lemp->nstate+lemp->nrule);
4324     if( j==9 || i==n-1 ){
4325       fprintf(out, "\n"); lineno++;
4326       j = 0;
4327     }else{
4328       j++;
4329     }
4330   }
4331   fprintf(out, "};\n"); lineno++;
4332   tplt_xfer(lemp->name,in,out,&lineno);
4333 
4334   /* Generate the table of fallback tokens.
4335   */
4336   if( lemp->has_fallback ){
4337     int mx = lemp->nterminal - 1;
4338     while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; }
4339     lemp->tablesize += (mx+1)*szCodeType;
4340     for(i=0; i<=mx; i++){
4341       struct symbol *p = lemp->symbols[i];
4342       if( p->fallback==0 ){
4343         fprintf(out, "    0,  /* %10s => nothing */\n", p->name);
4344       }else{
4345         fprintf(out, "  %3d,  /* %10s => %s */\n", p->fallback->index,
4346           p->name, p->fallback->name);
4347       }
4348       lineno++;
4349     }
4350   }
4351   tplt_xfer(lemp->name, in, out, &lineno);
4352 
4353   /* Generate a table containing the symbolic name of every symbol
4354   */
4355   for(i=0; i<lemp->nsymbol; i++){
4356     lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
4357     fprintf(out,"  %-15s",line);
4358     if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
4359   }
4360   if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
4361   tplt_xfer(lemp->name,in,out,&lineno);
4362 
4363   /* Generate a table containing a text string that describes every
4364   ** rule in the rule set of the grammar.  This information is used
4365   ** when tracing REDUCE actions.
4366   */
4367   for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
4368     assert( rp->iRule==i );
4369     fprintf(out," /* %3d */ \"", i);
4370     writeRuleText(out, rp);
4371     fprintf(out,"\",\n"); lineno++;
4372   }
4373   tplt_xfer(lemp->name,in,out,&lineno);
4374 
4375   /* Generate code which executes every time a symbol is popped from
4376   ** the stack while processing errors or while destroying the parser.
4377   ** (In other words, generate the %destructor actions)
4378   */
4379   if( lemp->tokendest ){
4380     int once = 1;
4381     for(i=0; i<lemp->nsymbol; i++){
4382       struct symbol *sp = lemp->symbols[i];
4383       if( sp==0 || sp->type!=TERMINAL ) continue;
4384       if( once ){
4385         fprintf(out, "      /* TERMINAL Destructor */\n"); lineno++;
4386         once = 0;
4387       }
4388       fprintf(out,"    case %d: /* %s */\n", sp->index, sp->name); lineno++;
4389     }
4390     for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
4391     if( i<lemp->nsymbol ){
4392       emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
4393       fprintf(out,"      break;\n"); lineno++;
4394     }
4395   }
4396   if( lemp->vardest ){
4397     struct symbol *dflt_sp = 0;
4398     int once = 1;
4399     for(i=0; i<lemp->nsymbol; i++){
4400       struct symbol *sp = lemp->symbols[i];
4401       if( sp==0 || sp->type==TERMINAL ||
4402           sp->index<=0 || sp->destructor!=0 ) continue;
4403       if( once ){
4404         fprintf(out, "      /* Default NON-TERMINAL Destructor */\n"); lineno++;
4405         once = 0;
4406       }
4407       fprintf(out,"    case %d: /* %s */\n", sp->index, sp->name); lineno++;
4408       dflt_sp = sp;
4409     }
4410     if( dflt_sp!=0 ){
4411       emit_destructor_code(out,dflt_sp,lemp,&lineno);
4412     }
4413     fprintf(out,"      break;\n"); lineno++;
4414   }
4415   for(i=0; i<lemp->nsymbol; i++){
4416     struct symbol *sp = lemp->symbols[i];
4417     if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
4418     if( sp->destLineno<0 ) continue;  /* Already emitted */
4419     fprintf(out,"    case %d: /* %s */\n", sp->index, sp->name); lineno++;
4420 
4421     /* Combine duplicate destructors into a single case */
4422     for(j=i+1; j<lemp->nsymbol; j++){
4423       struct symbol *sp2 = lemp->symbols[j];
4424       if( sp2 && sp2->type!=TERMINAL && sp2->destructor
4425           && sp2->dtnum==sp->dtnum
4426           && strcmp(sp->destructor,sp2->destructor)==0 ){
4427          fprintf(out,"    case %d: /* %s */\n",
4428                  sp2->index, sp2->name); lineno++;
4429          sp2->destLineno = -1;  /* Avoid emitting this destructor again */
4430       }
4431     }
4432 
4433     emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
4434     fprintf(out,"      break;\n"); lineno++;
4435   }
4436   tplt_xfer(lemp->name,in,out,&lineno);
4437 
4438   /* Generate code which executes whenever the parser stack overflows */
4439   tplt_print(out,lemp,lemp->overflow,&lineno);
4440   tplt_xfer(lemp->name,in,out,&lineno);
4441 
4442   /* Generate the table of rule information
4443   **
4444   ** Note: This code depends on the fact that rules are number
4445   ** sequentually beginning with 0.
4446   */
4447   for(rp=lemp->rule; rp; rp=rp->next){
4448     fprintf(out,"  { %d, %d },\n",rp->lhs->index,-rp->nrhs); lineno++;
4449   }
4450   tplt_xfer(lemp->name,in,out,&lineno);
4451 
4452   /* Generate code which execution during each REDUCE action */
4453   i = 0;
4454   for(rp=lemp->rule; rp; rp=rp->next){
4455     i += translate_code(lemp, rp);
4456   }
4457   if( i ){
4458     fprintf(out,"        YYMINORTYPE yylhsminor;\n"); lineno++;
4459   }
4460   /* First output rules other than the default: rule */
4461   for(rp=lemp->rule; rp; rp=rp->next){
4462     struct rule *rp2;               /* Other rules with the same action */
4463     if( rp->codeEmitted ) continue;
4464     if( rp->noCode ){
4465       /* No C code actions, so this will be part of the "default:" rule */
4466       continue;
4467     }
4468     fprintf(out,"      case %d: /* ", rp->iRule);
4469     writeRuleText(out, rp);
4470     fprintf(out, " */\n"); lineno++;
4471     for(rp2=rp->next; rp2; rp2=rp2->next){
4472       if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix
4473              && rp2->codeSuffix==rp->codeSuffix ){
4474         fprintf(out,"      case %d: /* ", rp2->iRule);
4475         writeRuleText(out, rp2);
4476         fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++;
4477         rp2->codeEmitted = 1;
4478       }
4479     }
4480     emit_code(out,rp,lemp,&lineno);
4481     fprintf(out,"        break;\n"); lineno++;
4482     rp->codeEmitted = 1;
4483   }
4484   /* Finally, output the default: rule.  We choose as the default: all
4485   ** empty actions. */
4486   fprintf(out,"      default:\n"); lineno++;
4487   for(rp=lemp->rule; rp; rp=rp->next){
4488     if( rp->codeEmitted ) continue;
4489     assert( rp->noCode );
4490     fprintf(out,"      /* (%d) ", rp->iRule);
4491     writeRuleText(out, rp);
4492     if( rp->doesReduce ){
4493       fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++;
4494     }else{
4495       fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n",
4496               rp->iRule); lineno++;
4497     }
4498   }
4499   fprintf(out,"        break;\n"); lineno++;
4500   tplt_xfer(lemp->name,in,out,&lineno);
4501 
4502   /* Generate code which executes if a parse fails */
4503   tplt_print(out,lemp,lemp->failure,&lineno);
4504   tplt_xfer(lemp->name,in,out,&lineno);
4505 
4506   /* Generate code which executes when a syntax error occurs */
4507   tplt_print(out,lemp,lemp->error,&lineno);
4508   tplt_xfer(lemp->name,in,out,&lineno);
4509 
4510   /* Generate code which executes when the parser accepts its input */
4511   tplt_print(out,lemp,lemp->accept,&lineno);
4512   tplt_xfer(lemp->name,in,out,&lineno);
4513 
4514   /* Append any addition code the user desires */
4515   tplt_print(out,lemp,lemp->extracode,&lineno);
4516 
4517   fclose(in);
4518   fclose(out);
4519   return;
4520 }
4521 
4522 /* Generate a header file for the parser */
ReportHeader(struct lemon * lemp)4523 void ReportHeader(struct lemon *lemp)
4524 {
4525   FILE *out, *in;
4526   const char *prefix;
4527   char line[LINESIZE];
4528   char pattern[LINESIZE];
4529   int i;
4530 
4531   if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
4532   else                    prefix = "";
4533   in = file_open(lemp,".h","rb");
4534   if( in ){
4535     int nextChar;
4536     for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
4537       lemon_sprintf(pattern,"#define %s%-30s %3d\n",
4538                     prefix,lemp->symbols[i]->name,i);
4539       if( strcmp(line,pattern) ) break;
4540     }
4541     nextChar = fgetc(in);
4542     fclose(in);
4543     if( i==lemp->nterminal && nextChar==EOF ){
4544       /* No change in the file.  Don't rewrite it. */
4545       return;
4546     }
4547   }
4548   out = file_open(lemp,".h","wb");
4549   if( out ){
4550     for(i=1; i<lemp->nterminal; i++){
4551       fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i);
4552     }
4553     fclose(out);
4554   }
4555   return;
4556 }
4557 
4558 /* Reduce the size of the action tables, if possible, by making use
4559 ** of defaults.
4560 **
4561 ** In this version, we take the most frequent REDUCE action and make
4562 ** it the default.  Except, there is no default if the wildcard token
4563 ** is a possible look-ahead.
4564 */
CompressTables(struct lemon * lemp)4565 void CompressTables(struct lemon *lemp)
4566 {
4567   struct state *stp;
4568   struct action *ap, *ap2, *nextap;
4569   struct rule *rp, *rp2, *rbest;
4570   int nbest, n;
4571   int i;
4572   int usesWildcard;
4573 
4574   for(i=0; i<lemp->nstate; i++){
4575     stp = lemp->sorted[i];
4576     nbest = 0;
4577     rbest = 0;
4578     usesWildcard = 0;
4579 
4580     for(ap=stp->ap; ap; ap=ap->next){
4581       if( ap->type==SHIFT && ap->sp==lemp->wildcard ){
4582         usesWildcard = 1;
4583       }
4584       if( ap->type!=REDUCE ) continue;
4585       rp = ap->x.rp;
4586       if( rp->lhsStart ) continue;
4587       if( rp==rbest ) continue;
4588       n = 1;
4589       for(ap2=ap->next; ap2; ap2=ap2->next){
4590         if( ap2->type!=REDUCE ) continue;
4591         rp2 = ap2->x.rp;
4592         if( rp2==rbest ) continue;
4593         if( rp2==rp ) n++;
4594       }
4595       if( n>nbest ){
4596         nbest = n;
4597         rbest = rp;
4598       }
4599     }
4600 
4601     /* Do not make a default if the number of rules to default
4602     ** is not at least 1 or if the wildcard token is a possible
4603     ** lookahead.
4604     */
4605     if( nbest<1 || usesWildcard ) continue;
4606 
4607 
4608     /* Combine matching REDUCE actions into a single default */
4609     for(ap=stp->ap; ap; ap=ap->next){
4610       if( ap->type==REDUCE && ap->x.rp==rbest ) break;
4611     }
4612     assert( ap );
4613     ap->sp = Symbol_new("{default}");
4614     for(ap=ap->next; ap; ap=ap->next){
4615       if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
4616     }
4617     stp->ap = Action_sort(stp->ap);
4618 
4619     for(ap=stp->ap; ap; ap=ap->next){
4620       if( ap->type==SHIFT ) break;
4621       if( ap->type==REDUCE && ap->x.rp!=rbest ) break;
4622     }
4623     if( ap==0 ){
4624       stp->autoReduce = 1;
4625       stp->pDfltReduce = rbest;
4626     }
4627   }
4628 
4629   /* Make a second pass over all states and actions.  Convert
4630   ** every action that is a SHIFT to an autoReduce state into
4631   ** a SHIFTREDUCE action.
4632   */
4633   for(i=0; i<lemp->nstate; i++){
4634     stp = lemp->sorted[i];
4635     for(ap=stp->ap; ap; ap=ap->next){
4636       struct state *pNextState;
4637       if( ap->type!=SHIFT ) continue;
4638       pNextState = ap->x.stp;
4639       if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){
4640         ap->type = SHIFTREDUCE;
4641         ap->x.rp = pNextState->pDfltReduce;
4642       }
4643     }
4644   }
4645 
4646   /* If a SHIFTREDUCE action specifies a rule that has a single RHS term
4647   ** (meaning that the SHIFTREDUCE will land back in the state where it
4648   ** started) and if there is no C-code associated with the reduce action,
4649   ** then we can go ahead and convert the action to be the same as the
4650   ** action for the RHS of the rule.
4651   */
4652   for(i=0; i<lemp->nstate; i++){
4653     stp = lemp->sorted[i];
4654     for(ap=stp->ap; ap; ap=nextap){
4655       nextap = ap->next;
4656       if( ap->type!=SHIFTREDUCE ) continue;
4657       rp = ap->x.rp;
4658       if( rp->noCode==0 ) continue;
4659       if( rp->nrhs!=1 ) continue;
4660 #if 1
4661       /* Only apply this optimization to non-terminals.  It would be OK to
4662       ** apply it to terminal symbols too, but that makes the parser tables
4663       ** larger. */
4664       if( ap->sp->index<lemp->nterminal ) continue;
4665 #endif
4666       /* If we reach this point, it means the optimization can be applied */
4667       nextap = ap;
4668       for(ap2=stp->ap; ap2 && (ap2==ap || ap2->sp!=rp->lhs); ap2=ap2->next){}
4669       assert( ap2!=0 );
4670       ap->spOpt = ap2->sp;
4671       ap->type = ap2->type;
4672       ap->x = ap2->x;
4673     }
4674   }
4675 }
4676 
4677 
4678 /*
4679 ** Compare two states for sorting purposes.  The smaller state is the
4680 ** one with the most non-terminal actions.  If they have the same number
4681 ** of non-terminal actions, then the smaller is the one with the most
4682 ** token actions.
4683 */
stateResortCompare(const void * a,const void * b)4684 static int stateResortCompare(const void *a, const void *b){
4685   const struct state *pA = *(const struct state**)a;
4686   const struct state *pB = *(const struct state**)b;
4687   int n;
4688 
4689   n = pB->nNtAct - pA->nNtAct;
4690   if( n==0 ){
4691     n = pB->nTknAct - pA->nTknAct;
4692     if( n==0 ){
4693       n = pB->statenum - pA->statenum;
4694     }
4695   }
4696   assert( n!=0 );
4697   return n;
4698 }
4699 
4700 
4701 /*
4702 ** Renumber and resort states so that states with fewer choices
4703 ** occur at the end.  Except, keep state 0 as the first state.
4704 */
ResortStates(struct lemon * lemp)4705 void ResortStates(struct lemon *lemp)
4706 {
4707   int i;
4708   struct state *stp;
4709   struct action *ap;
4710 
4711   for(i=0; i<lemp->nstate; i++){
4712     stp = lemp->sorted[i];
4713     stp->nTknAct = stp->nNtAct = 0;
4714     stp->iDfltReduce = lemp->nrule;  /* Init dflt action to "syntax error" */
4715     stp->iTknOfst = NO_OFFSET;
4716     stp->iNtOfst = NO_OFFSET;
4717     for(ap=stp->ap; ap; ap=ap->next){
4718       int iAction = compute_action(lemp,ap);
4719       if( iAction>=0 ){
4720         if( ap->sp->index<lemp->nterminal ){
4721           stp->nTknAct++;
4722         }else if( ap->sp->index<lemp->nsymbol ){
4723           stp->nNtAct++;
4724         }else{
4725           assert( stp->autoReduce==0 || stp->pDfltReduce==ap->x.rp );
4726           stp->iDfltReduce = iAction - lemp->nstate - lemp->nrule;
4727         }
4728       }
4729     }
4730   }
4731   qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]),
4732         stateResortCompare);
4733   for(i=0; i<lemp->nstate; i++){
4734     lemp->sorted[i]->statenum = i;
4735   }
4736   lemp->nxstate = lemp->nstate;
4737   while( lemp->nxstate>1 && lemp->sorted[lemp->nxstate-1]->autoReduce ){
4738     lemp->nxstate--;
4739   }
4740 }
4741 
4742 
4743 /***************** From the file "set.c" ************************************/
4744 /*
4745 ** Set manipulation routines for the LEMON parser generator.
4746 */
4747 
4748 static int size = 0;
4749 
4750 /* Set the set size */
SetSize(int n)4751 void SetSize(int n)
4752 {
4753   size = n+1;
4754 }
4755 
4756 /* Allocate a new set */
SetNew(void)4757 char *SetNew(void){
4758   char *s;
4759   s = (char*)calloc( size, 1);
4760   if( s==0 ){
4761     extern void memory_error();
4762     memory_error();
4763   }
4764   return s;
4765 }
4766 
4767 /* Deallocate a set */
SetFree(char * s)4768 void SetFree(char *s)
4769 {
4770   free(s);
4771 }
4772 
4773 /* Add a new element to the set.  Return TRUE if the element was added
4774 ** and FALSE if it was already there. */
SetAdd(char * s,int e)4775 int SetAdd(char *s, int e)
4776 {
4777   int rv;
4778   assert( e>=0 && e<size );
4779   rv = s[e];
4780   s[e] = 1;
4781   return !rv;
4782 }
4783 
4784 /* Add every element of s2 to s1.  Return TRUE if s1 changes. */
SetUnion(char * s1,char * s2)4785 int SetUnion(char *s1, char *s2)
4786 {
4787   int i, progress;
4788   progress = 0;
4789   for(i=0; i<size; i++){
4790     if( s2[i]==0 ) continue;
4791     if( s1[i]==0 ){
4792       progress = 1;
4793       s1[i] = 1;
4794     }
4795   }
4796   return progress;
4797 }
4798 /********************** From the file "table.c" ****************************/
4799 /*
4800 ** All code in this file has been automatically generated
4801 ** from a specification in the file
4802 **              "table.q"
4803 ** by the associative array code building program "aagen".
4804 ** Do not edit this file!  Instead, edit the specification
4805 ** file, then rerun aagen.
4806 */
4807 /*
4808 ** Code for processing tables in the LEMON parser generator.
4809 */
4810 
strhash(const char * x)4811 PRIVATE unsigned strhash(const char *x)
4812 {
4813   unsigned h = 0;
4814   while( *x ) h = h*13 + *(x++);
4815   return h;
4816 }
4817 
4818 /* Works like strdup, sort of.  Save a string in malloced memory, but
4819 ** keep strings in a table so that the same string is not in more
4820 ** than one place.
4821 */
Strsafe(const char * y)4822 const char *Strsafe(const char *y)
4823 {
4824   const char *z;
4825   char *cpy;
4826 
4827   if( y==0 ) return 0;
4828   z = Strsafe_find(y);
4829   if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){
4830     lemon_strcpy(cpy,y);
4831     z = cpy;
4832     Strsafe_insert(z);
4833   }
4834   MemoryCheck(z);
4835   return z;
4836 }
4837 
4838 /* There is one instance of the following structure for each
4839 ** associative array of type "x1".
4840 */
4841 struct s_x1 {
4842   int size;               /* The number of available slots. */
4843                           /*   Must be a power of 2 greater than or */
4844                           /*   equal to 1 */
4845   int count;              /* Number of currently slots filled */
4846   struct s_x1node *tbl;  /* The data stored here */
4847   struct s_x1node **ht;  /* Hash table for lookups */
4848 };
4849 
4850 /* There is one instance of this structure for every data element
4851 ** in an associative array of type "x1".
4852 */
4853 typedef struct s_x1node {
4854   const char *data;        /* The data */
4855   struct s_x1node *next;   /* Next entry with the same hash */
4856   struct s_x1node **from;  /* Previous link */
4857 } x1node;
4858 
4859 /* There is only one instance of the array, which is the following */
4860 static struct s_x1 *x1a;
4861 
4862 /* Allocate a new associative array */
Strsafe_init(void)4863 void Strsafe_init(void){
4864   if( x1a ) return;
4865   x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
4866   if( x1a ){
4867     x1a->size = 1024;
4868     x1a->count = 0;
4869     x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*));
4870     if( x1a->tbl==0 ){
4871       free(x1a);
4872       x1a = 0;
4873     }else{
4874       int i;
4875       x1a->ht = (x1node**)&(x1a->tbl[1024]);
4876       for(i=0; i<1024; i++) x1a->ht[i] = 0;
4877     }
4878   }
4879 }
4880 /* Insert a new record into the array.  Return TRUE if successful.
4881 ** Prior data with the same key is NOT overwritten */
Strsafe_insert(const char * data)4882 int Strsafe_insert(const char *data)
4883 {
4884   x1node *np;
4885   unsigned h;
4886   unsigned ph;
4887 
4888   if( x1a==0 ) return 0;
4889   ph = strhash(data);
4890   h = ph & (x1a->size-1);
4891   np = x1a->ht[h];
4892   while( np ){
4893     if( strcmp(np->data,data)==0 ){
4894       /* An existing entry with the same key is found. */
4895       /* Fail because overwrite is not allows. */
4896       return 0;
4897     }
4898     np = np->next;
4899   }
4900   if( x1a->count>=x1a->size ){
4901     /* Need to make the hash table bigger */
4902     int i,arrSize;
4903     struct s_x1 array;
4904     array.size = arrSize = x1a->size*2;
4905     array.count = x1a->count;
4906     array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*));
4907     if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
4908     array.ht = (x1node**)&(array.tbl[arrSize]);
4909     for(i=0; i<arrSize; i++) array.ht[i] = 0;
4910     for(i=0; i<x1a->count; i++){
4911       x1node *oldnp, *newnp;
4912       oldnp = &(x1a->tbl[i]);
4913       h = strhash(oldnp->data) & (arrSize-1);
4914       newnp = &(array.tbl[i]);
4915       if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4916       newnp->next = array.ht[h];
4917       newnp->data = oldnp->data;
4918       newnp->from = &(array.ht[h]);
4919       array.ht[h] = newnp;
4920     }
4921     free(x1a->tbl);
4922     *x1a = array;
4923   }
4924   /* Insert the new data */
4925   h = ph & (x1a->size-1);
4926   np = &(x1a->tbl[x1a->count++]);
4927   np->data = data;
4928   if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
4929   np->next = x1a->ht[h];
4930   x1a->ht[h] = np;
4931   np->from = &(x1a->ht[h]);
4932   return 1;
4933 }
4934 
4935 /* Return a pointer to data assigned to the given key.  Return NULL
4936 ** if no such key. */
Strsafe_find(const char * key)4937 const char *Strsafe_find(const char *key)
4938 {
4939   unsigned h;
4940   x1node *np;
4941 
4942   if( x1a==0 ) return 0;
4943   h = strhash(key) & (x1a->size-1);
4944   np = x1a->ht[h];
4945   while( np ){
4946     if( strcmp(np->data,key)==0 ) break;
4947     np = np->next;
4948   }
4949   return np ? np->data : 0;
4950 }
4951 
4952 /* Return a pointer to the (terminal or nonterminal) symbol "x".
4953 ** Create a new symbol if this is the first time "x" has been seen.
4954 */
Symbol_new(const char * x)4955 struct symbol *Symbol_new(const char *x)
4956 {
4957   struct symbol *sp;
4958 
4959   sp = Symbol_find(x);
4960   if( sp==0 ){
4961     sp = (struct symbol *)calloc(1, sizeof(struct symbol) );
4962     MemoryCheck(sp);
4963     sp->name = Strsafe(x);
4964     sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL;
4965     sp->rule = 0;
4966     sp->fallback = 0;
4967     sp->prec = -1;
4968     sp->assoc = UNK;
4969     sp->firstset = 0;
4970     sp->lambda = LEMON_FALSE;
4971     sp->destructor = 0;
4972     sp->destLineno = 0;
4973     sp->datatype = 0;
4974     sp->useCnt = 0;
4975     Symbol_insert(sp,sp->name);
4976   }
4977   sp->useCnt++;
4978   return sp;
4979 }
4980 
4981 /* Compare two symbols for sorting purposes.  Return negative,
4982 ** zero, or positive if a is less then, equal to, or greater
4983 ** than b.
4984 **
4985 ** Symbols that begin with upper case letters (terminals or tokens)
4986 ** must sort before symbols that begin with lower case letters
4987 ** (non-terminals).  And MULTITERMINAL symbols (created using the
4988 ** %token_class directive) must sort at the very end. Other than
4989 ** that, the order does not matter.
4990 **
4991 ** We find experimentally that leaving the symbols in their original
4992 ** order (the order they appeared in the grammar file) gives the
4993 ** smallest parser tables in SQLite.
4994 */
Symbolcmpp(const void * _a,const void * _b)4995 int Symbolcmpp(const void *_a, const void *_b)
4996 {
4997   const struct symbol *a = *(const struct symbol **) _a;
4998   const struct symbol *b = *(const struct symbol **) _b;
4999   int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1;
5000   int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1;
5001   return i1==i2 ? a->index - b->index : i1 - i2;
5002 }
5003 
5004 /* There is one instance of the following structure for each
5005 ** associative array of type "x2".
5006 */
5007 struct s_x2 {
5008   int size;               /* The number of available slots. */
5009                           /*   Must be a power of 2 greater than or */
5010                           /*   equal to 1 */
5011   int count;              /* Number of currently slots filled */
5012   struct s_x2node *tbl;  /* The data stored here */
5013   struct s_x2node **ht;  /* Hash table for lookups */
5014 };
5015 
5016 /* There is one instance of this structure for every data element
5017 ** in an associative array of type "x2".
5018 */
5019 typedef struct s_x2node {
5020   struct symbol *data;     /* The data */
5021   const char *key;         /* The key */
5022   struct s_x2node *next;   /* Next entry with the same hash */
5023   struct s_x2node **from;  /* Previous link */
5024 } x2node;
5025 
5026 /* There is only one instance of the array, which is the following */
5027 static struct s_x2 *x2a;
5028 
5029 /* Allocate a new associative array */
Symbol_init(void)5030 void Symbol_init(void){
5031   if( x2a ) return;
5032   x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
5033   if( x2a ){
5034     x2a->size = 128;
5035     x2a->count = 0;
5036     x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*));
5037     if( x2a->tbl==0 ){
5038       free(x2a);
5039       x2a = 0;
5040     }else{
5041       int i;
5042       x2a->ht = (x2node**)&(x2a->tbl[128]);
5043       for(i=0; i<128; i++) x2a->ht[i] = 0;
5044     }
5045   }
5046 }
5047 /* Insert a new record into the array.  Return TRUE if successful.
5048 ** Prior data with the same key is NOT overwritten */
Symbol_insert(struct symbol * data,const char * key)5049 int Symbol_insert(struct symbol *data, const char *key)
5050 {
5051   x2node *np;
5052   unsigned h;
5053   unsigned ph;
5054 
5055   if( x2a==0 ) return 0;
5056   ph = strhash(key);
5057   h = ph & (x2a->size-1);
5058   np = x2a->ht[h];
5059   while( np ){
5060     if( strcmp(np->key,key)==0 ){
5061       /* An existing entry with the same key is found. */
5062       /* Fail because overwrite is not allows. */
5063       return 0;
5064     }
5065     np = np->next;
5066   }
5067   if( x2a->count>=x2a->size ){
5068     /* Need to make the hash table bigger */
5069     int i,arrSize;
5070     struct s_x2 array;
5071     array.size = arrSize = x2a->size*2;
5072     array.count = x2a->count;
5073     array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*));
5074     if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
5075     array.ht = (x2node**)&(array.tbl[arrSize]);
5076     for(i=0; i<arrSize; i++) array.ht[i] = 0;
5077     for(i=0; i<x2a->count; i++){
5078       x2node *oldnp, *newnp;
5079       oldnp = &(x2a->tbl[i]);
5080       h = strhash(oldnp->key) & (arrSize-1);
5081       newnp = &(array.tbl[i]);
5082       if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
5083       newnp->next = array.ht[h];
5084       newnp->key = oldnp->key;
5085       newnp->data = oldnp->data;
5086       newnp->from = &(array.ht[h]);
5087       array.ht[h] = newnp;
5088     }
5089     free(x2a->tbl);
5090     *x2a = array;
5091   }
5092   /* Insert the new data */
5093   h = ph & (x2a->size-1);
5094   np = &(x2a->tbl[x2a->count++]);
5095   np->key = key;
5096   np->data = data;
5097   if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
5098   np->next = x2a->ht[h];
5099   x2a->ht[h] = np;
5100   np->from = &(x2a->ht[h]);
5101   return 1;
5102 }
5103 
5104 /* Return a pointer to data assigned to the given key.  Return NULL
5105 ** if no such key. */
Symbol_find(const char * key)5106 struct symbol *Symbol_find(const char *key)
5107 {
5108   unsigned h;
5109   x2node *np;
5110 
5111   if( x2a==0 ) return 0;
5112   h = strhash(key) & (x2a->size-1);
5113   np = x2a->ht[h];
5114   while( np ){
5115     if( strcmp(np->key,key)==0 ) break;
5116     np = np->next;
5117   }
5118   return np ? np->data : 0;
5119 }
5120 
5121 /* Return the n-th data.  Return NULL if n is out of range. */
Symbol_Nth(int n)5122 struct symbol *Symbol_Nth(int n)
5123 {
5124   struct symbol *data;
5125   if( x2a && n>0 && n<=x2a->count ){
5126     data = x2a->tbl[n-1].data;
5127   }else{
5128     data = 0;
5129   }
5130   return data;
5131 }
5132 
5133 /* Return the size of the array */
Symbol_count()5134 int Symbol_count()
5135 {
5136   return x2a ? x2a->count : 0;
5137 }
5138 
5139 /* Return an array of pointers to all data in the table.
5140 ** The array is obtained from malloc.  Return NULL if memory allocation
5141 ** problems, or if the array is empty. */
Symbol_arrayof()5142 struct symbol **Symbol_arrayof()
5143 {
5144   struct symbol **array;
5145   int i,arrSize;
5146   if( x2a==0 ) return 0;
5147   arrSize = x2a->count;
5148   array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *));
5149   if( array ){
5150     for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data;
5151   }
5152   return array;
5153 }
5154 
5155 /* Compare two configurations */
Configcmp(const char * _a,const char * _b)5156 int Configcmp(const char *_a,const char *_b)
5157 {
5158   const struct config *a = (struct config *) _a;
5159   const struct config *b = (struct config *) _b;
5160   int x;
5161   x = a->rp->index - b->rp->index;
5162   if( x==0 ) x = a->dot - b->dot;
5163   return x;
5164 }
5165 
5166 /* Compare two states */
statecmp(struct config * a,struct config * b)5167 PRIVATE int statecmp(struct config *a, struct config *b)
5168 {
5169   int rc;
5170   for(rc=0; rc==0 && a && b;  a=a->bp, b=b->bp){
5171     rc = a->rp->index - b->rp->index;
5172     if( rc==0 ) rc = a->dot - b->dot;
5173   }
5174   if( rc==0 ){
5175     if( a ) rc = 1;
5176     if( b ) rc = -1;
5177   }
5178   return rc;
5179 }
5180 
5181 /* Hash a state */
statehash(struct config * a)5182 PRIVATE unsigned statehash(struct config *a)
5183 {
5184   unsigned h=0;
5185   while( a ){
5186     h = h*571 + a->rp->index*37 + a->dot;
5187     a = a->bp;
5188   }
5189   return h;
5190 }
5191 
5192 /* Allocate a new state structure */
State_new()5193 struct state *State_new()
5194 {
5195   struct state *newstate;
5196   newstate = (struct state *)calloc(1, sizeof(struct state) );
5197   MemoryCheck(newstate);
5198   return newstate;
5199 }
5200 
5201 /* There is one instance of the following structure for each
5202 ** associative array of type "x3".
5203 */
5204 struct s_x3 {
5205   int size;               /* The number of available slots. */
5206                           /*   Must be a power of 2 greater than or */
5207                           /*   equal to 1 */
5208   int count;              /* Number of currently slots filled */
5209   struct s_x3node *tbl;  /* The data stored here */
5210   struct s_x3node **ht;  /* Hash table for lookups */
5211 };
5212 
5213 /* There is one instance of this structure for every data element
5214 ** in an associative array of type "x3".
5215 */
5216 typedef struct s_x3node {
5217   struct state *data;                  /* The data */
5218   struct config *key;                   /* The key */
5219   struct s_x3node *next;   /* Next entry with the same hash */
5220   struct s_x3node **from;  /* Previous link */
5221 } x3node;
5222 
5223 /* There is only one instance of the array, which is the following */
5224 static struct s_x3 *x3a;
5225 
5226 /* Allocate a new associative array */
State_init(void)5227 void State_init(void){
5228   if( x3a ) return;
5229   x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
5230   if( x3a ){
5231     x3a->size = 128;
5232     x3a->count = 0;
5233     x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*));
5234     if( x3a->tbl==0 ){
5235       free(x3a);
5236       x3a = 0;
5237     }else{
5238       int i;
5239       x3a->ht = (x3node**)&(x3a->tbl[128]);
5240       for(i=0; i<128; i++) x3a->ht[i] = 0;
5241     }
5242   }
5243 }
5244 /* Insert a new record into the array.  Return TRUE if successful.
5245 ** Prior data with the same key is NOT overwritten */
State_insert(struct state * data,struct config * key)5246 int State_insert(struct state *data, struct config *key)
5247 {
5248   x3node *np;
5249   unsigned h;
5250   unsigned ph;
5251 
5252   if( x3a==0 ) return 0;
5253   ph = statehash(key);
5254   h = ph & (x3a->size-1);
5255   np = x3a->ht[h];
5256   while( np ){
5257     if( statecmp(np->key,key)==0 ){
5258       /* An existing entry with the same key is found. */
5259       /* Fail because overwrite is not allows. */
5260       return 0;
5261     }
5262     np = np->next;
5263   }
5264   if( x3a->count>=x3a->size ){
5265     /* Need to make the hash table bigger */
5266     int i,arrSize;
5267     struct s_x3 array;
5268     array.size = arrSize = x3a->size*2;
5269     array.count = x3a->count;
5270     array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*));
5271     if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
5272     array.ht = (x3node**)&(array.tbl[arrSize]);
5273     for(i=0; i<arrSize; i++) array.ht[i] = 0;
5274     for(i=0; i<x3a->count; i++){
5275       x3node *oldnp, *newnp;
5276       oldnp = &(x3a->tbl[i]);
5277       h = statehash(oldnp->key) & (arrSize-1);
5278       newnp = &(array.tbl[i]);
5279       if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
5280       newnp->next = array.ht[h];
5281       newnp->key = oldnp->key;
5282       newnp->data = oldnp->data;
5283       newnp->from = &(array.ht[h]);
5284       array.ht[h] = newnp;
5285     }
5286     free(x3a->tbl);
5287     *x3a = array;
5288   }
5289   /* Insert the new data */
5290   h = ph & (x3a->size-1);
5291   np = &(x3a->tbl[x3a->count++]);
5292   np->key = key;
5293   np->data = data;
5294   if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
5295   np->next = x3a->ht[h];
5296   x3a->ht[h] = np;
5297   np->from = &(x3a->ht[h]);
5298   return 1;
5299 }
5300 
5301 /* Return a pointer to data assigned to the given key.  Return NULL
5302 ** if no such key. */
State_find(struct config * key)5303 struct state *State_find(struct config *key)
5304 {
5305   unsigned h;
5306   x3node *np;
5307 
5308   if( x3a==0 ) return 0;
5309   h = statehash(key) & (x3a->size-1);
5310   np = x3a->ht[h];
5311   while( np ){
5312     if( statecmp(np->key,key)==0 ) break;
5313     np = np->next;
5314   }
5315   return np ? np->data : 0;
5316 }
5317 
5318 /* Return an array of pointers to all data in the table.
5319 ** The array is obtained from malloc.  Return NULL if memory allocation
5320 ** problems, or if the array is empty. */
State_arrayof(void)5321 struct state **State_arrayof(void)
5322 {
5323   struct state **array;
5324   int i,arrSize;
5325   if( x3a==0 ) return 0;
5326   arrSize = x3a->count;
5327   array = (struct state **)calloc(arrSize, sizeof(struct state *));
5328   if( array ){
5329     for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data;
5330   }
5331   return array;
5332 }
5333 
5334 /* Hash a configuration */
confighash(struct config * a)5335 PRIVATE unsigned confighash(struct config *a)
5336 {
5337   unsigned h=0;
5338   h = h*571 + a->rp->index*37 + a->dot;
5339   return h;
5340 }
5341 
5342 /* There is one instance of the following structure for each
5343 ** associative array of type "x4".
5344 */
5345 struct s_x4 {
5346   int size;               /* The number of available slots. */
5347                           /*   Must be a power of 2 greater than or */
5348                           /*   equal to 1 */
5349   int count;              /* Number of currently slots filled */
5350   struct s_x4node *tbl;  /* The data stored here */
5351   struct s_x4node **ht;  /* Hash table for lookups */
5352 };
5353 
5354 /* There is one instance of this structure for every data element
5355 ** in an associative array of type "x4".
5356 */
5357 typedef struct s_x4node {
5358   struct config *data;                  /* The data */
5359   struct s_x4node *next;   /* Next entry with the same hash */
5360   struct s_x4node **from;  /* Previous link */
5361 } x4node;
5362 
5363 /* There is only one instance of the array, which is the following */
5364 static struct s_x4 *x4a;
5365 
5366 /* Allocate a new associative array */
Configtable_init(void)5367 void Configtable_init(void){
5368   if( x4a ) return;
5369   x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
5370   if( x4a ){
5371     x4a->size = 64;
5372     x4a->count = 0;
5373     x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*));
5374     if( x4a->tbl==0 ){
5375       free(x4a);
5376       x4a = 0;
5377     }else{
5378       int i;
5379       x4a->ht = (x4node**)&(x4a->tbl[64]);
5380       for(i=0; i<64; i++) x4a->ht[i] = 0;
5381     }
5382   }
5383 }
5384 /* Insert a new record into the array.  Return TRUE if successful.
5385 ** Prior data with the same key is NOT overwritten */
Configtable_insert(struct config * data)5386 int Configtable_insert(struct config *data)
5387 {
5388   x4node *np;
5389   unsigned h;
5390   unsigned ph;
5391 
5392   if( x4a==0 ) return 0;
5393   ph = confighash(data);
5394   h = ph & (x4a->size-1);
5395   np = x4a->ht[h];
5396   while( np ){
5397     if( Configcmp((const char *) np->data,(const char *) data)==0 ){
5398       /* An existing entry with the same key is found. */
5399       /* Fail because overwrite is not allows. */
5400       return 0;
5401     }
5402     np = np->next;
5403   }
5404   if( x4a->count>=x4a->size ){
5405     /* Need to make the hash table bigger */
5406     int i,arrSize;
5407     struct s_x4 array;
5408     array.size = arrSize = x4a->size*2;
5409     array.count = x4a->count;
5410     array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*));
5411     if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
5412     array.ht = (x4node**)&(array.tbl[arrSize]);
5413     for(i=0; i<arrSize; i++) array.ht[i] = 0;
5414     for(i=0; i<x4a->count; i++){
5415       x4node *oldnp, *newnp;
5416       oldnp = &(x4a->tbl[i]);
5417       h = confighash(oldnp->data) & (arrSize-1);
5418       newnp = &(array.tbl[i]);
5419       if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
5420       newnp->next = array.ht[h];
5421       newnp->data = oldnp->data;
5422       newnp->from = &(array.ht[h]);
5423       array.ht[h] = newnp;
5424     }
5425     free(x4a->tbl);
5426     *x4a = array;
5427   }
5428   /* Insert the new data */
5429   h = ph & (x4a->size-1);
5430   np = &(x4a->tbl[x4a->count++]);
5431   np->data = data;
5432   if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
5433   np->next = x4a->ht[h];
5434   x4a->ht[h] = np;
5435   np->from = &(x4a->ht[h]);
5436   return 1;
5437 }
5438 
5439 /* Return a pointer to data assigned to the given key.  Return NULL
5440 ** if no such key. */
Configtable_find(struct config * key)5441 struct config *Configtable_find(struct config *key)
5442 {
5443   int h;
5444   x4node *np;
5445 
5446   if( x4a==0 ) return 0;
5447   h = confighash(key) & (x4a->size-1);
5448   np = x4a->ht[h];
5449   while( np ){
5450     if( Configcmp((const char *) np->data,(const char *) key)==0 ) break;
5451     np = np->next;
5452   }
5453   return np ? np->data : 0;
5454 }
5455 
5456 /* Remove all data from the table.  Pass each data to the function "f"
5457 ** as it is removed.  ("f" may be null to avoid this step.) */
Configtable_clear(int (* f)(struct config *))5458 void Configtable_clear(int(*f)(struct config *))
5459 {
5460   int i;
5461   if( x4a==0 || x4a->count==0 ) return;
5462   if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
5463   for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
5464   x4a->count = 0;
5465   return;
5466 }
5467