blob: 8e33f16618cde3e960815d9933278ff6168581ba [file] [log] [blame]
drh75897232000-05-29 14:26:00 +00001/*
drh75897232000-05-29 14:26:00 +00002** This file contains all sources (including headers) to the LEMON
3** LALR(1) parser generator. The sources have been combined into a
drh960e8c62001-04-03 16:53:21 +00004** single file to make it easy to include LEMON in the source tree
5** and Makefile of another program.
drh75897232000-05-29 14:26:00 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** The author of this program disclaims copyright.
drh75897232000-05-29 14:26:00 +00008*/
9#include <stdio.h>
10#include <varargs.h>
11#include <string.h>
12#include <ctype.h>
13
14extern void qsort();
15extern double strtod();
16extern long strtol();
17extern void free();
18extern int access();
19extern int atoi();
20
21#ifndef __WIN32__
22# if defined(_WIN32) || defined(WIN32)
23# define __WIN32__
24# endif
25#endif
26
27/* #define PRIVATE static */
28#define PRIVATE
29
30#ifdef TEST
31#define MAXRHS 5 /* Set low to exercise exception code */
32#else
33#define MAXRHS 1000
34#endif
35
36char *msort();
37extern void *malloc();
38
39/******** From the file "action.h" *************************************/
40struct action *Action_new();
41struct action *Action_sort();
42void Action_add();
43
44/********* From the file "assert.h" ************************************/
45void myassert();
46#ifndef NDEBUG
47# define assert(X) if(!(X))myassert(__FILE__,__LINE__)
48#else
49# define assert(X)
50#endif
51
52/********** From the file "build.h" ************************************/
53void FindRulePrecedences();
54void FindFirstSets();
55void FindStates();
56void FindLinks();
57void FindFollowSets();
58void FindActions();
59
60/********* From the file "configlist.h" *********************************/
61void Configlist_init(/* void */);
62struct config *Configlist_add(/* struct rule *, int */);
63struct config *Configlist_addbasis(/* struct rule *, int */);
64void Configlist_closure(/* void */);
65void Configlist_sort(/* void */);
66void Configlist_sortbasis(/* void */);
67struct config *Configlist_return(/* void */);
68struct config *Configlist_basis(/* void */);
69void Configlist_eat(/* struct config * */);
70void Configlist_reset(/* void */);
71
72/********* From the file "error.h" ***************************************/
73void ErrorMsg( /* char *, int, char *, ... */ );
74
75/****** From the file "option.h" ******************************************/
76struct s_options {
77 enum { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
78 OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type;
79 char *label;
80 char *arg;
81 char *message;
82};
drhb0c86772000-06-02 23:21:26 +000083int OptInit(/* char**,struct s_options*,FILE* */);
84int OptNArgs(/* void */);
85char *OptArg(/* int */);
86void OptErr(/* int */);
87void OptPrint(/* void */);
drh75897232000-05-29 14:26:00 +000088
89/******** From the file "parse.h" *****************************************/
90void Parse(/* struct lemon *lemp */);
91
92/********* From the file "plink.h" ***************************************/
93struct plink *Plink_new(/* void */);
94void Plink_add(/* struct plink **, struct config * */);
95void Plink_copy(/* struct plink **, struct plink * */);
96void Plink_delete(/* struct plink * */);
97
98/********** From the file "report.h" *************************************/
99void Reprint(/* struct lemon * */);
100void ReportOutput(/* struct lemon * */);
101void ReportTable(/* struct lemon * */);
102void ReportHeader(/* struct lemon * */);
103void CompressTables(/* struct lemon * */);
104
105/********** From the file "set.h" ****************************************/
106void SetSize(/* int N */); /* All sets will be of size N */
107char *SetNew(/* void */); /* A new set for element 0..N */
108void SetFree(/* char* */); /* Deallocate a set */
109
110int SetAdd(/* char*,int */); /* Add element to a set */
111int SetUnion(/* char *A,char *B */); /* A <- A U B, thru element N */
112
113#define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
114
115/********** From the file "struct.h" *************************************/
116/*
117** Principal data structures for the LEMON parser generator.
118*/
119
120typedef enum {FALSE=0, TRUE} Boolean;
121
122/* Symbols (terminals and nonterminals) of the grammar are stored
123** in the following: */
124struct symbol {
125 char *name; /* Name of the symbol */
126 int index; /* Index number for this symbol */
127 enum {
128 TERMINAL,
129 NONTERMINAL
130 } type; /* Symbols are all either TERMINALS or NTs */
131 struct rule *rule; /* Linked list of rules of this (if an NT) */
drh0bd1f4e2002-06-06 18:54:39 +0000132 struct symbol *fallback; /* fallback token in case this token doesn't parse */
drh75897232000-05-29 14:26:00 +0000133 int prec; /* Precedence if defined (-1 otherwise) */
134 enum e_assoc {
135 LEFT,
136 RIGHT,
137 NONE,
138 UNK
139 } assoc; /* Associativity if predecence is defined */
140 char *firstset; /* First-set for all rules of this symbol */
141 Boolean lambda; /* True if NT and can generate an empty string */
142 char *destructor; /* Code which executes whenever this symbol is
143 ** popped from the stack during error processing */
144 int destructorln; /* Line number of destructor code */
145 char *datatype; /* The data type of information held by this
146 ** object. Only used if type==NONTERMINAL */
147 int dtnum; /* The data type number. In the parser, the value
148 ** stack is a union. The .yy%d element of this
149 ** union is the correct data type for this object */
150};
151
152/* Each production rule in the grammar is stored in the following
153** structure. */
154struct rule {
155 struct symbol *lhs; /* Left-hand side of the rule */
156 char *lhsalias; /* Alias for the LHS (NULL if none) */
157 int ruleline; /* Line number for the rule */
158 int nrhs; /* Number of RHS symbols */
159 struct symbol **rhs; /* The RHS symbols */
160 char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
161 int line; /* Line number at which code begins */
162 char *code; /* The code executed when this rule is reduced */
163 struct symbol *precsym; /* Precedence symbol for this rule */
164 int index; /* An index number for this rule */
165 Boolean canReduce; /* True if this rule is ever reduced */
166 struct rule *nextlhs; /* Next rule with the same LHS */
167 struct rule *next; /* Next rule in the global list */
168};
169
170/* A configuration is a production rule of the grammar together with
171** a mark (dot) showing how much of that rule has been processed so far.
172** Configurations also contain a follow-set which is a list of terminal
173** symbols which are allowed to immediately follow the end of the rule.
174** Every configuration is recorded as an instance of the following: */
175struct config {
176 struct rule *rp; /* The rule upon which the configuration is based */
177 int dot; /* The parse point */
178 char *fws; /* Follow-set for this configuration only */
179 struct plink *fplp; /* Follow-set forward propagation links */
180 struct plink *bplp; /* Follow-set backwards propagation links */
181 struct state *stp; /* Pointer to state which contains this */
182 enum {
183 COMPLETE, /* The status is used during followset and */
184 INCOMPLETE /* shift computations */
185 } status;
186 struct config *next; /* Next configuration in the state */
187 struct config *bp; /* The next basis configuration */
188};
189
190/* Every shift or reduce operation is stored as one of the following */
191struct action {
192 struct symbol *sp; /* The look-ahead symbol */
193 enum e_action {
194 SHIFT,
195 ACCEPT,
196 REDUCE,
197 ERROR,
198 CONFLICT, /* Was a reduce, but part of a conflict */
199 SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
200 RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
201 NOT_USED /* Deleted by compression */
202 } type;
203 union {
204 struct state *stp; /* The new state, if a shift */
205 struct rule *rp; /* The rule, if a reduce */
206 } x;
207 struct action *next; /* Next action for this state */
208 struct action *collide; /* Next action with the same hash */
209};
210
211/* Each state of the generated parser's finite state machine
212** is encoded as an instance of the following structure. */
213struct state {
214 struct config *bp; /* The basis configurations for this state */
215 struct config *cfp; /* All configurations in this set */
216 int index; /* Sequencial number for this state */
217 struct action *ap; /* Array of actions for this state */
218 int naction; /* Number of actions for this state */
219 int tabstart; /* First index of the action table */
220 int tabdfltact; /* Default action */
221};
222
223/* A followset propagation link indicates that the contents of one
224** configuration followset should be propagated to another whenever
225** the first changes. */
226struct plink {
227 struct config *cfp; /* The configuration to which linked */
228 struct plink *next; /* The next propagate link */
229};
230
231/* The state vector for the entire parser generator is recorded as
232** follows. (LEMON uses no global variables and makes little use of
233** static variables. Fields in the following structure can be thought
234** of as begin global variables in the program.) */
235struct lemon {
236 struct state **sorted; /* Table of states sorted by state number */
237 struct rule *rule; /* List of all rules */
238 int nstate; /* Number of states */
239 int nrule; /* Number of rules */
240 int nsymbol; /* Number of terminal and nonterminal symbols */
241 int nterminal; /* Number of terminal symbols */
242 struct symbol **symbols; /* Sorted array of pointers to symbols */
243 int errorcnt; /* Number of errors */
244 struct symbol *errsym; /* The error symbol */
245 char *name; /* Name of the generated parser */
246 char *arg; /* Declaration of the 3th argument to parser */
247 char *tokentype; /* Type of terminal symbols in the parser stack */
drh960e8c62001-04-03 16:53:21 +0000248 char *vartype; /* The default type of non-terminal symbols */
drh75897232000-05-29 14:26:00 +0000249 char *start; /* Name of the start symbol for the grammar */
250 char *stacksize; /* Size of the parser stack */
251 char *include; /* Code to put at the start of the C file */
252 int includeln; /* Line number for start of include code */
253 char *error; /* Code to execute when an error is seen */
254 int errorln; /* Line number for start of error code */
255 char *overflow; /* Code to execute on a stack overflow */
256 int overflowln; /* Line number for start of overflow code */
257 char *failure; /* Code to execute on parser failure */
258 int failureln; /* Line number for start of failure code */
259 char *accept; /* Code to execute when the parser excepts */
260 int acceptln; /* Line number for the start of accept code */
261 char *extracode; /* Code appended to the generated file */
262 int extracodeln; /* Line number for the start of the extra code */
263 char *tokendest; /* Code to execute to destroy token data */
264 int tokendestln; /* Line number for token destroyer code */
drh960e8c62001-04-03 16:53:21 +0000265 char *vardest; /* Code for the default non-terminal destructor */
266 int vardestln; /* Line number for default non-term destructor code*/
drh75897232000-05-29 14:26:00 +0000267 char *filename; /* Name of the input file */
268 char *outname; /* Name of the current output file */
269 char *tokenprefix; /* A prefix added to token names in the .h file */
270 int nconflict; /* Number of parsing conflicts */
271 int tablesize; /* Size of the parse tables */
272 int basisflag; /* Print only basis configurations */
drh0bd1f4e2002-06-06 18:54:39 +0000273 int has_fallback; /* True if any %fallback is seen in the grammer */
drh75897232000-05-29 14:26:00 +0000274 char *argv0; /* Name of the program */
275};
276
277#define MemoryCheck(X) if((X)==0){ \
278 extern void memory_error(); \
279 memory_error(); \
280}
281
282/**************** From the file "table.h" *********************************/
283/*
284** All code in this file has been automatically generated
285** from a specification in the file
286** "table.q"
287** by the associative array code building program "aagen".
288** Do not edit this file! Instead, edit the specification
289** file, then rerun aagen.
290*/
291/*
292** Code for processing tables in the LEMON parser generator.
293*/
294
295/* Routines for handling a strings */
296
297char *Strsafe();
298
299void Strsafe_init(/* void */);
300int Strsafe_insert(/* char * */);
301char *Strsafe_find(/* char * */);
302
303/* Routines for handling symbols of the grammar */
304
305struct symbol *Symbol_new();
306int Symbolcmpp(/* struct symbol **, struct symbol ** */);
307void Symbol_init(/* void */);
308int Symbol_insert(/* struct symbol *, char * */);
309struct symbol *Symbol_find(/* char * */);
310struct symbol *Symbol_Nth(/* int */);
311int Symbol_count(/* */);
312struct symbol **Symbol_arrayof(/* */);
313
314/* Routines to manage the state table */
315
316int Configcmp(/* struct config *, struct config * */);
317struct state *State_new();
318void State_init(/* void */);
319int State_insert(/* struct state *, struct config * */);
320struct state *State_find(/* struct config * */);
321struct state **State_arrayof(/* */);
322
323/* Routines used for efficiency in Configlist_add */
324
325void Configtable_init(/* void */);
326int Configtable_insert(/* struct config * */);
327struct config *Configtable_find(/* struct config * */);
328void Configtable_clear(/* int(*)(struct config *) */);
329/****************** From the file "action.c" *******************************/
330/*
331** Routines processing parser actions in the LEMON parser generator.
332*/
333
334/* Allocate a new parser action */
335struct action *Action_new(){
336 static struct action *freelist = 0;
337 struct action *new;
338
339 if( freelist==0 ){
340 int i;
341 int amt = 100;
342 freelist = (struct action *)malloc( sizeof(struct action)*amt );
343 if( freelist==0 ){
344 fprintf(stderr,"Unable to allocate memory for a new parser action.");
345 exit(1);
346 }
347 for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
348 freelist[amt-1].next = 0;
349 }
350 new = freelist;
351 freelist = freelist->next;
352 return new;
353}
354
355/* Compare two actions */
356static int actioncmp(ap1,ap2)
357struct action *ap1;
358struct action *ap2;
359{
360 int rc;
361 rc = ap1->sp->index - ap2->sp->index;
362 if( rc==0 ) rc = (int)ap1->type - (int)ap2->type;
363 if( rc==0 ){
drh61bc2722000-08-20 11:42:46 +0000364 assert( ap1->type==REDUCE || ap1->type==RD_RESOLVED || ap1->type==CONFLICT);
365 assert( ap2->type==REDUCE || ap2->type==RD_RESOLVED || ap2->type==CONFLICT);
drh75897232000-05-29 14:26:00 +0000366 rc = ap1->x.rp->index - ap2->x.rp->index;
367 }
368 return rc;
369}
370
371/* Sort parser actions */
372struct action *Action_sort(ap)
373struct action *ap;
374{
375 ap = (struct action *)msort(ap,&ap->next,actioncmp);
376 return ap;
377}
378
379void Action_add(app,type,sp,arg)
380struct action **app;
381enum e_action type;
382struct symbol *sp;
383char *arg;
384{
385 struct action *new;
386 new = Action_new();
387 new->next = *app;
388 *app = new;
389 new->type = type;
390 new->sp = sp;
391 if( type==SHIFT ){
392 new->x.stp = (struct state *)arg;
393 }else{
394 new->x.rp = (struct rule *)arg;
395 }
396}
397/********************** From the file "assert.c" ****************************/
398/*
399** A more efficient way of handling assertions.
400*/
401void myassert(file,line)
402char *file;
403int line;
404{
405 fprintf(stderr,"Assertion failed on line %d of file \"%s\"\n",line,file);
406 exit(1);
407}
408/********************** From the file "build.c" *****************************/
409/*
410** Routines to construction the finite state machine for the LEMON
411** parser generator.
412*/
413
414/* Find a precedence symbol of every rule in the grammar.
415**
416** Those rules which have a precedence symbol coded in the input
417** grammar using the "[symbol]" construct will already have the
418** rp->precsym field filled. Other rules take as their precedence
419** symbol the first RHS symbol with a defined precedence. If there
420** are not RHS symbols with a defined precedence, the precedence
421** symbol field is left blank.
422*/
423void FindRulePrecedences(xp)
424struct lemon *xp;
425{
426 struct rule *rp;
427 for(rp=xp->rule; rp; rp=rp->next){
428 if( rp->precsym==0 ){
429 int i;
430 for(i=0; i<rp->nrhs; i++){
431 if( rp->rhs[i]->prec>=0 ){
432 rp->precsym = rp->rhs[i];
433 break;
434 }
435 }
436 }
437 }
438 return;
439}
440
441/* Find all nonterminals which will generate the empty string.
442** Then go back and compute the first sets of every nonterminal.
443** The first set is the set of all terminal symbols which can begin
444** a string generated by that nonterminal.
445*/
446void FindFirstSets(lemp)
447struct lemon *lemp;
448{
449 int i;
450 struct rule *rp;
451 int progress;
452
453 for(i=0; i<lemp->nsymbol; i++){
454 lemp->symbols[i]->lambda = FALSE;
455 }
456 for(i=lemp->nterminal; i<lemp->nsymbol; i++){
457 lemp->symbols[i]->firstset = SetNew();
458 }
459
460 /* First compute all lambdas */
461 do{
462 progress = 0;
463 for(rp=lemp->rule; rp; rp=rp->next){
464 if( rp->lhs->lambda ) continue;
465 for(i=0; i<rp->nrhs; i++){
466 if( rp->rhs[i]->lambda==FALSE ) break;
467 }
468 if( i==rp->nrhs ){
469 rp->lhs->lambda = TRUE;
470 progress = 1;
471 }
472 }
473 }while( progress );
474
475 /* Now compute all first sets */
476 do{
477 struct symbol *s1, *s2;
478 progress = 0;
479 for(rp=lemp->rule; rp; rp=rp->next){
480 s1 = rp->lhs;
481 for(i=0; i<rp->nrhs; i++){
482 s2 = rp->rhs[i];
483 if( s2->type==TERMINAL ){
484 progress += SetAdd(s1->firstset,s2->index);
485 break;
486 }else if( s1==s2 ){
487 if( s1->lambda==FALSE ) break;
488 }else{
489 progress += SetUnion(s1->firstset,s2->firstset);
490 if( s2->lambda==FALSE ) break;
491 }
492 }
493 }
494 }while( progress );
495 return;
496}
497
498/* Compute all LR(0) states for the grammar. Links
499** are added to between some states so that the LR(1) follow sets
500** can be computed later.
501*/
502PRIVATE struct state *getstate(/* struct lemon * */); /* forward reference */
503void FindStates(lemp)
504struct lemon *lemp;
505{
506 struct symbol *sp;
507 struct rule *rp;
508
509 Configlist_init();
510
511 /* Find the start symbol */
512 if( lemp->start ){
513 sp = Symbol_find(lemp->start);
514 if( sp==0 ){
515 ErrorMsg(lemp->filename,0,
516"The specified start symbol \"%s\" is not \
517in a nonterminal of the grammar. \"%s\" will be used as the start \
518symbol instead.",lemp->start,lemp->rule->lhs->name);
519 lemp->errorcnt++;
520 sp = lemp->rule->lhs;
521 }
522 }else{
523 sp = lemp->rule->lhs;
524 }
525
526 /* Make sure the start symbol doesn't occur on the right-hand side of
527 ** any rule. Report an error if it does. (YACC would generate a new
528 ** start symbol in this case.) */
529 for(rp=lemp->rule; rp; rp=rp->next){
530 int i;
531 for(i=0; i<rp->nrhs; i++){
532 if( rp->rhs[i]==sp ){
533 ErrorMsg(lemp->filename,0,
534"The start symbol \"%s\" occurs on the \
535right-hand side of a rule. This will result in a parser which \
536does not work properly.",sp->name);
537 lemp->errorcnt++;
538 }
539 }
540 }
541
542 /* The basis configuration set for the first state
543 ** is all rules which have the start symbol as their
544 ** left-hand side */
545 for(rp=sp->rule; rp; rp=rp->nextlhs){
546 struct config *newcfp;
547 newcfp = Configlist_addbasis(rp,0);
548 SetAdd(newcfp->fws,0);
549 }
550
551 /* Compute the first state. All other states will be
552 ** computed automatically during the computation of the first one.
553 ** The returned pointer to the first state is not used. */
554 (void)getstate(lemp);
555 return;
556}
557
558/* Return a pointer to a state which is described by the configuration
559** list which has been built from calls to Configlist_add.
560*/
561PRIVATE void buildshifts(/* struct lemon *, struct state * */); /* Forwd ref */
562PRIVATE struct state *getstate(lemp)
563struct lemon *lemp;
564{
565 struct config *cfp, *bp;
566 struct state *stp;
567
568 /* Extract the sorted basis of the new state. The basis was constructed
569 ** by prior calls to "Configlist_addbasis()". */
570 Configlist_sortbasis();
571 bp = Configlist_basis();
572
573 /* Get a state with the same basis */
574 stp = State_find(bp);
575 if( stp ){
576 /* A state with the same basis already exists! Copy all the follow-set
577 ** propagation links from the state under construction into the
578 ** preexisting state, then return a pointer to the preexisting state */
579 struct config *x, *y;
580 for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
581 Plink_copy(&y->bplp,x->bplp);
582 Plink_delete(x->fplp);
583 x->fplp = x->bplp = 0;
584 }
585 cfp = Configlist_return();
586 Configlist_eat(cfp);
587 }else{
588 /* This really is a new state. Construct all the details */
589 Configlist_closure(lemp); /* Compute the configuration closure */
590 Configlist_sort(); /* Sort the configuration closure */
591 cfp = Configlist_return(); /* Get a pointer to the config list */
592 stp = State_new(); /* A new state structure */
593 MemoryCheck(stp);
594 stp->bp = bp; /* Remember the configuration basis */
595 stp->cfp = cfp; /* Remember the configuration closure */
596 stp->index = lemp->nstate++; /* Every state gets a sequence number */
597 stp->ap = 0; /* No actions, yet. */
598 State_insert(stp,stp->bp); /* Add to the state table */
599 buildshifts(lemp,stp); /* Recursively compute successor states */
600 }
601 return stp;
602}
603
604/* Construct all successor states to the given state. A "successor"
605** state is any state which can be reached by a shift action.
606*/
607PRIVATE void buildshifts(lemp,stp)
608struct lemon *lemp;
609struct state *stp; /* The state from which successors are computed */
610{
611 struct config *cfp; /* For looping thru the config closure of "stp" */
612 struct config *bcfp; /* For the inner loop on config closure of "stp" */
613 struct config *new; /* */
614 struct symbol *sp; /* Symbol following the dot in configuration "cfp" */
615 struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
616 struct state *newstp; /* A pointer to a successor state */
617
618 /* Each configuration becomes complete after it contibutes to a successor
619 ** state. Initially, all configurations are incomplete */
620 for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
621
622 /* Loop through all configurations of the state "stp" */
623 for(cfp=stp->cfp; cfp; cfp=cfp->next){
624 if( cfp->status==COMPLETE ) continue; /* Already used by inner loop */
625 if( cfp->dot>=cfp->rp->nrhs ) continue; /* Can't shift this config */
626 Configlist_reset(); /* Reset the new config set */
627 sp = cfp->rp->rhs[cfp->dot]; /* Symbol after the dot */
628
629 /* For every configuration in the state "stp" which has the symbol "sp"
630 ** following its dot, add the same configuration to the basis set under
631 ** construction but with the dot shifted one symbol to the right. */
632 for(bcfp=cfp; bcfp; bcfp=bcfp->next){
633 if( bcfp->status==COMPLETE ) continue; /* Already used */
634 if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
635 bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
636 if( bsp!=sp ) continue; /* Must be same as for "cfp" */
637 bcfp->status = COMPLETE; /* Mark this config as used */
638 new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
639 Plink_add(&new->bplp,bcfp);
640 }
641
642 /* Get a pointer to the state described by the basis configuration set
643 ** constructed in the preceding loop */
644 newstp = getstate(lemp);
645
646 /* The state "newstp" is reached from the state "stp" by a shift action
647 ** on the symbol "sp" */
648 Action_add(&stp->ap,SHIFT,sp,newstp);
649 }
650}
651
652/*
653** Construct the propagation links
654*/
655void FindLinks(lemp)
656struct lemon *lemp;
657{
658 int i;
659 struct config *cfp, *other;
660 struct state *stp;
661 struct plink *plp;
662
663 /* Housekeeping detail:
664 ** Add to every propagate link a pointer back to the state to
665 ** which the link is attached. */
666 for(i=0; i<lemp->nstate; i++){
667 stp = lemp->sorted[i];
668 for(cfp=stp->cfp; cfp; cfp=cfp->next){
669 cfp->stp = stp;
670 }
671 }
672
673 /* Convert all backlinks into forward links. Only the forward
674 ** links are used in the follow-set computation. */
675 for(i=0; i<lemp->nstate; i++){
676 stp = lemp->sorted[i];
677 for(cfp=stp->cfp; cfp; cfp=cfp->next){
678 for(plp=cfp->bplp; plp; plp=plp->next){
679 other = plp->cfp;
680 Plink_add(&other->fplp,cfp);
681 }
682 }
683 }
684}
685
686/* Compute all followsets.
687**
688** A followset is the set of all symbols which can come immediately
689** after a configuration.
690*/
691void FindFollowSets(lemp)
692struct lemon *lemp;
693{
694 int i;
695 struct config *cfp;
696 struct plink *plp;
697 int progress;
698 int change;
699
700 for(i=0; i<lemp->nstate; i++){
701 for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
702 cfp->status = INCOMPLETE;
703 }
704 }
705
706 do{
707 progress = 0;
708 for(i=0; i<lemp->nstate; i++){
709 for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
710 if( cfp->status==COMPLETE ) continue;
711 for(plp=cfp->fplp; plp; plp=plp->next){
712 change = SetUnion(plp->cfp->fws,cfp->fws);
713 if( change ){
714 plp->cfp->status = INCOMPLETE;
715 progress = 1;
716 }
717 }
718 cfp->status = COMPLETE;
719 }
720 }
721 }while( progress );
722}
723
724static int resolve_conflict();
725
726/* Compute the reduce actions, and resolve conflicts.
727*/
728void FindActions(lemp)
729struct lemon *lemp;
730{
731 int i,j;
732 struct config *cfp;
733 struct state *stp;
734 struct symbol *sp;
735 struct rule *rp;
736
737 /* Add all of the reduce actions
738 ** A reduce action is added for each element of the followset of
739 ** a configuration which has its dot at the extreme right.
740 */
741 for(i=0; i<lemp->nstate; i++){ /* Loop over all states */
742 stp = lemp->sorted[i];
743 for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */
744 if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */
745 for(j=0; j<lemp->nterminal; j++){
746 if( SetFind(cfp->fws,j) ){
747 /* Add a reduce action to the state "stp" which will reduce by the
748 ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
749 Action_add(&stp->ap,REDUCE,lemp->symbols[j],cfp->rp);
750 }
751 }
752 }
753 }
754 }
755
756 /* Add the accepting token */
757 if( lemp->start ){
758 sp = Symbol_find(lemp->start);
759 if( sp==0 ) sp = lemp->rule->lhs;
760 }else{
761 sp = lemp->rule->lhs;
762 }
763 /* Add to the first state (which is always the starting state of the
764 ** finite state machine) an action to ACCEPT if the lookahead is the
765 ** start nonterminal. */
766 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
767
768 /* Resolve conflicts */
769 for(i=0; i<lemp->nstate; i++){
770 struct action *ap, *nap;
771 struct state *stp;
772 stp = lemp->sorted[i];
773 assert( stp->ap );
774 stp->ap = Action_sort(stp->ap);
drhb59499c2002-02-23 18:45:13 +0000775 for(ap=stp->ap; ap && ap->next; ap=ap->next){
drh75897232000-05-29 14:26:00 +0000776 for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
777 /* The two actions "ap" and "nap" have the same lookahead.
778 ** Figure out which one should be used */
779 lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym);
780 }
781 }
782 }
783
784 /* Report an error for each rule that can never be reduced. */
785 for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = FALSE;
786 for(i=0; i<lemp->nstate; i++){
787 struct action *ap;
788 for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
789 if( ap->type==REDUCE ) ap->x.rp->canReduce = TRUE;
790 }
791 }
792 for(rp=lemp->rule; rp; rp=rp->next){
793 if( rp->canReduce ) continue;
794 ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
795 lemp->errorcnt++;
796 }
797}
798
799/* Resolve a conflict between the two given actions. If the
800** conflict can't be resolve, return non-zero.
801**
802** NO LONGER TRUE:
803** To resolve a conflict, first look to see if either action
804** is on an error rule. In that case, take the action which
805** is not associated with the error rule. If neither or both
806** actions are associated with an error rule, then try to
807** use precedence to resolve the conflict.
808**
809** If either action is a SHIFT, then it must be apx. This
810** function won't work if apx->type==REDUCE and apy->type==SHIFT.
811*/
812static int resolve_conflict(apx,apy,errsym)
813struct action *apx;
814struct action *apy;
815struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
816{
817 struct symbol *spx, *spy;
818 int errcnt = 0;
819 assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
820 if( apx->type==SHIFT && apy->type==REDUCE ){
821 spx = apx->sp;
822 spy = apy->x.rp->precsym;
823 if( spy==0 || spx->prec<0 || spy->prec<0 ){
824 /* Not enough precedence information. */
825 apy->type = CONFLICT;
826 errcnt++;
827 }else if( spx->prec>spy->prec ){ /* Lower precedence wins */
828 apy->type = RD_RESOLVED;
829 }else if( spx->prec<spy->prec ){
830 apx->type = SH_RESOLVED;
831 }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
832 apy->type = RD_RESOLVED; /* associativity */
833 }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */
834 apx->type = SH_RESOLVED;
835 }else{
836 assert( spx->prec==spy->prec && spx->assoc==NONE );
837 apy->type = CONFLICT;
838 errcnt++;
839 }
840 }else if( apx->type==REDUCE && apy->type==REDUCE ){
841 spx = apx->x.rp->precsym;
842 spy = apy->x.rp->precsym;
843 if( spx==0 || spy==0 || spx->prec<0 ||
844 spy->prec<0 || spx->prec==spy->prec ){
845 apy->type = CONFLICT;
846 errcnt++;
847 }else if( spx->prec>spy->prec ){
848 apy->type = RD_RESOLVED;
849 }else if( spx->prec<spy->prec ){
850 apx->type = RD_RESOLVED;
851 }
852 }else{
drhb59499c2002-02-23 18:45:13 +0000853 assert(
854 apx->type==SH_RESOLVED ||
855 apx->type==RD_RESOLVED ||
856 apx->type==CONFLICT ||
857 apy->type==SH_RESOLVED ||
858 apy->type==RD_RESOLVED ||
859 apy->type==CONFLICT
860 );
861 /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
862 ** REDUCEs on the list. If we reach this point it must be because
863 ** the parser conflict had already been resolved. */
drh75897232000-05-29 14:26:00 +0000864 }
865 return errcnt;
866}
867/********************* From the file "configlist.c" *************************/
868/*
869** Routines to processing a configuration list and building a state
870** in the LEMON parser generator.
871*/
872
873static struct config *freelist = 0; /* List of free configurations */
874static struct config *current = 0; /* Top of list of configurations */
875static struct config **currentend = 0; /* Last on list of configs */
876static struct config *basis = 0; /* Top of list of basis configs */
877static struct config **basisend = 0; /* End of list of basis configs */
878
879/* Return a pointer to a new configuration */
880PRIVATE struct config *newconfig(){
881 struct config *new;
882 if( freelist==0 ){
883 int i;
884 int amt = 3;
885 freelist = (struct config *)malloc( sizeof(struct config)*amt );
886 if( freelist==0 ){
887 fprintf(stderr,"Unable to allocate memory for a new configuration.");
888 exit(1);
889 }
890 for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
891 freelist[amt-1].next = 0;
892 }
893 new = freelist;
894 freelist = freelist->next;
895 return new;
896}
897
898/* The configuration "old" is no longer used */
899PRIVATE void deleteconfig(old)
900struct config *old;
901{
902 old->next = freelist;
903 freelist = old;
904}
905
906/* Initialized the configuration list builder */
907void Configlist_init(){
908 current = 0;
909 currentend = &current;
910 basis = 0;
911 basisend = &basis;
912 Configtable_init();
913 return;
914}
915
916/* Initialized the configuration list builder */
917void Configlist_reset(){
918 current = 0;
919 currentend = &current;
920 basis = 0;
921 basisend = &basis;
922 Configtable_clear(0);
923 return;
924}
925
926/* Add another configuration to the configuration list */
927struct config *Configlist_add(rp,dot)
928struct rule *rp; /* The rule */
929int dot; /* Index into the RHS of the rule where the dot goes */
930{
931 struct config *cfp, model;
932
933 assert( currentend!=0 );
934 model.rp = rp;
935 model.dot = dot;
936 cfp = Configtable_find(&model);
937 if( cfp==0 ){
938 cfp = newconfig();
939 cfp->rp = rp;
940 cfp->dot = dot;
941 cfp->fws = SetNew();
942 cfp->stp = 0;
943 cfp->fplp = cfp->bplp = 0;
944 cfp->next = 0;
945 cfp->bp = 0;
946 *currentend = cfp;
947 currentend = &cfp->next;
948 Configtable_insert(cfp);
949 }
950 return cfp;
951}
952
953/* Add a basis configuration to the configuration list */
954struct config *Configlist_addbasis(rp,dot)
955struct rule *rp;
956int dot;
957{
958 struct config *cfp, model;
959
960 assert( basisend!=0 );
961 assert( currentend!=0 );
962 model.rp = rp;
963 model.dot = dot;
964 cfp = Configtable_find(&model);
965 if( cfp==0 ){
966 cfp = newconfig();
967 cfp->rp = rp;
968 cfp->dot = dot;
969 cfp->fws = SetNew();
970 cfp->stp = 0;
971 cfp->fplp = cfp->bplp = 0;
972 cfp->next = 0;
973 cfp->bp = 0;
974 *currentend = cfp;
975 currentend = &cfp->next;
976 *basisend = cfp;
977 basisend = &cfp->bp;
978 Configtable_insert(cfp);
979 }
980 return cfp;
981}
982
983/* Compute the closure of the configuration list */
984void Configlist_closure(lemp)
985struct lemon *lemp;
986{
987 struct config *cfp, *newcfp;
988 struct rule *rp, *newrp;
989 struct symbol *sp, *xsp;
990 int i, dot;
991
992 assert( currentend!=0 );
993 for(cfp=current; cfp; cfp=cfp->next){
994 rp = cfp->rp;
995 dot = cfp->dot;
996 if( dot>=rp->nrhs ) continue;
997 sp = rp->rhs[dot];
998 if( sp->type==NONTERMINAL ){
999 if( sp->rule==0 && sp!=lemp->errsym ){
1000 ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
1001 sp->name);
1002 lemp->errorcnt++;
1003 }
1004 for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
1005 newcfp = Configlist_add(newrp,0);
1006 for(i=dot+1; i<rp->nrhs; i++){
1007 xsp = rp->rhs[i];
1008 if( xsp->type==TERMINAL ){
1009 SetAdd(newcfp->fws,xsp->index);
1010 break;
1011 }else{
1012 SetUnion(newcfp->fws,xsp->firstset);
1013 if( xsp->lambda==FALSE ) break;
1014 }
1015 }
1016 if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
1017 }
1018 }
1019 }
1020 return;
1021}
1022
1023/* Sort the configuration list */
1024void Configlist_sort(){
1025 current = (struct config *)msort(current,&(current->next),Configcmp);
1026 currentend = 0;
1027 return;
1028}
1029
1030/* Sort the basis configuration list */
1031void Configlist_sortbasis(){
1032 basis = (struct config *)msort(current,&(current->bp),Configcmp);
1033 basisend = 0;
1034 return;
1035}
1036
1037/* Return a pointer to the head of the configuration list and
1038** reset the list */
1039struct config *Configlist_return(){
1040 struct config *old;
1041 old = current;
1042 current = 0;
1043 currentend = 0;
1044 return old;
1045}
1046
1047/* Return a pointer to the head of the configuration list and
1048** reset the list */
1049struct config *Configlist_basis(){
1050 struct config *old;
1051 old = basis;
1052 basis = 0;
1053 basisend = 0;
1054 return old;
1055}
1056
1057/* Free all elements of the given configuration list */
1058void Configlist_eat(cfp)
1059struct config *cfp;
1060{
1061 struct config *nextcfp;
1062 for(; cfp; cfp=nextcfp){
1063 nextcfp = cfp->next;
1064 assert( cfp->fplp==0 );
1065 assert( cfp->bplp==0 );
1066 if( cfp->fws ) SetFree(cfp->fws);
1067 deleteconfig(cfp);
1068 }
1069 return;
1070}
1071/***************** From the file "error.c" *********************************/
1072/*
1073** Code for printing error message.
1074*/
1075
1076/* Find a good place to break "msg" so that its length is at least "min"
1077** but no more than "max". Make the point as close to max as possible.
1078*/
1079static int findbreak(msg,min,max)
1080char *msg;
1081int min;
1082int max;
1083{
1084 int i,spot;
1085 char c;
1086 for(i=spot=min; i<=max; i++){
1087 c = msg[i];
1088 if( c=='\t' ) msg[i] = ' ';
1089 if( c=='\n' ){ msg[i] = ' '; spot = i; break; }
1090 if( c==0 ){ spot = i; break; }
1091 if( c=='-' && i<max-1 ) spot = i+1;
1092 if( c==' ' ) spot = i;
1093 }
1094 return spot;
1095}
1096
1097/*
1098** The error message is split across multiple lines if necessary. The
1099** splits occur at a space, if there is a space available near the end
1100** of the line.
1101*/
1102#define ERRMSGSIZE 10000 /* Hope this is big enough. No way to error check */
1103#define LINEWIDTH 79 /* Max width of any output line */
1104#define PREFIXLIMIT 30 /* Max width of the prefix on each line */
1105void ErrorMsg(va_alist)
1106va_dcl
1107{
1108 char *filename;
1109 int lineno;
1110 char *format;
1111 char errmsg[ERRMSGSIZE];
1112 char prefix[PREFIXLIMIT+10];
1113 int errmsgsize;
1114 int prefixsize;
1115 int availablewidth;
1116 va_list ap;
1117 int end, restart, base;
1118
1119 va_start(ap);
1120 filename = va_arg(ap,char*);
1121 lineno = va_arg(ap,int);
1122 format = va_arg(ap,char*);
1123 /* Prepare a prefix to be prepended to every output line */
1124 if( lineno>0 ){
1125 sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno);
1126 }else{
1127 sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename);
1128 }
1129 prefixsize = strlen(prefix);
1130 availablewidth = LINEWIDTH - prefixsize;
1131
1132 /* Generate the error message */
1133 vsprintf(errmsg,format,ap);
1134 va_end(ap);
1135 errmsgsize = strlen(errmsg);
1136 /* Remove trailing '\n's from the error message. */
1137 while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){
1138 errmsg[--errmsgsize] = 0;
1139 }
1140
1141 /* Print the error message */
1142 base = 0;
1143 while( errmsg[base]!=0 ){
1144 end = restart = findbreak(&errmsg[base],0,availablewidth);
1145 restart += base;
1146 while( errmsg[restart]==' ' ) restart++;
1147 fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]);
1148 base = restart;
1149 }
1150}
1151/**************** From the file "main.c" ************************************/
1152/*
1153** Main program file for the LEMON parser generator.
1154*/
1155
1156/* Report an out-of-memory condition and abort. This function
1157** is used mostly by the "MemoryCheck" macro in struct.h
1158*/
1159void memory_error(){
1160 fprintf(stderr,"Out of memory. Aborting...\n");
1161 exit(1);
1162}
1163
1164
1165/* The main program. Parse the command line and do it... */
1166int main(argc,argv)
1167int argc;
1168char **argv;
1169{
1170 static int version = 0;
1171 static int rpflag = 0;
1172 static int basisflag = 0;
1173 static int compress = 0;
1174 static int quiet = 0;
1175 static int statistics = 0;
1176 static int mhflag = 0;
1177 static struct s_options options[] = {
1178 {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
1179 {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
1180 {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
1181 {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"},
1182 {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
1183 {OPT_FLAG, "s", (char*)&statistics, "Print parser stats to standard output."},
1184 {OPT_FLAG, "x", (char*)&version, "Print the version number."},
1185 {OPT_FLAG,0,0,0}
1186 };
1187 int i;
1188 struct lemon lem;
1189
drhb0c86772000-06-02 23:21:26 +00001190 OptInit(argv,options,stderr);
drh75897232000-05-29 14:26:00 +00001191 if( version ){
drhb19a2bc2001-09-16 00:13:26 +00001192 printf("Lemon version 1.0\n");
drh75897232000-05-29 14:26:00 +00001193 exit(0);
1194 }
drhb0c86772000-06-02 23:21:26 +00001195 if( OptNArgs()!=1 ){
drh75897232000-05-29 14:26:00 +00001196 fprintf(stderr,"Exactly one filename argument is required.\n");
1197 exit(1);
1198 }
1199 lem.errorcnt = 0;
1200
1201 /* Initialize the machine */
1202 Strsafe_init();
1203 Symbol_init();
1204 State_init();
1205 lem.argv0 = argv[0];
drhb0c86772000-06-02 23:21:26 +00001206 lem.filename = OptArg(0);
drh75897232000-05-29 14:26:00 +00001207 lem.basisflag = basisflag;
drh0bd1f4e2002-06-06 18:54:39 +00001208 lem.has_fallback = 0;
drh75897232000-05-29 14:26:00 +00001209 lem.nconflict = 0;
1210 lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
drh960e8c62001-04-03 16:53:21 +00001211 lem.vartype = 0;
drh75897232000-05-29 14:26:00 +00001212 lem.stacksize = 0;
1213 lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
1214 lem.tokenprefix = lem.outname = lem.extracode = 0;
drh960e8c62001-04-03 16:53:21 +00001215 lem.vardest = 0;
drh75897232000-05-29 14:26:00 +00001216 lem.tablesize = 0;
1217 Symbol_new("$");
1218 lem.errsym = Symbol_new("error");
1219
1220 /* Parse the input file */
1221 Parse(&lem);
1222 if( lem.errorcnt ) exit(lem.errorcnt);
1223 if( lem.rule==0 ){
1224 fprintf(stderr,"Empty grammar.\n");
1225 exit(1);
1226 }
1227
1228 /* Count and index the symbols of the grammar */
1229 lem.nsymbol = Symbol_count();
1230 Symbol_new("{default}");
1231 lem.symbols = Symbol_arrayof();
1232 qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
1233 (int(*)())Symbolcmpp);
1234 for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
1235 for(i=1; isupper(lem.symbols[i]->name[0]); i++);
1236 lem.nterminal = i;
1237
1238 /* Generate a reprint of the grammar, if requested on the command line */
1239 if( rpflag ){
1240 Reprint(&lem);
1241 }else{
1242 /* Initialize the size for all follow and first sets */
1243 SetSize(lem.nterminal);
1244
1245 /* Find the precedence for every production rule (that has one) */
1246 FindRulePrecedences(&lem);
1247
1248 /* Compute the lambda-nonterminals and the first-sets for every
1249 ** nonterminal */
1250 FindFirstSets(&lem);
1251
1252 /* Compute all LR(0) states. Also record follow-set propagation
1253 ** links so that the follow-set can be computed later */
1254 lem.nstate = 0;
1255 FindStates(&lem);
1256 lem.sorted = State_arrayof();
1257
1258 /* Tie up loose ends on the propagation links */
1259 FindLinks(&lem);
1260
1261 /* Compute the follow set of every reducible configuration */
1262 FindFollowSets(&lem);
1263
1264 /* Compute the action tables */
1265 FindActions(&lem);
1266
1267 /* Compress the action tables */
1268 if( compress==0 ) CompressTables(&lem);
1269
1270 /* Generate a report of the parser generated. (the "y.output" file) */
1271 if( !quiet ) ReportOutput(&lem);
1272
1273 /* Generate the source code for the parser */
1274 ReportTable(&lem, mhflag);
1275
1276 /* Produce a header file for use by the scanner. (This step is
1277 ** omitted if the "-m" option is used because makeheaders will
1278 ** generate the file for us.) */
1279 if( !mhflag ) ReportHeader(&lem);
1280 }
1281 if( statistics ){
1282 printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
1283 lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
1284 printf(" %d states, %d parser table entries, %d conflicts\n",
1285 lem.nstate, lem.tablesize, lem.nconflict);
1286 }
1287 if( lem.nconflict ){
1288 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
1289 }
1290 exit(lem.errorcnt + lem.nconflict);
1291}
1292/******************** From the file "msort.c" *******************************/
1293/*
1294** A generic merge-sort program.
1295**
1296** USAGE:
1297** Let "ptr" be a pointer to some structure which is at the head of
1298** a null-terminated list. Then to sort the list call:
1299**
1300** ptr = msort(ptr,&(ptr->next),cmpfnc);
1301**
1302** In the above, "cmpfnc" is a pointer to a function which compares
1303** two instances of the structure and returns an integer, as in
1304** strcmp. The second argument is a pointer to the pointer to the
1305** second element of the linked list. This address is used to compute
1306** the offset to the "next" field within the structure. The offset to
1307** the "next" field must be constant for all structures in the list.
1308**
1309** The function returns a new pointer which is the head of the list
1310** after sorting.
1311**
1312** ALGORITHM:
1313** Merge-sort.
1314*/
1315
1316/*
1317** Return a pointer to the next structure in the linked list.
1318*/
drhba99af52001-10-25 20:37:16 +00001319#define NEXT(A) (*(char**)(((unsigned long)A)+offset))
drh75897232000-05-29 14:26:00 +00001320
1321/*
1322** Inputs:
1323** a: A sorted, null-terminated linked list. (May be null).
1324** b: A sorted, null-terminated linked list. (May be null).
1325** cmp: A pointer to the comparison function.
1326** offset: Offset in the structure to the "next" field.
1327**
1328** Return Value:
1329** A pointer to the head of a sorted list containing the elements
1330** of both a and b.
1331**
1332** Side effects:
1333** The "next" pointers for elements in the lists a and b are
1334** changed.
1335*/
1336static char *merge(a,b,cmp,offset)
1337char *a;
1338char *b;
1339int (*cmp)();
1340int offset;
1341{
1342 char *ptr, *head;
1343
1344 if( a==0 ){
1345 head = b;
1346 }else if( b==0 ){
1347 head = a;
1348 }else{
1349 if( (*cmp)(a,b)<0 ){
1350 ptr = a;
1351 a = NEXT(a);
1352 }else{
1353 ptr = b;
1354 b = NEXT(b);
1355 }
1356 head = ptr;
1357 while( a && b ){
1358 if( (*cmp)(a,b)<0 ){
1359 NEXT(ptr) = a;
1360 ptr = a;
1361 a = NEXT(a);
1362 }else{
1363 NEXT(ptr) = b;
1364 ptr = b;
1365 b = NEXT(b);
1366 }
1367 }
1368 if( a ) NEXT(ptr) = a;
1369 else NEXT(ptr) = b;
1370 }
1371 return head;
1372}
1373
1374/*
1375** Inputs:
1376** list: Pointer to a singly-linked list of structures.
1377** next: Pointer to pointer to the second element of the list.
1378** cmp: A comparison function.
1379**
1380** Return Value:
1381** A pointer to the head of a sorted list containing the elements
1382** orginally in list.
1383**
1384** Side effects:
1385** The "next" pointers for elements in list are changed.
1386*/
1387#define LISTSIZE 30
1388char *msort(list,next,cmp)
1389char *list;
1390char **next;
1391int (*cmp)();
1392{
drhba99af52001-10-25 20:37:16 +00001393 unsigned long offset;
drh75897232000-05-29 14:26:00 +00001394 char *ep;
1395 char *set[LISTSIZE];
1396 int i;
drhba99af52001-10-25 20:37:16 +00001397 offset = (unsigned long)next - (unsigned long)list;
drh75897232000-05-29 14:26:00 +00001398 for(i=0; i<LISTSIZE; i++) set[i] = 0;
1399 while( list ){
1400 ep = list;
1401 list = NEXT(list);
1402 NEXT(ep) = 0;
1403 for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
1404 ep = merge(ep,set[i],cmp,offset);
1405 set[i] = 0;
1406 }
1407 set[i] = ep;
1408 }
1409 ep = 0;
1410 for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset);
1411 return ep;
1412}
1413/************************ From the file "option.c" **************************/
1414static char **argv;
1415static struct s_options *op;
1416static FILE *errstream;
1417
1418#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
1419
1420/*
1421** Print the command line with a carrot pointing to the k-th character
1422** of the n-th field.
1423*/
1424static void errline(n,k,err)
1425int n;
1426int k;
1427FILE *err;
1428{
1429 int spcnt, i;
1430 spcnt = 0;
1431 if( argv[0] ) fprintf(err,"%s",argv[0]);
1432 spcnt = strlen(argv[0]) + 1;
1433 for(i=1; i<n && argv[i]; i++){
1434 fprintf(err," %s",argv[i]);
1435 spcnt += strlen(argv[i]+1);
1436 }
1437 spcnt += k;
1438 for(; argv[i]; i++) fprintf(err," %s",argv[i]);
1439 if( spcnt<20 ){
1440 fprintf(err,"\n%*s^-- here\n",spcnt,"");
1441 }else{
1442 fprintf(err,"\n%*shere --^\n",spcnt-7,"");
1443 }
1444}
1445
1446/*
1447** Return the index of the N-th non-switch argument. Return -1
1448** if N is out of range.
1449*/
1450static int argindex(n)
1451int n;
1452{
1453 int i;
1454 int dashdash = 0;
1455 if( argv!=0 && *argv!=0 ){
1456 for(i=1; argv[i]; i++){
1457 if( dashdash || !ISOPT(argv[i]) ){
1458 if( n==0 ) return i;
1459 n--;
1460 }
1461 if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1462 }
1463 }
1464 return -1;
1465}
1466
1467static char emsg[] = "Command line syntax error: ";
1468
1469/*
1470** Process a flag command line argument.
1471*/
1472static int handleflags(i,err)
1473int i;
1474FILE *err;
1475{
1476 int v;
1477 int errcnt = 0;
1478 int j;
1479 for(j=0; op[j].label; j++){
1480 if( strcmp(&argv[i][1],op[j].label)==0 ) break;
1481 }
1482 v = argv[i][0]=='-' ? 1 : 0;
1483 if( op[j].label==0 ){
1484 if( err ){
1485 fprintf(err,"%sundefined option.\n",emsg);
1486 errline(i,1,err);
1487 }
1488 errcnt++;
1489 }else if( op[j].type==OPT_FLAG ){
1490 *((int*)op[j].arg) = v;
1491 }else if( op[j].type==OPT_FFLAG ){
1492 (*(void(*)())(op[j].arg))(v);
1493 }else{
1494 if( err ){
1495 fprintf(err,"%smissing argument on switch.\n",emsg);
1496 errline(i,1,err);
1497 }
1498 errcnt++;
1499 }
1500 return errcnt;
1501}
1502
1503/*
1504** Process a command line switch which has an argument.
1505*/
1506static int handleswitch(i,err)
1507int i;
1508FILE *err;
1509{
1510 int lv = 0;
1511 double dv = 0.0;
1512 char *sv = 0, *end;
1513 char *cp;
1514 int j;
1515 int errcnt = 0;
1516 cp = strchr(argv[i],'=');
1517 *cp = 0;
1518 for(j=0; op[j].label; j++){
1519 if( strcmp(argv[i],op[j].label)==0 ) break;
1520 }
1521 *cp = '=';
1522 if( op[j].label==0 ){
1523 if( err ){
1524 fprintf(err,"%sundefined option.\n",emsg);
1525 errline(i,0,err);
1526 }
1527 errcnt++;
1528 }else{
1529 cp++;
1530 switch( op[j].type ){
1531 case OPT_FLAG:
1532 case OPT_FFLAG:
1533 if( err ){
1534 fprintf(err,"%soption requires an argument.\n",emsg);
1535 errline(i,0,err);
1536 }
1537 errcnt++;
1538 break;
1539 case OPT_DBL:
1540 case OPT_FDBL:
1541 dv = strtod(cp,&end);
1542 if( *end ){
1543 if( err ){
1544 fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
drhba99af52001-10-25 20:37:16 +00001545 errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
drh75897232000-05-29 14:26:00 +00001546 }
1547 errcnt++;
1548 }
1549 break;
1550 case OPT_INT:
1551 case OPT_FINT:
1552 lv = strtol(cp,&end,0);
1553 if( *end ){
1554 if( err ){
1555 fprintf(err,"%sillegal character in integer argument.\n",emsg);
drhba99af52001-10-25 20:37:16 +00001556 errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
drh75897232000-05-29 14:26:00 +00001557 }
1558 errcnt++;
1559 }
1560 break;
1561 case OPT_STR:
1562 case OPT_FSTR:
1563 sv = cp;
1564 break;
1565 }
1566 switch( op[j].type ){
1567 case OPT_FLAG:
1568 case OPT_FFLAG:
1569 break;
1570 case OPT_DBL:
1571 *(double*)(op[j].arg) = dv;
1572 break;
1573 case OPT_FDBL:
1574 (*(void(*)())(op[j].arg))(dv);
1575 break;
1576 case OPT_INT:
1577 *(int*)(op[j].arg) = lv;
1578 break;
1579 case OPT_FINT:
1580 (*(void(*)())(op[j].arg))((int)lv);
1581 break;
1582 case OPT_STR:
1583 *(char**)(op[j].arg) = sv;
1584 break;
1585 case OPT_FSTR:
1586 (*(void(*)())(op[j].arg))(sv);
1587 break;
1588 }
1589 }
1590 return errcnt;
1591}
1592
drhb0c86772000-06-02 23:21:26 +00001593int OptInit(a,o,err)
drh75897232000-05-29 14:26:00 +00001594char **a;
1595struct s_options *o;
1596FILE *err;
1597{
1598 int errcnt = 0;
1599 argv = a;
1600 op = o;
1601 errstream = err;
1602 if( argv && *argv && op ){
1603 int i;
1604 for(i=1; argv[i]; i++){
1605 if( argv[i][0]=='+' || argv[i][0]=='-' ){
1606 errcnt += handleflags(i,err);
1607 }else if( strchr(argv[i],'=') ){
1608 errcnt += handleswitch(i,err);
1609 }
1610 }
1611 }
1612 if( errcnt>0 ){
1613 fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
drhb0c86772000-06-02 23:21:26 +00001614 OptPrint();
drh75897232000-05-29 14:26:00 +00001615 exit(1);
1616 }
1617 return 0;
1618}
1619
drhb0c86772000-06-02 23:21:26 +00001620int OptNArgs(){
drh75897232000-05-29 14:26:00 +00001621 int cnt = 0;
1622 int dashdash = 0;
1623 int i;
1624 if( argv!=0 && argv[0]!=0 ){
1625 for(i=1; argv[i]; i++){
1626 if( dashdash || !ISOPT(argv[i]) ) cnt++;
1627 if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1628 }
1629 }
1630 return cnt;
1631}
1632
drhb0c86772000-06-02 23:21:26 +00001633char *OptArg(n)
drh75897232000-05-29 14:26:00 +00001634int n;
1635{
1636 int i;
1637 i = argindex(n);
1638 return i>=0 ? argv[i] : 0;
1639}
1640
drhb0c86772000-06-02 23:21:26 +00001641void OptErr(n)
drh75897232000-05-29 14:26:00 +00001642int n;
1643{
1644 int i;
1645 i = argindex(n);
1646 if( i>=0 ) errline(i,0,errstream);
1647}
1648
drhb0c86772000-06-02 23:21:26 +00001649void OptPrint(){
drh75897232000-05-29 14:26:00 +00001650 int i;
1651 int max, len;
1652 max = 0;
1653 for(i=0; op[i].label; i++){
1654 len = strlen(op[i].label) + 1;
1655 switch( op[i].type ){
1656 case OPT_FLAG:
1657 case OPT_FFLAG:
1658 break;
1659 case OPT_INT:
1660 case OPT_FINT:
1661 len += 9; /* length of "<integer>" */
1662 break;
1663 case OPT_DBL:
1664 case OPT_FDBL:
1665 len += 6; /* length of "<real>" */
1666 break;
1667 case OPT_STR:
1668 case OPT_FSTR:
1669 len += 8; /* length of "<string>" */
1670 break;
1671 }
1672 if( len>max ) max = len;
1673 }
1674 for(i=0; op[i].label; i++){
1675 switch( op[i].type ){
1676 case OPT_FLAG:
1677 case OPT_FFLAG:
1678 fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message);
1679 break;
1680 case OPT_INT:
1681 case OPT_FINT:
1682 fprintf(errstream," %s=<integer>%*s %s\n",op[i].label,
1683 max-strlen(op[i].label)-9,"",op[i].message);
1684 break;
1685 case OPT_DBL:
1686 case OPT_FDBL:
1687 fprintf(errstream," %s=<real>%*s %s\n",op[i].label,
1688 max-strlen(op[i].label)-6,"",op[i].message);
1689 break;
1690 case OPT_STR:
1691 case OPT_FSTR:
1692 fprintf(errstream," %s=<string>%*s %s\n",op[i].label,
1693 max-strlen(op[i].label)-8,"",op[i].message);
1694 break;
1695 }
1696 }
1697}
1698/*********************** From the file "parse.c" ****************************/
1699/*
1700** Input file parser for the LEMON parser generator.
1701*/
1702
1703/* The state of the parser */
1704struct pstate {
1705 char *filename; /* Name of the input file */
1706 int tokenlineno; /* Linenumber at which current token starts */
1707 int errorcnt; /* Number of errors so far */
1708 char *tokenstart; /* Text of current token */
1709 struct lemon *gp; /* Global state vector */
1710 enum e_state {
1711 INITIALIZE,
1712 WAITING_FOR_DECL_OR_RULE,
1713 WAITING_FOR_DECL_KEYWORD,
1714 WAITING_FOR_DECL_ARG,
1715 WAITING_FOR_PRECEDENCE_SYMBOL,
1716 WAITING_FOR_ARROW,
1717 IN_RHS,
1718 LHS_ALIAS_1,
1719 LHS_ALIAS_2,
1720 LHS_ALIAS_3,
1721 RHS_ALIAS_1,
1722 RHS_ALIAS_2,
1723 PRECEDENCE_MARK_1,
1724 PRECEDENCE_MARK_2,
1725 RESYNC_AFTER_RULE_ERROR,
1726 RESYNC_AFTER_DECL_ERROR,
1727 WAITING_FOR_DESTRUCTOR_SYMBOL,
drh0bd1f4e2002-06-06 18:54:39 +00001728 WAITING_FOR_DATATYPE_SYMBOL,
1729 WAITING_FOR_FALLBACK_ID
drh75897232000-05-29 14:26:00 +00001730 } state; /* The state of the parser */
drh0bd1f4e2002-06-06 18:54:39 +00001731 struct symbol *fallback; /* The fallback token */
drh75897232000-05-29 14:26:00 +00001732 struct symbol *lhs; /* Left-hand side of current rule */
1733 char *lhsalias; /* Alias for the LHS */
1734 int nrhs; /* Number of right-hand side symbols seen */
1735 struct symbol *rhs[MAXRHS]; /* RHS symbols */
1736 char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
1737 struct rule *prevrule; /* Previous rule parsed */
1738 char *declkeyword; /* Keyword of a declaration */
1739 char **declargslot; /* Where the declaration argument should be put */
1740 int *decllnslot; /* Where the declaration linenumber is put */
1741 enum e_assoc declassoc; /* Assign this association to decl arguments */
1742 int preccounter; /* Assign this precedence to decl arguments */
1743 struct rule *firstrule; /* Pointer to first rule in the grammar */
1744 struct rule *lastrule; /* Pointer to the most recently parsed rule */
1745};
1746
1747/* Parse a single token */
1748static void parseonetoken(psp)
1749struct pstate *psp;
1750{
1751 char *x;
1752 x = Strsafe(psp->tokenstart); /* Save the token permanently */
1753#if 0
1754 printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
1755 x,psp->state);
1756#endif
1757 switch( psp->state ){
1758 case INITIALIZE:
1759 psp->prevrule = 0;
1760 psp->preccounter = 0;
1761 psp->firstrule = psp->lastrule = 0;
1762 psp->gp->nrule = 0;
1763 /* Fall thru to next case */
1764 case WAITING_FOR_DECL_OR_RULE:
1765 if( x[0]=='%' ){
1766 psp->state = WAITING_FOR_DECL_KEYWORD;
1767 }else if( islower(x[0]) ){
1768 psp->lhs = Symbol_new(x);
1769 psp->nrhs = 0;
1770 psp->lhsalias = 0;
1771 psp->state = WAITING_FOR_ARROW;
1772 }else if( x[0]=='{' ){
1773 if( psp->prevrule==0 ){
1774 ErrorMsg(psp->filename,psp->tokenlineno,
1775"There is not prior rule opon which to attach the code \
1776fragment which begins on this line.");
1777 psp->errorcnt++;
1778 }else if( psp->prevrule->code!=0 ){
1779 ErrorMsg(psp->filename,psp->tokenlineno,
1780"Code fragment beginning on this line is not the first \
1781to follow the previous rule.");
1782 psp->errorcnt++;
1783 }else{
1784 psp->prevrule->line = psp->tokenlineno;
1785 psp->prevrule->code = &x[1];
1786 }
1787 }else if( x[0]=='[' ){
1788 psp->state = PRECEDENCE_MARK_1;
1789 }else{
1790 ErrorMsg(psp->filename,psp->tokenlineno,
1791 "Token \"%s\" should be either \"%%\" or a nonterminal name.",
1792 x);
1793 psp->errorcnt++;
1794 }
1795 break;
1796 case PRECEDENCE_MARK_1:
1797 if( !isupper(x[0]) ){
1798 ErrorMsg(psp->filename,psp->tokenlineno,
1799 "The precedence symbol must be a terminal.");
1800 psp->errorcnt++;
1801 }else if( psp->prevrule==0 ){
1802 ErrorMsg(psp->filename,psp->tokenlineno,
1803 "There is no prior rule to assign precedence \"[%s]\".",x);
1804 psp->errorcnt++;
1805 }else if( psp->prevrule->precsym!=0 ){
1806 ErrorMsg(psp->filename,psp->tokenlineno,
1807"Precedence mark on this line is not the first \
1808to follow the previous rule.");
1809 psp->errorcnt++;
1810 }else{
1811 psp->prevrule->precsym = Symbol_new(x);
1812 }
1813 psp->state = PRECEDENCE_MARK_2;
1814 break;
1815 case PRECEDENCE_MARK_2:
1816 if( x[0]!=']' ){
1817 ErrorMsg(psp->filename,psp->tokenlineno,
1818 "Missing \"]\" on precedence mark.");
1819 psp->errorcnt++;
1820 }
1821 psp->state = WAITING_FOR_DECL_OR_RULE;
1822 break;
1823 case WAITING_FOR_ARROW:
1824 if( x[0]==':' && x[1]==':' && x[2]=='=' ){
1825 psp->state = IN_RHS;
1826 }else if( x[0]=='(' ){
1827 psp->state = LHS_ALIAS_1;
1828 }else{
1829 ErrorMsg(psp->filename,psp->tokenlineno,
1830 "Expected to see a \":\" following the LHS symbol \"%s\".",
1831 psp->lhs->name);
1832 psp->errorcnt++;
1833 psp->state = RESYNC_AFTER_RULE_ERROR;
1834 }
1835 break;
1836 case LHS_ALIAS_1:
1837 if( isalpha(x[0]) ){
1838 psp->lhsalias = x;
1839 psp->state = LHS_ALIAS_2;
1840 }else{
1841 ErrorMsg(psp->filename,psp->tokenlineno,
1842 "\"%s\" is not a valid alias for the LHS \"%s\"\n",
1843 x,psp->lhs->name);
1844 psp->errorcnt++;
1845 psp->state = RESYNC_AFTER_RULE_ERROR;
1846 }
1847 break;
1848 case LHS_ALIAS_2:
1849 if( x[0]==')' ){
1850 psp->state = LHS_ALIAS_3;
1851 }else{
1852 ErrorMsg(psp->filename,psp->tokenlineno,
1853 "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
1854 psp->errorcnt++;
1855 psp->state = RESYNC_AFTER_RULE_ERROR;
1856 }
1857 break;
1858 case LHS_ALIAS_3:
1859 if( x[0]==':' && x[1]==':' && x[2]=='=' ){
1860 psp->state = IN_RHS;
1861 }else{
1862 ErrorMsg(psp->filename,psp->tokenlineno,
1863 "Missing \"->\" following: \"%s(%s)\".",
1864 psp->lhs->name,psp->lhsalias);
1865 psp->errorcnt++;
1866 psp->state = RESYNC_AFTER_RULE_ERROR;
1867 }
1868 break;
1869 case IN_RHS:
1870 if( x[0]=='.' ){
1871 struct rule *rp;
1872 rp = (struct rule *)malloc( sizeof(struct rule) +
1873 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
1874 if( rp==0 ){
1875 ErrorMsg(psp->filename,psp->tokenlineno,
1876 "Can't allocate enough memory for this rule.");
1877 psp->errorcnt++;
1878 psp->prevrule = 0;
1879 }else{
1880 int i;
1881 rp->ruleline = psp->tokenlineno;
1882 rp->rhs = (struct symbol**)&rp[1];
1883 rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]);
1884 for(i=0; i<psp->nrhs; i++){
1885 rp->rhs[i] = psp->rhs[i];
1886 rp->rhsalias[i] = psp->alias[i];
1887 }
1888 rp->lhs = psp->lhs;
1889 rp->lhsalias = psp->lhsalias;
1890 rp->nrhs = psp->nrhs;
1891 rp->code = 0;
1892 rp->precsym = 0;
1893 rp->index = psp->gp->nrule++;
1894 rp->nextlhs = rp->lhs->rule;
1895 rp->lhs->rule = rp;
1896 rp->next = 0;
1897 if( psp->firstrule==0 ){
1898 psp->firstrule = psp->lastrule = rp;
1899 }else{
1900 psp->lastrule->next = rp;
1901 psp->lastrule = rp;
1902 }
1903 psp->prevrule = rp;
1904 }
1905 psp->state = WAITING_FOR_DECL_OR_RULE;
1906 }else if( isalpha(x[0]) ){
1907 if( psp->nrhs>=MAXRHS ){
1908 ErrorMsg(psp->filename,psp->tokenlineno,
1909 "Too many symbol on RHS or rule beginning at \"%s\".",
1910 x);
1911 psp->errorcnt++;
1912 psp->state = RESYNC_AFTER_RULE_ERROR;
1913 }else{
1914 psp->rhs[psp->nrhs] = Symbol_new(x);
1915 psp->alias[psp->nrhs] = 0;
1916 psp->nrhs++;
1917 }
1918 }else if( x[0]=='(' && psp->nrhs>0 ){
1919 psp->state = RHS_ALIAS_1;
1920 }else{
1921 ErrorMsg(psp->filename,psp->tokenlineno,
1922 "Illegal character on RHS of rule: \"%s\".",x);
1923 psp->errorcnt++;
1924 psp->state = RESYNC_AFTER_RULE_ERROR;
1925 }
1926 break;
1927 case RHS_ALIAS_1:
1928 if( isalpha(x[0]) ){
1929 psp->alias[psp->nrhs-1] = x;
1930 psp->state = RHS_ALIAS_2;
1931 }else{
1932 ErrorMsg(psp->filename,psp->tokenlineno,
1933 "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
1934 x,psp->rhs[psp->nrhs-1]->name);
1935 psp->errorcnt++;
1936 psp->state = RESYNC_AFTER_RULE_ERROR;
1937 }
1938 break;
1939 case RHS_ALIAS_2:
1940 if( x[0]==')' ){
1941 psp->state = IN_RHS;
1942 }else{
1943 ErrorMsg(psp->filename,psp->tokenlineno,
1944 "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
1945 psp->errorcnt++;
1946 psp->state = RESYNC_AFTER_RULE_ERROR;
1947 }
1948 break;
1949 case WAITING_FOR_DECL_KEYWORD:
1950 if( isalpha(x[0]) ){
1951 psp->declkeyword = x;
1952 psp->declargslot = 0;
1953 psp->decllnslot = 0;
1954 psp->state = WAITING_FOR_DECL_ARG;
1955 if( strcmp(x,"name")==0 ){
1956 psp->declargslot = &(psp->gp->name);
1957 }else if( strcmp(x,"include")==0 ){
1958 psp->declargslot = &(psp->gp->include);
1959 psp->decllnslot = &psp->gp->includeln;
1960 }else if( strcmp(x,"code")==0 ){
1961 psp->declargslot = &(psp->gp->extracode);
1962 psp->decllnslot = &psp->gp->extracodeln;
1963 }else if( strcmp(x,"token_destructor")==0 ){
1964 psp->declargslot = &psp->gp->tokendest;
1965 psp->decllnslot = &psp->gp->tokendestln;
drh960e8c62001-04-03 16:53:21 +00001966 }else if( strcmp(x,"default_destructor")==0 ){
1967 psp->declargslot = &psp->gp->vardest;
1968 psp->decllnslot = &psp->gp->vardestln;
drh75897232000-05-29 14:26:00 +00001969 }else if( strcmp(x,"token_prefix")==0 ){
1970 psp->declargslot = &psp->gp->tokenprefix;
1971 }else if( strcmp(x,"syntax_error")==0 ){
1972 psp->declargslot = &(psp->gp->error);
1973 psp->decllnslot = &psp->gp->errorln;
1974 }else if( strcmp(x,"parse_accept")==0 ){
1975 psp->declargslot = &(psp->gp->accept);
1976 psp->decllnslot = &psp->gp->acceptln;
1977 }else if( strcmp(x,"parse_failure")==0 ){
1978 psp->declargslot = &(psp->gp->failure);
1979 psp->decllnslot = &psp->gp->failureln;
1980 }else if( strcmp(x,"stack_overflow")==0 ){
1981 psp->declargslot = &(psp->gp->overflow);
1982 psp->decllnslot = &psp->gp->overflowln;
1983 }else if( strcmp(x,"extra_argument")==0 ){
1984 psp->declargslot = &(psp->gp->arg);
1985 }else if( strcmp(x,"token_type")==0 ){
1986 psp->declargslot = &(psp->gp->tokentype);
drh960e8c62001-04-03 16:53:21 +00001987 }else if( strcmp(x,"default_type")==0 ){
1988 psp->declargslot = &(psp->gp->vartype);
drh75897232000-05-29 14:26:00 +00001989 }else if( strcmp(x,"stack_size")==0 ){
1990 psp->declargslot = &(psp->gp->stacksize);
1991 }else if( strcmp(x,"start_symbol")==0 ){
1992 psp->declargslot = &(psp->gp->start);
1993 }else if( strcmp(x,"left")==0 ){
1994 psp->preccounter++;
1995 psp->declassoc = LEFT;
1996 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
1997 }else if( strcmp(x,"right")==0 ){
1998 psp->preccounter++;
1999 psp->declassoc = RIGHT;
2000 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2001 }else if( strcmp(x,"nonassoc")==0 ){
2002 psp->preccounter++;
2003 psp->declassoc = NONE;
2004 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
2005 }else if( strcmp(x,"destructor")==0 ){
2006 psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
2007 }else if( strcmp(x,"type")==0 ){
2008 psp->state = WAITING_FOR_DATATYPE_SYMBOL;
drh0bd1f4e2002-06-06 18:54:39 +00002009 }else if( strcmp(x,"fallback")==0 ){
2010 psp->fallback = 0;
2011 psp->state = WAITING_FOR_FALLBACK_ID;
drh75897232000-05-29 14:26:00 +00002012 }else{
2013 ErrorMsg(psp->filename,psp->tokenlineno,
2014 "Unknown declaration keyword: \"%%%s\".",x);
2015 psp->errorcnt++;
2016 psp->state = RESYNC_AFTER_DECL_ERROR;
2017 }
2018 }else{
2019 ErrorMsg(psp->filename,psp->tokenlineno,
2020 "Illegal declaration keyword: \"%s\".",x);
2021 psp->errorcnt++;
2022 psp->state = RESYNC_AFTER_DECL_ERROR;
2023 }
2024 break;
2025 case WAITING_FOR_DESTRUCTOR_SYMBOL:
2026 if( !isalpha(x[0]) ){
2027 ErrorMsg(psp->filename,psp->tokenlineno,
2028 "Symbol name missing after %destructor keyword");
2029 psp->errorcnt++;
2030 psp->state = RESYNC_AFTER_DECL_ERROR;
2031 }else{
2032 struct symbol *sp = Symbol_new(x);
2033 psp->declargslot = &sp->destructor;
2034 psp->decllnslot = &sp->destructorln;
2035 psp->state = WAITING_FOR_DECL_ARG;
2036 }
2037 break;
2038 case WAITING_FOR_DATATYPE_SYMBOL:
2039 if( !isalpha(x[0]) ){
2040 ErrorMsg(psp->filename,psp->tokenlineno,
2041 "Symbol name missing after %destructor keyword");
2042 psp->errorcnt++;
2043 psp->state = RESYNC_AFTER_DECL_ERROR;
2044 }else{
2045 struct symbol *sp = Symbol_new(x);
2046 psp->declargslot = &sp->datatype;
2047 psp->decllnslot = 0;
2048 psp->state = WAITING_FOR_DECL_ARG;
2049 }
2050 break;
2051 case WAITING_FOR_PRECEDENCE_SYMBOL:
2052 if( x[0]=='.' ){
2053 psp->state = WAITING_FOR_DECL_OR_RULE;
2054 }else if( isupper(x[0]) ){
2055 struct symbol *sp;
2056 sp = Symbol_new(x);
2057 if( sp->prec>=0 ){
2058 ErrorMsg(psp->filename,psp->tokenlineno,
2059 "Symbol \"%s\" has already be given a precedence.",x);
2060 psp->errorcnt++;
2061 }else{
2062 sp->prec = psp->preccounter;
2063 sp->assoc = psp->declassoc;
2064 }
2065 }else{
2066 ErrorMsg(psp->filename,psp->tokenlineno,
2067 "Can't assign a precedence to \"%s\".",x);
2068 psp->errorcnt++;
2069 }
2070 break;
2071 case WAITING_FOR_DECL_ARG:
2072 if( (x[0]=='{' || x[0]=='\"' || isalnum(x[0])) ){
2073 if( *(psp->declargslot)!=0 ){
2074 ErrorMsg(psp->filename,psp->tokenlineno,
2075 "The argument \"%s\" to declaration \"%%%s\" is not the first.",
2076 x[0]=='\"' ? &x[1] : x,psp->declkeyword);
2077 psp->errorcnt++;
2078 psp->state = RESYNC_AFTER_DECL_ERROR;
2079 }else{
2080 *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x;
2081 if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno;
2082 psp->state = WAITING_FOR_DECL_OR_RULE;
2083 }
2084 }else{
2085 ErrorMsg(psp->filename,psp->tokenlineno,
2086 "Illegal argument to %%%s: %s",psp->declkeyword,x);
2087 psp->errorcnt++;
2088 psp->state = RESYNC_AFTER_DECL_ERROR;
2089 }
2090 break;
drh0bd1f4e2002-06-06 18:54:39 +00002091 case WAITING_FOR_FALLBACK_ID:
2092 if( x[0]=='.' ){
2093 psp->state = WAITING_FOR_DECL_OR_RULE;
2094 }else if( !isupper(x[0]) ){
2095 ErrorMsg(psp->filename, psp->tokenlineno,
2096 "%%fallback argument \"%s\" should be a token", x);
2097 psp->errorcnt++;
2098 }else{
2099 struct symbol *sp = Symbol_new(x);
2100 if( psp->fallback==0 ){
2101 psp->fallback = sp;
2102 }else if( sp->fallback ){
2103 ErrorMsg(psp->filename, psp->tokenlineno,
2104 "More than one fallback assigned to token %s", x);
2105 psp->errorcnt++;
2106 }else{
2107 sp->fallback = psp->fallback;
2108 psp->gp->has_fallback = 1;
2109 }
2110 }
2111 break;
drh75897232000-05-29 14:26:00 +00002112 case RESYNC_AFTER_RULE_ERROR:
2113/* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2114** break; */
2115 case RESYNC_AFTER_DECL_ERROR:
2116 if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2117 if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
2118 break;
2119 }
2120}
2121
2122/* In spite of its name, this function is really a scanner. It read
2123** in the entire input file (all at once) then tokenizes it. Each
2124** token is passed to the function "parseonetoken" which builds all
2125** the appropriate data structures in the global state vector "gp".
2126*/
2127void Parse(gp)
2128struct lemon *gp;
2129{
2130 struct pstate ps;
2131 FILE *fp;
2132 char *filebuf;
2133 int filesize;
2134 int lineno;
2135 int c;
2136 char *cp, *nextcp;
2137 int startline = 0;
2138
2139 ps.gp = gp;
2140 ps.filename = gp->filename;
2141 ps.errorcnt = 0;
2142 ps.state = INITIALIZE;
2143
2144 /* Begin by reading the input file */
2145 fp = fopen(ps.filename,"rb");
2146 if( fp==0 ){
2147 ErrorMsg(ps.filename,0,"Can't open this file for reading.");
2148 gp->errorcnt++;
2149 return;
2150 }
2151 fseek(fp,0,2);
2152 filesize = ftell(fp);
2153 rewind(fp);
2154 filebuf = (char *)malloc( filesize+1 );
2155 if( filebuf==0 ){
2156 ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.",
2157 filesize+1);
2158 gp->errorcnt++;
2159 return;
2160 }
2161 if( fread(filebuf,1,filesize,fp)!=filesize ){
2162 ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
2163 filesize);
2164 free(filebuf);
2165 gp->errorcnt++;
2166 return;
2167 }
2168 fclose(fp);
2169 filebuf[filesize] = 0;
2170
2171 /* Now scan the text of the input file */
2172 lineno = 1;
2173 for(cp=filebuf; (c= *cp)!=0; ){
2174 if( c=='\n' ) lineno++; /* Keep track of the line number */
2175 if( isspace(c) ){ cp++; continue; } /* Skip all white space */
2176 if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */
2177 cp+=2;
2178 while( (c= *cp)!=0 && c!='\n' ) cp++;
2179 continue;
2180 }
2181 if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */
2182 cp+=2;
2183 while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
2184 if( c=='\n' ) lineno++;
2185 cp++;
2186 }
2187 if( c ) cp++;
2188 continue;
2189 }
2190 ps.tokenstart = cp; /* Mark the beginning of the token */
2191 ps.tokenlineno = lineno; /* Linenumber on which token begins */
2192 if( c=='\"' ){ /* String literals */
2193 cp++;
2194 while( (c= *cp)!=0 && c!='\"' ){
2195 if( c=='\n' ) lineno++;
2196 cp++;
2197 }
2198 if( c==0 ){
2199 ErrorMsg(ps.filename,startline,
2200"String starting on this line is not terminated before the end of the file.");
2201 ps.errorcnt++;
2202 nextcp = cp;
2203 }else{
2204 nextcp = cp+1;
2205 }
2206 }else if( c=='{' ){ /* A block of C code */
2207 int level;
2208 cp++;
2209 for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
2210 if( c=='\n' ) lineno++;
2211 else if( c=='{' ) level++;
2212 else if( c=='}' ) level--;
2213 else if( c=='/' && cp[1]=='*' ){ /* Skip comments */
2214 int prevc;
2215 cp = &cp[2];
2216 prevc = 0;
2217 while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
2218 if( c=='\n' ) lineno++;
2219 prevc = c;
2220 cp++;
2221 }
2222 }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
2223 cp = &cp[2];
2224 while( (c= *cp)!=0 && c!='\n' ) cp++;
2225 if( c ) lineno++;
2226 }else if( c=='\'' || c=='\"' ){ /* String a character literals */
2227 int startchar, prevc;
2228 startchar = c;
2229 prevc = 0;
2230 for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
2231 if( c=='\n' ) lineno++;
2232 if( prevc=='\\' ) prevc = 0;
2233 else prevc = c;
2234 }
2235 }
2236 }
2237 if( c==0 ){
drh960e8c62001-04-03 16:53:21 +00002238 ErrorMsg(ps.filename,ps.tokenlineno,
drh75897232000-05-29 14:26:00 +00002239"C code starting on this line is not terminated before the end of the file.");
2240 ps.errorcnt++;
2241 nextcp = cp;
2242 }else{
2243 nextcp = cp+1;
2244 }
2245 }else if( isalnum(c) ){ /* Identifiers */
2246 while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
2247 nextcp = cp;
2248 }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
2249 cp += 3;
2250 nextcp = cp;
2251 }else{ /* All other (one character) operators */
2252 cp++;
2253 nextcp = cp;
2254 }
2255 c = *cp;
2256 *cp = 0; /* Null terminate the token */
2257 parseonetoken(&ps); /* Parse the token */
2258 *cp = c; /* Restore the buffer */
2259 cp = nextcp;
2260 }
2261 free(filebuf); /* Release the buffer after parsing */
2262 gp->rule = ps.firstrule;
2263 gp->errorcnt = ps.errorcnt;
2264}
2265/*************************** From the file "plink.c" *********************/
2266/*
2267** Routines processing configuration follow-set propagation links
2268** in the LEMON parser generator.
2269*/
2270static struct plink *plink_freelist = 0;
2271
2272/* Allocate a new plink */
2273struct plink *Plink_new(){
2274 struct plink *new;
2275
2276 if( plink_freelist==0 ){
2277 int i;
2278 int amt = 100;
2279 plink_freelist = (struct plink *)malloc( sizeof(struct plink)*amt );
2280 if( plink_freelist==0 ){
2281 fprintf(stderr,
2282 "Unable to allocate memory for a new follow-set propagation link.\n");
2283 exit(1);
2284 }
2285 for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
2286 plink_freelist[amt-1].next = 0;
2287 }
2288 new = plink_freelist;
2289 plink_freelist = plink_freelist->next;
2290 return new;
2291}
2292
2293/* Add a plink to a plink list */
2294void Plink_add(plpp,cfp)
2295struct plink **plpp;
2296struct config *cfp;
2297{
2298 struct plink *new;
2299 new = Plink_new();
2300 new->next = *plpp;
2301 *plpp = new;
2302 new->cfp = cfp;
2303}
2304
2305/* Transfer every plink on the list "from" to the list "to" */
2306void Plink_copy(to,from)
2307struct plink **to;
2308struct plink *from;
2309{
2310 struct plink *nextpl;
2311 while( from ){
2312 nextpl = from->next;
2313 from->next = *to;
2314 *to = from;
2315 from = nextpl;
2316 }
2317}
2318
2319/* Delete every plink on the list */
2320void Plink_delete(plp)
2321struct plink *plp;
2322{
2323 struct plink *nextpl;
2324
2325 while( plp ){
2326 nextpl = plp->next;
2327 plp->next = plink_freelist;
2328 plink_freelist = plp;
2329 plp = nextpl;
2330 }
2331}
2332/*********************** From the file "report.c" **************************/
2333/*
2334** Procedures for generating reports and tables in the LEMON parser generator.
2335*/
2336
2337/* Generate a filename with the given suffix. Space to hold the
2338** name comes from malloc() and must be freed by the calling
2339** function.
2340*/
2341PRIVATE char *file_makename(lemp,suffix)
2342struct lemon *lemp;
2343char *suffix;
2344{
2345 char *name;
2346 char *cp;
2347
2348 name = malloc( strlen(lemp->filename) + strlen(suffix) + 5 );
2349 if( name==0 ){
2350 fprintf(stderr,"Can't allocate space for a filename.\n");
2351 exit(1);
2352 }
2353 strcpy(name,lemp->filename);
2354 cp = strrchr(name,'.');
2355 if( cp ) *cp = 0;
2356 strcat(name,suffix);
2357 return name;
2358}
2359
2360/* Open a file with a name based on the name of the input file,
2361** but with a different (specified) suffix, and return a pointer
2362** to the stream */
2363PRIVATE FILE *file_open(lemp,suffix,mode)
2364struct lemon *lemp;
2365char *suffix;
2366char *mode;
2367{
2368 FILE *fp;
2369
2370 if( lemp->outname ) free(lemp->outname);
2371 lemp->outname = file_makename(lemp, suffix);
2372 fp = fopen(lemp->outname,mode);
2373 if( fp==0 && *mode=='w' ){
2374 fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
2375 lemp->errorcnt++;
2376 return 0;
2377 }
2378 return fp;
2379}
2380
2381/* Duplicate the input file without comments and without actions
2382** on rules */
2383void Reprint(lemp)
2384struct lemon *lemp;
2385{
2386 struct rule *rp;
2387 struct symbol *sp;
2388 int i, j, maxlen, len, ncolumns, skip;
2389 printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
2390 maxlen = 10;
2391 for(i=0; i<lemp->nsymbol; i++){
2392 sp = lemp->symbols[i];
2393 len = strlen(sp->name);
2394 if( len>maxlen ) maxlen = len;
2395 }
2396 ncolumns = 76/(maxlen+5);
2397 if( ncolumns<1 ) ncolumns = 1;
2398 skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
2399 for(i=0; i<skip; i++){
2400 printf("//");
2401 for(j=i; j<lemp->nsymbol; j+=skip){
2402 sp = lemp->symbols[j];
2403 assert( sp->index==j );
2404 printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
2405 }
2406 printf("\n");
2407 }
2408 for(rp=lemp->rule; rp; rp=rp->next){
2409 printf("%s",rp->lhs->name);
2410/* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
2411 printf(" ::=");
2412 for(i=0; i<rp->nrhs; i++){
2413 printf(" %s",rp->rhs[i]->name);
2414/* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
2415 }
2416 printf(".");
2417 if( rp->precsym ) printf(" [%s]",rp->precsym->name);
2418/* if( rp->code ) printf("\n %s",rp->code); */
2419 printf("\n");
2420 }
2421}
2422
2423void ConfigPrint(fp,cfp)
2424FILE *fp;
2425struct config *cfp;
2426{
2427 struct rule *rp;
2428 int i;
2429 rp = cfp->rp;
2430 fprintf(fp,"%s ::=",rp->lhs->name);
2431 for(i=0; i<=rp->nrhs; i++){
2432 if( i==cfp->dot ) fprintf(fp," *");
2433 if( i==rp->nrhs ) break;
2434 fprintf(fp," %s",rp->rhs[i]->name);
2435 }
2436}
2437
2438/* #define TEST */
2439#ifdef TEST
2440/* Print a set */
2441PRIVATE void SetPrint(out,set,lemp)
2442FILE *out;
2443char *set;
2444struct lemon *lemp;
2445{
2446 int i;
2447 char *spacer;
2448 spacer = "";
2449 fprintf(out,"%12s[","");
2450 for(i=0; i<lemp->nterminal; i++){
2451 if( SetFind(set,i) ){
2452 fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
2453 spacer = " ";
2454 }
2455 }
2456 fprintf(out,"]\n");
2457}
2458
2459/* Print a plink chain */
2460PRIVATE void PlinkPrint(out,plp,tag)
2461FILE *out;
2462struct plink *plp;
2463char *tag;
2464{
2465 while( plp ){
2466 fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->index);
2467 ConfigPrint(out,plp->cfp);
2468 fprintf(out,"\n");
2469 plp = plp->next;
2470 }
2471}
2472#endif
2473
2474/* Print an action to the given file descriptor. Return FALSE if
2475** nothing was actually printed.
2476*/
2477int PrintAction(struct action *ap, FILE *fp, int indent){
2478 int result = 1;
2479 switch( ap->type ){
2480 case SHIFT:
2481 fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->index);
2482 break;
2483 case REDUCE:
2484 fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
2485 break;
2486 case ACCEPT:
2487 fprintf(fp,"%*s accept",indent,ap->sp->name);
2488 break;
2489 case ERROR:
2490 fprintf(fp,"%*s error",indent,ap->sp->name);
2491 break;
2492 case CONFLICT:
2493 fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
2494 indent,ap->sp->name,ap->x.rp->index);
2495 break;
2496 case SH_RESOLVED:
2497 case RD_RESOLVED:
2498 case NOT_USED:
2499 result = 0;
2500 break;
2501 }
2502 return result;
2503}
2504
2505/* Generate the "y.output" log file */
2506void ReportOutput(lemp)
2507struct lemon *lemp;
2508{
2509 int i;
2510 struct state *stp;
2511 struct config *cfp;
2512 struct action *ap;
2513 FILE *fp;
2514
2515 fp = file_open(lemp,".out","w");
2516 if( fp==0 ) return;
2517 fprintf(fp," \b");
2518 for(i=0; i<lemp->nstate; i++){
2519 stp = lemp->sorted[i];
2520 fprintf(fp,"State %d:\n",stp->index);
2521 if( lemp->basisflag ) cfp=stp->bp;
2522 else cfp=stp->cfp;
2523 while( cfp ){
2524 char buf[20];
2525 if( cfp->dot==cfp->rp->nrhs ){
2526 sprintf(buf,"(%d)",cfp->rp->index);
2527 fprintf(fp," %5s ",buf);
2528 }else{
2529 fprintf(fp," ");
2530 }
2531 ConfigPrint(fp,cfp);
2532 fprintf(fp,"\n");
2533#ifdef TEST
2534 SetPrint(fp,cfp->fws,lemp);
2535 PlinkPrint(fp,cfp->fplp,"To ");
2536 PlinkPrint(fp,cfp->bplp,"From");
2537#endif
2538 if( lemp->basisflag ) cfp=cfp->bp;
2539 else cfp=cfp->next;
2540 }
2541 fprintf(fp,"\n");
2542 for(ap=stp->ap; ap; ap=ap->next){
2543 if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
2544 }
2545 fprintf(fp,"\n");
2546 }
2547 fclose(fp);
2548 return;
2549}
2550
2551/* Search for the file "name" which is in the same directory as
2552** the exacutable */
2553PRIVATE char *pathsearch(argv0,name,modemask)
2554char *argv0;
2555char *name;
2556int modemask;
2557{
2558 char *pathlist;
2559 char *path,*cp;
2560 char c;
2561 extern int access();
2562
2563#ifdef __WIN32__
2564 cp = strrchr(argv0,'\\');
2565#else
2566 cp = strrchr(argv0,'/');
2567#endif
2568 if( cp ){
2569 c = *cp;
2570 *cp = 0;
2571 path = (char *)malloc( strlen(argv0) + strlen(name) + 2 );
2572 if( path ) sprintf(path,"%s/%s",argv0,name);
2573 *cp = c;
2574 }else{
2575 extern char *getenv();
2576 pathlist = getenv("PATH");
2577 if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
2578 path = (char *)malloc( strlen(pathlist)+strlen(name)+2 );
2579 if( path!=0 ){
2580 while( *pathlist ){
2581 cp = strchr(pathlist,':');
2582 if( cp==0 ) cp = &pathlist[strlen(pathlist)];
2583 c = *cp;
2584 *cp = 0;
2585 sprintf(path,"%s/%s",pathlist,name);
2586 *cp = c;
2587 if( c==0 ) pathlist = "";
2588 else pathlist = &cp[1];
2589 if( access(path,modemask)==0 ) break;
2590 }
2591 }
2592 }
2593 return path;
2594}
2595
2596/* Given an action, compute the integer value for that action
2597** which is to be put in the action table of the generated machine.
2598** Return negative if no action should be generated.
2599*/
2600PRIVATE int compute_action(lemp,ap)
2601struct lemon *lemp;
2602struct action *ap;
2603{
2604 int act;
2605 switch( ap->type ){
2606 case SHIFT: act = ap->x.stp->index; break;
2607 case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
2608 case ERROR: act = lemp->nstate + lemp->nrule; break;
2609 case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
2610 default: act = -1; break;
2611 }
2612 return act;
2613}
2614
2615#define LINESIZE 1000
2616/* The next cluster of routines are for reading the template file
2617** and writing the results to the generated parser */
2618/* The first function transfers data from "in" to "out" until
2619** a line is seen which begins with "%%". The line number is
2620** tracked.
2621**
2622** if name!=0, then any word that begin with "Parse" is changed to
2623** begin with *name instead.
2624*/
2625PRIVATE void tplt_xfer(name,in,out,lineno)
2626char *name;
2627FILE *in;
2628FILE *out;
2629int *lineno;
2630{
2631 int i, iStart;
2632 char line[LINESIZE];
2633 while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
2634 (*lineno)++;
2635 iStart = 0;
2636 if( name ){
2637 for(i=0; line[i]; i++){
2638 if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
2639 && (i==0 || !isalpha(line[i-1]))
2640 ){
2641 if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
2642 fprintf(out,"%s",name);
2643 i += 4;
2644 iStart = i+1;
2645 }
2646 }
2647 }
2648 fprintf(out,"%s",&line[iStart]);
2649 }
2650}
2651
2652/* The next function finds the template file and opens it, returning
2653** a pointer to the opened file. */
2654PRIVATE FILE *tplt_open(lemp)
2655struct lemon *lemp;
2656{
2657 static char templatename[] = "lempar.c";
2658 char buf[1000];
2659 FILE *in;
2660 char *tpltname;
2661 char *cp;
2662
2663 cp = strrchr(lemp->filename,'.');
2664 if( cp ){
drhba99af52001-10-25 20:37:16 +00002665 sprintf(buf,"%.*s.lt",(unsigned long)cp-(unsigned long)lemp->filename,lemp->filename);
drh75897232000-05-29 14:26:00 +00002666 }else{
2667 sprintf(buf,"%s.lt",lemp->filename);
2668 }
2669 if( access(buf,004)==0 ){
2670 tpltname = buf;
drh960e8c62001-04-03 16:53:21 +00002671 }else if( access(templatename,004)==0 ){
2672 tpltname = templatename;
drh75897232000-05-29 14:26:00 +00002673 }else{
2674 tpltname = pathsearch(lemp->argv0,templatename,0);
2675 }
2676 if( tpltname==0 ){
2677 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
2678 templatename);
2679 lemp->errorcnt++;
2680 return 0;
2681 }
2682 in = fopen(tpltname,"r");
2683 if( in==0 ){
2684 fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
2685 lemp->errorcnt++;
2686 return 0;
2687 }
2688 return in;
2689}
2690
2691/* Print a string to the file and keep the linenumber up to date */
2692PRIVATE void tplt_print(out,lemp,str,strln,lineno)
2693FILE *out;
2694struct lemon *lemp;
2695char *str;
2696int strln;
2697int *lineno;
2698{
2699 if( str==0 ) return;
2700 fprintf(out,"#line %d \"%s\"\n",strln,lemp->filename); (*lineno)++;
2701 while( *str ){
2702 if( *str=='\n' ) (*lineno)++;
2703 putc(*str,out);
2704 str++;
2705 }
2706 fprintf(out,"\n#line %d \"%s\"\n",*lineno+2,lemp->outname); (*lineno)+=2;
2707 return;
2708}
2709
2710/*
2711** The following routine emits code for the destructor for the
2712** symbol sp
2713*/
2714void emit_destructor_code(out,sp,lemp,lineno)
2715FILE *out;
2716struct symbol *sp;
2717struct lemon *lemp;
2718int *lineno;
2719{
2720 char *cp;
2721
2722 int linecnt = 0;
2723 if( sp->type==TERMINAL ){
2724 cp = lemp->tokendest;
2725 if( cp==0 ) return;
2726 fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
drh960e8c62001-04-03 16:53:21 +00002727 }else if( sp->destructor ){
drh75897232000-05-29 14:26:00 +00002728 cp = sp->destructor;
drh75897232000-05-29 14:26:00 +00002729 fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
drh960e8c62001-04-03 16:53:21 +00002730 }else if( lemp->vardest ){
2731 cp = lemp->vardest;
2732 if( cp==0 ) return;
2733 fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
drh75897232000-05-29 14:26:00 +00002734 }
2735 for(; *cp; cp++){
2736 if( *cp=='$' && cp[1]=='$' ){
2737 fprintf(out,"(yypminor->yy%d)",sp->dtnum);
2738 cp++;
2739 continue;
2740 }
2741 if( *cp=='\n' ) linecnt++;
2742 fputc(*cp,out);
2743 }
2744 (*lineno) += 3 + linecnt;
2745 fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
2746 return;
2747}
2748
2749/*
drh960e8c62001-04-03 16:53:21 +00002750** Return TRUE (non-zero) if the given symbol has a destructor.
drh75897232000-05-29 14:26:00 +00002751*/
2752int has_destructor(sp, lemp)
2753struct symbol *sp;
2754struct lemon *lemp;
2755{
2756 int ret;
2757 if( sp->type==TERMINAL ){
2758 ret = lemp->tokendest!=0;
2759 }else{
drh960e8c62001-04-03 16:53:21 +00002760 ret = lemp->vardest!=0 || sp->destructor!=0;
drh75897232000-05-29 14:26:00 +00002761 }
2762 return ret;
2763}
2764
2765/*
2766** Generate code which executes when the rule "rp" is reduced. Write
2767** the code to "out". Make sure lineno stays up-to-date.
2768*/
2769PRIVATE void emit_code(out,rp,lemp,lineno)
2770FILE *out;
2771struct rule *rp;
2772struct lemon *lemp;
2773int *lineno;
2774{
2775 char *cp, *xp;
2776 int linecnt = 0;
2777 int i;
2778 char lhsused = 0; /* True if the LHS element has been used */
2779 char used[MAXRHS]; /* True for each RHS element which is used */
2780
2781 for(i=0; i<rp->nrhs; i++) used[i] = 0;
2782 lhsused = 0;
2783
2784 /* Generate code to do the reduce action */
2785 if( rp->code ){
2786 fprintf(out,"#line %d \"%s\"\n{",rp->line,lemp->filename);
2787 for(cp=rp->code; *cp; cp++){
drh7218ac72002-03-10 21:21:00 +00002788 if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
drh75897232000-05-29 14:26:00 +00002789 char saved;
drh7218ac72002-03-10 21:21:00 +00002790 for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
drh75897232000-05-29 14:26:00 +00002791 saved = *xp;
2792 *xp = 0;
2793 if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
2794 fprintf(out,"yygotominor.yy%d",rp->lhs->dtnum);
2795 cp = xp;
2796 lhsused = 1;
2797 }else{
2798 for(i=0; i<rp->nrhs; i++){
2799 if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
2800 fprintf(out,"yymsp[%d].minor.yy%d",i-rp->nrhs+1,rp->rhs[i]->dtnum);
2801 cp = xp;
2802 used[i] = 1;
2803 break;
2804 }
2805 }
2806 }
2807 *xp = saved;
2808 }
2809 if( *cp=='\n' ) linecnt++;
2810 fputc(*cp,out);
2811 } /* End loop */
2812 (*lineno) += 3 + linecnt;
2813 fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
2814 } /* End if( rp->code ) */
2815
2816 /* Check to make sure the LHS has been used */
2817 if( rp->lhsalias && !lhsused ){
2818 ErrorMsg(lemp->filename,rp->ruleline,
2819 "Label \"%s\" for \"%s(%s)\" is never used.",
2820 rp->lhsalias,rp->lhs->name,rp->lhsalias);
2821 lemp->errorcnt++;
2822 }
2823
2824 /* Generate destructor code for RHS symbols which are not used in the
2825 ** reduce code */
2826 for(i=0; i<rp->nrhs; i++){
2827 if( rp->rhsalias[i] && !used[i] ){
2828 ErrorMsg(lemp->filename,rp->ruleline,
drh960e8c62001-04-03 16:53:21 +00002829 "Label %s for \"%s(%s)\" is never used.",
drh75897232000-05-29 14:26:00 +00002830 rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
2831 lemp->errorcnt++;
2832 }else if( rp->rhsalias[i]==0 ){
2833 if( has_destructor(rp->rhs[i],lemp) ){
2834 fprintf(out," yy_destructor(%d,&yymsp[%d].minor);\n",
2835 rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++;
2836 }else{
2837 fprintf(out," /* No destructor defined for %s */\n",
2838 rp->rhs[i]->name);
2839 (*lineno)++;
2840 }
2841 }
2842 }
2843 return;
2844}
2845
2846/*
2847** Print the definition of the union used for the parser's data stack.
2848** This union contains fields for every possible data type for tokens
2849** and nonterminals. In the process of computing and printing this
2850** union, also set the ".dtnum" field of every terminal and nonterminal
2851** symbol.
2852*/
2853void print_stack_union(out,lemp,plineno,mhflag)
2854FILE *out; /* The output stream */
2855struct lemon *lemp; /* The main info structure for this parser */
2856int *plineno; /* Pointer to the line number */
2857int mhflag; /* True if generating makeheaders output */
2858{
2859 int lineno = *plineno; /* The line number of the output */
2860 char **types; /* A hash table of datatypes */
2861 int arraysize; /* Size of the "types" array */
2862 int maxdtlength; /* Maximum length of any ".datatype" field. */
2863 char *stddt; /* Standardized name for a datatype */
2864 int i,j; /* Loop counters */
2865 int hash; /* For hashing the name of a type */
2866 char *name; /* Name of the parser */
2867
2868 /* Allocate and initialize types[] and allocate stddt[] */
2869 arraysize = lemp->nsymbol * 2;
2870 types = (char**)malloc( arraysize * sizeof(char*) );
2871 for(i=0; i<arraysize; i++) types[i] = 0;
2872 maxdtlength = 0;
drh960e8c62001-04-03 16:53:21 +00002873 if( lemp->vartype ){
2874 maxdtlength = strlen(lemp->vartype);
2875 }
drh75897232000-05-29 14:26:00 +00002876 for(i=0; i<lemp->nsymbol; i++){
2877 int len;
2878 struct symbol *sp = lemp->symbols[i];
2879 if( sp->datatype==0 ) continue;
2880 len = strlen(sp->datatype);
2881 if( len>maxdtlength ) maxdtlength = len;
2882 }
2883 stddt = (char*)malloc( maxdtlength*2 + 1 );
2884 if( types==0 || stddt==0 ){
2885 fprintf(stderr,"Out of memory.\n");
2886 exit(1);
2887 }
2888
2889 /* Build a hash table of datatypes. The ".dtnum" field of each symbol
2890 ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
drh960e8c62001-04-03 16:53:21 +00002891 ** used for terminal symbols. If there is no %default_type defined then
2892 ** 0 is also used as the .dtnum value for nonterminals which do not specify
2893 ** a datatype using the %type directive.
2894 */
drh75897232000-05-29 14:26:00 +00002895 for(i=0; i<lemp->nsymbol; i++){
2896 struct symbol *sp = lemp->symbols[i];
2897 char *cp;
2898 if( sp==lemp->errsym ){
2899 sp->dtnum = arraysize+1;
2900 continue;
2901 }
drh960e8c62001-04-03 16:53:21 +00002902 if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
drh75897232000-05-29 14:26:00 +00002903 sp->dtnum = 0;
2904 continue;
2905 }
2906 cp = sp->datatype;
drh960e8c62001-04-03 16:53:21 +00002907 if( cp==0 ) cp = lemp->vartype;
drh75897232000-05-29 14:26:00 +00002908 j = 0;
2909 while( isspace(*cp) ) cp++;
2910 while( *cp ) stddt[j++] = *cp++;
2911 while( j>0 && isspace(stddt[j-1]) ) j--;
2912 stddt[j] = 0;
2913 hash = 0;
2914 for(j=0; stddt[j]; j++){
2915 hash = hash*53 + stddt[j];
2916 }
2917 if( hash<0 ) hash = -hash;
2918 hash = hash%arraysize;
2919 while( types[hash] ){
2920 if( strcmp(types[hash],stddt)==0 ){
2921 sp->dtnum = hash + 1;
2922 break;
2923 }
2924 hash++;
2925 if( hash>=arraysize ) hash = 0;
2926 }
2927 if( types[hash]==0 ){
2928 sp->dtnum = hash + 1;
2929 types[hash] = (char*)malloc( strlen(stddt)+1 );
2930 if( types[hash]==0 ){
2931 fprintf(stderr,"Out of memory.\n");
2932 exit(1);
2933 }
2934 strcpy(types[hash],stddt);
2935 }
2936 }
2937
2938 /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
2939 name = lemp->name ? lemp->name : "Parse";
2940 lineno = *plineno;
2941 if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
2942 fprintf(out,"#define %sTOKENTYPE %s\n",name,
2943 lemp->tokentype?lemp->tokentype:"void*"); lineno++;
2944 if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
2945 fprintf(out,"typedef union {\n"); lineno++;
2946 fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++;
2947 for(i=0; i<arraysize; i++){
2948 if( types[i]==0 ) continue;
2949 fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
2950 free(types[i]);
2951 }
2952 fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
2953 free(stddt);
2954 free(types);
2955 fprintf(out,"} YYMINORTYPE;\n"); lineno++;
2956 *plineno = lineno;
2957}
2958
drhb29b0a52002-02-23 19:39:46 +00002959/*
2960** Return the name of a C datatype able to represent values between
2961** 0 and N, inclusive.
2962*/
2963static const char *minimum_size_type(int N){
2964 if( N<=255 ){
2965 return "unsigned char";
2966 }else if( N<65535 ){
2967 return "unsigned short int";
2968 }else{
2969 return "unsigned int";
2970 }
2971}
2972
drh75897232000-05-29 14:26:00 +00002973/* Generate C source code for the parser */
2974void ReportTable(lemp, mhflag)
2975struct lemon *lemp;
2976int mhflag; /* Output in makeheaders format if true */
2977{
2978 FILE *out, *in;
2979 char line[LINESIZE];
2980 int lineno;
2981 struct state *stp;
2982 struct action *ap;
2983 struct rule *rp;
drh0bd1f4e2002-06-06 18:54:39 +00002984 int i, j;
drh75897232000-05-29 14:26:00 +00002985 int tablecnt;
2986 char *name;
2987
2988 in = tplt_open(lemp);
2989 if( in==0 ) return;
2990 out = file_open(lemp,".c","w");
2991 if( out==0 ){
2992 fclose(in);
2993 return;
2994 }
2995 lineno = 1;
2996 tplt_xfer(lemp->name,in,out,&lineno);
2997
2998 /* Generate the include code, if any */
2999 tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno);
3000 if( mhflag ){
3001 char *name = file_makename(lemp, ".h");
3002 fprintf(out,"#include \"%s\"\n", name); lineno++;
3003 free(name);
3004 }
3005 tplt_xfer(lemp->name,in,out,&lineno);
3006
3007 /* Generate #defines for all tokens */
3008 if( mhflag ){
3009 char *prefix;
3010 fprintf(out,"#if INTERFACE\n"); lineno++;
3011 if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3012 else prefix = "";
3013 for(i=1; i<lemp->nterminal; i++){
3014 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3015 lineno++;
3016 }
3017 fprintf(out,"#endif\n"); lineno++;
3018 }
3019 tplt_xfer(lemp->name,in,out,&lineno);
3020
3021 /* Generate the defines */
3022 fprintf(out,"/* \001 */\n");
3023 fprintf(out,"#define YYCODETYPE %s\n",
drhb29b0a52002-02-23 19:39:46 +00003024 minimum_size_type(lemp->nsymbol+5)); lineno++;
drh75897232000-05-29 14:26:00 +00003025 fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
3026 fprintf(out,"#define YYACTIONTYPE %s\n",
drhb29b0a52002-02-23 19:39:46 +00003027 minimum_size_type(lemp->nstate+lemp->nrule+5)); lineno++;
drh75897232000-05-29 14:26:00 +00003028 print_stack_union(out,lemp,&lineno,mhflag);
3029 if( lemp->stacksize ){
3030 if( atoi(lemp->stacksize)<=0 ){
3031 ErrorMsg(lemp->filename,0,
3032"Illegal stack size: [%s]. The stack size should be an integer constant.",
3033 lemp->stacksize);
3034 lemp->errorcnt++;
3035 lemp->stacksize = "100";
3036 }
3037 fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
3038 }else{
3039 fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
3040 }
3041 if( mhflag ){
3042 fprintf(out,"#if INTERFACE\n"); lineno++;
3043 }
3044 name = lemp->name ? lemp->name : "Parse";
3045 if( lemp->arg && lemp->arg[0] ){
3046 int i;
3047 i = strlen(lemp->arg);
drhb1edd012000-06-02 18:52:12 +00003048 while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
3049 while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
drh1f245e42002-03-11 13:55:50 +00003050 fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
3051 fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
3052 fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
3053 name,lemp->arg,&lemp->arg[i]); lineno++;
3054 fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
3055 name,&lemp->arg[i],&lemp->arg[i]); lineno++;
drh75897232000-05-29 14:26:00 +00003056 }else{
drh1f245e42002-03-11 13:55:50 +00003057 fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
3058 fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
3059 fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
3060 fprintf(out,"#define %sARG_STORE\n",name); lineno++;
drh75897232000-05-29 14:26:00 +00003061 }
3062 if( mhflag ){
3063 fprintf(out,"#endif\n"); lineno++;
3064 }
3065 fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++;
3066 fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
3067 fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
3068 fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
drh0bd1f4e2002-06-06 18:54:39 +00003069 if( lemp->has_fallback ){
3070 fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
3071 }
drh75897232000-05-29 14:26:00 +00003072 tplt_xfer(lemp->name,in,out,&lineno);
3073
3074 /* Generate the action table.
3075 **
3076 ** Each entry in the action table is an element of the following
3077 ** structure:
3078 ** struct yyActionEntry {
3079 ** YYCODETYPE lookahead;
drhb29b0a52002-02-23 19:39:46 +00003080 ** YYCODETYPE next;
drh75897232000-05-29 14:26:00 +00003081 ** YYACTIONTYPE action;
drh75897232000-05-29 14:26:00 +00003082 ** }
3083 **
3084 ** The entries are grouped into hash tables, one hash table for each
drhb29b0a52002-02-23 19:39:46 +00003085 ** parser state. The hash table has a size which is the number of
3086 ** entries in that table. In case of a collision, the "next" value
3087 ** contains one more than the index into the hash table of the next
3088 ** entry in the collision chain. A "next" value of 0 means the end
3089 ** of the chain has been reached.
drh75897232000-05-29 14:26:00 +00003090 */
3091 tablecnt = 0;
3092
3093 /* Loop over parser states */
3094 for(i=0; i<lemp->nstate; i++){
3095 int tablesize; /* size of the hash table */
3096 int j,k; /* Loop counter */
3097 int collide[2048]; /* The collision chain for the table */
3098 struct action *table[2048]; /* Build the hash table here */
3099
3100 /* Find the number of actions and initialize the hash table */
3101 stp = lemp->sorted[i];
3102 stp->tabstart = tablecnt;
3103 stp->naction = 0;
3104 for(ap=stp->ap; ap; ap=ap->next){
3105 if( ap->sp->index!=lemp->nsymbol && compute_action(lemp,ap)>=0 ){
3106 stp->naction++;
3107 }
3108 }
drhb29b0a52002-02-23 19:39:46 +00003109 tablesize = stp->naction;
drh75897232000-05-29 14:26:00 +00003110 assert( tablesize<= sizeof(table)/sizeof(table[0]) );
3111 for(j=0; j<tablesize; j++){
3112 table[j] = 0;
3113 collide[j] = -1;
3114 }
3115
3116 /* Hash the actions into the hash table */
3117 stp->tabdfltact = lemp->nstate + lemp->nrule;
3118 for(ap=stp->ap; ap; ap=ap->next){
3119 int action = compute_action(lemp,ap);
3120 int h;
3121 if( ap->sp->index==lemp->nsymbol ){
3122 stp->tabdfltact = action;
3123 }else if( action>=0 ){
drhb29b0a52002-02-23 19:39:46 +00003124 h = ap->sp->index % tablesize;
drh75897232000-05-29 14:26:00 +00003125 ap->collide = table[h];
3126 table[h] = ap;
3127 }
3128 }
3129
3130 /* Resolve collisions */
3131 for(j=k=0; j<tablesize; j++){
3132 if( table[j] && table[j]->collide ){
3133 while( table[k] ) k++;
3134 table[k] = table[j]->collide;
3135 collide[j] = k;
3136 table[j]->collide = 0;
3137 if( k<j ) j = k-1;
3138 }
3139 }
3140
3141 /* Print the hash table */
drh1b2e0322002-03-03 02:49:51 +00003142 if( tablesize>0 ){
3143 fprintf(out,"/* State %d */\n",stp->index); lineno++;
3144 }
drh75897232000-05-29 14:26:00 +00003145 for(j=0; j<tablesize; j++){
drhb29b0a52002-02-23 19:39:46 +00003146 assert( table[j]!=0 );
drh1b2e0322002-03-03 02:49:51 +00003147 fprintf(out," {%4d,%4d,%4d}, /* %2d: ",
drh75897232000-05-29 14:26:00 +00003148 table[j]->sp->index,
drhb29b0a52002-02-23 19:39:46 +00003149 collide[j]+1,
drh1b2e0322002-03-03 02:49:51 +00003150 compute_action(lemp,table[j]),
3151 j+1);
drhb29b0a52002-02-23 19:39:46 +00003152 PrintAction(table[j],out,22);
3153 fprintf(out," */\n");
drh75897232000-05-29 14:26:00 +00003154 lineno++;
3155 }
3156
3157 /* Update the table count */
3158 tablecnt += tablesize;
3159 }
3160 tplt_xfer(lemp->name,in,out,&lineno);
3161 lemp->tablesize = tablecnt;
3162
3163 /* Generate the state table
3164 **
3165 ** Each entry is an element of the following structure:
3166 ** struct yyStateEntry {
3167 ** struct yyActionEntry *hashtbl;
drhb29b0a52002-02-23 19:39:46 +00003168 ** YYCODETYPE nEntry;
drh75897232000-05-29 14:26:00 +00003169 ** YYACTIONTYPE actionDefault;
3170 ** }
3171 */
3172 for(i=0; i<lemp->nstate; i++){
drh75897232000-05-29 14:26:00 +00003173 stp = lemp->sorted[i];
drhb29b0a52002-02-23 19:39:46 +00003174 fprintf(out," { &yyActionTable[%d],%4d,%4d },\n",
drh75897232000-05-29 14:26:00 +00003175 stp->tabstart,
drhb29b0a52002-02-23 19:39:46 +00003176 stp->naction,
drh75897232000-05-29 14:26:00 +00003177 stp->tabdfltact); lineno++;
3178 }
3179 tplt_xfer(lemp->name,in,out,&lineno);
3180
drh0bd1f4e2002-06-06 18:54:39 +00003181 /* Generate the table of fallback tokens.
3182 */
3183 if( lemp->has_fallback ){
3184 for(i=0; i<lemp->nterminal; i++){
3185 struct symbol *p = lemp->symbols[i];
3186 if( p->fallback==0 ){
3187 fprintf(out, " 0, /* %10s => nothing */\n", p->name);
3188 }else{
3189 fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index,
3190 p->name, p->fallback->name);
3191 }
3192 lineno++;
3193 }
3194 }
3195 tplt_xfer(lemp->name, in, out, &lineno);
3196
3197 /* Generate a table containing the symbolic name of every symbol
3198 */
drh75897232000-05-29 14:26:00 +00003199 for(i=0; i<lemp->nsymbol; i++){
3200 sprintf(line,"\"%s\",",lemp->symbols[i]->name);
3201 fprintf(out," %-15s",line);
3202 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
3203 }
3204 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
3205 tplt_xfer(lemp->name,in,out,&lineno);
3206
drh0bd1f4e2002-06-06 18:54:39 +00003207 /* Generate a table containing a text string that describes every
3208 ** rule in the rule set of the grammer. This information is used
3209 ** when tracing REDUCE actions.
3210 */
3211 for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
3212 assert( rp->index==i );
3213 fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
3214 for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name);
3215 fprintf(out,"\",\n"); lineno++;
3216 }
3217 tplt_xfer(lemp->name,in,out,&lineno);
3218
drh75897232000-05-29 14:26:00 +00003219 /* Generate code which executes every time a symbol is popped from
3220 ** the stack while processing errors or while destroying the parser.
drh0bd1f4e2002-06-06 18:54:39 +00003221 ** (In other words, generate the %destructor actions)
3222 */
drh75897232000-05-29 14:26:00 +00003223 if( lemp->tokendest ){
3224 for(i=0; i<lemp->nsymbol; i++){
3225 struct symbol *sp = lemp->symbols[i];
3226 if( sp==0 || sp->type!=TERMINAL ) continue;
3227 fprintf(out," case %d:\n",sp->index); lineno++;
3228 }
3229 for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
3230 if( i<lemp->nsymbol ){
3231 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3232 fprintf(out," break;\n"); lineno++;
3233 }
3234 }
3235 for(i=0; i<lemp->nsymbol; i++){
3236 struct symbol *sp = lemp->symbols[i];
3237 if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
3238 fprintf(out," case %d:\n",sp->index); lineno++;
3239 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3240 fprintf(out," break;\n"); lineno++;
3241 }
drh960e8c62001-04-03 16:53:21 +00003242 if( lemp->vardest ){
3243 struct symbol *dflt_sp = 0;
3244 for(i=0; i<lemp->nsymbol; i++){
3245 struct symbol *sp = lemp->symbols[i];
3246 if( sp==0 || sp->type==TERMINAL ||
3247 sp->index<=0 || sp->destructor!=0 ) continue;
3248 fprintf(out," case %d:\n",sp->index); lineno++;
3249 dflt_sp = sp;
3250 }
3251 if( dflt_sp!=0 ){
3252 emit_destructor_code(out,dflt_sp,lemp,&lineno);
3253 fprintf(out," break;\n"); lineno++;
3254 }
3255 }
drh75897232000-05-29 14:26:00 +00003256 tplt_xfer(lemp->name,in,out,&lineno);
3257
3258 /* Generate code which executes whenever the parser stack overflows */
3259 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
3260 tplt_xfer(lemp->name,in,out,&lineno);
3261
3262 /* Generate the table of rule information
3263 **
3264 ** Note: This code depends on the fact that rules are number
3265 ** sequentually beginning with 0.
3266 */
3267 for(rp=lemp->rule; rp; rp=rp->next){
3268 fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
3269 }
3270 tplt_xfer(lemp->name,in,out,&lineno);
3271
3272 /* Generate code which execution during each REDUCE action */
3273 for(rp=lemp->rule; rp; rp=rp->next){
3274 fprintf(out," case %d:\n",rp->index); lineno++;
drh75897232000-05-29 14:26:00 +00003275 emit_code(out,rp,lemp,&lineno);
3276 fprintf(out," break;\n"); lineno++;
3277 }
3278 tplt_xfer(lemp->name,in,out,&lineno);
3279
3280 /* Generate code which executes if a parse fails */
3281 tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);
3282 tplt_xfer(lemp->name,in,out,&lineno);
3283
3284 /* Generate code which executes when a syntax error occurs */
3285 tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno);
3286 tplt_xfer(lemp->name,in,out,&lineno);
3287
3288 /* Generate code which executes when the parser accepts its input */
3289 tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno);
3290 tplt_xfer(lemp->name,in,out,&lineno);
3291
3292 /* Append any addition code the user desires */
3293 tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno);
3294
3295 fclose(in);
3296 fclose(out);
3297 return;
3298}
3299
3300/* Generate a header file for the parser */
3301void ReportHeader(lemp)
3302struct lemon *lemp;
3303{
3304 FILE *out, *in;
3305 char *prefix;
3306 char line[LINESIZE];
3307 char pattern[LINESIZE];
3308 int i;
3309
3310 if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3311 else prefix = "";
3312 in = file_open(lemp,".h","r");
3313 if( in ){
3314 for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
3315 sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3316 if( strcmp(line,pattern) ) break;
3317 }
3318 fclose(in);
3319 if( i==lemp->nterminal ){
3320 /* No change in the file. Don't rewrite it. */
3321 return;
3322 }
3323 }
3324 out = file_open(lemp,".h","w");
3325 if( out ){
3326 for(i=1; i<lemp->nterminal; i++){
3327 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3328 }
3329 fclose(out);
3330 }
3331 return;
3332}
3333
3334/* Reduce the size of the action tables, if possible, by making use
3335** of defaults.
3336**
drhb59499c2002-02-23 18:45:13 +00003337** In this version, we take the most frequent REDUCE action and make
3338** it the default. Only default a reduce if there are more than one.
drh75897232000-05-29 14:26:00 +00003339*/
3340void CompressTables(lemp)
3341struct lemon *lemp;
3342{
3343 struct state *stp;
drhb59499c2002-02-23 18:45:13 +00003344 struct action *ap, *ap2;
3345 struct rule *rp, *rp2, *rbest;
3346 int nbest, n;
drh75897232000-05-29 14:26:00 +00003347 int i;
3348 int cnt;
3349
3350 for(i=0; i<lemp->nstate; i++){
3351 stp = lemp->sorted[i];
drhb59499c2002-02-23 18:45:13 +00003352 nbest = 0;
3353 rbest = 0;
drh75897232000-05-29 14:26:00 +00003354
drhb59499c2002-02-23 18:45:13 +00003355 for(ap=stp->ap; ap; ap=ap->next){
3356 if( ap->type!=REDUCE ) continue;
3357 rp = ap->x.rp;
3358 if( rp==rbest ) continue;
3359 n = 1;
3360 for(ap2=ap->next; ap2; ap2=ap2->next){
3361 if( ap2->type!=REDUCE ) continue;
3362 rp2 = ap2->x.rp;
3363 if( rp2==rbest ) continue;
3364 if( rp2==rp ) n++;
3365 }
3366 if( n>nbest ){
3367 nbest = n;
3368 rbest = rp;
drh75897232000-05-29 14:26:00 +00003369 }
3370 }
drhb59499c2002-02-23 18:45:13 +00003371
3372 /* Do not make a default if the number of rules to default
3373 ** is not at least 2 */
3374 if( nbest<2 ) continue;
drh75897232000-05-29 14:26:00 +00003375
drhb59499c2002-02-23 18:45:13 +00003376
3377 /* Combine matching REDUCE actions into a single default */
3378 for(ap=stp->ap; ap; ap=ap->next){
3379 if( ap->type==REDUCE && ap->x.rp==rbest ) break;
3380 }
drh75897232000-05-29 14:26:00 +00003381 assert( ap );
3382 ap->sp = Symbol_new("{default}");
3383 for(ap=ap->next; ap; ap=ap->next){
drhb59499c2002-02-23 18:45:13 +00003384 if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
drh75897232000-05-29 14:26:00 +00003385 }
3386 stp->ap = Action_sort(stp->ap);
3387 }
3388}
drhb59499c2002-02-23 18:45:13 +00003389
drh75897232000-05-29 14:26:00 +00003390/***************** From the file "set.c" ************************************/
3391/*
3392** Set manipulation routines for the LEMON parser generator.
3393*/
3394
3395static int size = 0;
3396
3397/* Set the set size */
3398void SetSize(n)
3399int n;
3400{
3401 size = n+1;
3402}
3403
3404/* Allocate a new set */
3405char *SetNew(){
3406 char *s;
3407 int i;
3408 s = (char*)malloc( size );
3409 if( s==0 ){
3410 extern void memory_error();
3411 memory_error();
3412 }
3413 for(i=0; i<size; i++) s[i] = 0;
3414 return s;
3415}
3416
3417/* Deallocate a set */
3418void SetFree(s)
3419char *s;
3420{
3421 free(s);
3422}
3423
3424/* Add a new element to the set. Return TRUE if the element was added
3425** and FALSE if it was already there. */
3426int SetAdd(s,e)
3427char *s;
3428int e;
3429{
3430 int rv;
3431 rv = s[e];
3432 s[e] = 1;
3433 return !rv;
3434}
3435
3436/* Add every element of s2 to s1. Return TRUE if s1 changes. */
3437int SetUnion(s1,s2)
3438char *s1;
3439char *s2;
3440{
3441 int i, progress;
3442 progress = 0;
3443 for(i=0; i<size; i++){
3444 if( s2[i]==0 ) continue;
3445 if( s1[i]==0 ){
3446 progress = 1;
3447 s1[i] = 1;
3448 }
3449 }
3450 return progress;
3451}
3452/********************** From the file "table.c" ****************************/
3453/*
3454** All code in this file has been automatically generated
3455** from a specification in the file
3456** "table.q"
3457** by the associative array code building program "aagen".
3458** Do not edit this file! Instead, edit the specification
3459** file, then rerun aagen.
3460*/
3461/*
3462** Code for processing tables in the LEMON parser generator.
3463*/
3464
3465PRIVATE int strhash(x)
3466char *x;
3467{
3468 int h = 0;
3469 while( *x) h = h*13 + *(x++);
3470 return h;
3471}
3472
3473/* Works like strdup, sort of. Save a string in malloced memory, but
3474** keep strings in a table so that the same string is not in more
3475** than one place.
3476*/
3477char *Strsafe(y)
3478char *y;
3479{
3480 char *z;
3481
3482 z = Strsafe_find(y);
3483 if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
3484 strcpy(z,y);
3485 Strsafe_insert(z);
3486 }
3487 MemoryCheck(z);
3488 return z;
3489}
3490
3491/* There is one instance of the following structure for each
3492** associative array of type "x1".
3493*/
3494struct s_x1 {
3495 int size; /* The number of available slots. */
3496 /* Must be a power of 2 greater than or */
3497 /* equal to 1 */
3498 int count; /* Number of currently slots filled */
3499 struct s_x1node *tbl; /* The data stored here */
3500 struct s_x1node **ht; /* Hash table for lookups */
3501};
3502
3503/* There is one instance of this structure for every data element
3504** in an associative array of type "x1".
3505*/
3506typedef struct s_x1node {
3507 char *data; /* The data */
3508 struct s_x1node *next; /* Next entry with the same hash */
3509 struct s_x1node **from; /* Previous link */
3510} x1node;
3511
3512/* There is only one instance of the array, which is the following */
3513static struct s_x1 *x1a;
3514
3515/* Allocate a new associative array */
3516void Strsafe_init(){
3517 if( x1a ) return;
3518 x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
3519 if( x1a ){
3520 x1a->size = 1024;
3521 x1a->count = 0;
3522 x1a->tbl = (x1node*)malloc(
3523 (sizeof(x1node) + sizeof(x1node*))*1024 );
3524 if( x1a->tbl==0 ){
3525 free(x1a);
3526 x1a = 0;
3527 }else{
3528 int i;
3529 x1a->ht = (x1node**)&(x1a->tbl[1024]);
3530 for(i=0; i<1024; i++) x1a->ht[i] = 0;
3531 }
3532 }
3533}
3534/* Insert a new record into the array. Return TRUE if successful.
3535** Prior data with the same key is NOT overwritten */
3536int Strsafe_insert(data)
3537char *data;
3538{
3539 x1node *np;
3540 int h;
3541 int ph;
3542
3543 if( x1a==0 ) return 0;
3544 ph = strhash(data);
3545 h = ph & (x1a->size-1);
3546 np = x1a->ht[h];
3547 while( np ){
3548 if( strcmp(np->data,data)==0 ){
3549 /* An existing entry with the same key is found. */
3550 /* Fail because overwrite is not allows. */
3551 return 0;
3552 }
3553 np = np->next;
3554 }
3555 if( x1a->count>=x1a->size ){
3556 /* Need to make the hash table bigger */
3557 int i,size;
3558 struct s_x1 array;
3559 array.size = size = x1a->size*2;
3560 array.count = x1a->count;
3561 array.tbl = (x1node*)malloc(
3562 (sizeof(x1node) + sizeof(x1node*))*size );
3563 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3564 array.ht = (x1node**)&(array.tbl[size]);
3565 for(i=0; i<size; i++) array.ht[i] = 0;
3566 for(i=0; i<x1a->count; i++){
3567 x1node *oldnp, *newnp;
3568 oldnp = &(x1a->tbl[i]);
3569 h = strhash(oldnp->data) & (size-1);
3570 newnp = &(array.tbl[i]);
3571 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3572 newnp->next = array.ht[h];
3573 newnp->data = oldnp->data;
3574 newnp->from = &(array.ht[h]);
3575 array.ht[h] = newnp;
3576 }
3577 free(x1a->tbl);
3578 *x1a = array;
3579 }
3580 /* Insert the new data */
3581 h = ph & (x1a->size-1);
3582 np = &(x1a->tbl[x1a->count++]);
3583 np->data = data;
3584 if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
3585 np->next = x1a->ht[h];
3586 x1a->ht[h] = np;
3587 np->from = &(x1a->ht[h]);
3588 return 1;
3589}
3590
3591/* Return a pointer to data assigned to the given key. Return NULL
3592** if no such key. */
3593char *Strsafe_find(key)
3594char *key;
3595{
3596 int h;
3597 x1node *np;
3598
3599 if( x1a==0 ) return 0;
3600 h = strhash(key) & (x1a->size-1);
3601 np = x1a->ht[h];
3602 while( np ){
3603 if( strcmp(np->data,key)==0 ) break;
3604 np = np->next;
3605 }
3606 return np ? np->data : 0;
3607}
3608
3609/* Return a pointer to the (terminal or nonterminal) symbol "x".
3610** Create a new symbol if this is the first time "x" has been seen.
3611*/
3612struct symbol *Symbol_new(x)
3613char *x;
3614{
3615 struct symbol *sp;
3616
3617 sp = Symbol_find(x);
3618 if( sp==0 ){
3619 sp = (struct symbol *)malloc( sizeof(struct symbol) );
3620 MemoryCheck(sp);
3621 sp->name = Strsafe(x);
3622 sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
3623 sp->rule = 0;
drh0bd1f4e2002-06-06 18:54:39 +00003624 sp->fallback = 0;
drh75897232000-05-29 14:26:00 +00003625 sp->prec = -1;
3626 sp->assoc = UNK;
3627 sp->firstset = 0;
3628 sp->lambda = FALSE;
3629 sp->destructor = 0;
3630 sp->datatype = 0;
3631 Symbol_insert(sp,sp->name);
3632 }
3633 return sp;
3634}
3635
3636/* Compare two symbols */
3637int Symbolcmpp(a,b)
3638struct symbol **a;
3639struct symbol **b;
3640{
3641 return strcmp((**a).name,(**b).name);
3642}
3643
3644/* There is one instance of the following structure for each
3645** associative array of type "x2".
3646*/
3647struct s_x2 {
3648 int size; /* The number of available slots. */
3649 /* Must be a power of 2 greater than or */
3650 /* equal to 1 */
3651 int count; /* Number of currently slots filled */
3652 struct s_x2node *tbl; /* The data stored here */
3653 struct s_x2node **ht; /* Hash table for lookups */
3654};
3655
3656/* There is one instance of this structure for every data element
3657** in an associative array of type "x2".
3658*/
3659typedef struct s_x2node {
3660 struct symbol *data; /* The data */
3661 char *key; /* The key */
3662 struct s_x2node *next; /* Next entry with the same hash */
3663 struct s_x2node **from; /* Previous link */
3664} x2node;
3665
3666/* There is only one instance of the array, which is the following */
3667static struct s_x2 *x2a;
3668
3669/* Allocate a new associative array */
3670void Symbol_init(){
3671 if( x2a ) return;
3672 x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
3673 if( x2a ){
3674 x2a->size = 128;
3675 x2a->count = 0;
3676 x2a->tbl = (x2node*)malloc(
3677 (sizeof(x2node) + sizeof(x2node*))*128 );
3678 if( x2a->tbl==0 ){
3679 free(x2a);
3680 x2a = 0;
3681 }else{
3682 int i;
3683 x2a->ht = (x2node**)&(x2a->tbl[128]);
3684 for(i=0; i<128; i++) x2a->ht[i] = 0;
3685 }
3686 }
3687}
3688/* Insert a new record into the array. Return TRUE if successful.
3689** Prior data with the same key is NOT overwritten */
3690int Symbol_insert(data,key)
3691struct symbol *data;
3692char *key;
3693{
3694 x2node *np;
3695 int h;
3696 int ph;
3697
3698 if( x2a==0 ) return 0;
3699 ph = strhash(key);
3700 h = ph & (x2a->size-1);
3701 np = x2a->ht[h];
3702 while( np ){
3703 if( strcmp(np->key,key)==0 ){
3704 /* An existing entry with the same key is found. */
3705 /* Fail because overwrite is not allows. */
3706 return 0;
3707 }
3708 np = np->next;
3709 }
3710 if( x2a->count>=x2a->size ){
3711 /* Need to make the hash table bigger */
3712 int i,size;
3713 struct s_x2 array;
3714 array.size = size = x2a->size*2;
3715 array.count = x2a->count;
3716 array.tbl = (x2node*)malloc(
3717 (sizeof(x2node) + sizeof(x2node*))*size );
3718 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3719 array.ht = (x2node**)&(array.tbl[size]);
3720 for(i=0; i<size; i++) array.ht[i] = 0;
3721 for(i=0; i<x2a->count; i++){
3722 x2node *oldnp, *newnp;
3723 oldnp = &(x2a->tbl[i]);
3724 h = strhash(oldnp->key) & (size-1);
3725 newnp = &(array.tbl[i]);
3726 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3727 newnp->next = array.ht[h];
3728 newnp->key = oldnp->key;
3729 newnp->data = oldnp->data;
3730 newnp->from = &(array.ht[h]);
3731 array.ht[h] = newnp;
3732 }
3733 free(x2a->tbl);
3734 *x2a = array;
3735 }
3736 /* Insert the new data */
3737 h = ph & (x2a->size-1);
3738 np = &(x2a->tbl[x2a->count++]);
3739 np->key = key;
3740 np->data = data;
3741 if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
3742 np->next = x2a->ht[h];
3743 x2a->ht[h] = np;
3744 np->from = &(x2a->ht[h]);
3745 return 1;
3746}
3747
3748/* Return a pointer to data assigned to the given key. Return NULL
3749** if no such key. */
3750struct symbol *Symbol_find(key)
3751char *key;
3752{
3753 int h;
3754 x2node *np;
3755
3756 if( x2a==0 ) return 0;
3757 h = strhash(key) & (x2a->size-1);
3758 np = x2a->ht[h];
3759 while( np ){
3760 if( strcmp(np->key,key)==0 ) break;
3761 np = np->next;
3762 }
3763 return np ? np->data : 0;
3764}
3765
3766/* Return the n-th data. Return NULL if n is out of range. */
3767struct symbol *Symbol_Nth(n)
3768int n;
3769{
3770 struct symbol *data;
3771 if( x2a && n>0 && n<=x2a->count ){
3772 data = x2a->tbl[n-1].data;
3773 }else{
3774 data = 0;
3775 }
3776 return data;
3777}
3778
3779/* Return the size of the array */
3780int Symbol_count()
3781{
3782 return x2a ? x2a->count : 0;
3783}
3784
3785/* Return an array of pointers to all data in the table.
3786** The array is obtained from malloc. Return NULL if memory allocation
3787** problems, or if the array is empty. */
3788struct symbol **Symbol_arrayof()
3789{
3790 struct symbol **array;
3791 int i,size;
3792 if( x2a==0 ) return 0;
3793 size = x2a->count;
3794 array = (struct symbol **)malloc( sizeof(struct symbol *)*size );
3795 if( array ){
3796 for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
3797 }
3798 return array;
3799}
3800
3801/* Compare two configurations */
3802int Configcmp(a,b)
3803struct config *a;
3804struct config *b;
3805{
3806 int x;
3807 x = a->rp->index - b->rp->index;
3808 if( x==0 ) x = a->dot - b->dot;
3809 return x;
3810}
3811
3812/* Compare two states */
3813PRIVATE int statecmp(a,b)
3814struct config *a;
3815struct config *b;
3816{
3817 int rc;
3818 for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
3819 rc = a->rp->index - b->rp->index;
3820 if( rc==0 ) rc = a->dot - b->dot;
3821 }
3822 if( rc==0 ){
3823 if( a ) rc = 1;
3824 if( b ) rc = -1;
3825 }
3826 return rc;
3827}
3828
3829/* Hash a state */
3830PRIVATE int statehash(a)
3831struct config *a;
3832{
3833 int h=0;
3834 while( a ){
3835 h = h*571 + a->rp->index*37 + a->dot;
3836 a = a->bp;
3837 }
3838 return h;
3839}
3840
3841/* Allocate a new state structure */
3842struct state *State_new()
3843{
3844 struct state *new;
3845 new = (struct state *)malloc( sizeof(struct state) );
3846 MemoryCheck(new);
3847 return new;
3848}
3849
3850/* There is one instance of the following structure for each
3851** associative array of type "x3".
3852*/
3853struct s_x3 {
3854 int size; /* The number of available slots. */
3855 /* Must be a power of 2 greater than or */
3856 /* equal to 1 */
3857 int count; /* Number of currently slots filled */
3858 struct s_x3node *tbl; /* The data stored here */
3859 struct s_x3node **ht; /* Hash table for lookups */
3860};
3861
3862/* There is one instance of this structure for every data element
3863** in an associative array of type "x3".
3864*/
3865typedef struct s_x3node {
3866 struct state *data; /* The data */
3867 struct config *key; /* The key */
3868 struct s_x3node *next; /* Next entry with the same hash */
3869 struct s_x3node **from; /* Previous link */
3870} x3node;
3871
3872/* There is only one instance of the array, which is the following */
3873static struct s_x3 *x3a;
3874
3875/* Allocate a new associative array */
3876void State_init(){
3877 if( x3a ) return;
3878 x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
3879 if( x3a ){
3880 x3a->size = 128;
3881 x3a->count = 0;
3882 x3a->tbl = (x3node*)malloc(
3883 (sizeof(x3node) + sizeof(x3node*))*128 );
3884 if( x3a->tbl==0 ){
3885 free(x3a);
3886 x3a = 0;
3887 }else{
3888 int i;
3889 x3a->ht = (x3node**)&(x3a->tbl[128]);
3890 for(i=0; i<128; i++) x3a->ht[i] = 0;
3891 }
3892 }
3893}
3894/* Insert a new record into the array. Return TRUE if successful.
3895** Prior data with the same key is NOT overwritten */
3896int State_insert(data,key)
3897struct state *data;
3898struct config *key;
3899{
3900 x3node *np;
3901 int h;
3902 int ph;
3903
3904 if( x3a==0 ) return 0;
3905 ph = statehash(key);
3906 h = ph & (x3a->size-1);
3907 np = x3a->ht[h];
3908 while( np ){
3909 if( statecmp(np->key,key)==0 ){
3910 /* An existing entry with the same key is found. */
3911 /* Fail because overwrite is not allows. */
3912 return 0;
3913 }
3914 np = np->next;
3915 }
3916 if( x3a->count>=x3a->size ){
3917 /* Need to make the hash table bigger */
3918 int i,size;
3919 struct s_x3 array;
3920 array.size = size = x3a->size*2;
3921 array.count = x3a->count;
3922 array.tbl = (x3node*)malloc(
3923 (sizeof(x3node) + sizeof(x3node*))*size );
3924 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3925 array.ht = (x3node**)&(array.tbl[size]);
3926 for(i=0; i<size; i++) array.ht[i] = 0;
3927 for(i=0; i<x3a->count; i++){
3928 x3node *oldnp, *newnp;
3929 oldnp = &(x3a->tbl[i]);
3930 h = statehash(oldnp->key) & (size-1);
3931 newnp = &(array.tbl[i]);
3932 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3933 newnp->next = array.ht[h];
3934 newnp->key = oldnp->key;
3935 newnp->data = oldnp->data;
3936 newnp->from = &(array.ht[h]);
3937 array.ht[h] = newnp;
3938 }
3939 free(x3a->tbl);
3940 *x3a = array;
3941 }
3942 /* Insert the new data */
3943 h = ph & (x3a->size-1);
3944 np = &(x3a->tbl[x3a->count++]);
3945 np->key = key;
3946 np->data = data;
3947 if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
3948 np->next = x3a->ht[h];
3949 x3a->ht[h] = np;
3950 np->from = &(x3a->ht[h]);
3951 return 1;
3952}
3953
3954/* Return a pointer to data assigned to the given key. Return NULL
3955** if no such key. */
3956struct state *State_find(key)
3957struct config *key;
3958{
3959 int h;
3960 x3node *np;
3961
3962 if( x3a==0 ) return 0;
3963 h = statehash(key) & (x3a->size-1);
3964 np = x3a->ht[h];
3965 while( np ){
3966 if( statecmp(np->key,key)==0 ) break;
3967 np = np->next;
3968 }
3969 return np ? np->data : 0;
3970}
3971
3972/* Return an array of pointers to all data in the table.
3973** The array is obtained from malloc. Return NULL if memory allocation
3974** problems, or if the array is empty. */
3975struct state **State_arrayof()
3976{
3977 struct state **array;
3978 int i,size;
3979 if( x3a==0 ) return 0;
3980 size = x3a->count;
3981 array = (struct state **)malloc( sizeof(struct state *)*size );
3982 if( array ){
3983 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
3984 }
3985 return array;
3986}
3987
3988/* Hash a configuration */
3989PRIVATE int confighash(a)
3990struct config *a;
3991{
3992 int h=0;
3993 h = h*571 + a->rp->index*37 + a->dot;
3994 return h;
3995}
3996
3997/* There is one instance of the following structure for each
3998** associative array of type "x4".
3999*/
4000struct s_x4 {
4001 int size; /* The number of available slots. */
4002 /* Must be a power of 2 greater than or */
4003 /* equal to 1 */
4004 int count; /* Number of currently slots filled */
4005 struct s_x4node *tbl; /* The data stored here */
4006 struct s_x4node **ht; /* Hash table for lookups */
4007};
4008
4009/* There is one instance of this structure for every data element
4010** in an associative array of type "x4".
4011*/
4012typedef struct s_x4node {
4013 struct config *data; /* The data */
4014 struct s_x4node *next; /* Next entry with the same hash */
4015 struct s_x4node **from; /* Previous link */
4016} x4node;
4017
4018/* There is only one instance of the array, which is the following */
4019static struct s_x4 *x4a;
4020
4021/* Allocate a new associative array */
4022void Configtable_init(){
4023 if( x4a ) return;
4024 x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
4025 if( x4a ){
4026 x4a->size = 64;
4027 x4a->count = 0;
4028 x4a->tbl = (x4node*)malloc(
4029 (sizeof(x4node) + sizeof(x4node*))*64 );
4030 if( x4a->tbl==0 ){
4031 free(x4a);
4032 x4a = 0;
4033 }else{
4034 int i;
4035 x4a->ht = (x4node**)&(x4a->tbl[64]);
4036 for(i=0; i<64; i++) x4a->ht[i] = 0;
4037 }
4038 }
4039}
4040/* Insert a new record into the array. Return TRUE if successful.
4041** Prior data with the same key is NOT overwritten */
4042int Configtable_insert(data)
4043struct config *data;
4044{
4045 x4node *np;
4046 int h;
4047 int ph;
4048
4049 if( x4a==0 ) return 0;
4050 ph = confighash(data);
4051 h = ph & (x4a->size-1);
4052 np = x4a->ht[h];
4053 while( np ){
4054 if( Configcmp(np->data,data)==0 ){
4055 /* An existing entry with the same key is found. */
4056 /* Fail because overwrite is not allows. */
4057 return 0;
4058 }
4059 np = np->next;
4060 }
4061 if( x4a->count>=x4a->size ){
4062 /* Need to make the hash table bigger */
4063 int i,size;
4064 struct s_x4 array;
4065 array.size = size = x4a->size*2;
4066 array.count = x4a->count;
4067 array.tbl = (x4node*)malloc(
4068 (sizeof(x4node) + sizeof(x4node*))*size );
4069 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
4070 array.ht = (x4node**)&(array.tbl[size]);
4071 for(i=0; i<size; i++) array.ht[i] = 0;
4072 for(i=0; i<x4a->count; i++){
4073 x4node *oldnp, *newnp;
4074 oldnp = &(x4a->tbl[i]);
4075 h = confighash(oldnp->data) & (size-1);
4076 newnp = &(array.tbl[i]);
4077 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4078 newnp->next = array.ht[h];
4079 newnp->data = oldnp->data;
4080 newnp->from = &(array.ht[h]);
4081 array.ht[h] = newnp;
4082 }
4083 free(x4a->tbl);
4084 *x4a = array;
4085 }
4086 /* Insert the new data */
4087 h = ph & (x4a->size-1);
4088 np = &(x4a->tbl[x4a->count++]);
4089 np->data = data;
4090 if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
4091 np->next = x4a->ht[h];
4092 x4a->ht[h] = np;
4093 np->from = &(x4a->ht[h]);
4094 return 1;
4095}
4096
4097/* Return a pointer to data assigned to the given key. Return NULL
4098** if no such key. */
4099struct config *Configtable_find(key)
4100struct config *key;
4101{
4102 int h;
4103 x4node *np;
4104
4105 if( x4a==0 ) return 0;
4106 h = confighash(key) & (x4a->size-1);
4107 np = x4a->ht[h];
4108 while( np ){
4109 if( Configcmp(np->data,key)==0 ) break;
4110 np = np->next;
4111 }
4112 return np ? np->data : 0;
4113}
4114
4115/* Remove all data from the table. Pass each data to the function "f"
4116** as it is removed. ("f" may be null to avoid this step.) */
4117void Configtable_clear(f)
4118int(*f)(/* struct config * */);
4119{
4120 int i;
4121 if( x4a==0 || x4a->count==0 ) return;
4122 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
4123 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
4124 x4a->count = 0;
4125 return;
4126}