[lemon] standalone; remove #include "first.h"
[lighttpd.git] / src / lemon.c
blobaa86b09b968949b3cd00e6887d8b5d53a63626d9
1 #ifndef _GNU_SOURCE
2 #define _GNU_SOURCE
3 #endif
5 /*
6 ** This file contains all sources (including headers) to the LEMON
7 ** LALR(1) parser generator. The sources have been combined into a
8 ** single file to make it easy to include LEMON in the source tree
9 ** and Makefile of another program.
11 ** The author of this program disclaims copyright.
13 #include <stdio.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <stdlib.h>
18 #include <inttypes.h>
19 #include <unistd.h> /* access() */
21 #define UNUSED(x) ( (void)(x) )
23 #ifndef __WIN32__
24 # if defined(_WIN32) || defined(WIN32)
25 # define __WIN32__
26 # endif
27 #endif
29 #if __GNUC__ > 2
30 #define NORETURN __attribute__ ((__noreturn__))
31 #else
32 #define NORETURN
33 #endif
35 /* #define PRIVATE static */
36 #define PRIVATE static
38 #ifdef TEST
39 #define MAXRHS 5 /* Set low to exercise exception code */
40 #else
41 #define MAXRHS 1000
42 #endif
44 void *msort(void *list, void **next, int(*cmp)(void *, void *));
46 static void memory_error() NORETURN;
48 /******** From the file "action.h" *************************************/
49 struct action *Action_new();
50 struct action *Action_sort();
51 void Action_add();
53 /********* From the file "assert.h" ************************************/
54 void myassert() NORETURN;
55 #ifndef NDEBUG
56 # define assert(X) if(!(X))myassert(__FILE__,__LINE__)
57 #else
58 # define assert(X)
59 #endif
61 /********** From the file "build.h" ************************************/
62 void FindRulePrecedences();
63 void FindFirstSets();
64 void FindStates();
65 void FindLinks();
66 void FindFollowSets();
67 void FindActions();
69 /********* From the file "configlist.h" *********************************/
70 void Configlist_init(/* void */);
71 struct config *Configlist_add(/* struct rule *, int */);
72 struct config *Configlist_addbasis(/* struct rule *, int */);
73 void Configlist_closure(/* void */);
74 void Configlist_sort(/* void */);
75 void Configlist_sortbasis(/* void */);
76 struct config *Configlist_return(/* void */);
77 struct config *Configlist_basis(/* void */);
78 void Configlist_eat(/* struct config * */);
79 void Configlist_reset(/* void */);
81 /********* From the file "error.h" ***************************************/
82 void ErrorMsg(const char *, int,const char *, ...);
84 /****** From the file "option.h" ******************************************/
85 struct s_options {
86 enum { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
87 OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type;
88 char *label;
89 void *arg;
90 const char *message;
92 int OptInit(/* char**,struct s_options*,FILE* */);
93 int OptNArgs(/* void */);
94 char *OptArg(/* int */);
95 void OptErr(/* int */);
96 void OptPrint(/* void */);
98 /******** From the file "parse.h" *****************************************/
99 void Parse(/* struct lemon *lemp */);
101 /********* From the file "plink.h" ***************************************/
102 struct plink *Plink_new(/* void */);
103 void Plink_add(/* struct plink **, struct config * */);
104 void Plink_copy(/* struct plink **, struct plink * */);
105 void Plink_delete(/* struct plink * */);
107 /********** From the file "report.h" *************************************/
108 void Reprint(/* struct lemon * */);
109 void ReportOutput(/* struct lemon * */);
110 void ReportTable(/* struct lemon * */);
111 void ReportHeader(/* struct lemon * */);
112 void CompressTables(/* struct lemon * */);
114 /********** From the file "set.h" ****************************************/
115 void SetSize(/* int N */); /* All sets will be of size N */
116 char *SetNew(/* void */); /* A new set for element 0..N */
117 void SetFree(/* char* */); /* Deallocate a set */
119 int SetAdd(/* char*,int */); /* Add element to a set */
120 int SetUnion(/* char *A,char *B */); /* A <- A U B, thru element N */
122 #define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
124 /********** From the file "struct.h" *************************************/
126 ** Principal data structures for the LEMON parser generator.
129 typedef enum {Bo_FALSE=0, Bo_TRUE} Boolean;
131 /* Symbols (terminals and nonterminals) of the grammar are stored
132 ** in the following: */
133 struct symbol {
134 char *name; /* Name of the symbol */
135 int index; /* Index number for this symbol */
136 enum {
137 TERMINAL,
138 NONTERMINAL
139 } type; /* Symbols are all either TERMINALS or NTs */
140 struct rule *rule; /* Linked list of rules of this (if an NT) */
141 struct symbol *fallback; /* fallback token in case this token doesn't parse */
142 int prec; /* Precedence if defined (-1 otherwise) */
143 enum e_assoc {
144 LEFT,
145 RIGHT,
146 NONE,
148 } assoc; /* Associativity if predecence is defined */
149 char *firstset; /* First-set for all rules of this symbol */
150 Boolean lambda; /* True if NT and can generate an empty string */
151 char *destructor; /* Code which executes whenever this symbol is
152 ** popped from the stack during error processing */
153 int destructorln; /* Line number of destructor code */
154 char *datatype; /* The data type of information held by this
155 ** object. Only used if type==NONTERMINAL */
156 int dtnum; /* The data type number. In the parser, the value
157 ** stack is a union. The .yy%d element of this
158 ** union is the correct data type for this object */
161 /* Each production rule in the grammar is stored in the following
162 ** structure. */
163 struct rule {
164 struct symbol *lhs; /* Left-hand side of the rule */
165 char *lhsalias; /* Alias for the LHS (NULL if none) */
166 int ruleline; /* Line number for the rule */
167 int nrhs; /* Number of RHS symbols */
168 struct symbol **rhs; /* The RHS symbols */
169 char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
170 int line; /* Line number at which code begins */
171 char *code; /* The code executed when this rule is reduced */
172 struct symbol *precsym; /* Precedence symbol for this rule */
173 int index; /* An index number for this rule */
174 Boolean canReduce; /* True if this rule is ever reduced */
175 struct rule *nextlhs; /* Next rule with the same LHS */
176 struct rule *next; /* Next rule in the global list */
179 /* A configuration is a production rule of the grammar together with
180 ** a mark (dot) showing how much of that rule has been processed so far.
181 ** Configurations also contain a follow-set which is a list of terminal
182 ** symbols which are allowed to immediately follow the end of the rule.
183 ** Every configuration is recorded as an instance of the following: */
184 struct config {
185 struct rule *rp; /* The rule upon which the configuration is based */
186 int dot; /* The parse point */
187 char *fws; /* Follow-set for this configuration only */
188 struct plink *fplp; /* Follow-set forward propagation links */
189 struct plink *bplp; /* Follow-set backwards propagation links */
190 struct state *stp; /* Pointer to state which contains this */
191 enum {
192 COMPLETE, /* The status is used during followset and */
193 INCOMPLETE /* shift computations */
194 } status;
195 struct config *next; /* Next configuration in the state */
196 struct config *bp; /* The next basis configuration */
199 /* Every shift or reduce operation is stored as one of the following */
200 struct action {
201 struct symbol *sp; /* The look-ahead symbol */
202 enum e_action {
203 SHIFT,
204 ACCEPT,
205 REDUCE,
206 ERROR,
207 CONFLICT, /* Was a reduce, but part of a conflict */
208 SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
209 RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
210 NOT_USED /* Deleted by compression */
211 } type;
212 union {
213 struct state *stp; /* The new state, if a shift */
214 struct rule *rp; /* The rule, if a reduce */
215 } x;
216 struct action *next; /* Next action for this state */
217 struct action *collide; /* Next action with the same hash */
220 /* Each state of the generated parser's finite state machine
221 ** is encoded as an instance of the following structure. */
222 struct state {
223 struct config *bp; /* The basis configurations for this state */
224 struct config *cfp; /* All configurations in this set */
225 int index; /* Sequencial number for this state */
226 struct action *ap; /* Array of actions for this state */
227 int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */
228 int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */
229 int iDflt; /* Default action */
231 #define NO_OFFSET (-2147483647)
233 /* A followset propagation link indicates that the contents of one
234 ** configuration followset should be propagated to another whenever
235 ** the first changes. */
236 struct plink {
237 struct config *cfp; /* The configuration to which linked */
238 struct plink *next; /* The next propagate link */
241 /* The state vector for the entire parser generator is recorded as
242 ** follows. (LEMON uses no global variables and makes little use of
243 ** static variables. Fields in the following structure can be thought
244 ** of as begin global variables in the program.) */
245 struct lemon {
246 struct state **sorted; /* Table of states sorted by state number */
247 struct rule *rule; /* List of all rules */
248 int nstate; /* Number of states */
249 int nrule; /* Number of rules */
250 int nsymbol; /* Number of terminal and nonterminal symbols */
251 int nterminal; /* Number of terminal symbols */
252 struct symbol **symbols; /* Sorted array of pointers to symbols */
253 int errorcnt; /* Number of errors */
254 struct symbol *errsym; /* The error symbol */
255 char *name; /* Name of the generated parser */
256 char *arg; /* Declaration of the 3th argument to parser */
257 char *tokentype; /* Type of terminal symbols in the parser stack */
258 char *vartype; /* The default type of non-terminal symbols */
259 char *start; /* Name of the start symbol for the grammar */
260 char *stacksize; /* Size of the parser stack */
261 char *include; /* Code to put at the start of the C file */
262 int includeln; /* Line number for start of include code */
263 char *error; /* Code to execute when an error is seen */
264 int errorln; /* Line number for start of error code */
265 char *overflow; /* Code to execute on a stack overflow */
266 int overflowln; /* Line number for start of overflow code */
267 char *failure; /* Code to execute on parser failure */
268 int failureln; /* Line number for start of failure code */
269 char *accept; /* Code to execute when the parser excepts */
270 int acceptln; /* Line number for the start of accept code */
271 char *extracode; /* Code appended to the generated file */
272 int extracodeln; /* Line number for the start of the extra code */
273 char *tokendest; /* Code to execute to destroy token data */
274 int tokendestln; /* Line number for token destroyer code */
275 char *vardest; /* Code for the default non-terminal destructor */
276 int vardestln; /* Line number for default non-term destructor code*/
277 char *filename; /* Name of the input file */
278 char *tmplname; /* Name of the template file */
279 char *outname; /* Name of the current output file */
280 char *tokenprefix; /* A prefix added to token names in the .h file */
281 int nconflict; /* Number of parsing conflicts */
282 int tablesize; /* Size of the parse tables */
283 int basisflag; /* Print only basis configurations */
284 int has_fallback; /* True if any %fallback is seen in the grammer */
285 char *argv0; /* Name of the program */
288 #define MemoryCheck(X) if((X)==0){ \
289 memory_error(); \
292 /**************** From the file "table.h" *********************************/
294 ** All code in this file has been automatically generated
295 ** from a specification in the file
296 ** "table.q"
297 ** by the associative array code building program "aagen".
298 ** Do not edit this file! Instead, edit the specification
299 ** file, then rerun aagen.
302 ** Code for processing tables in the LEMON parser generator.
305 /* Routines for handling a strings */
307 char *Strsafe();
309 void Strsafe_init(/* void */);
310 int Strsafe_insert(/* char * */);
311 char *Strsafe_find(/* char * */);
313 /* Routines for handling symbols of the grammar */
315 struct symbol *Symbol_new();
316 int Symbolcmpp(/* struct symbol **, struct symbol ** */);
317 void Symbol_init(/* void */);
318 int Symbol_insert(/* struct symbol *, char * */);
319 struct symbol *Symbol_find(/* char * */);
320 struct symbol *Symbol_Nth(/* int */);
321 int Symbol_count(/* */);
322 int State_count(void);
323 struct symbol **Symbol_arrayof(/* */);
325 /* Routines to manage the state table */
327 int Configcmp(/* struct config *, struct config * */);
328 struct state *State_new();
329 void State_init(/* void */);
330 int State_insert(/* struct state *, struct config * */);
331 struct state *State_find(/* struct config * */);
332 struct state **State_arrayof(/* */);
334 /* Routines used for efficiency in Configlist_add */
336 void Configtable_init(/* void */);
337 int Configtable_insert(/* struct config * */);
338 struct config *Configtable_find(/* struct config * */);
339 void Configtable_clear(/* int(*)(struct config *) */);
340 /****************** From the file "action.c" *******************************/
342 ** Routines processing parser actions in the LEMON parser generator.
345 /* Allocate a new parser action */
346 struct action *Action_new(){
347 static struct action *freelist = NULL;
348 struct action *new;
350 if( freelist==NULL ){
351 int i;
352 int amt = 100;
353 freelist = (struct action *)malloc( sizeof(struct action)*amt );
354 if( freelist==0 ){
355 fprintf(stderr,"Unable to allocate memory for a new parser action.");
356 exit(1);
358 for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
359 freelist[amt-1].next = 0;
361 new = freelist;
362 freelist = freelist->next;
363 return new;
366 /* Compare two actions */
367 static int actioncmp(ap1,ap2)
368 struct action *ap1;
369 struct action *ap2;
371 int rc;
372 rc = ap1->sp->index - ap2->sp->index;
373 if( rc==0 ) rc = (int)ap1->type - (int)ap2->type;
374 if( rc==0 ){
375 assert( ap1->type==REDUCE || ap1->type==RD_RESOLVED || ap1->type==CONFLICT);
376 assert( ap2->type==REDUCE || ap2->type==RD_RESOLVED || ap2->type==CONFLICT);
377 rc = ap1->x.rp->index - ap2->x.rp->index;
379 return rc;
382 /* Sort parser actions */
383 struct action *Action_sort(ap)
384 struct action *ap;
386 ap = (struct action *)msort(ap,(void **)&ap->next,actioncmp);
387 return ap;
390 void Action_add(app,type,sp,arg)
391 struct action **app;
392 enum e_action type;
393 struct symbol *sp;
394 void *arg;
396 struct action *new;
397 new = Action_new();
398 new->next = *app;
399 *app = new;
400 new->type = type;
401 new->sp = sp;
402 if( type==SHIFT ){
403 new->x.stp = (struct state *)arg;
404 }else{
405 new->x.rp = (struct rule *)arg;
408 /********************** New code to implement the "acttab" module ***********/
410 ** This module implements routines use to construct the yy_action[] table.
414 ** The state of the yy_action table under construction is an instance of
415 ** the following structure
417 typedef struct acttab acttab;
418 struct acttab {
419 int nAction; /* Number of used slots in aAction[] */
420 int nActionAlloc; /* Slots allocated for aAction[] */
421 struct {
422 int lookahead; /* Value of the lookahead token */
423 int action; /* Action to take on the given lookahead */
424 } *aAction, /* The yy_action[] table under construction */
425 *aLookahead; /* A single new transaction set */
426 int mnLookahead; /* Minimum aLookahead[].lookahead */
427 int mnAction; /* Action associated with mnLookahead */
428 int mxLookahead; /* Maximum aLookahead[].lookahead */
429 int nLookahead; /* Used slots in aLookahead[] */
430 int nLookaheadAlloc; /* Slots allocated in aLookahead[] */
433 /* Return the number of entries in the yy_action table */
434 #define acttab_size(X) ((X)->nAction)
436 /* The value for the N-th entry in yy_action */
437 #define acttab_yyaction(X,N) ((X)->aAction[N].action)
439 /* The value for the N-th entry in yy_lookahead */
440 #define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
442 /* Free all memory associated with the given acttab */
444 PRIVATE void acttab_free(acttab *p){
445 free( p->aAction );
446 free( p->aLookahead );
447 free( p );
451 /* Allocate a new acttab structure */
452 PRIVATE acttab *acttab_alloc(void){
453 acttab *p = malloc( sizeof(*p) );
454 if( p==0 ){
455 fprintf(stderr,"Unable to allocate memory for a new acttab.");
456 exit(1);
458 memset(p, 0, sizeof(*p));
459 return p;
462 /* Add a new action to the current transaction set
464 PRIVATE void acttab_action(acttab *p, int lookahead, int action){
465 if( p->nLookahead>=p->nLookaheadAlloc ){
466 p->nLookaheadAlloc += 25;
467 p->aLookahead = realloc( p->aLookahead,
468 sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
469 if( p->aLookahead==0 ){
470 fprintf(stderr,"malloc failed\n");
471 exit(1);
474 if( p->nLookahead==0 ){
475 p->mxLookahead = lookahead;
476 p->mnLookahead = lookahead;
477 p->mnAction = action;
478 }else{
479 if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
480 if( p->mnLookahead>lookahead ){
481 p->mnLookahead = lookahead;
482 p->mnAction = action;
485 p->aLookahead[p->nLookahead].lookahead = lookahead;
486 p->aLookahead[p->nLookahead].action = action;
487 p->nLookahead++;
491 ** Add the transaction set built up with prior calls to acttab_action()
492 ** into the current action table. Then reset the transaction set back
493 ** to an empty set in preparation for a new round of acttab_action() calls.
495 ** Return the offset into the action table of the new transaction.
497 PRIVATE int acttab_insert(acttab *p){
498 int i, j, k, n;
499 assert( p->nLookahead>0 );
501 /* Make sure we have enough space to hold the expanded action table
502 ** in the worst case. The worst case occurs if the transaction set
503 ** must be appended to the current action table
505 n = p->mxLookahead + 1;
506 if( p->nAction + n >= p->nActionAlloc ){
507 int oldAlloc = p->nActionAlloc;
508 p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
509 p->aAction = realloc( p->aAction,
510 sizeof(p->aAction[0])*p->nActionAlloc);
511 if( p->aAction==0 ){
512 fprintf(stderr,"malloc failed\n");
513 exit(1);
515 for(i=oldAlloc; i<p->nActionAlloc; i++){
516 p->aAction[i].lookahead = -1;
517 p->aAction[i].action = -1;
521 /* Scan the existing action table looking for an offset where we can
522 ** insert the current transaction set. Fall out of the loop when that
523 ** offset is found. In the worst case, we fall out of the loop when
524 ** i reaches p->nAction, which means we append the new transaction set.
526 ** i is the index in p->aAction[] where p->mnLookahead is inserted.
528 for(i=0; i<p->nAction+p->mnLookahead; i++){
529 if( p->aAction[i].lookahead<0 ){
530 for(j=0; j<p->nLookahead; j++){
531 k = p->aLookahead[j].lookahead - p->mnLookahead + i;
532 if( k<0 ) break;
533 if( p->aAction[k].lookahead>=0 ) break;
535 if( j<p->nLookahead ) continue;
536 for(j=0; j<p->nAction; j++){
537 if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
539 if( j==p->nAction ){
540 break; /* Fits in empty slots */
542 }else if( p->aAction[i].lookahead==p->mnLookahead ){
543 if( p->aAction[i].action!=p->mnAction ) continue;
544 for(j=0; j<p->nLookahead; j++){
545 k = p->aLookahead[j].lookahead - p->mnLookahead + i;
546 if( k<0 || k>=p->nAction ) break;
547 if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
548 if( p->aLookahead[j].action!=p->aAction[k].action ) break;
550 if( j<p->nLookahead ) continue;
551 n = 0;
552 for(j=0; j<p->nAction; j++){
553 if( p->aAction[j].lookahead<0 ) continue;
554 if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
556 if( n==p->nLookahead ){
557 break; /* Same as a prior transaction set */
561 /* Insert transaction set at index i. */
562 for(j=0; j<p->nLookahead; j++){
563 k = p->aLookahead[j].lookahead - p->mnLookahead + i;
564 p->aAction[k] = p->aLookahead[j];
565 if( k>=p->nAction ) p->nAction = k+1;
567 p->nLookahead = 0;
569 /* Return the offset that is added to the lookahead in order to get the
570 ** index into yy_action of the action */
571 return i - p->mnLookahead;
574 /********************** From the file "assert.c" ****************************/
576 ** A more efficient way of handling assertions.
578 void myassert(file,line)
579 char *file;
580 int line;
582 fprintf(stderr,"Assertion failed on line %d of file \"%s\"\n",line,file);
583 exit(1);
585 /********************** From the file "build.c" *****************************/
587 ** Routines to construction the finite state machine for the LEMON
588 ** parser generator.
591 /* Find a precedence symbol of every rule in the grammar.
593 ** Those rules which have a precedence symbol coded in the input
594 ** grammar using the "[symbol]" construct will already have the
595 ** rp->precsym field filled. Other rules take as their precedence
596 ** symbol the first RHS symbol with a defined precedence. If there
597 ** are not RHS symbols with a defined precedence, the precedence
598 ** symbol field is left blank.
600 void FindRulePrecedences(xp)
601 struct lemon *xp;
603 struct rule *rp;
604 for(rp=xp->rule; rp; rp=rp->next){
605 if( rp->precsym==0 ){
606 int i;
607 for(i=0; i<rp->nrhs; i++){
608 if( rp->rhs[i]->prec>=0 ){
609 rp->precsym = rp->rhs[i];
610 break;
615 return;
618 /* Find all nonterminals which will generate the empty string.
619 ** Then go back and compute the first sets of every nonterminal.
620 ** The first set is the set of all terminal symbols which can begin
621 ** a string generated by that nonterminal.
623 void FindFirstSets(lemp)
624 struct lemon *lemp;
626 int i;
627 struct rule *rp;
628 int progress;
630 for(i=0; i<lemp->nsymbol; i++){
631 lemp->symbols[i]->lambda = Bo_FALSE;
633 for(i=lemp->nterminal; i<lemp->nsymbol; i++){
634 lemp->symbols[i]->firstset = SetNew();
637 /* First compute all lambdas */
639 progress = 0;
640 for(rp=lemp->rule; rp; rp=rp->next){
641 if( rp->lhs->lambda ) continue;
642 for(i=0; i<rp->nrhs; i++){
643 if( rp->rhs[i]->lambda==Bo_FALSE ) break;
645 if( i==rp->nrhs ){
646 rp->lhs->lambda = Bo_TRUE;
647 progress = 1;
650 }while( progress );
652 /* Now compute all first sets */
654 struct symbol *s1, *s2;
655 progress = 0;
656 for(rp=lemp->rule; rp; rp=rp->next){
657 s1 = rp->lhs;
658 for(i=0; i<rp->nrhs; i++){
659 s2 = rp->rhs[i];
660 if( s2->type==TERMINAL ){
661 progress += SetAdd(s1->firstset,s2->index);
662 break;
663 }else if( s1==s2 ){
664 if( s1->lambda==Bo_FALSE ) break;
665 }else{
666 progress += SetUnion(s1->firstset,s2->firstset);
667 if( s2->lambda==Bo_FALSE ) break;
671 }while( progress );
672 return;
675 /* Compute all LR(0) states for the grammar. Links
676 ** are added to between some states so that the LR(1) follow sets
677 ** can be computed later.
679 PRIVATE struct state *getstate(/* struct lemon * */); /* forward reference */
680 void FindStates(lemp)
681 struct lemon *lemp;
683 struct symbol *sp;
684 struct rule *rp;
686 Configlist_init();
688 /* Find the start symbol */
689 if( lemp->start ){
690 sp = Symbol_find(lemp->start);
691 if( sp==0 ){
692 ErrorMsg(lemp->filename,0,
693 "The specified start symbol \"%s\" is not \
694 in a nonterminal of the grammar. \"%s\" will be used as the start \
695 symbol instead.",lemp->start,lemp->rule->lhs->name);
696 lemp->errorcnt++;
697 sp = lemp->rule->lhs;
699 }else{
700 sp = lemp->rule->lhs;
703 /* Make sure the start symbol doesn't occur on the right-hand side of
704 ** any rule. Report an error if it does. (YACC would generate a new
705 ** start symbol in this case.) */
706 for(rp=lemp->rule; rp; rp=rp->next){
707 int i;
708 for(i=0; i<rp->nrhs; i++){
709 if( rp->rhs[i]==sp ){
710 ErrorMsg(lemp->filename,0,
711 "The start symbol \"%s\" occurs on the \
712 right-hand side of a rule. This will result in a parser which \
713 does not work properly.",sp->name);
714 lemp->errorcnt++;
719 /* The basis configuration set for the first state
720 ** is all rules which have the start symbol as their
721 ** left-hand side */
722 for(rp=sp->rule; rp; rp=rp->nextlhs){
723 struct config *newcfp;
724 newcfp = Configlist_addbasis(rp,0);
725 SetAdd(newcfp->fws,0);
728 /* Compute the first state. All other states will be
729 ** computed automatically during the computation of the first one.
730 ** The returned pointer to the first state is not used. */
731 (void)getstate(lemp);
732 return;
735 /* Return a pointer to a state which is described by the configuration
736 ** list which has been built from calls to Configlist_add.
738 PRIVATE void buildshifts(/* struct lemon *, struct state * */); /* Forwd ref */
739 PRIVATE struct state *getstate(lemp)
740 struct lemon *lemp;
742 struct config *cfp, *bp;
743 struct state *stp;
745 /* Extract the sorted basis of the new state. The basis was constructed
746 ** by prior calls to "Configlist_addbasis()". */
747 Configlist_sortbasis();
748 bp = Configlist_basis();
750 /* Get a state with the same basis */
751 stp = State_find(bp);
752 if( stp ){
753 /* A state with the same basis already exists! Copy all the follow-set
754 ** propagation links from the state under construction into the
755 ** preexisting state, then return a pointer to the preexisting state */
756 struct config *x, *y;
757 for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
758 Plink_copy(&y->bplp,x->bplp);
759 Plink_delete(x->fplp);
760 x->fplp = x->bplp = 0;
762 cfp = Configlist_return();
763 Configlist_eat(cfp);
764 }else{
765 /* This really is a new state. Construct all the details */
766 Configlist_closure(lemp); /* Compute the configuration closure */
767 Configlist_sort(); /* Sort the configuration closure */
768 cfp = Configlist_return(); /* Get a pointer to the config list */
769 stp = State_new(); /* A new state structure */
770 MemoryCheck(stp);
771 stp->bp = bp; /* Remember the configuration basis */
772 stp->cfp = cfp; /* Remember the configuration closure */
773 stp->index = lemp->nstate++; /* Every state gets a sequence number */
774 stp->ap = 0; /* No actions, yet. */
775 State_insert(stp,stp->bp); /* Add to the state table */
776 buildshifts(lemp,stp); /* Recursively compute successor states */
778 return stp;
781 /* Construct all successor states to the given state. A "successor"
782 ** state is any state which can be reached by a shift action.
784 PRIVATE void buildshifts(lemp,stp)
785 struct lemon *lemp;
786 struct state *stp; /* The state from which successors are computed */
788 struct config *cfp; /* For looping thru the config closure of "stp" */
789 struct config *bcfp; /* For the inner loop on config closure of "stp" */
790 struct config *new; /* */
791 struct symbol *sp; /* Symbol following the dot in configuration "cfp" */
792 struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
793 struct state *newstp; /* A pointer to a successor state */
795 /* Each configuration becomes complete after it contibutes to a successor
796 ** state. Initially, all configurations are incomplete */
797 for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
799 /* Loop through all configurations of the state "stp" */
800 for(cfp=stp->cfp; cfp; cfp=cfp->next){
801 if( cfp->status==COMPLETE ) continue; /* Already used by inner loop */
802 if( cfp->dot>=cfp->rp->nrhs ) continue; /* Can't shift this config */
803 Configlist_reset(); /* Reset the new config set */
804 sp = cfp->rp->rhs[cfp->dot]; /* Symbol after the dot */
806 /* For every configuration in the state "stp" which has the symbol "sp"
807 ** following its dot, add the same configuration to the basis set under
808 ** construction but with the dot shifted one symbol to the right. */
809 for(bcfp=cfp; bcfp; bcfp=bcfp->next){
810 if( bcfp->status==COMPLETE ) continue; /* Already used */
811 if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
812 bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
813 if( bsp!=sp ) continue; /* Must be same as for "cfp" */
814 bcfp->status = COMPLETE; /* Mark this config as used */
815 new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
816 Plink_add(&new->bplp,bcfp);
819 /* Get a pointer to the state described by the basis configuration set
820 ** constructed in the preceding loop */
821 newstp = getstate(lemp);
823 /* The state "newstp" is reached from the state "stp" by a shift action
824 ** on the symbol "sp" */
825 Action_add(&stp->ap,SHIFT,sp,newstp);
830 ** Construct the propagation links
832 void FindLinks(lemp)
833 struct lemon *lemp;
835 int i;
836 struct config *cfp, *other;
837 struct state *stp;
838 struct plink *plp;
840 /* Housekeeping detail:
841 ** Add to every propagate link a pointer back to the state to
842 ** which the link is attached. */
843 for(i=0; i<lemp->nstate; i++){
844 stp = lemp->sorted[i];
845 for(cfp=stp->cfp; cfp; cfp=cfp->next){
846 cfp->stp = stp;
850 /* Convert all backlinks into forward links. Only the forward
851 ** links are used in the follow-set computation. */
852 for(i=0; i<lemp->nstate; i++){
853 stp = lemp->sorted[i];
854 for(cfp=stp->cfp; cfp; cfp=cfp->next){
855 for(plp=cfp->bplp; plp; plp=plp->next){
856 other = plp->cfp;
857 Plink_add(&other->fplp,cfp);
863 /* Compute all followsets.
865 ** A followset is the set of all symbols which can come immediately
866 ** after a configuration.
868 void FindFollowSets(lemp)
869 struct lemon *lemp;
871 int i;
872 struct config *cfp;
873 struct state *stp;
874 struct plink *plp;
875 int progress;
876 int change;
878 for(i=0; i<lemp->nstate; i++){
879 stp = lemp->sorted[i];
880 for(cfp=stp->cfp; cfp; cfp=cfp->next){
881 cfp->status = INCOMPLETE;
886 progress = 0;
887 for(i=0; i<lemp->nstate; i++){
888 stp = lemp->sorted[i];
889 for(cfp=stp->cfp; cfp; cfp=cfp->next){
890 if( cfp->status==COMPLETE ) continue;
891 for(plp=cfp->fplp; plp; plp=plp->next){
892 change = SetUnion(plp->cfp->fws,cfp->fws);
893 if( change ){
894 plp->cfp->status = INCOMPLETE;
895 progress = 1;
898 cfp->status = COMPLETE;
901 }while( progress );
904 static int resolve_conflict();
906 /* Compute the reduce actions, and resolve conflicts.
908 void FindActions(lemp)
909 struct lemon *lemp;
911 int i,j;
912 struct config *cfp;
913 struct symbol *sp;
914 struct rule *rp;
916 /* Add all of the reduce actions
917 ** A reduce action is added for each element of the followset of
918 ** a configuration which has its dot at the extreme right.
920 for(i=0; i<lemp->nstate; i++){ /* Loop over all states */
921 struct state *stp;
922 stp = lemp->sorted[i];
923 for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */
924 if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */
925 for(j=0; j<lemp->nterminal; j++){
926 if( SetFind(cfp->fws,j) ){
927 /* Add a reduce action to the state "stp" which will reduce by the
928 ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
929 Action_add(&stp->ap,REDUCE,lemp->symbols[j],cfp->rp);
936 /* Add the accepting token */
937 if( lemp->start ){
938 sp = Symbol_find(lemp->start);
939 if( sp==0 ) sp = lemp->rule->lhs;
940 }else{
941 sp = lemp->rule->lhs;
943 /* Add to the first state (which is always the starting state of the
944 ** finite state machine) an action to ACCEPT if the lookahead is the
945 ** start nonterminal. */
946 if (lemp->nstate) { /*(should always be true)*/
947 struct state *stp;
948 stp = lemp->sorted[0];
949 Action_add(&stp->ap,ACCEPT,sp,0);
952 /* Resolve conflicts */
953 for(i=0; i<lemp->nstate; i++){
954 struct action *ap, *nap;
955 struct state *stp;
956 stp = lemp->sorted[i];
957 assert( stp->ap );
958 stp->ap = Action_sort(stp->ap);
959 for(ap=stp->ap; ap && ap->next; ap=ap->next){
960 for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
961 /* The two actions "ap" and "nap" have the same lookahead.
962 ** Figure out which one should be used */
963 lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym);
968 /* Report an error for each rule that can never be reduced. */
969 for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = Bo_FALSE;
970 for(i=0; i<lemp->nstate; i++){
971 struct action *ap;
972 for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
973 if( ap->type==REDUCE ) ap->x.rp->canReduce = Bo_TRUE;
976 for(rp=lemp->rule; rp; rp=rp->next){
977 if( rp->canReduce ) continue;
978 ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
979 lemp->errorcnt++;
983 /* Resolve a conflict between the two given actions. If the
984 ** conflict can't be resolve, return non-zero.
986 ** NO LONGER TRUE:
987 ** To resolve a conflict, first look to see if either action
988 ** is on an error rule. In that case, take the action which
989 ** is not associated with the error rule. If neither or both
990 ** actions are associated with an error rule, then try to
991 ** use precedence to resolve the conflict.
993 ** If either action is a SHIFT, then it must be apx. This
994 ** function won't work if apx->type==REDUCE and apy->type==SHIFT.
996 static int resolve_conflict(apx,apy,errsym)
997 struct action *apx;
998 struct action *apy;
999 struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
1001 struct symbol *spx, *spy;
1002 int errcnt = 0;
1003 UNUSED(errsym);
1004 assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
1005 if( apx->type==SHIFT && apy->type==REDUCE ){
1006 spx = apx->sp;
1007 spy = apy->x.rp->precsym;
1008 if( spy==0 || spx->prec<0 || spy->prec<0 ){
1009 /* Not enough precedence information. */
1010 apy->type = CONFLICT;
1011 errcnt++;
1012 }else if( spx->prec>spy->prec ){ /* Lower precedence wins */
1013 apy->type = RD_RESOLVED;
1014 }else if( spx->prec<spy->prec ){
1015 apx->type = SH_RESOLVED;
1016 }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
1017 apy->type = RD_RESOLVED; /* associativity */
1018 }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */
1019 apx->type = SH_RESOLVED;
1020 }else{
1021 assert( spx->prec==spy->prec && spx->assoc==NONE );
1022 apy->type = CONFLICT;
1023 errcnt++;
1025 }else if( apx->type==REDUCE && apy->type==REDUCE ){
1026 spx = apx->x.rp->precsym;
1027 spy = apy->x.rp->precsym;
1028 if( spx==0 || spy==0 || spx->prec<0 ||
1029 spy->prec<0 || spx->prec==spy->prec ){
1030 apy->type = CONFLICT;
1031 errcnt++;
1032 }else if( spx->prec>spy->prec ){
1033 apy->type = RD_RESOLVED;
1034 }else if( spx->prec<spy->prec ){
1035 apx->type = RD_RESOLVED;
1037 }else{
1038 assert(
1039 apx->type==SH_RESOLVED ||
1040 apx->type==RD_RESOLVED ||
1041 apx->type==CONFLICT ||
1042 apy->type==SH_RESOLVED ||
1043 apy->type==RD_RESOLVED ||
1044 apy->type==CONFLICT
1046 /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
1047 ** REDUCEs on the list. If we reach this point it must be because
1048 ** the parser conflict had already been resolved. */
1050 return errcnt;
1052 /********************* From the file "configlist.c" *************************/
1054 ** Routines to processing a configuration list and building a state
1055 ** in the LEMON parser generator.
1058 static struct config *freelist = 0; /* List of free configurations */
1059 static struct config *current = 0; /* Top of list of configurations */
1060 static struct config **currentend = 0; /* Last on list of configs */
1061 static struct config *basis = 0; /* Top of list of basis configs */
1062 static struct config **basisend = 0; /* End of list of basis configs */
1064 /* Return a pointer to a new configuration */
1065 PRIVATE struct config *newconfig(){
1066 struct config *new;
1067 if( freelist==0 ){
1068 int i;
1069 int amt = 3;
1070 freelist = (struct config *)malloc( sizeof(struct config)*amt );
1071 if( freelist==0 ){
1072 fprintf(stderr,"Unable to allocate memory for a new configuration.");
1073 exit(1);
1075 for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
1076 freelist[amt-1].next = 0;
1078 new = freelist;
1079 freelist = freelist->next;
1080 return new;
1083 /* The configuration "old" is no longer used */
1084 PRIVATE void deleteconfig(old)
1085 struct config *old;
1087 old->next = freelist;
1088 freelist = old;
1091 /* Initialized the configuration list builder */
1092 void Configlist_init(){
1093 current = 0;
1094 currentend = &current;
1095 basis = 0;
1096 basisend = &basis;
1097 Configtable_init();
1098 return;
1101 /* Initialized the configuration list builder */
1102 void Configlist_reset(){
1103 current = 0;
1104 currentend = &current;
1105 basis = 0;
1106 basisend = &basis;
1107 Configtable_clear(0);
1108 return;
1111 /* Add another configuration to the configuration list */
1112 struct config *Configlist_add(rp,dot)
1113 struct rule *rp; /* The rule */
1114 int dot; /* Index into the RHS of the rule where the dot goes */
1116 struct config *cfp, model;
1118 assert( currentend!=0 );
1119 model.rp = rp;
1120 model.dot = dot;
1121 cfp = Configtable_find(&model);
1122 if( cfp==0 ){
1123 cfp = newconfig();
1124 cfp->rp = rp;
1125 cfp->dot = dot;
1126 cfp->fws = SetNew();
1127 cfp->stp = 0;
1128 cfp->fplp = cfp->bplp = 0;
1129 cfp->next = 0;
1130 cfp->bp = 0;
1131 *currentend = cfp;
1132 currentend = &cfp->next;
1133 Configtable_insert(cfp);
1135 return cfp;
1138 /* Add a basis configuration to the configuration list */
1139 struct config *Configlist_addbasis(rp,dot)
1140 struct rule *rp;
1141 int dot;
1143 struct config *cfp, model;
1145 assert( basisend!=0 );
1146 assert( currentend!=0 );
1147 model.rp = rp;
1148 model.dot = dot;
1149 cfp = Configtable_find(&model);
1150 if( cfp==0 ){
1151 cfp = newconfig();
1152 cfp->rp = rp;
1153 cfp->dot = dot;
1154 cfp->fws = SetNew();
1155 cfp->stp = 0;
1156 cfp->fplp = cfp->bplp = 0;
1157 cfp->next = 0;
1158 cfp->bp = 0;
1159 *currentend = cfp;
1160 currentend = &cfp->next;
1161 *basisend = cfp;
1162 basisend = &cfp->bp;
1163 Configtable_insert(cfp);
1165 return cfp;
1168 /* Compute the closure of the configuration list */
1169 void Configlist_closure(lemp)
1170 struct lemon *lemp;
1172 struct config *cfp, *newcfp;
1173 struct rule *rp, *newrp;
1174 struct symbol *sp, *xsp;
1175 int i, dot;
1177 assert( currentend!=0 );
1178 for(cfp=current; cfp; cfp=cfp->next){
1179 rp = cfp->rp;
1180 dot = cfp->dot;
1181 if( dot>=rp->nrhs ) continue;
1182 sp = rp->rhs[dot];
1183 if( sp->type==NONTERMINAL ){
1184 if( sp->rule==0 && sp!=lemp->errsym ){
1185 ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
1186 sp->name);
1187 lemp->errorcnt++;
1189 for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
1190 newcfp = Configlist_add(newrp,0);
1191 for(i=dot+1; i<rp->nrhs; i++){
1192 xsp = rp->rhs[i];
1193 if( xsp->type==TERMINAL ){
1194 SetAdd(newcfp->fws,xsp->index);
1195 break;
1196 }else{
1197 SetUnion(newcfp->fws,xsp->firstset);
1198 if( xsp->lambda==Bo_FALSE ) break;
1201 if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
1205 return;
1208 /* Sort the configuration list */
1209 void Configlist_sort(){
1210 current = (struct config *)msort(current,(void **)&(current->next),Configcmp);
1211 currentend = 0;
1212 return;
1215 /* Sort the basis configuration list */
1216 void Configlist_sortbasis(){
1217 basis = (struct config *)msort(current,(void **)&(current->bp),Configcmp);
1218 basisend = 0;
1219 return;
1222 /* Return a pointer to the head of the configuration list and
1223 ** reset the list */
1224 struct config *Configlist_return(){
1225 struct config *old;
1226 old = current;
1227 current = 0;
1228 currentend = 0;
1229 return old;
1232 /* Return a pointer to the head of the configuration list and
1233 ** reset the list */
1234 struct config *Configlist_basis(){
1235 struct config *old;
1236 old = basis;
1237 basis = 0;
1238 basisend = 0;
1239 return old;
1242 /* Free all elements of the given configuration list */
1243 void Configlist_eat(cfp)
1244 struct config *cfp;
1246 struct config *nextcfp;
1247 for(; cfp; cfp=nextcfp){
1248 nextcfp = cfp->next;
1249 assert( cfp->fplp==0 );
1250 assert( cfp->bplp==0 );
1251 if( cfp->fws ) SetFree(cfp->fws);
1252 deleteconfig(cfp);
1254 return;
1256 /***************** From the file "error.c" *********************************/
1258 ** Code for printing error message.
1261 /* Find a good place to break "msg" so that its length is at least "min"
1262 ** but no more than "max". Make the point as close to max as possible.
1264 static int findbreak(msg,min,max)
1265 char *msg;
1266 int min;
1267 int max;
1269 int i,spot;
1270 char c;
1271 for(i=spot=min; i<=max; i++){
1272 c = msg[i];
1273 if( c=='\t' ) msg[i] = ' ';
1274 if( c=='\n' ){ msg[i] = ' '; spot = i; break; }
1275 if( c==0 ){ spot = i; break; }
1276 if( c=='-' && i<max-1 ) spot = i+1;
1277 if( c==' ' ) spot = i;
1279 return spot;
1283 ** The error message is split across multiple lines if necessary. The
1284 ** splits occur at a space, if there is a space available near the end
1285 ** of the line.
1287 #define ERRMSGSIZE 10000 /* Hope this is big enough. No way to error check */
1288 #define LINEWIDTH 79 /* Max width of any output line */
1289 #define PREFIXLIMIT 30 /* Max width of the prefix on each line */
1290 void ErrorMsg(const char *filename, int lineno, const char *format, ...){
1291 char errmsg[ERRMSGSIZE];
1292 char prefix[PREFIXLIMIT+10];
1293 int errmsgsize;
1294 int prefixsize;
1295 int availablewidth;
1296 va_list ap;
1297 int end, restart, base;
1299 va_start(ap, format);
1300 /* Prepare a prefix to be prepended to every output line */
1301 if( lineno>0 ){
1302 sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno);
1303 }else{
1304 sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename);
1306 prefixsize = strlen(prefix);
1307 availablewidth = LINEWIDTH - prefixsize;
1309 /* Generate the error message */
1310 vsprintf(errmsg,format,ap);
1311 va_end(ap);
1312 errmsgsize = strlen(errmsg);
1313 /* Remove trailing '\n's from the error message. */
1314 while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){
1315 errmsg[--errmsgsize] = 0;
1318 /* Print the error message */
1319 base = 0;
1320 while( errmsg[base]!=0 ){
1321 end = restart = findbreak(&errmsg[base],0,availablewidth);
1322 restart += base;
1323 while( errmsg[restart]==' ' ) restart++;
1324 fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]);
1325 base = restart;
1328 /**************** From the file "main.c" ************************************/
1330 ** Main program file for the LEMON parser generator.
1333 /* Report an out-of-memory condition and abort. This function
1334 ** is used mostly by the "MemoryCheck" macro in struct.h
1336 void memory_error() {
1337 fprintf(stderr,"Out of memory. Aborting...\n");
1338 exit(1);
1342 /* The main program. Parse the command line and do it... */
1343 int main(argc,argv)
1344 int argc;
1345 char **argv;
1347 static int version = 0;
1348 static int rpflag = 0;
1349 static int basisflag = 0;
1350 static int compress = 0;
1351 static int quiet = 0;
1352 static int statistics = 0;
1353 static int mhflag = 0;
1354 static struct s_options options[] = {
1355 {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
1356 {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
1357 {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
1358 {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"},
1359 {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
1360 {OPT_FLAG, "s", (char*)&statistics, "Print parser stats to standard output."},
1361 {OPT_FLAG, "x", (char*)&version, "Print the version number."},
1362 {OPT_FLAG,0,0,0}
1364 int i;
1365 struct lemon lem;
1366 char *def_tmpl_name = "lempar.c";
1368 UNUSED(argc);
1369 OptInit(argv,options,stderr);
1370 if( version ){
1371 printf("Lemon version 1.0\n");
1372 exit(0);
1374 if( OptNArgs() < 1 ){
1375 fprintf(stderr,"Exactly one filename argument is required.\n");
1376 exit(1);
1378 lem.errorcnt = 0;
1380 /* Initialize the machine */
1381 Strsafe_init();
1382 Symbol_init();
1383 State_init();
1384 lem.argv0 = argv[0];
1385 lem.filename = OptArg(0);
1386 lem.tmplname = (OptNArgs() == 2) ? OptArg(1) : def_tmpl_name;
1387 lem.basisflag = basisflag;
1388 lem.has_fallback = 0;
1389 lem.nconflict = 0;
1390 lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
1391 lem.vartype = 0;
1392 lem.stacksize = 0;
1393 lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
1394 lem.tokenprefix = lem.outname = lem.extracode = 0;
1395 lem.vardest = 0;
1396 lem.tablesize = 0;
1397 Symbol_new("$");
1398 lem.errsym = Symbol_new("error");
1400 /* Parse the input file */
1401 Parse(&lem);
1402 if( lem.errorcnt ) exit(lem.errorcnt);
1403 if( lem.rule==0 ){
1404 fprintf(stderr,"Empty grammar.\n");
1405 exit(1);
1408 /* Count and index the symbols of the grammar */
1409 Symbol_new("{default}");
1410 lem.nsymbol = Symbol_count();
1411 lem.symbols = Symbol_arrayof();
1412 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
1413 qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*),
1414 (int(*)())Symbolcmpp);
1415 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
1416 for(i=1; i<lem.nsymbol && isupper(lem.symbols[i]->name[0]); i++);
1417 lem.nsymbol--; /*(do not count "{default}")*/
1418 lem.nterminal = i;
1420 /* Generate a reprint of the grammar, if requested on the command line */
1421 if( rpflag ){
1422 Reprint(&lem);
1423 }else{
1424 /* Initialize the size for all follow and first sets */
1425 SetSize(lem.nterminal);
1427 /* Find the precedence for every production rule (that has one) */
1428 FindRulePrecedences(&lem);
1430 /* Compute the lambda-nonterminals and the first-sets for every
1431 ** nonterminal */
1432 FindFirstSets(&lem);
1434 /* Compute all LR(0) states. Also record follow-set propagation
1435 ** links so that the follow-set can be computed later */
1436 lem.nstate = 0;
1437 FindStates(&lem);
1438 lem.nstate = State_count();
1439 lem.sorted = State_arrayof();
1441 /* Tie up loose ends on the propagation links */
1442 FindLinks(&lem);
1444 /* Compute the follow set of every reducible configuration */
1445 FindFollowSets(&lem);
1447 /* Compute the action tables */
1448 FindActions(&lem);
1450 /* Compress the action tables */
1451 if( compress==0 ) CompressTables(&lem);
1453 /* Generate a report of the parser generated. (the "y.output" file) */
1454 if( !quiet ) ReportOutput(&lem);
1456 /* Generate the source code for the parser */
1457 ReportTable(&lem, mhflag);
1459 /* Produce a header file for use by the scanner. (This step is
1460 ** omitted if the "-m" option is used because makeheaders will
1461 ** generate the file for us.) */
1462 if( !mhflag ) ReportHeader(&lem);
1464 if( statistics ){
1465 printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
1466 lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
1467 printf(" %d states, %d parser table entries, %d conflicts\n",
1468 lem.nstate, lem.tablesize, lem.nconflict);
1470 if( lem.nconflict ){
1471 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
1473 exit(lem.errorcnt + lem.nconflict);
1475 /******************** From the file "msort.c" *******************************/
1477 ** A generic merge-sort program.
1479 ** USAGE:
1480 ** Let "ptr" be a pointer to some structure which is at the head of
1481 ** a null-terminated list. Then to sort the list call:
1483 ** ptr = msort(ptr,&(ptr->next),cmpfnc);
1485 ** In the above, "cmpfnc" is a pointer to a function which compares
1486 ** two instances of the structure and returns an integer, as in
1487 ** strcmp. The second argument is a pointer to the pointer to the
1488 ** second element of the linked list. This address is used to compute
1489 ** the offset to the "next" field within the structure. The offset to
1490 ** the "next" field must be constant for all structures in the list.
1492 ** The function returns a new pointer which is the head of the list
1493 ** after sorting.
1495 ** ALGORITHM:
1496 ** Merge-sort.
1500 ** Return a pointer to the next structure in the linked list.
1502 #define NEXT(A) (*(char**)(((unsigned long)A)+offset))
1505 ** Inputs:
1506 ** a: A sorted, null-terminated linked list. (May be null).
1507 ** b: A sorted, null-terminated linked list. (May be null).
1508 ** cmp: A pointer to the comparison function.
1509 ** offset: Offset in the structure to the "next" field.
1511 ** Return Value:
1512 ** A pointer to the head of a sorted list containing the elements
1513 ** of both a and b.
1515 ** Side effects:
1516 ** The "next" pointers for elements in the lists a and b are
1517 ** changed.
1519 static char *merge(a,b,cmp,offset)
1520 char *a;
1521 char *b;
1522 int (*cmp)();
1523 int offset;
1525 char *ptr, *head;
1527 if( a==0 ){
1528 head = b;
1529 }else if( b==0 ){
1530 head = a;
1531 }else{
1532 if( (*cmp)(a,b)<0 ){
1533 ptr = a;
1534 a = NEXT(a);
1535 }else{
1536 ptr = b;
1537 b = NEXT(b);
1539 head = ptr;
1540 while( a && b ){
1541 if( (*cmp)(a,b)<0 ){
1542 NEXT(ptr) = a;
1543 ptr = a;
1544 a = NEXT(a);
1545 }else{
1546 NEXT(ptr) = b;
1547 ptr = b;
1548 b = NEXT(b);
1551 if( a ) NEXT(ptr) = a;
1552 else NEXT(ptr) = b;
1554 return head;
1558 ** Inputs:
1559 ** list: Pointer to a singly-linked list of structures.
1560 ** next: Pointer to pointer to the second element of the list.
1561 ** cmp: A comparison function.
1563 ** Return Value:
1564 ** A pointer to the head of a sorted list containing the elements
1565 ** orginally in list.
1567 ** Side effects:
1568 ** The "next" pointers for elements in list are changed.
1570 #define LISTSIZE 30
1571 void *msort(void *list, void **next, int(*cmp)(void *, void *))
1573 unsigned long offset;
1574 char *ep;
1575 char *set[LISTSIZE];
1576 int i;
1577 offset = (unsigned long)next - (unsigned long)list;
1578 for(i=0; i<LISTSIZE; i++) set[i] = 0;
1579 while( list ){
1580 ep = list;
1581 list = NEXT(list);
1582 NEXT(ep) = 0;
1583 for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
1584 ep = merge(ep,set[i],cmp,offset);
1585 set[i] = 0;
1587 set[i] = ep;
1589 ep = 0;
1590 for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset);
1591 return ep;
1593 /************************ From the file "option.c" **************************/
1594 static char **argv;
1595 static struct s_options *op;
1596 static FILE *errstream;
1598 #define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
1601 ** Print the command line with a carrot pointing to the k-th character
1602 ** of the n-th field.
1604 static void errline(n,k,err)
1605 int n;
1606 int k;
1607 FILE *err;
1609 int spcnt = 0, i;
1610 if( argv[0] ) {
1611 fprintf(err,"%s",argv[0]);
1612 spcnt += strlen(argv[0]) + 1;
1614 for(i=1; i<n && argv[i]; i++){
1615 fprintf(err," %s",argv[i]);
1616 spcnt += strlen(argv[i]) + 1;
1618 spcnt += k;
1619 for(; argv[i]; i++) fprintf(err," %s",argv[i]);
1620 if( spcnt<20 ){
1621 fprintf(err,"\n%*s^-- here\n",spcnt,"");
1622 }else{
1623 fprintf(err,"\n%*shere --^\n",spcnt-7,"");
1628 ** Return the index of the N-th non-switch argument. Return -1
1629 ** if N is out of range.
1631 static int argindex(n)
1632 int n;
1634 int i;
1635 int dashdash = 0;
1636 if( argv!=0 && *argv!=0 ){
1637 for(i=1; argv[i]; i++){
1638 if( dashdash || !ISOPT(argv[i]) ){
1639 if( n==0 ) return i;
1640 n--;
1642 if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1645 return -1;
1648 static char emsg[] = "Command line syntax error: ";
1651 ** Process a flag command line argument.
1653 static int handleflags(i,err)
1654 int i;
1655 FILE *err;
1657 int v;
1658 int errcnt = 0;
1659 int j;
1660 for(j=0; op[j].label; j++){
1661 if( strcmp(&argv[i][1],op[j].label)==0 ) break;
1663 v = argv[i][0]=='-' ? 1 : 0;
1664 if( op[j].label==0 ){
1665 if( err ){
1666 fprintf(err,"%sundefined option.\n",emsg);
1667 errline(i,1,err);
1669 errcnt++;
1670 }else if( op[j].type==OPT_FLAG ){
1671 *((int*)op[j].arg) = v;
1672 }else if( op[j].type==OPT_FFLAG ){
1673 (*(void(*)())(intptr_t)(op[j].arg))(v);
1674 }else{
1675 if( err ){
1676 fprintf(err,"%smissing argument on switch.\n",emsg);
1677 errline(i,1,err);
1679 errcnt++;
1681 return errcnt;
1685 ** Process a command line switch which has an argument.
1687 static int handleswitch(i,err)
1688 int i;
1689 FILE *err;
1691 int lv = 0;
1692 double dv = 0.0;
1693 char *sv = 0, *end;
1694 char *cp;
1695 int j;
1696 int errcnt = 0;
1697 cp = strchr(argv[i],'=');
1698 *cp = 0;
1699 for(j=0; op[j].label; j++){
1700 if( strcmp(argv[i],op[j].label)==0 ) break;
1702 *cp = '=';
1703 if( op[j].label==0 ){
1704 if( err ){
1705 fprintf(err,"%sundefined option.\n",emsg);
1706 errline(i,0,err);
1708 errcnt++;
1709 }else{
1710 cp++;
1711 switch( op[j].type ){
1712 case OPT_FLAG:
1713 case OPT_FFLAG:
1714 if( err ){
1715 fprintf(err,"%soption requires an argument.\n",emsg);
1716 errline(i,0,err);
1718 errcnt++;
1719 break;
1720 case OPT_DBL:
1721 case OPT_FDBL:
1722 dv = strtod(cp,&end);
1723 if( *end ){
1724 if( err ){
1725 fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
1726 errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
1728 errcnt++;
1730 break;
1731 case OPT_INT:
1732 case OPT_FINT:
1733 lv = strtol(cp,&end,0);
1734 if( *end ){
1735 if( err ){
1736 fprintf(err,"%sillegal character in integer argument.\n",emsg);
1737 errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
1739 errcnt++;
1741 break;
1742 case OPT_STR:
1743 case OPT_FSTR:
1744 sv = cp;
1745 break;
1747 switch( op[j].type ){
1748 case OPT_FLAG:
1749 case OPT_FFLAG:
1750 break;
1751 case OPT_DBL:
1752 *(double*)(op[j].arg) = dv;
1753 break;
1754 case OPT_FDBL:
1755 (*(void(*)())(intptr_t)(op[j].arg))(dv);
1756 break;
1757 case OPT_INT:
1758 *(int*)(op[j].arg) = lv;
1759 break;
1760 case OPT_FINT:
1761 (*(void(*)())(intptr_t)(op[j].arg))((int)lv);
1762 break;
1763 case OPT_STR:
1764 *(char**)(op[j].arg) = sv;
1765 break;
1766 case OPT_FSTR:
1767 (*(void(*)())(intptr_t)(op[j].arg))(sv);
1768 break;
1771 return errcnt;
1774 int OptInit(a,o,err)
1775 char **a;
1776 struct s_options *o;
1777 FILE *err;
1779 int errcnt = 0;
1780 argv = a;
1781 op = o;
1782 errstream = err;
1783 if( argv && *argv && op ){
1784 int i;
1785 for(i=1; argv[i]; i++){
1786 if( argv[i][0]=='+' || argv[i][0]=='-' ){
1787 errcnt += handleflags(i,err);
1788 }else if( strchr(argv[i],'=') ){
1789 errcnt += handleswitch(i,err);
1793 if( errcnt>0 ){
1794 fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
1795 OptPrint();
1796 exit(1);
1798 return 0;
1801 int OptNArgs(){
1802 int cnt = 0;
1803 int dashdash = 0;
1804 int i;
1805 if( argv!=0 && argv[0]!=0 ){
1806 for(i=1; argv[i]; i++){
1807 if( dashdash || !ISOPT(argv[i]) ) cnt++;
1808 if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1811 return cnt;
1814 char *OptArg(n)
1815 int n;
1817 int i;
1818 i = argindex(n);
1819 return i>=0 ? argv[i] : 0;
1822 void OptErr(n)
1823 int n;
1825 int i;
1826 i = argindex(n);
1827 if( i>=0 ) errline(i,0,errstream);
1830 void OptPrint(){
1831 int i;
1832 int max, len;
1833 max = 0;
1834 for(i=0; op[i].label; i++){
1835 len = strlen(op[i].label) + 1;
1836 switch( op[i].type ){
1837 case OPT_FLAG:
1838 case OPT_FFLAG:
1839 break;
1840 case OPT_INT:
1841 case OPT_FINT:
1842 len += 9; /* length of "<integer>" */
1843 break;
1844 case OPT_DBL:
1845 case OPT_FDBL:
1846 len += 6; /* length of "<real>" */
1847 break;
1848 case OPT_STR:
1849 case OPT_FSTR:
1850 len += 8; /* length of "<string>" */
1851 break;
1853 if( len>max ) max = len;
1855 for(i=0; op[i].label; i++){
1856 switch( op[i].type ){
1857 case OPT_FLAG:
1858 case OPT_FFLAG:
1859 fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message);
1860 break;
1861 case OPT_INT:
1862 case OPT_FINT:
1863 fprintf(errstream," %s=<integer>%*s %s\n",op[i].label,
1864 (int)(max-strlen(op[i].label)-9),"",op[i].message);
1865 break;
1866 case OPT_DBL:
1867 case OPT_FDBL:
1868 fprintf(errstream," %s=<real>%*s %s\n",op[i].label,
1869 (int)(max-strlen(op[i].label)-6),"",op[i].message);
1870 break;
1871 case OPT_STR:
1872 case OPT_FSTR:
1873 fprintf(errstream," %s=<string>%*s %s\n",op[i].label,
1874 (int)(max-strlen(op[i].label)-8),"",op[i].message);
1875 break;
1879 /*********************** From the file "parse.c" ****************************/
1881 ** Input file parser for the LEMON parser generator.
1884 /* The state of the parser */
1885 struct pstate {
1886 char *filename; /* Name of the input file */
1887 int tokenlineno; /* Linenumber at which current token starts */
1888 int errorcnt; /* Number of errors so far */
1889 char *tokenstart; /* Text of current token */
1890 struct lemon *gp; /* Global state vector */
1891 enum e_state {
1892 INITIALIZE,
1893 WAITING_FOR_DECL_OR_RULE,
1894 WAITING_FOR_DECL_KEYWORD,
1895 WAITING_FOR_DECL_ARG,
1896 WAITING_FOR_PRECEDENCE_SYMBOL,
1897 WAITING_FOR_ARROW,
1898 IN_RHS,
1899 LHS_ALIAS_1,
1900 LHS_ALIAS_2,
1901 LHS_ALIAS_3,
1902 RHS_ALIAS_1,
1903 RHS_ALIAS_2,
1904 PRECEDENCE_MARK_1,
1905 PRECEDENCE_MARK_2,
1906 RESYNC_AFTER_RULE_ERROR,
1907 RESYNC_AFTER_DECL_ERROR,
1908 WAITING_FOR_DESTRUCTOR_SYMBOL,
1909 WAITING_FOR_DATATYPE_SYMBOL,
1910 WAITING_FOR_FALLBACK_ID
1911 } state; /* The state of the parser */
1912 struct symbol *fallback; /* The fallback token */
1913 struct symbol *lhs; /* Left-hand side of current rule */
1914 char *lhsalias; /* Alias for the LHS */
1915 int nrhs; /* Number of right-hand side symbols seen */
1916 struct symbol *rhs[MAXRHS]; /* RHS symbols */
1917 char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
1918 struct rule *prevrule; /* Previous rule parsed */
1919 char *declkeyword; /* Keyword of a declaration */
1920 char **declargslot; /* Where the declaration argument should be put */
1921 int *decllnslot; /* Where the declaration linenumber is put */
1922 enum e_assoc declassoc; /* Assign this association to decl arguments */
1923 int preccounter; /* Assign this precedence to decl arguments */
1924 struct rule *firstrule; /* Pointer to first rule in the grammar */
1925 struct rule *lastrule; /* Pointer to the most recently parsed rule */
1928 /* Parse a single token */
1929 static void parseonetoken(psp)
1930 struct pstate *psp;
1932 char *x;
1933 x = Strsafe(psp->tokenstart); /* Save the token permanently */
1934 #if 0
1935 printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
1936 x,psp->state);
1937 #endif
1938 switch( psp->state ){
1939 case INITIALIZE:
1940 psp->prevrule = 0;
1941 psp->preccounter = 0;
1942 psp->firstrule = psp->lastrule = 0;
1943 psp->gp->nrule = 0;
1944 /* Fall thru to next case */
1945 case WAITING_FOR_DECL_OR_RULE:
1946 if( x[0]=='%' ){
1947 psp->state = WAITING_FOR_DECL_KEYWORD;
1948 }else if( islower(x[0]) ){
1949 psp->lhs = Symbol_new(x);
1950 psp->nrhs = 0;
1951 psp->lhsalias = 0;
1952 psp->state = WAITING_FOR_ARROW;
1953 }else if( x[0]=='{' ){
1954 if( psp->prevrule==0 ){
1955 ErrorMsg(psp->filename,psp->tokenlineno,
1956 "There is not prior rule opon which to attach the code \
1957 fragment which begins on this line.");
1958 psp->errorcnt++;
1959 }else if( psp->prevrule->code!=0 ){
1960 ErrorMsg(psp->filename,psp->tokenlineno,
1961 "Code fragment beginning on this line is not the first \
1962 to follow the previous rule.");
1963 psp->errorcnt++;
1964 }else{
1965 psp->prevrule->line = psp->tokenlineno;
1966 psp->prevrule->code = &x[1];
1968 }else if( x[0]=='[' ){
1969 psp->state = PRECEDENCE_MARK_1;
1970 }else{
1971 ErrorMsg(psp->filename,psp->tokenlineno,
1972 "Token \"%s\" should be either \"%%\" or a nonterminal name.",
1974 psp->errorcnt++;
1976 break;
1977 case PRECEDENCE_MARK_1:
1978 if( !isupper(x[0]) ){
1979 ErrorMsg(psp->filename,psp->tokenlineno,
1980 "The precedence symbol must be a terminal.");
1981 psp->errorcnt++;
1982 }else if( psp->prevrule==0 ){
1983 ErrorMsg(psp->filename,psp->tokenlineno,
1984 "There is no prior rule to assign precedence \"[%s]\".",x);
1985 psp->errorcnt++;
1986 }else if( psp->prevrule->precsym!=0 ){
1987 ErrorMsg(psp->filename,psp->tokenlineno,
1988 "Precedence mark on this line is not the first \
1989 to follow the previous rule.");
1990 psp->errorcnt++;
1991 }else{
1992 psp->prevrule->precsym = Symbol_new(x);
1994 psp->state = PRECEDENCE_MARK_2;
1995 break;
1996 case PRECEDENCE_MARK_2:
1997 if( x[0]!=']' ){
1998 ErrorMsg(psp->filename,psp->tokenlineno,
1999 "Missing \"]\" on precedence mark.");
2000 psp->errorcnt++;
2002 psp->state = WAITING_FOR_DECL_OR_RULE;
2003 break;
2004 case WAITING_FOR_ARROW:
2005 if( x[0]==':' && x[1]==':' && x[2]=='=' ){
2006 psp->state = IN_RHS;
2007 }else if( x[0]=='(' ){
2008 psp->state = LHS_ALIAS_1;
2009 }else{
2010 ErrorMsg(psp->filename,psp->tokenlineno,
2011 "Expected to see a \":\" following the LHS symbol \"%s\".",
2012 psp->lhs->name);
2013 psp->errorcnt++;
2014 psp->state = RESYNC_AFTER_RULE_ERROR;
2016 break;
2017 case LHS_ALIAS_1:
2018 if( isalpha(x[0]) ){
2019 psp->lhsalias = x;
2020 psp->state = LHS_ALIAS_2;
2021 }else{
2022 ErrorMsg(psp->filename,psp->tokenlineno,
2023 "\"%s\" is not a valid alias for the LHS \"%s\"\n",
2024 x,psp->lhs->name);
2025 psp->errorcnt++;
2026 psp->state = RESYNC_AFTER_RULE_ERROR;
2028 break;
2029 case LHS_ALIAS_2:
2030 if( x[0]==')' ){
2031 psp->state = LHS_ALIAS_3;
2032 }else{
2033 ErrorMsg(psp->filename,psp->tokenlineno,
2034 "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
2035 psp->errorcnt++;
2036 psp->state = RESYNC_AFTER_RULE_ERROR;
2038 break;
2039 case LHS_ALIAS_3:
2040 if( x[0]==':' && x[1]==':' && x[2]=='=' ){
2041 psp->state = IN_RHS;
2042 }else{
2043 ErrorMsg(psp->filename,psp->tokenlineno,
2044 "Missing \"->\" following: \"%s(%s)\".",
2045 psp->lhs->name,psp->lhsalias);
2046 psp->errorcnt++;
2047 psp->state = RESYNC_AFTER_RULE_ERROR;
2049 break;
2050 case IN_RHS:
2051 if( x[0]=='.' ){
2052 struct rule *rp;
2053 rp = (struct rule *)malloc( sizeof(struct rule) +
2054 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
2055 if( rp==0 ){
2056 ErrorMsg(psp->filename,psp->tokenlineno,
2057 "Can't allocate enough memory for this rule.");
2058 psp->errorcnt++;
2059 psp->prevrule = 0;
2060 }else{
2061 int i;
2062 rp->ruleline = psp->tokenlineno;
2063 rp->rhs = (struct symbol**)&rp[1];
2064 rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]);
2065 for(i=0; i<psp->nrhs; i++){
2066 rp->rhs[i] = psp->rhs[i];
2067 rp->rhsalias[i] = psp->alias[i];
2069 rp->lhs = psp->lhs;
2070 rp->lhsalias = psp->lhsalias;
2071 rp->nrhs = psp->nrhs;
2072 rp->code = 0;
2073 rp->precsym = 0;
2074 rp->index = psp->gp->nrule++;
2075 rp->nextlhs = rp->lhs->rule;
2076 rp->lhs->rule = rp;
2077 rp->next = 0;
2078 if( psp->firstrule==0 ){
2079 psp->firstrule = psp->lastrule = rp;
2080 }else{
2081 psp->lastrule->next = rp;
2082 psp->lastrule = rp;
2084 psp->prevrule = rp;
2086 psp->state = WAITING_FOR_DECL_OR_RULE;
2087 }else if( isalpha(x[0]) ){
2088 if( psp->nrhs>=MAXRHS ){
2089 ErrorMsg(psp->filename,psp->tokenlineno,
2090 "Too many symbol on RHS or rule beginning at \"%s\".",
2092 psp->errorcnt++;
2093 psp->state = RESYNC_AFTER_RULE_ERROR;
2094 }else{
2095 psp->rhs[psp->nrhs] = Symbol_new(x);
2096 psp->alias[psp->nrhs] = 0;
2097 psp->nrhs++;
2099 }else if( x[0]=='(' && psp->nrhs>0 ){
2100 psp->state = RHS_ALIAS_1;
2101 }else{
2102 ErrorMsg(psp->filename,psp->tokenlineno,
2103 "Illegal character on RHS of rule: \"%s\".",x);
2104 psp->errorcnt++;
2105 psp->state = RESYNC_AFTER_RULE_ERROR;
2107 break;
2108 case RHS_ALIAS_1:
2109 if( isalpha(x[0]) ){
2110 psp->alias[psp->nrhs-1] = x;
2111 psp->state = RHS_ALIAS_2;
2112 }else{
2113 ErrorMsg(psp->filename,psp->tokenlineno,
2114 "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
2115 x,psp->rhs[psp->nrhs-1]->name);
2116 psp->errorcnt++;
2117 psp->state = RESYNC_AFTER_RULE_ERROR;
2119 break;
2120 case RHS_ALIAS_2:
2121 if( x[0]==')' ){
2122 psp->state = IN_RHS;
2123 }else{
2124 ErrorMsg(psp->filename,psp->tokenlineno,
2125 "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
2126 psp->errorcnt++;
2127 psp->state = RESYNC_AFTER_RULE_ERROR;
2129 break;
2130 case WAITING_FOR_DECL_KEYWORD:
2131 if( isalpha(x[0]) ){
2132 psp->declkeyword = x;
2133 psp->declargslot = 0;
2134 psp->decllnslot = 0;
2135 psp->state = WAITING_FOR_DECL_ARG;
2136 if( strcmp(x,"name")==0 ){
2137 psp->declargslot = &(psp->gp->name);
2138 }else if( strcmp(x,"include")==0 ){
2139 psp->declargslot = &(psp->gp->include);
2140 psp->decllnslot = &psp->gp->includeln;
2141 }else if( strcmp(x,"code")==0 ){
2142 psp->declargslot = &(psp->gp->extracode);
2143 psp->decllnslot = &psp->gp->extracodeln;
2144 }else if( strcmp(x,"token_destructor")==0 ){
2145 psp->declargslot = &psp->gp->tokendest;
2146 psp->decllnslot = &psp->gp->tokendestln;
2147 }else if( strcmp(x,"default_destructor")==0 ){
2148 psp->declargslot = &psp->gp->vardest;
2149 psp->decllnslot = &psp->gp->vardestln;
2150 }else if( strcmp(x,"token_prefix")==0 ){
2151 psp->declargslot = &psp->gp->tokenprefix;
2152 }else if( strcmp(x,"syntax_error")==0 ){
2153 psp->declargslot = &(psp->gp->error);
2154 psp->decllnslot = &psp->gp->errorln;
2155 }else if( strcmp(x,"parse_accept")==0 ){
2156 psp->declargslot = &(psp->gp->accept);
2157 psp->decllnslot = &psp->gp->acceptln;
2158 }else if( strcmp(x,"parse_failure")==0 ){
2159 psp->declargslot = &(psp->gp->failure);
2160 psp->decllnslot = &psp->gp->failureln;
2161 }else if( strcmp(x,"stack_overflow")==0 ){
2162 psp->declargslot = &(psp->gp->overflow);
2163 psp->decllnslot = &psp->gp->overflowln;
2164 }else if( strcmp(x,"extra_argument")==0 ){
2165 psp->declargslot = &(psp->gp->arg);
2166 }else if( strcmp(x,"token_type")==0 ){
2167 psp->declargslot = &(psp->gp->tokentype);
2168 }else if( strcmp(x,"default_type")==0 ){
2169 psp->declargslot = &(psp->gp->vartype);
2170 }else if( strcmp(x,"stack_size")==0 ){
2171 psp->declargslot = &(psp->gp->stacksize);
2172 }else if( strcmp(x,"start_symbol")==0 ){
2173 psp->declargslot = &(psp->gp->start);
2174 }else if( strcmp(x,"left")==0 ){
2175 psp->preccounter++;
2176 psp->declassoc = LEFT;
2177 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2178 }else if( strcmp(x,"right")==0 ){
2179 psp->preccounter++;
2180 psp->declassoc = RIGHT;
2181 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2182 }else if( strcmp(x,"nonassoc")==0 ){
2183 psp->preccounter++;
2184 psp->declassoc = NONE;
2185 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2186 }else if( strcmp(x,"destructor")==0 ){
2187 psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
2188 }else if( strcmp(x,"type")==0 ){
2189 psp->state = WAITING_FOR_DATATYPE_SYMBOL;
2190 }else if( strcmp(x,"fallback")==0 ){
2191 psp->fallback = 0;
2192 psp->state = WAITING_FOR_FALLBACK_ID;
2193 }else{
2194 ErrorMsg(psp->filename,psp->tokenlineno,
2195 "Unknown declaration keyword: \"%%%s\".",x);
2196 psp->errorcnt++;
2197 psp->state = RESYNC_AFTER_DECL_ERROR;
2199 }else{
2200 ErrorMsg(psp->filename,psp->tokenlineno,
2201 "Illegal declaration keyword: \"%s\".",x);
2202 psp->errorcnt++;
2203 psp->state = RESYNC_AFTER_DECL_ERROR;
2205 break;
2206 case WAITING_FOR_DESTRUCTOR_SYMBOL:
2207 if( !isalpha(x[0]) ){
2208 ErrorMsg(psp->filename,psp->tokenlineno,
2209 "Symbol name missing after %destructor keyword");
2210 psp->errorcnt++;
2211 psp->state = RESYNC_AFTER_DECL_ERROR;
2212 }else{
2213 struct symbol *sp = Symbol_new(x);
2214 psp->declargslot = &sp->destructor;
2215 psp->decllnslot = &sp->destructorln;
2216 psp->state = WAITING_FOR_DECL_ARG;
2218 break;
2219 case WAITING_FOR_DATATYPE_SYMBOL:
2220 if( !isalpha(x[0]) ){
2221 ErrorMsg(psp->filename,psp->tokenlineno,
2222 "Symbol name missing after %destructor keyword");
2223 psp->errorcnt++;
2224 psp->state = RESYNC_AFTER_DECL_ERROR;
2225 }else{
2226 struct symbol *sp = Symbol_new(x);
2227 psp->declargslot = &sp->datatype;
2228 psp->decllnslot = 0;
2229 psp->state = WAITING_FOR_DECL_ARG;
2231 break;
2232 case WAITING_FOR_PRECEDENCE_SYMBOL:
2233 if( x[0]=='.' ){
2234 psp->state = WAITING_FOR_DECL_OR_RULE;
2235 }else if( isupper(x[0]) ){
2236 struct symbol *sp;
2237 sp = Symbol_new(x);
2238 if( sp->prec>=0 ){
2239 ErrorMsg(psp->filename,psp->tokenlineno,
2240 "Symbol \"%s\" has already be given a precedence.",x);
2241 psp->errorcnt++;
2242 }else{
2243 sp->prec = psp->preccounter;
2244 sp->assoc = psp->declassoc;
2246 }else{
2247 ErrorMsg(psp->filename,psp->tokenlineno,
2248 "Can't assign a precedence to \"%s\".",x);
2249 psp->errorcnt++;
2251 break;
2252 case WAITING_FOR_DECL_ARG:
2253 if( (x[0]=='{' || x[0]=='\"' || isalnum(x[0])) ){
2254 if( *(psp->declargslot)!=0 ){
2255 ErrorMsg(psp->filename,psp->tokenlineno,
2256 "The argument \"%s\" to declaration \"%%%s\" is not the first.",
2257 x[0]=='\"' ? &x[1] : x,psp->declkeyword);
2258 psp->errorcnt++;
2259 psp->state = RESYNC_AFTER_DECL_ERROR;
2260 }else{
2261 *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x;
2262 if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno;
2263 psp->state = WAITING_FOR_DECL_OR_RULE;
2265 }else{
2266 ErrorMsg(psp->filename,psp->tokenlineno,
2267 "Illegal argument to %%%s: %s",psp->declkeyword,x);
2268 psp->errorcnt++;
2269 psp->state = RESYNC_AFTER_DECL_ERROR;
2271 break;
2272 case WAITING_FOR_FALLBACK_ID:
2273 if( x[0]=='.' ){
2274 psp->state = WAITING_FOR_DECL_OR_RULE;
2275 }else if( !isupper(x[0]) ){
2276 ErrorMsg(psp->filename, psp->tokenlineno,
2277 "%%fallback argument \"%s\" should be a token", x);
2278 psp->errorcnt++;
2279 }else{
2280 struct symbol *sp = Symbol_new(x);
2281 if( psp->fallback==0 ){
2282 psp->fallback = sp;
2283 }else if( sp->fallback ){
2284 ErrorMsg(psp->filename, psp->tokenlineno,
2285 "More than one fallback assigned to token %s", x);
2286 psp->errorcnt++;
2287 }else{
2288 sp->fallback = psp->fallback;
2289 psp->gp->has_fallback = 1;
2292 break;
2293 case RESYNC_AFTER_RULE_ERROR:
2294 /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2295 ** break; */
2296 case RESYNC_AFTER_DECL_ERROR:
2297 if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2298 if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
2299 break;
2303 /* In spite of its name, this function is really a scanner. It read
2304 ** in the entire input file (all at once) then tokenizes it. Each
2305 ** token is passed to the function "parseonetoken" which builds all
2306 ** the appropriate data structures in the global state vector "gp".
2308 struct pstate ps;
2309 void Parse(gp)
2310 struct lemon *gp;
2312 FILE *fp;
2313 char *filebuf;
2314 size_t filesize;
2315 int lineno;
2316 int c;
2317 char *cp, *nextcp;
2318 int startline = 0;
2320 ps.gp = gp;
2321 ps.filename = gp->filename;
2322 ps.errorcnt = 0;
2323 ps.state = INITIALIZE;
2325 /* Begin by reading the input file */
2326 fp = fopen(ps.filename,"rb");
2327 if( fp==0 ){
2328 ErrorMsg(ps.filename,0,"Can't open this file for reading.");
2329 gp->errorcnt++;
2330 return;
2332 fseek(fp,0,2);
2333 filesize = ftell(fp);
2334 rewind(fp);
2335 filebuf = (char *)malloc( filesize+1 );
2336 if( filebuf==0 ){
2337 ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.",
2338 filesize+1);
2339 fclose(fp);
2340 gp->errorcnt++;
2341 return;
2343 if( fread(filebuf,1,filesize,fp)!=filesize ){
2344 ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
2345 filesize);
2346 free(filebuf);
2347 fclose(fp);
2348 gp->errorcnt++;
2349 return;
2351 fclose(fp);
2352 filebuf[filesize] = 0;
2354 /* Now scan the text of the input file */
2355 lineno = 1;
2356 for(cp=filebuf; (c= *cp)!=0; ){
2357 if( c=='\n' ) lineno++; /* Keep track of the line number */
2358 if( isspace(c) ){ cp++; continue; } /* Skip all white space */
2359 if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */
2360 cp+=2;
2361 while( (c= *cp)!=0 && c!='\n' ) cp++;
2362 continue;
2364 if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */
2365 cp+=2;
2366 while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
2367 if( c=='\n' ) lineno++;
2368 cp++;
2370 if( c ) cp++;
2371 continue;
2373 ps.tokenstart = cp; /* Mark the beginning of the token */
2374 ps.tokenlineno = lineno; /* Linenumber on which token begins */
2375 if( c=='\"' ){ /* String literals */
2376 cp++;
2377 while( (c= *cp)!=0 && c!='\"' ){
2378 if( c=='\n' ) lineno++;
2379 cp++;
2381 if( c==0 ){
2382 ErrorMsg(ps.filename,startline,
2383 "String starting on this line is not terminated before the end of the file.");
2384 ps.errorcnt++;
2385 nextcp = cp;
2386 }else{
2387 nextcp = cp+1;
2389 }else if( c=='{' ){ /* A block of C code */
2390 int level;
2391 cp++;
2392 for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
2393 if( c=='\n' ) lineno++;
2394 else if( c=='{' ) level++;
2395 else if( c=='}' ) level--;
2396 else if( c=='/' && cp[1]=='*' ){ /* Skip comments */
2397 int prevc;
2398 cp = &cp[2];
2399 prevc = 0;
2400 while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
2401 if( c=='\n' ) lineno++;
2402 prevc = c;
2403 cp++;
2405 }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
2406 cp = &cp[2];
2407 while( (c= *cp)!=0 && c!='\n' ) cp++;
2408 if( c ) lineno++;
2409 }else if( c=='\'' || c=='\"' ){ /* String a character literals */
2410 int startchar, prevc;
2411 startchar = c;
2412 prevc = 0;
2413 for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
2414 if( c=='\n' ) lineno++;
2415 if( prevc=='\\' ) prevc = 0;
2416 else prevc = c;
2420 if( c==0 ){
2421 ErrorMsg(ps.filename,ps.tokenlineno,
2422 "C code starting on this line is not terminated before the end of the file.");
2423 ps.errorcnt++;
2424 nextcp = cp;
2425 }else{
2426 nextcp = cp+1;
2428 }else if( isalnum(c) ){ /* Identifiers */
2429 while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
2430 nextcp = cp;
2431 }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
2432 cp += 3;
2433 nextcp = cp;
2434 }else{ /* All other (one character) operators */
2435 cp++;
2436 nextcp = cp;
2438 c = *cp;
2439 *cp = 0; /* Null terminate the token */
2440 parseonetoken(&ps); /* Parse the token */
2441 *cp = c; /* Restore the buffer */
2442 cp = nextcp;
2444 free(filebuf); /* Release the buffer after parsing */
2445 gp->rule = ps.firstrule;
2446 gp->errorcnt = ps.errorcnt;
2448 /*************************** From the file "plink.c" *********************/
2450 ** Routines processing configuration follow-set propagation links
2451 ** in the LEMON parser generator.
2453 static struct plink *plink_freelist = 0;
2455 /* Allocate a new plink */
2456 struct plink *Plink_new(){
2457 struct plink *new;
2459 if( plink_freelist==0 ){
2460 int i;
2461 int amt = 100;
2462 plink_freelist = (struct plink *)malloc( sizeof(struct plink)*amt );
2463 if( plink_freelist==0 ){
2464 fprintf(stderr,
2465 "Unable to allocate memory for a new follow-set propagation link.\n");
2466 exit(1);
2468 for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
2469 plink_freelist[amt-1].next = 0;
2471 new = plink_freelist;
2472 plink_freelist = plink_freelist->next;
2473 return new;
2476 /* Add a plink to a plink list */
2477 void Plink_add(plpp,cfp)
2478 struct plink **plpp;
2479 struct config *cfp;
2481 struct plink *new;
2482 new = Plink_new();
2483 new->next = *plpp;
2484 *plpp = new;
2485 new->cfp = cfp;
2488 /* Transfer every plink on the list "from" to the list "to" */
2489 void Plink_copy(to,from)
2490 struct plink **to;
2491 struct plink *from;
2493 struct plink *nextpl;
2494 while( from ){
2495 nextpl = from->next;
2496 from->next = *to;
2497 *to = from;
2498 from = nextpl;
2502 /* Delete every plink on the list */
2503 void Plink_delete(plp)
2504 struct plink *plp;
2506 struct plink *nextpl;
2508 while( plp ){
2509 nextpl = plp->next;
2510 plp->next = plink_freelist;
2511 plink_freelist = plp;
2512 plp = nextpl;
2515 /*********************** From the file "report.c" **************************/
2517 ** Procedures for generating reports and tables in the LEMON parser generator.
2520 /* Generate a filename with the given suffix. Space to hold the
2521 ** name comes from malloc() and must be freed by the calling
2522 ** function.
2524 PRIVATE char *file_makename(lemp,suffix)
2525 struct lemon *lemp;
2526 char *suffix;
2528 char *name;
2529 char *cp;
2531 name = malloc( strlen(lemp->filename) + strlen(suffix) + 5 );
2532 if( name==0 ){
2533 fprintf(stderr,"Can't allocate space for a filename.\n");
2534 exit(1);
2536 /* skip directory, JK */
2537 if (NULL == (cp = strrchr(lemp->filename, '/'))) {
2538 cp = lemp->filename;
2539 } else {
2540 cp++;
2542 strcpy(name,cp);
2543 cp = strrchr(name,'.');
2544 if( cp ) *cp = 0;
2545 strcat(name,suffix);
2546 return name;
2549 /* Open a file with a name based on the name of the input file,
2550 ** but with a different (specified) suffix, and return a pointer
2551 ** to the stream */
2552 PRIVATE FILE *file_open(lemp,suffix,mode)
2553 struct lemon *lemp;
2554 char *suffix;
2555 char *mode;
2557 FILE *fp;
2559 if( lemp->outname ) free(lemp->outname);
2560 lemp->outname = file_makename(lemp, suffix);
2561 fp = fopen(lemp->outname,mode);
2562 if( fp==0 && *mode=='w' ){
2563 fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
2564 lemp->errorcnt++;
2565 return 0;
2567 return fp;
2570 /* Duplicate the input file without comments and without actions
2571 ** on rules */
2572 void Reprint(lemp)
2573 struct lemon *lemp;
2575 struct rule *rp;
2576 struct symbol *sp;
2577 int i, j, maxlen, len, ncolumns, skip;
2578 printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
2579 maxlen = 10;
2580 for(i=0; i<lemp->nsymbol; i++){
2581 sp = lemp->symbols[i];
2582 len = strlen(sp->name);
2583 if( len>maxlen ) maxlen = len;
2585 ncolumns = 76/(maxlen+5);
2586 if( ncolumns<1 ) ncolumns = 1;
2587 skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
2588 for(i=0; i<skip; i++){
2589 printf("//");
2590 for(j=i; j<lemp->nsymbol; j+=skip){
2591 sp = lemp->symbols[j];
2592 assert( sp->index==j );
2593 printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
2595 printf("\n");
2597 for(rp=lemp->rule; rp; rp=rp->next){
2598 printf("%s",rp->lhs->name);
2599 /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
2600 printf(" ::=");
2601 for(i=0; i<rp->nrhs; i++){
2602 printf(" %s",rp->rhs[i]->name);
2603 /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
2605 printf(".");
2606 if( rp->precsym ) printf(" [%s]",rp->precsym->name);
2607 /* if( rp->code ) printf("\n %s",rp->code); */
2608 printf("\n");
2612 PRIVATE void ConfigPrint(fp,cfp)
2613 FILE *fp;
2614 struct config *cfp;
2616 struct rule *rp;
2617 int i;
2618 rp = cfp->rp;
2619 fprintf(fp,"%s ::=",rp->lhs->name);
2620 for(i=0; i<=rp->nrhs; i++){
2621 if( i==cfp->dot ) fprintf(fp," *");
2622 if( i==rp->nrhs ) break;
2623 fprintf(fp," %s",rp->rhs[i]->name);
2627 /* #define TEST */
2628 #ifdef TEST
2629 /* Print a set */
2630 PRIVATE void SetPrint(out,set,lemp)
2631 FILE *out;
2632 char *set;
2633 struct lemon *lemp;
2635 int i;
2636 char *spacer;
2637 spacer = "";
2638 fprintf(out,"%12s[","");
2639 for(i=0; i<lemp->nterminal; i++){
2640 if( SetFind(set,i) ){
2641 fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
2642 spacer = " ";
2645 fprintf(out,"]\n");
2648 /* Print a plink chain */
2649 void PlinkPrint(out,plp,tag)
2650 FILE *out;
2651 struct plink *plp;
2652 char *tag;
2654 while( plp ){
2655 fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->index);
2656 ConfigPrint(out,plp->cfp);
2657 fprintf(out,"\n");
2658 plp = plp->next;
2661 #endif
2663 /* Print an action to the given file descriptor. Return FALSE if
2664 ** nothing was actually printed.
2666 PRIVATE int PrintAction(struct action *ap, FILE *fp, int indent){
2667 int result = 1;
2668 switch( ap->type ){
2669 case SHIFT:
2670 fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->index);
2671 break;
2672 case REDUCE:
2673 fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
2674 break;
2675 case ACCEPT:
2676 fprintf(fp,"%*s accept",indent,ap->sp->name);
2677 break;
2678 case ERROR:
2679 fprintf(fp,"%*s error",indent,ap->sp->name);
2680 break;
2681 case CONFLICT:
2682 fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
2683 indent,ap->sp->name,ap->x.rp->index);
2684 break;
2685 case SH_RESOLVED:
2686 case RD_RESOLVED:
2687 case NOT_USED:
2688 result = 0;
2689 break;
2691 return result;
2694 /* Generate the "y.output" log file */
2695 void ReportOutput(lemp)
2696 struct lemon *lemp;
2698 int i;
2699 struct state *stp;
2700 struct config *cfp;
2701 struct action *ap;
2702 FILE *fp;
2704 fp = file_open(lemp,".out","w");
2705 if( fp==0 ) return;
2706 fprintf(fp," \b");
2707 for(i=0; i<lemp->nstate; i++){
2708 stp = lemp->sorted[i];
2709 fprintf(fp,"State %d:\n",stp->index);
2710 if( lemp->basisflag ) cfp=stp->bp;
2711 else cfp=stp->cfp;
2712 while( cfp ){
2713 char buf[20];
2714 if( cfp->dot==cfp->rp->nrhs ){
2715 sprintf(buf,"(%d)",cfp->rp->index);
2716 fprintf(fp," %5s ",buf);
2717 }else{
2718 fprintf(fp," ");
2720 ConfigPrint(fp,cfp);
2721 fprintf(fp,"\n");
2722 #ifdef TEST
2723 SetPrint(fp,cfp->fws,lemp);
2724 PlinkPrint(fp,cfp->fplp,"To ");
2725 PlinkPrint(fp,cfp->bplp,"From");
2726 #endif
2727 if( lemp->basisflag ) cfp=cfp->bp;
2728 else cfp=cfp->next;
2730 fprintf(fp,"\n");
2731 for(ap=stp->ap; ap; ap=ap->next){
2732 if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
2734 fprintf(fp,"\n");
2736 fclose(fp);
2737 return;
2740 /* Search for the file "name" which is in the same directory as
2741 ** the exacutable */
2742 PRIVATE char *pathsearch(argv0,name,modemask)
2743 char *argv0;
2744 char *name;
2745 int modemask;
2747 char *pathlist;
2748 char *path,*cp;
2749 char c;
2751 #ifdef __WIN32__
2752 cp = strrchr(argv0,'\\');
2753 #else
2754 cp = strrchr(argv0,'/');
2755 #endif
2756 if( cp ){
2757 c = *cp;
2758 *cp = 0;
2759 path = (char *)malloc( strlen(argv0) + strlen(name) + 2 );
2760 if( path ) sprintf(path,"%s/%s",argv0,name);
2761 *cp = c;
2762 }else{
2763 pathlist = getenv("PATH");
2764 if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
2765 path = (char *)malloc( strlen(pathlist)+strlen(name)+2 );
2766 if( path!=0 ){
2767 while( *pathlist ){
2768 cp = strchr(pathlist,':');
2769 if( cp==0 ) cp = &pathlist[strlen(pathlist)];
2770 c = *cp;
2771 *cp = 0;
2772 sprintf(path,"%s/%s",pathlist,name);
2773 *cp = c;
2774 if( c==0 ) pathlist = "";
2775 else pathlist = &cp[1];
2776 if( access(path,modemask)==0 ) break;
2780 return path;
2783 /* Given an action, compute the integer value for that action
2784 ** which is to be put in the action table of the generated machine.
2785 ** Return negative if no action should be generated.
2787 PRIVATE int compute_action(lemp,ap)
2788 struct lemon *lemp;
2789 struct action *ap;
2791 int act;
2792 switch( ap->type ){
2793 case SHIFT: act = ap->x.stp->index; break;
2794 case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
2795 case ERROR: act = lemp->nstate + lemp->nrule; break;
2796 case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
2797 default: act = -1; break;
2799 return act;
2802 #define LINESIZE 1000
2803 /* The next cluster of routines are for reading the template file
2804 ** and writing the results to the generated parser */
2805 /* The first function transfers data from "in" to "out" until
2806 ** a line is seen which begins with "%%". The line number is
2807 ** tracked.
2809 ** if name!=0, then any word that begin with "Parse" is changed to
2810 ** begin with *name instead.
2812 PRIVATE void tplt_xfer(name,in,out,lineno)
2813 char *name;
2814 FILE *in;
2815 FILE *out;
2816 int *lineno;
2818 int i, iStart;
2819 char line[LINESIZE];
2820 while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
2821 (*lineno)++;
2822 iStart = 0;
2823 if( name ){
2824 for(i=0; line[i]; i++){
2825 if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
2826 && (i==0 || !isalpha(line[i-1]))
2828 if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
2829 fprintf(out,"%s",name);
2830 i += 4;
2831 iStart = i+1;
2835 fprintf(out,"%s",&line[iStart]);
2839 /* The next function finds the template file and opens it, returning
2840 ** a pointer to the opened file. */
2841 PRIVATE FILE *tplt_open(lemp)
2842 struct lemon *lemp;
2845 char buf[1000];
2846 FILE *in;
2847 char *tpltname;
2848 char *tpltname_alloc = NULL;
2849 char *cp;
2851 cp = strrchr(lemp->filename,'.');
2852 if( cp ){
2853 sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
2854 }else{
2855 sprintf(buf,"%s.lt",lemp->filename);
2857 if( access(buf,004)==0 ){
2858 tpltname = buf;
2859 }else if( access(lemp->tmplname,004)==0 ){
2860 tpltname = lemp->tmplname;
2861 }else{
2862 tpltname = tpltname_alloc = pathsearch(lemp->argv0,lemp->tmplname,0);
2864 if( tpltname==0 ){
2865 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
2866 lemp->tmplname);
2867 lemp->errorcnt++;
2868 return 0;
2870 in = fopen(tpltname,"r");
2871 if( in==0 ){
2872 fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname);
2873 lemp->errorcnt++;
2875 if (tpltname_alloc) free(tpltname_alloc);
2876 return in;
2879 /* Print a string to the file and keep the linenumber up to date */
2880 PRIVATE void tplt_print(out,lemp,str,strln,lineno)
2881 FILE *out;
2882 struct lemon *lemp;
2883 char *str;
2884 int strln;
2885 int *lineno;
2887 if( str==0 ) return;
2888 fprintf(out,"#line %d \"%s\"\n",strln,lemp->filename); (*lineno)++;
2889 while( *str ){
2890 if( *str=='\n' ) (*lineno)++;
2891 putc(*str,out);
2892 str++;
2894 fprintf(out,"\n#line %d \"%s\"\n",*lineno+2,lemp->outname); (*lineno)+=2;
2895 return;
2899 ** The following routine emits code for the destructor for the
2900 ** symbol sp
2902 PRIVATE void emit_destructor_code(out,sp,lemp,lineno)
2903 FILE *out;
2904 struct symbol *sp;
2905 struct lemon *lemp;
2906 int *lineno;
2908 char *cp = 0;
2910 int linecnt = 0;
2911 if( sp->type==TERMINAL ){
2912 cp = lemp->tokendest;
2913 if( cp==0 ) return;
2914 fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
2915 }else if( sp->destructor ){
2916 cp = sp->destructor;
2917 fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
2918 }else{
2919 cp = lemp->vardest;
2920 if( cp==0 ) return;
2921 fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
2923 for(; *cp; cp++){
2924 if( *cp=='$' && cp[1]=='$' ){
2925 fprintf(out,"(yypminor->yy%d)",sp->dtnum);
2926 cp++;
2927 continue;
2929 if( *cp=='\n' ) linecnt++;
2930 fputc(*cp,out);
2932 (*lineno) += 3 + linecnt;
2933 fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
2934 return;
2938 ** Return TRUE (non-zero) if the given symbol has a destructor.
2940 PRIVATE int has_destructor(sp, lemp)
2941 struct symbol *sp;
2942 struct lemon *lemp;
2944 int ret;
2945 if( sp->type==TERMINAL ){
2946 ret = lemp->tokendest!=0;
2947 }else{
2948 ret = lemp->vardest!=0 || sp->destructor!=0;
2950 return ret;
2954 ** Generate code which executes when the rule "rp" is reduced. Write
2955 ** the code to "out". Make sure lineno stays up-to-date.
2957 PRIVATE void emit_code(out,rp,lemp,lineno)
2958 FILE *out;
2959 struct rule *rp;
2960 struct lemon *lemp;
2961 int *lineno;
2963 char *cp, *xp;
2964 int linecnt = 0;
2965 int i;
2966 char lhsused = 0; /* True if the LHS element has been used */
2967 char used[MAXRHS]; /* True for each RHS element which is used */
2969 for(i=0; i<rp->nrhs; i++) used[i] = 0;
2970 lhsused = 0;
2972 /* Generate code to do the reduce action */
2973 if( rp->code ){
2974 fprintf(out,"#line %d \"%s\"\n{",rp->line,lemp->filename);
2975 for(cp=rp->code; *cp; cp++){
2976 if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
2977 char saved;
2978 for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
2979 saved = *xp;
2980 *xp = 0;
2981 if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
2982 fprintf(out,"yygotominor.yy%d",rp->lhs->dtnum);
2983 cp = xp;
2984 lhsused = 1;
2985 }else{
2986 for(i=0; i<rp->nrhs; i++){
2987 if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
2988 fprintf(out,"yymsp[%d].minor.yy%d",i-rp->nrhs+1,rp->rhs[i]->dtnum);
2989 cp = xp;
2990 used[i] = 1;
2991 break;
2995 *xp = saved;
2997 if( *cp=='\n' ) linecnt++;
2998 fputc(*cp,out);
2999 } /* End loop */
3000 (*lineno) += 3 + linecnt;
3001 fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
3002 } /* End if( rp->code ) */
3004 /* Check to make sure the LHS has been used */
3005 if( rp->lhsalias && !lhsused ){
3006 ErrorMsg(lemp->filename,rp->ruleline,
3007 "Label \"%s\" for \"%s(%s)\" is never used.",
3008 rp->lhsalias,rp->lhs->name,rp->lhsalias);
3009 lemp->errorcnt++;
3012 /* Generate destructor code for RHS symbols which are not used in the
3013 ** reduce code */
3014 for(i=0; i<rp->nrhs; i++){
3015 if( rp->rhsalias[i] && !used[i] ){
3016 ErrorMsg(lemp->filename,rp->ruleline,
3017 "Label %s for \"%s(%s)\" is never used.",
3018 rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
3019 lemp->errorcnt++;
3020 }else if( rp->rhsalias[i]==0 ){
3021 if( has_destructor(rp->rhs[i],lemp) ){
3022 fprintf(out," yy_destructor(%d,&yymsp[%d].minor);\n",
3023 rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++;
3024 }else{
3025 fprintf(out," /* No destructor defined for %s */\n",
3026 rp->rhs[i]->name);
3027 (*lineno)++;
3031 return;
3035 ** Print the definition of the union used for the parser's data stack.
3036 ** This union contains fields for every possible data type for tokens
3037 ** and nonterminals. In the process of computing and printing this
3038 ** union, also set the ".dtnum" field of every terminal and nonterminal
3039 ** symbol.
3041 PRIVATE void print_stack_union(out,lemp,plineno,mhflag)
3042 FILE *out; /* The output stream */
3043 struct lemon *lemp; /* The main info structure for this parser */
3044 int *plineno; /* Pointer to the line number */
3045 int mhflag; /* True if generating makeheaders output */
3047 int lineno; /* The line number of the output */
3048 char **types; /* A hash table of datatypes */
3049 int arraysize; /* Size of the "types" array */
3050 int maxdtlength; /* Maximum length of any ".datatype" field. */
3051 char *stddt; /* Standardized name for a datatype */
3052 int i,j; /* Loop counters */
3053 int hash; /* For hashing the name of a type */
3054 char *name; /* Name of the parser */
3056 /* Allocate and initialize types[] and allocate stddt[] */
3057 arraysize = lemp->nsymbol * 2;
3058 types = (char**)malloc( arraysize * sizeof(char*) );
3059 for(i=0; i<arraysize; i++) types[i] = 0;
3060 maxdtlength = 0;
3061 if( lemp->vartype ){
3062 maxdtlength = strlen(lemp->vartype);
3064 for(i=0; i<lemp->nsymbol; i++){
3065 int len;
3066 struct symbol *sp = lemp->symbols[i];
3067 if( sp->datatype==0 ) continue;
3068 len = strlen(sp->datatype);
3069 if( len>maxdtlength ) maxdtlength = len;
3071 stddt = (char*)malloc( maxdtlength*2 + 1 );
3072 if( types==0 || stddt==0 ){
3073 fprintf(stderr,"Out of memory.\n");
3074 exit(1);
3077 /* Build a hash table of datatypes. The ".dtnum" field of each symbol
3078 ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
3079 ** used for terminal symbols. If there is no %default_type defined then
3080 ** 0 is also used as the .dtnum value for nonterminals which do not specify
3081 ** a datatype using the %type directive.
3083 for(i=0; i<lemp->nsymbol; i++){
3084 struct symbol *sp = lemp->symbols[i];
3085 char *cp;
3086 if( sp==lemp->errsym ){
3087 sp->dtnum = arraysize+1;
3088 continue;
3090 if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
3091 sp->dtnum = 0;
3092 continue;
3094 cp = sp->datatype;
3095 if( cp==0 ) cp = lemp->vartype;
3096 j = 0;
3097 while( isspace(*cp) ) cp++;
3098 while( *cp ) stddt[j++] = *cp++;
3099 while( j>0 && isspace(stddt[j-1]) ) j--;
3100 stddt[j] = 0;
3101 hash = 0;
3102 for(j=0; stddt[j]; j++){
3103 hash = (unsigned int)hash*53u + (unsigned int) stddt[j];
3105 hash = (hash & 0x7fffffff)%arraysize;
3106 while( types[hash] ){
3107 if( strcmp(types[hash],stddt)==0 ){
3108 sp->dtnum = hash + 1;
3109 break;
3111 hash++;
3112 if( hash>=arraysize ) hash = 0;
3114 if( types[hash]==0 ){
3115 sp->dtnum = hash + 1;
3116 types[hash] = (char*)malloc( strlen(stddt)+1 );
3117 if( types[hash]==0 ){
3118 fprintf(stderr,"Out of memory.\n");
3119 exit(1);
3121 strcpy(types[hash],stddt);
3125 /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
3126 name = lemp->name ? lemp->name : "Parse";
3127 lineno = *plineno;
3128 if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
3129 fprintf(out,"#define %sTOKENTYPE %s\n",name,
3130 lemp->tokentype?lemp->tokentype:"void*"); lineno++;
3131 if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
3132 fprintf(out,"typedef union {\n"); lineno++;
3133 fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++;
3134 for(i=0; i<arraysize; i++){
3135 if( types[i]==0 ) continue;
3136 fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
3137 free(types[i]);
3139 fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
3140 free(stddt);
3141 free(types);
3142 fprintf(out,"} YYMINORTYPE;\n"); lineno++;
3143 *plineno = lineno;
3147 ** Return the name of a C datatype able to represent values between
3148 ** lwr and upr, inclusive.
3150 static const char *minimum_size_type(int lwr, int upr){
3151 if( lwr>=0 ){
3152 if( upr<=255 ){
3153 return "unsigned char";
3154 }else if( upr<65535 ){
3155 return "unsigned short int";
3156 }else{
3157 return "unsigned int";
3159 }else if( lwr>=-127 && upr<=127 ){
3160 return "signed char";
3161 }else if( lwr>=-32767 && upr<32767 ){
3162 return "short";
3163 }else{
3164 return "int";
3169 ** Each state contains a set of token transaction and a set of
3170 ** nonterminal transactions. Each of these sets makes an instance
3171 ** of the following structure. An array of these structures is used
3172 ** to order the creation of entries in the yy_action[] table.
3174 struct axset {
3175 struct state *stp; /* A pointer to a state */
3176 int isTkn; /* True to use tokens. False for non-terminals */
3177 int nAction; /* Number of actions */
3181 ** Compare to axset structures for sorting purposes
3183 static int axset_compare(const void *a, const void *b){
3184 struct axset *p1 = (struct axset*)a;
3185 struct axset *p2 = (struct axset*)b;
3186 return p2->nAction - p1->nAction;
3189 /* Generate C source code for the parser */
3190 void ReportTable(lemp, mhflag)
3191 struct lemon *lemp;
3192 int mhflag; /* Output in makeheaders format if true */
3194 FILE *out, *in;
3195 char line[LINESIZE];
3196 int lineno;
3197 struct state *stp;
3198 struct action *ap;
3199 struct rule *rp;
3200 struct acttab *pActtab;
3201 int i, j, n;
3202 int mnTknOfst, mxTknOfst;
3203 int mnNtOfst, mxNtOfst;
3204 struct axset *ax;
3205 char *name;
3207 in = tplt_open(lemp);
3208 if( in==0 ) return;
3209 out = file_open(lemp,".c","w");
3210 if( out==0 ){
3211 fclose(in);
3212 return;
3214 lineno = 1;
3215 tplt_xfer(lemp->name,in,out,&lineno);
3217 /* Generate the include code, if any */
3218 tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno);
3219 if( mhflag ){
3220 name = file_makename(lemp, ".h");
3221 fprintf(out,"#include \"%s\"\n", name); lineno++;
3222 free(name);
3224 tplt_xfer(lemp->name,in,out,&lineno);
3226 /* Generate #defines for all tokens */
3227 if( mhflag ){
3228 char *prefix;
3229 fprintf(out,"#if INTERFACE\n"); lineno++;
3230 if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3231 else prefix = "";
3232 for(i=1; i<lemp->nterminal; i++){
3233 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3234 lineno++;
3236 fprintf(out,"#endif\n"); lineno++;
3238 tplt_xfer(lemp->name,in,out,&lineno);
3240 /* Generate the defines */
3241 fprintf(out,"/* \001 */\n");
3242 fprintf(out,"#define YYCODETYPE %s\n",
3243 minimum_size_type(0, lemp->nsymbol+5)); lineno++;
3244 fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
3245 fprintf(out,"#define YYACTIONTYPE %s\n",
3246 minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++;
3247 print_stack_union(out,lemp,&lineno,mhflag);
3248 if( lemp->stacksize ){
3249 if( atoi(lemp->stacksize)<=0 ){
3250 ErrorMsg(lemp->filename,0,
3251 "Illegal stack size: [%s]. The stack size should be an integer constant.",
3252 lemp->stacksize);
3253 lemp->errorcnt++;
3254 lemp->stacksize = "100";
3256 fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
3257 }else{
3258 fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
3260 if( mhflag ){
3261 fprintf(out,"#if INTERFACE\n"); lineno++;
3263 name = lemp->name ? lemp->name : "Parse";
3264 if( lemp->arg && lemp->arg[0] ){
3265 i = strlen(lemp->arg);
3266 while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
3267 while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
3268 fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
3269 fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
3270 fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
3271 name,lemp->arg,&lemp->arg[i]); lineno++;
3272 fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
3273 name,&lemp->arg[i],&lemp->arg[i]); lineno++;
3274 }else{
3275 fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
3276 fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
3277 fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
3278 fprintf(out,"#define %sARG_STORE\n",name); lineno++;
3280 if( mhflag ){
3281 fprintf(out,"#endif\n"); lineno++;
3283 fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++;
3284 fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
3285 fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
3286 fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
3287 if( lemp->has_fallback ){
3288 fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
3290 tplt_xfer(lemp->name,in,out,&lineno);
3292 /* Generate the action table and its associates:
3294 ** yy_action[] A single table containing all actions.
3295 ** yy_lookahead[] A table containing the lookahead for each entry in
3296 ** yy_action. Used to detect hash collisions.
3297 ** yy_shift_ofst[] For each state, the offset into yy_action for
3298 ** shifting terminals.
3299 ** yy_reduce_ofst[] For each state, the offset into yy_action for
3300 ** shifting non-terminals after a reduce.
3301 ** yy_default[] Default action for each state.
3304 /* Compute the actions on all states and count them up */
3305 ax = malloc( sizeof(ax[0])*lemp->nstate*2 );
3306 if( ax==0 ){
3307 fprintf(stderr,"malloc failed\n");
3308 exit(1);
3310 for(i=0; i<lemp->nstate; i++){
3311 stp = lemp->sorted[i];
3312 stp->nTknAct = stp->nNtAct = 0;
3313 stp->iDflt = lemp->nstate + lemp->nrule;
3314 stp->iTknOfst = NO_OFFSET;
3315 stp->iNtOfst = NO_OFFSET;
3316 for(ap=stp->ap; ap; ap=ap->next){
3317 if( compute_action(lemp,ap)>=0 ){
3318 if( ap->sp->index<lemp->nterminal ){
3319 stp->nTknAct++;
3320 }else if( ap->sp->index<lemp->nsymbol ){
3321 stp->nNtAct++;
3322 }else{
3323 stp->iDflt = compute_action(lemp, ap);
3327 ax[i*2].stp = stp;
3328 ax[i*2].isTkn = 1;
3329 ax[i*2].nAction = stp->nTknAct;
3330 ax[i*2+1].stp = stp;
3331 ax[i*2+1].isTkn = 0;
3332 ax[i*2+1].nAction = stp->nNtAct;
3334 mxTknOfst = mnTknOfst = 0;
3335 mxNtOfst = mnNtOfst = 0;
3337 /* Compute the action table. In order to try to keep the size of the
3338 ** action table to a minimum, the heuristic of placing the largest action
3339 ** sets first is used.
3341 qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare);
3342 pActtab = acttab_alloc();
3343 for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){
3344 stp = ax[i].stp;
3345 if( ax[i].isTkn ){
3346 for(ap=stp->ap; ap; ap=ap->next){
3347 int action;
3348 if( ap->sp->index>=lemp->nterminal ) continue;
3349 action = compute_action(lemp, ap);
3350 if( action<0 ) continue;
3351 acttab_action(pActtab, ap->sp->index, action);
3353 stp->iTknOfst = acttab_insert(pActtab);
3354 if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
3355 if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
3356 }else{
3357 for(ap=stp->ap; ap; ap=ap->next){
3358 int action;
3359 if( ap->sp->index<lemp->nterminal ) continue;
3360 if( ap->sp->index==lemp->nsymbol ) continue;
3361 action = compute_action(lemp, ap);
3362 if( action<0 ) continue;
3363 acttab_action(pActtab, ap->sp->index, action);
3365 stp->iNtOfst = acttab_insert(pActtab);
3366 if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
3367 if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
3370 free(ax);
3372 /* Output the yy_action table */
3373 fprintf(out,"static YYACTIONTYPE yy_action[] = {\n"); lineno++;
3374 n = acttab_size(pActtab);
3375 for(i=j=0; i<n; i++){
3376 int action = acttab_yyaction(pActtab, i);
3377 if( action<0 ) action = lemp->nsymbol + lemp->nrule + 2;
3378 if( j==0 ) fprintf(out," /* %5d */ ", i);
3379 fprintf(out, " %4d,", action);
3380 if( j==9 || i==n-1 ){
3381 fprintf(out, "\n"); lineno++;
3382 j = 0;
3383 }else{
3384 j++;
3387 fprintf(out, "};\n"); lineno++;
3389 /* Output the yy_lookahead table */
3390 fprintf(out,"static YYCODETYPE yy_lookahead[] = {\n"); lineno++;
3391 for(i=j=0; i<n; i++){
3392 int la = acttab_yylookahead(pActtab, i);
3393 if( la<0 ) la = lemp->nsymbol;
3394 if( j==0 ) fprintf(out," /* %5d */ ", i);
3395 fprintf(out, " %4d,", la);
3396 if( j==9 || i==n-1 ){
3397 fprintf(out, "\n"); lineno++;
3398 j = 0;
3399 }else{
3400 j++;
3403 fprintf(out, "};\n"); lineno++;
3405 /* Output the yy_shift_ofst[] table */
3406 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
3407 fprintf(out, "static %s yy_shift_ofst[] = {\n",
3408 minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
3409 n = lemp->nstate;
3410 for(i=j=0; i<n; i++){
3411 int ofst;
3412 stp = lemp->sorted[i];
3413 ofst = stp->iTknOfst;
3414 if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
3415 if( j==0 ) fprintf(out," /* %5d */ ", i);
3416 fprintf(out, " %4d,", ofst);
3417 if( j==9 || i==n-1 ){
3418 fprintf(out, "\n"); lineno++;
3419 j = 0;
3420 }else{
3421 j++;
3424 fprintf(out, "};\n"); lineno++;
3426 /* Output the yy_reduce_ofst[] table */
3427 fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
3428 fprintf(out, "static %s yy_reduce_ofst[] = {\n",
3429 minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
3430 n = lemp->nstate;
3431 for(i=j=0; i<n; i++){
3432 int ofst;
3433 stp = lemp->sorted[i];
3434 ofst = stp->iNtOfst;
3435 if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
3436 if( j==0 ) fprintf(out," /* %5d */ ", i);
3437 fprintf(out, " %4d,", ofst);
3438 if( j==9 || i==n-1 ){
3439 fprintf(out, "\n"); lineno++;
3440 j = 0;
3441 }else{
3442 j++;
3445 fprintf(out, "};\n"); lineno++;
3447 /* Output the default action table */
3448 fprintf(out, "static YYACTIONTYPE yy_default[] = {\n"); lineno++;
3449 n = lemp->nstate;
3450 for(i=j=0; i<n; i++){
3451 stp = lemp->sorted[i];
3452 if( j==0 ) fprintf(out," /* %5d */ ", i);
3453 fprintf(out, " %4d,", stp->iDflt);
3454 if( j==9 || i==n-1 ){
3455 fprintf(out, "\n"); lineno++;
3456 j = 0;
3457 }else{
3458 j++;
3461 fprintf(out, "};\n"); lineno++;
3462 tplt_xfer(lemp->name,in,out,&lineno);
3464 /* Generate the table of fallback tokens.
3466 if( lemp->has_fallback ){
3467 for(i=0; i<lemp->nterminal; i++){
3468 struct symbol *p = lemp->symbols[i];
3469 if( p->fallback==0 ){
3470 fprintf(out, " 0, /* %10s => nothing */\n", p->name);
3471 }else{
3472 fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index,
3473 p->name, p->fallback->name);
3475 lineno++;
3478 tplt_xfer(lemp->name, in, out, &lineno);
3480 /* Generate a table containing the symbolic name of every symbol
3482 for(i=0; i<lemp->nsymbol; i++){
3483 sprintf(line,"\"%s\",",lemp->symbols[i]->name);
3484 fprintf(out," %-15s",line);
3485 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
3487 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
3488 tplt_xfer(lemp->name,in,out,&lineno);
3490 /* Generate a table containing a text string that describes every
3491 ** rule in the rule set of the grammer. This information is used
3492 ** when tracing REDUCE actions.
3494 for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
3495 assert( rp->index==i );
3496 fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
3497 for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name);
3498 fprintf(out,"\",\n"); lineno++;
3500 tplt_xfer(lemp->name,in,out,&lineno);
3502 /* Generate code which executes every time a symbol is popped from
3503 ** the stack while processing errors or while destroying the parser.
3504 ** (In other words, generate the %destructor actions)
3506 if( lemp->tokendest ){
3507 for(i=0; i<lemp->nsymbol; i++){
3508 struct symbol *sp = lemp->symbols[i];
3509 if( sp==0 || sp->type!=TERMINAL ) continue;
3510 fprintf(out," case %d:\n",sp->index); lineno++;
3512 for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
3513 if( i<lemp->nsymbol ){
3514 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3515 fprintf(out," break;\n"); lineno++;
3518 for(i=0; i<lemp->nsymbol; i++){
3519 struct symbol *sp = lemp->symbols[i];
3520 if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
3521 fprintf(out," case %d:\n",sp->index); lineno++;
3522 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3523 fprintf(out," break;\n"); lineno++;
3525 if( lemp->vardest ){
3526 struct symbol *dflt_sp = 0;
3527 for(i=0; i<lemp->nsymbol; i++){
3528 struct symbol *sp = lemp->symbols[i];
3529 if( sp==0 || sp->type==TERMINAL ||
3530 sp->index<=0 || sp->destructor!=0 ) continue;
3531 fprintf(out," case %d:\n",sp->index); lineno++;
3532 dflt_sp = sp;
3534 if( dflt_sp!=0 ){
3535 emit_destructor_code(out,dflt_sp,lemp,&lineno);
3536 fprintf(out," break;\n"); lineno++;
3539 tplt_xfer(lemp->name,in,out,&lineno);
3541 /* Generate code which executes whenever the parser stack overflows */
3542 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
3543 tplt_xfer(lemp->name,in,out,&lineno);
3545 /* Generate the table of rule information
3547 ** Note: This code depends on the fact that rules are number
3548 ** sequentually beginning with 0.
3550 for(rp=lemp->rule; rp; rp=rp->next){
3551 fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
3553 tplt_xfer(lemp->name,in,out,&lineno);
3555 /* Generate code which execution during each REDUCE action */
3556 for(rp=lemp->rule; rp; rp=rp->next){
3557 fprintf(out," case %d:\n",rp->index); lineno++;
3558 emit_code(out,rp,lemp,&lineno);
3559 fprintf(out," break;\n"); lineno++;
3561 tplt_xfer(lemp->name,in,out,&lineno);
3563 /* Generate code which executes if a parse fails */
3564 tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);
3565 tplt_xfer(lemp->name,in,out,&lineno);
3567 /* Generate code which executes when a syntax error occurs */
3568 tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno);
3569 tplt_xfer(lemp->name,in,out,&lineno);
3571 /* Generate code which executes when the parser accepts its input */
3572 tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno);
3573 tplt_xfer(lemp->name,in,out,&lineno);
3575 /* Append any addition code the user desires */
3576 tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno);
3578 fclose(in);
3579 fclose(out);
3580 return;
3583 /* Generate a header file for the parser */
3584 void ReportHeader(lemp)
3585 struct lemon *lemp;
3587 FILE *out, *in;
3588 char *prefix;
3589 char line[LINESIZE];
3590 char pattern[LINESIZE];
3591 int i;
3593 if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3594 else prefix = "";
3595 in = file_open(lemp,".h","r");
3596 if( in ){
3597 for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
3598 sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3599 if( strcmp(line,pattern) ) break;
3601 fclose(in);
3602 if( i==lemp->nterminal ){
3603 /* No change in the file. Don't rewrite it. */
3604 return;
3607 out = file_open(lemp,".h","w");
3608 if( out ){
3609 for(i=1; i<lemp->nterminal; i++){
3610 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3612 fclose(out);
3614 return;
3617 /* Reduce the size of the action tables, if possible, by making use
3618 ** of defaults.
3620 ** In this version, we take the most frequent REDUCE action and make
3621 ** it the default. Only default a reduce if there are more than one.
3623 void CompressTables(lemp)
3624 struct lemon *lemp;
3626 struct state *stp;
3627 struct action *ap, *ap2;
3628 struct rule *rp, *rp2, *rbest;
3629 int nbest, n;
3630 int i;
3632 for(i=0; i<lemp->nstate; i++){
3633 stp = lemp->sorted[i];
3634 nbest = 0;
3635 rbest = 0;
3637 for(ap=stp->ap; ap; ap=ap->next){
3638 if( ap->type!=REDUCE ) continue;
3639 rp = ap->x.rp;
3640 if( rp==rbest ) continue;
3641 n = 1;
3642 for(ap2=ap->next; ap2; ap2=ap2->next){
3643 if( ap2->type!=REDUCE ) continue;
3644 rp2 = ap2->x.rp;
3645 if( rp2==rbest ) continue;
3646 if( rp2==rp ) n++;
3648 if( n>nbest ){
3649 nbest = n;
3650 rbest = rp;
3654 /* Do not make a default if the number of rules to default
3655 ** is not at least 2 */
3656 if( nbest<2 ) continue;
3659 /* Combine matching REDUCE actions into a single default */
3660 for(ap=stp->ap; ap; ap=ap->next){
3661 if( ap->type==REDUCE && ap->x.rp==rbest ) break;
3663 assert( ap );
3664 ap->sp = Symbol_new("{default}");
3665 for(ap=ap->next; ap; ap=ap->next){
3666 if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
3668 stp->ap = Action_sort(stp->ap);
3672 /***************** From the file "set.c" ************************************/
3674 ** Set manipulation routines for the LEMON parser generator.
3677 static int global_size = 0;
3679 /* Set the set size */
3680 void SetSize(n)
3681 int n;
3683 global_size = n+1;
3686 /* Allocate a new set */
3687 char *SetNew(){
3688 char *s;
3689 int i;
3690 s = (char*)malloc( global_size );
3691 if( s==0 ){
3692 memory_error();
3694 for(i=0; i<global_size; i++) s[i] = 0;
3695 return s;
3698 /* Deallocate a set */
3699 void SetFree(s)
3700 char *s;
3702 free(s);
3705 /* Add a new element to the set. Return TRUE if the element was added
3706 ** and FALSE if it was already there. */
3707 int SetAdd(s,e)
3708 char *s;
3709 int e;
3711 int rv;
3712 rv = s[e];
3713 s[e] = 1;
3714 return !rv;
3717 /* Add every element of s2 to s1. Return TRUE if s1 changes. */
3718 int SetUnion(s1,s2)
3719 char *s1;
3720 char *s2;
3722 int i, progress;
3723 progress = 0;
3724 for(i=0; i<global_size; i++){
3725 if( s2[i]==0 ) continue;
3726 if( s1[i]==0 ){
3727 progress = 1;
3728 s1[i] = 1;
3731 return progress;
3733 /********************** From the file "table.c" ****************************/
3735 ** All code in this file has been automatically generated
3736 ** from a specification in the file
3737 ** "table.q"
3738 ** by the associative array code building program "aagen".
3739 ** Do not edit this file! Instead, edit the specification
3740 ** file, then rerun aagen.
3743 ** Code for processing tables in the LEMON parser generator.
3746 PRIVATE int strhash(x)
3747 char *x;
3749 unsigned int h = 0;
3750 while( *x) h = h*13u + (unsigned int) *(x++);
3751 return h;
3754 /* Works like strdup, sort of. Save a string in malloced memory, but
3755 ** keep strings in a table so that the same string is not in more
3756 ** than one place.
3758 char *Strsafe(y)
3759 char *y;
3761 char *z;
3763 z = Strsafe_find(y);
3764 if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
3765 strcpy(z,y);
3766 Strsafe_insert(z);
3768 MemoryCheck(z);
3769 return z;
3772 /* There is one instance of the following structure for each
3773 ** associative array of type "x1".
3775 struct s_x1 {
3776 int size; /* The number of available slots. */
3777 /* Must be a power of 2 greater than or */
3778 /* equal to 1 */
3779 int count; /* Number of currently slots filled */
3780 struct s_x1node *tbl; /* The data stored here */
3781 struct s_x1node **ht; /* Hash table for lookups */
3784 /* There is one instance of this structure for every data element
3785 ** in an associative array of type "x1".
3787 typedef struct s_x1node {
3788 char *data; /* The data */
3789 struct s_x1node *next; /* Next entry with the same hash */
3790 struct s_x1node **from; /* Previous link */
3791 } x1node;
3793 /* There is only one instance of the array, which is the following */
3794 static struct s_x1 *x1a;
3796 /* Allocate a new associative array */
3797 void Strsafe_init(){
3798 if( x1a ) return;
3799 x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
3800 if( x1a ){
3801 x1a->size = 1024;
3802 x1a->count = 0;
3803 x1a->tbl = (x1node*)malloc(
3804 (sizeof(x1node) + sizeof(x1node*))*1024 );
3805 if( x1a->tbl==0 ){
3806 free(x1a);
3807 x1a = 0;
3808 }else{
3809 int i;
3810 x1a->ht = (x1node**)&(x1a->tbl[1024]);
3811 for(i=0; i<1024; i++) x1a->ht[i] = 0;
3815 /* Insert a new record into the array. Return TRUE if successful.
3816 ** Prior data with the same key is NOT overwritten */
3817 int Strsafe_insert(data)
3818 char *data;
3820 x1node *np;
3821 int h;
3822 int ph;
3824 if( x1a==0 ) return 0;
3825 ph = strhash(data);
3826 h = ph & (x1a->size-1);
3827 np = x1a->ht[h];
3828 while( np ){
3829 if( strcmp(np->data,data)==0 ){
3830 /* An existing entry with the same key is found. */
3831 /* Fail because overwrite is not allows. */
3832 return 0;
3834 np = np->next;
3836 if( x1a->count>=x1a->size ){
3837 /* Need to make the hash table bigger */
3838 int i,size;
3839 struct s_x1 array;
3840 array.size = size = x1a->size*2;
3841 array.count = x1a->count;
3842 array.tbl = (x1node*)malloc(
3843 (sizeof(x1node) + sizeof(x1node*))*size );
3844 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3845 array.ht = (x1node**)&(array.tbl[size]);
3846 for(i=0; i<size; i++) array.ht[i] = 0;
3847 for(i=0; i<x1a->count; i++){
3848 x1node *oldnp, *newnp;
3849 oldnp = &(x1a->tbl[i]);
3850 h = strhash(oldnp->data) & (size-1);
3851 newnp = &(array.tbl[i]);
3852 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3853 newnp->next = array.ht[h];
3854 newnp->data = oldnp->data;
3855 newnp->from = &(array.ht[h]);
3856 array.ht[h] = newnp;
3858 free(x1a->tbl);
3859 /* *x1a = array; *//* copy 'array' */
3860 memcpy(x1a, &array, sizeof(array));
3862 /* Insert the new data */
3863 h = ph & (x1a->size-1);
3864 np = &(x1a->tbl[x1a->count++]);
3865 np->data = data;
3866 if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
3867 np->next = x1a->ht[h];
3868 x1a->ht[h] = np;
3869 np->from = &(x1a->ht[h]);
3870 return 1;
3873 /* Return a pointer to data assigned to the given key. Return NULL
3874 ** if no such key. */
3875 char *Strsafe_find(key)
3876 char *key;
3878 int h;
3879 x1node *np;
3881 if( x1a==0 ) return 0;
3882 h = strhash(key) & (x1a->size-1);
3883 np = x1a->ht[h];
3884 while( np ){
3885 if( strcmp(np->data,key)==0 ) break;
3886 np = np->next;
3888 return np ? np->data : 0;
3891 /* Return a pointer to the (terminal or nonterminal) symbol "x".
3892 ** Create a new symbol if this is the first time "x" has been seen.
3894 struct symbol *Symbol_new(x)
3895 char *x;
3897 struct symbol *sp;
3899 sp = Symbol_find(x);
3900 if( sp==0 ){
3901 sp = (struct symbol *)malloc( sizeof(struct symbol) );
3902 MemoryCheck(sp);
3903 sp->name = Strsafe(x);
3904 sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
3905 sp->rule = 0;
3906 sp->fallback = 0;
3907 sp->prec = -1;
3908 sp->assoc = UNK;
3909 sp->firstset = 0;
3910 sp->lambda = Bo_FALSE;
3911 sp->destructor = 0;
3912 sp->datatype = 0;
3913 Symbol_insert(sp,sp->name);
3915 return sp;
3918 /* Compare two symbols for working purposes
3920 ** Symbols that begin with upper case letters (terminals or tokens)
3921 ** must sort before symbols that begin with lower case letters
3922 ** (non-terminals). Other than that, the order does not matter.
3924 ** We find experimentally that leaving the symbols in their original
3925 ** order (the order they appeared in the grammar file) gives the
3926 ** smallest parser tables in SQLite.
3928 int Symbolcmpp(struct symbol **a, struct symbol **b){
3929 int i1 = (**a).index + 10000000*((**a).name[0]>'Z');
3930 int i2 = (**b).index + 10000000*((**b).name[0]>'Z');
3931 return i1-i2;
3934 /* There is one instance of the following structure for each
3935 ** associative array of type "x2".
3937 struct s_x2 {
3938 int size; /* The number of available slots. */
3939 /* Must be a power of 2 greater than or */
3940 /* equal to 1 */
3941 int count; /* Number of currently slots filled */
3942 struct s_x2node *tbl; /* The data stored here */
3943 struct s_x2node **ht; /* Hash table for lookups */
3946 /* There is one instance of this structure for every data element
3947 ** in an associative array of type "x2".
3949 typedef struct s_x2node {
3950 struct symbol *data; /* The data */
3951 char *key; /* The key */
3952 struct s_x2node *next; /* Next entry with the same hash */
3953 struct s_x2node **from; /* Previous link */
3954 } x2node;
3956 /* There is only one instance of the array, which is the following */
3957 static struct s_x2 *x2a;
3959 /* Allocate a new associative array */
3960 void Symbol_init(){
3961 if( x2a ) return;
3962 x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
3963 if( x2a ){
3964 x2a->size = 128;
3965 x2a->count = 0;
3966 x2a->tbl = (x2node*)malloc(
3967 (sizeof(x2node) + sizeof(x2node*))*128 );
3968 if( x2a->tbl==0 ){
3969 free(x2a);
3970 x2a = 0;
3971 }else{
3972 int i;
3973 x2a->ht = (x2node**)&(x2a->tbl[128]);
3974 for(i=0; i<128; i++) x2a->ht[i] = 0;
3978 /* Insert a new record into the array. Return TRUE if successful.
3979 ** Prior data with the same key is NOT overwritten */
3980 int Symbol_insert(data,key)
3981 struct symbol *data;
3982 char *key;
3984 x2node *np;
3985 int h;
3986 int ph;
3988 if( x2a==0 ) return 0;
3989 ph = strhash(key);
3990 h = ph & (x2a->size-1);
3991 np = x2a->ht[h];
3992 while( np ){
3993 if( strcmp(np->key,key)==0 ){
3994 /* An existing entry with the same key is found. */
3995 /* Fail because overwrite is not allows. */
3996 return 0;
3998 np = np->next;
4000 if( x2a->count>=x2a->size ){
4001 /* Need to make the hash table bigger */
4002 int i,size;
4003 struct s_x2 array;
4004 array.size = size = x2a->size*2;
4005 array.count = x2a->count;
4006 array.tbl = (x2node*)malloc(
4007 (sizeof(x2node) + sizeof(x2node*))*size );
4008 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
4009 array.ht = (x2node**)&(array.tbl[size]);
4010 for(i=0; i<size; i++) array.ht[i] = 0;
4011 for(i=0; i<x2a->count; i++){
4012 x2node *oldnp, *newnp;
4013 oldnp = &(x2a->tbl[i]);
4014 h = strhash(oldnp->key) & (size-1);
4015 newnp = &(array.tbl[i]);
4016 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4017 newnp->next = array.ht[h];
4018 newnp->key = oldnp->key;
4019 newnp->data = oldnp->data;
4020 newnp->from = &(array.ht[h]);
4021 array.ht[h] = newnp;
4023 free(x2a->tbl);
4024 /* *x2a = array; *//* copy 'array' */
4025 memcpy(x2a, &array, sizeof(array));
4027 /* Insert the new data */
4028 h = ph & (x2a->size-1);
4029 np = &(x2a->tbl[x2a->count++]);
4030 np->key = key;
4031 np->data = data;
4032 if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
4033 np->next = x2a->ht[h];
4034 x2a->ht[h] = np;
4035 np->from = &(x2a->ht[h]);
4036 return 1;
4039 /* Return a pointer to data assigned to the given key. Return NULL
4040 ** if no such key. */
4041 struct symbol *Symbol_find(key)
4042 char *key;
4044 int h;
4045 x2node *np;
4047 if( x2a==0 ) return 0;
4048 h = strhash(key) & (x2a->size-1);
4049 np = x2a->ht[h];
4050 while( np ){
4051 if( strcmp(np->key,key)==0 ) break;
4052 np = np->next;
4054 return np ? np->data : 0;
4057 /* Return the n-th data. Return NULL if n is out of range. */
4058 struct symbol *Symbol_Nth(n)
4059 int n;
4061 struct symbol *data;
4062 if( x2a && n>0 && n<=x2a->count ){
4063 data = x2a->tbl[n-1].data;
4064 }else{
4065 data = 0;
4067 return data;
4070 /* Return the size of the array */
4071 int Symbol_count()
4073 return x2a ? x2a->count : 0;
4076 /* Return an array of pointers to all data in the table.
4077 ** The array is obtained from malloc. Return NULL if memory allocation
4078 ** problems, or if the array is empty. */
4079 struct symbol **Symbol_arrayof()
4081 struct symbol **array;
4082 int i,size;
4083 if( x2a==0 ) return 0;
4084 size = x2a->count;
4085 array = (struct symbol **)malloc( sizeof(struct symbol *)*size );
4086 if( array ){
4087 for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
4089 return array;
4092 /* Compare two configurations */
4093 int Configcmp(a,b)
4094 struct config *a;
4095 struct config *b;
4097 int x;
4098 x = a->rp->index - b->rp->index;
4099 if( x==0 ) x = a->dot - b->dot;
4100 return x;
4103 /* Compare two states */
4104 PRIVATE int statecmp(a,b)
4105 struct config *a;
4106 struct config *b;
4108 int rc;
4109 for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
4110 rc = a->rp->index - b->rp->index;
4111 if( rc==0 ) rc = a->dot - b->dot;
4113 if( rc==0 ){
4114 if( a ) rc = 1;
4115 if( b ) rc = -1;
4117 return rc;
4120 /* Hash a state */
4121 PRIVATE int statehash(a)
4122 struct config *a;
4124 unsigned int h=0;
4125 while( a ){
4126 h = h*571u + (unsigned int)a->rp->index*37u + (unsigned int)a->dot;
4127 a = a->bp;
4129 return h;
4132 /* Allocate a new state structure */
4133 struct state *State_new()
4135 struct state *new;
4136 new = (struct state *)malloc( sizeof(struct state) );
4137 MemoryCheck(new);
4138 return new;
4141 /* There is one instance of the following structure for each
4142 ** associative array of type "x3".
4144 struct s_x3 {
4145 int size; /* The number of available slots. */
4146 /* Must be a power of 2 greater than or */
4147 /* equal to 1 */
4148 int count; /* Number of currently slots filled */
4149 struct s_x3node *tbl; /* The data stored here */
4150 struct s_x3node **ht; /* Hash table for lookups */
4153 /* There is one instance of this structure for every data element
4154 ** in an associative array of type "x3".
4156 typedef struct s_x3node {
4157 struct state *data; /* The data */
4158 struct config *key; /* The key */
4159 struct s_x3node *next; /* Next entry with the same hash */
4160 struct s_x3node **from; /* Previous link */
4161 } x3node;
4163 /* There is only one instance of the array, which is the following */
4164 static struct s_x3 *x3a;
4166 /* Allocate a new associative array */
4167 void State_init(){
4168 if( x3a ) return;
4169 x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
4170 if( x3a ){
4171 x3a->size = 128;
4172 x3a->count = 0;
4173 x3a->tbl = (x3node*)malloc(
4174 (sizeof(x3node) + sizeof(x3node*))*128 );
4175 if( x3a->tbl==0 ){
4176 free(x3a);
4177 x3a = 0;
4178 }else{
4179 int i;
4180 x3a->ht = (x3node**)&(x3a->tbl[128]);
4181 for(i=0; i<128; i++) x3a->ht[i] = 0;
4185 /* Insert a new record into the array. Return TRUE if successful.
4186 ** Prior data with the same key is NOT overwritten */
4187 int State_insert(data,key)
4188 struct state *data;
4189 struct config *key;
4191 x3node *np;
4192 int h;
4193 int ph;
4195 if( x3a==0 ) return 0;
4196 ph = statehash(key);
4197 h = ph & (x3a->size-1);
4198 np = x3a->ht[h];
4199 while( np ){
4200 if( statecmp(np->key,key)==0 ){
4201 /* An existing entry with the same key is found. */
4202 /* Fail because overwrite is not allows. */
4203 return 0;
4205 np = np->next;
4207 if( x3a->count>=x3a->size ){
4208 /* Need to make the hash table bigger */
4209 int i,size;
4210 struct s_x3 array;
4211 array.size = size = x3a->size*2;
4212 array.count = x3a->count;
4213 array.tbl = (x3node*)malloc(
4214 (sizeof(x3node) + sizeof(x3node*))*size );
4215 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
4216 array.ht = (x3node**)&(array.tbl[size]);
4217 for(i=0; i<size; i++) array.ht[i] = 0;
4218 for(i=0; i<x3a->count; i++){
4219 x3node *oldnp, *newnp;
4220 oldnp = &(x3a->tbl[i]);
4221 h = statehash(oldnp->key) & (size-1);
4222 newnp = &(array.tbl[i]);
4223 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4224 newnp->next = array.ht[h];
4225 newnp->key = oldnp->key;
4226 newnp->data = oldnp->data;
4227 newnp->from = &(array.ht[h]);
4228 array.ht[h] = newnp;
4230 free(x3a->tbl);
4231 /* *x3a = array; *//* copy 'array' */
4232 memcpy(x3a, &array, sizeof(array));
4234 /* Insert the new data */
4235 h = ph & (x3a->size-1);
4236 np = &(x3a->tbl[x3a->count++]);
4237 np->key = key;
4238 np->data = data;
4239 if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
4240 np->next = x3a->ht[h];
4241 x3a->ht[h] = np;
4242 np->from = &(x3a->ht[h]);
4243 return 1;
4246 /* Return a pointer to data assigned to the given key. Return NULL
4247 ** if no such key. */
4248 struct state *State_find(key)
4249 struct config *key;
4251 int h;
4252 x3node *np;
4254 if( x3a==0 ) return 0;
4255 h = statehash(key) & (x3a->size-1);
4256 np = x3a->ht[h];
4257 while( np ){
4258 if( statecmp(np->key,key)==0 ) break;
4259 np = np->next;
4261 return np ? np->data : 0;
4264 /* Return the size of the array */
4265 int State_count(void)
4267 return x3a ? x3a->count : 0;
4270 /* Return an array of pointers to all data in the table.
4271 ** The array is obtained from malloc. Return NULL if memory allocation
4272 ** problems, or if the array is empty. */
4273 struct state **State_arrayof()
4275 struct state **array;
4276 int i,size;
4277 if( x3a==0 ) return 0;
4278 size = x3a->count;
4279 array = (struct state **)malloc( sizeof(struct state *)*size );
4280 if( array ){
4281 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
4283 return array;
4286 /* Hash a configuration */
4287 PRIVATE int confighash(a)
4288 struct config *a;
4290 int h=0;
4291 h = h*571 + a->rp->index*37 + a->dot;
4292 return h;
4295 /* There is one instance of the following structure for each
4296 ** associative array of type "x4".
4298 struct s_x4 {
4299 int size; /* The number of available slots. */
4300 /* Must be a power of 2 greater than or */
4301 /* equal to 1 */
4302 int count; /* Number of currently slots filled */
4303 struct s_x4node *tbl; /* The data stored here */
4304 struct s_x4node **ht; /* Hash table for lookups */
4307 /* There is one instance of this structure for every data element
4308 ** in an associative array of type "x4".
4310 typedef struct s_x4node {
4311 struct config *data; /* The data */
4312 struct s_x4node *next; /* Next entry with the same hash */
4313 struct s_x4node **from; /* Previous link */
4314 } x4node;
4316 /* There is only one instance of the array, which is the following */
4317 static struct s_x4 *x4a;
4319 /* Allocate a new associative array */
4320 void Configtable_init(){
4321 if( x4a ) return;
4322 x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
4323 if( x4a ){
4324 x4a->size = 64;
4325 x4a->count = 0;
4326 x4a->tbl = (x4node*)malloc(
4327 (sizeof(x4node) + sizeof(x4node*))*64 );
4328 if( x4a->tbl==0 ){
4329 free(x4a);
4330 x4a = 0;
4331 }else{
4332 int i;
4333 x4a->ht = (x4node**)&(x4a->tbl[64]);
4334 for(i=0; i<64; i++) x4a->ht[i] = 0;
4338 /* Insert a new record into the array. Return TRUE if successful.
4339 ** Prior data with the same key is NOT overwritten */
4340 int Configtable_insert(data)
4341 struct config *data;
4343 x4node *np;
4344 int h;
4345 int ph;
4347 if( x4a==0 ) return 0;
4348 ph = confighash(data);
4349 h = ph & (x4a->size-1);
4350 np = x4a->ht[h];
4351 while( np ){
4352 if( Configcmp(np->data,data)==0 ){
4353 /* An existing entry with the same key is found. */
4354 /* Fail because overwrite is not allows. */
4355 return 0;
4357 np = np->next;
4359 if( x4a->count>=x4a->size ){
4360 /* Need to make the hash table bigger */
4361 int i,size;
4362 struct s_x4 array;
4363 array.size = size = x4a->size*2;
4364 array.count = x4a->count;
4365 array.tbl = (x4node*)malloc(
4366 (sizeof(x4node) + sizeof(x4node*))*size );
4367 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
4368 array.ht = (x4node**)&(array.tbl[size]);
4369 for(i=0; i<size; i++) array.ht[i] = 0;
4370 for(i=0; i<x4a->count; i++){
4371 x4node *oldnp, *newnp;
4372 oldnp = &(x4a->tbl[i]);
4373 h = confighash(oldnp->data) & (size-1);
4374 newnp = &(array.tbl[i]);
4375 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4376 newnp->next = array.ht[h];
4377 newnp->data = oldnp->data;
4378 newnp->from = &(array.ht[h]);
4379 array.ht[h] = newnp;
4381 free(x4a->tbl);
4382 /* *x4a = array; *//* copy 'array' */
4383 memcpy(x4a, &array, sizeof(array));
4385 /* Insert the new data */
4386 h = ph & (x4a->size-1);
4387 np = &(x4a->tbl[x4a->count++]);
4388 np->data = data;
4389 if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
4390 np->next = x4a->ht[h];
4391 x4a->ht[h] = np;
4392 np->from = &(x4a->ht[h]);
4393 return 1;
4396 /* Return a pointer to data assigned to the given key. Return NULL
4397 ** if no such key. */
4398 struct config *Configtable_find(key)
4399 struct config *key;
4401 int h;
4402 x4node *np;
4404 if( x4a==0 ) return 0;
4405 h = confighash(key) & (x4a->size-1);
4406 np = x4a->ht[h];
4407 while( np ){
4408 if( Configcmp(np->data,key)==0 ) break;
4409 np = np->next;
4411 return np ? np->data : 0;
4414 /* Remove all data from the table. Pass each data to the function "f"
4415 ** as it is removed. ("f" may be null to avoid this step.) */
4416 void Configtable_clear(f)
4417 int(*f)(/* struct config * */);
4419 int i;
4420 if( x4a==0 || x4a->count==0 ) return;
4421 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
4422 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
4423 x4a->count = 0;
4424 return;