blob: ad4be199bfc9c2b0da2f7ef0ed8f44533921c89e [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>
drhf9a2e7b2003-04-15 01:49:48 +000010#include <stdarg.h>
drh75897232000-05-29 14:26:00 +000011#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" ***************************************/
drhf9a2e7b2003-04-15 01:49:48 +000073void ErrorMsg(const char *, int,const char *, ...);
drh75897232000-05-29 14:26:00 +000074
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
drhb27b83a2002-08-14 23:18:57 +0000120typedef enum {B_FALSE=0, B_TRUE} Boolean;
drh75897232000-05-29 14:26:00 +0000121
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++){
drhb27b83a2002-08-14 23:18:57 +0000454 lemp->symbols[i]->lambda = B_FALSE;
drh75897232000-05-29 14:26:00 +0000455 }
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++){
drhb27b83a2002-08-14 23:18:57 +0000466 if( rp->rhs[i]->lambda==B_FALSE ) break;
drh75897232000-05-29 14:26:00 +0000467 }
468 if( i==rp->nrhs ){
drhb27b83a2002-08-14 23:18:57 +0000469 rp->lhs->lambda = B_TRUE;
drh75897232000-05-29 14:26:00 +0000470 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 ){
drhb27b83a2002-08-14 23:18:57 +0000487 if( s1->lambda==B_FALSE ) break;
drh75897232000-05-29 14:26:00 +0000488 }else{
489 progress += SetUnion(s1->firstset,s2->firstset);
drhb27b83a2002-08-14 23:18:57 +0000490 if( s2->lambda==B_FALSE ) break;
drh75897232000-05-29 14:26:00 +0000491 }
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. */
drhb27b83a2002-08-14 23:18:57 +0000785 for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = B_FALSE;
drh75897232000-05-29 14:26:00 +0000786 for(i=0; i<lemp->nstate; i++){
787 struct action *ap;
788 for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
drhb27b83a2002-08-14 23:18:57 +0000789 if( ap->type==REDUCE ) ap->x.rp->canReduce = B_TRUE;
drh75897232000-05-29 14:26:00 +0000790 }
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);
drhb27b83a2002-08-14 23:18:57 +00001013 if( xsp->lambda==B_FALSE ) break;
drh75897232000-05-29 14:26:00 +00001014 }
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 */
drhf9a2e7b2003-04-15 01:49:48 +00001105void ErrorMsg(const char *filename, int lineno, const char *format, ...){
drh75897232000-05-29 14:26:00 +00001106 char errmsg[ERRMSGSIZE];
1107 char prefix[PREFIXLIMIT+10];
1108 int errmsgsize;
1109 int prefixsize;
1110 int availablewidth;
1111 va_list ap;
1112 int end, restart, base;
1113
drhf9a2e7b2003-04-15 01:49:48 +00001114 va_start(ap, format);
drh75897232000-05-29 14:26:00 +00001115 /* Prepare a prefix to be prepended to every output line */
1116 if( lineno>0 ){
1117 sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno);
1118 }else{
1119 sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename);
1120 }
1121 prefixsize = strlen(prefix);
1122 availablewidth = LINEWIDTH - prefixsize;
1123
1124 /* Generate the error message */
1125 vsprintf(errmsg,format,ap);
1126 va_end(ap);
1127 errmsgsize = strlen(errmsg);
1128 /* Remove trailing '\n's from the error message. */
1129 while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){
1130 errmsg[--errmsgsize] = 0;
1131 }
1132
1133 /* Print the error message */
1134 base = 0;
1135 while( errmsg[base]!=0 ){
1136 end = restart = findbreak(&errmsg[base],0,availablewidth);
1137 restart += base;
1138 while( errmsg[restart]==' ' ) restart++;
1139 fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]);
1140 base = restart;
1141 }
1142}
1143/**************** From the file "main.c" ************************************/
1144/*
1145** Main program file for the LEMON parser generator.
1146*/
1147
1148/* Report an out-of-memory condition and abort. This function
1149** is used mostly by the "MemoryCheck" macro in struct.h
1150*/
1151void memory_error(){
1152 fprintf(stderr,"Out of memory. Aborting...\n");
1153 exit(1);
1154}
1155
1156
1157/* The main program. Parse the command line and do it... */
1158int main(argc,argv)
1159int argc;
1160char **argv;
1161{
1162 static int version = 0;
1163 static int rpflag = 0;
1164 static int basisflag = 0;
1165 static int compress = 0;
1166 static int quiet = 0;
1167 static int statistics = 0;
1168 static int mhflag = 0;
1169 static struct s_options options[] = {
1170 {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
1171 {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
1172 {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
1173 {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"},
1174 {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
1175 {OPT_FLAG, "s", (char*)&statistics, "Print parser stats to standard output."},
1176 {OPT_FLAG, "x", (char*)&version, "Print the version number."},
1177 {OPT_FLAG,0,0,0}
1178 };
1179 int i;
1180 struct lemon lem;
1181
drhb0c86772000-06-02 23:21:26 +00001182 OptInit(argv,options,stderr);
drh75897232000-05-29 14:26:00 +00001183 if( version ){
drhb19a2bc2001-09-16 00:13:26 +00001184 printf("Lemon version 1.0\n");
drh75897232000-05-29 14:26:00 +00001185 exit(0);
1186 }
drhb0c86772000-06-02 23:21:26 +00001187 if( OptNArgs()!=1 ){
drh75897232000-05-29 14:26:00 +00001188 fprintf(stderr,"Exactly one filename argument is required.\n");
1189 exit(1);
1190 }
1191 lem.errorcnt = 0;
1192
1193 /* Initialize the machine */
1194 Strsafe_init();
1195 Symbol_init();
1196 State_init();
1197 lem.argv0 = argv[0];
drhb0c86772000-06-02 23:21:26 +00001198 lem.filename = OptArg(0);
drh75897232000-05-29 14:26:00 +00001199 lem.basisflag = basisflag;
drh0bd1f4e2002-06-06 18:54:39 +00001200 lem.has_fallback = 0;
drh75897232000-05-29 14:26:00 +00001201 lem.nconflict = 0;
1202 lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
drh960e8c62001-04-03 16:53:21 +00001203 lem.vartype = 0;
drh75897232000-05-29 14:26:00 +00001204 lem.stacksize = 0;
1205 lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
1206 lem.tokenprefix = lem.outname = lem.extracode = 0;
drh960e8c62001-04-03 16:53:21 +00001207 lem.vardest = 0;
drh75897232000-05-29 14:26:00 +00001208 lem.tablesize = 0;
1209 Symbol_new("$");
1210 lem.errsym = Symbol_new("error");
1211
1212 /* Parse the input file */
1213 Parse(&lem);
1214 if( lem.errorcnt ) exit(lem.errorcnt);
1215 if( lem.rule==0 ){
1216 fprintf(stderr,"Empty grammar.\n");
1217 exit(1);
1218 }
1219
1220 /* Count and index the symbols of the grammar */
1221 lem.nsymbol = Symbol_count();
1222 Symbol_new("{default}");
1223 lem.symbols = Symbol_arrayof();
1224 qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
1225 (int(*)())Symbolcmpp);
1226 for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
1227 for(i=1; isupper(lem.symbols[i]->name[0]); i++);
1228 lem.nterminal = i;
1229
1230 /* Generate a reprint of the grammar, if requested on the command line */
1231 if( rpflag ){
1232 Reprint(&lem);
1233 }else{
1234 /* Initialize the size for all follow and first sets */
1235 SetSize(lem.nterminal);
1236
1237 /* Find the precedence for every production rule (that has one) */
1238 FindRulePrecedences(&lem);
1239
1240 /* Compute the lambda-nonterminals and the first-sets for every
1241 ** nonterminal */
1242 FindFirstSets(&lem);
1243
1244 /* Compute all LR(0) states. Also record follow-set propagation
1245 ** links so that the follow-set can be computed later */
1246 lem.nstate = 0;
1247 FindStates(&lem);
1248 lem.sorted = State_arrayof();
1249
1250 /* Tie up loose ends on the propagation links */
1251 FindLinks(&lem);
1252
1253 /* Compute the follow set of every reducible configuration */
1254 FindFollowSets(&lem);
1255
1256 /* Compute the action tables */
1257 FindActions(&lem);
1258
1259 /* Compress the action tables */
1260 if( compress==0 ) CompressTables(&lem);
1261
1262 /* Generate a report of the parser generated. (the "y.output" file) */
1263 if( !quiet ) ReportOutput(&lem);
1264
1265 /* Generate the source code for the parser */
1266 ReportTable(&lem, mhflag);
1267
1268 /* Produce a header file for use by the scanner. (This step is
1269 ** omitted if the "-m" option is used because makeheaders will
1270 ** generate the file for us.) */
1271 if( !mhflag ) ReportHeader(&lem);
1272 }
1273 if( statistics ){
1274 printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
1275 lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
1276 printf(" %d states, %d parser table entries, %d conflicts\n",
1277 lem.nstate, lem.tablesize, lem.nconflict);
1278 }
1279 if( lem.nconflict ){
1280 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
1281 }
1282 exit(lem.errorcnt + lem.nconflict);
1283}
1284/******************** From the file "msort.c" *******************************/
1285/*
1286** A generic merge-sort program.
1287**
1288** USAGE:
1289** Let "ptr" be a pointer to some structure which is at the head of
1290** a null-terminated list. Then to sort the list call:
1291**
1292** ptr = msort(ptr,&(ptr->next),cmpfnc);
1293**
1294** In the above, "cmpfnc" is a pointer to a function which compares
1295** two instances of the structure and returns an integer, as in
1296** strcmp. The second argument is a pointer to the pointer to the
1297** second element of the linked list. This address is used to compute
1298** the offset to the "next" field within the structure. The offset to
1299** the "next" field must be constant for all structures in the list.
1300**
1301** The function returns a new pointer which is the head of the list
1302** after sorting.
1303**
1304** ALGORITHM:
1305** Merge-sort.
1306*/
1307
1308/*
1309** Return a pointer to the next structure in the linked list.
1310*/
drhba99af52001-10-25 20:37:16 +00001311#define NEXT(A) (*(char**)(((unsigned long)A)+offset))
drh75897232000-05-29 14:26:00 +00001312
1313/*
1314** Inputs:
1315** a: A sorted, null-terminated linked list. (May be null).
1316** b: A sorted, null-terminated linked list. (May be null).
1317** cmp: A pointer to the comparison function.
1318** offset: Offset in the structure to the "next" field.
1319**
1320** Return Value:
1321** A pointer to the head of a sorted list containing the elements
1322** of both a and b.
1323**
1324** Side effects:
1325** The "next" pointers for elements in the lists a and b are
1326** changed.
1327*/
1328static char *merge(a,b,cmp,offset)
1329char *a;
1330char *b;
1331int (*cmp)();
1332int offset;
1333{
1334 char *ptr, *head;
1335
1336 if( a==0 ){
1337 head = b;
1338 }else if( b==0 ){
1339 head = a;
1340 }else{
1341 if( (*cmp)(a,b)<0 ){
1342 ptr = a;
1343 a = NEXT(a);
1344 }else{
1345 ptr = b;
1346 b = NEXT(b);
1347 }
1348 head = ptr;
1349 while( a && b ){
1350 if( (*cmp)(a,b)<0 ){
1351 NEXT(ptr) = a;
1352 ptr = a;
1353 a = NEXT(a);
1354 }else{
1355 NEXT(ptr) = b;
1356 ptr = b;
1357 b = NEXT(b);
1358 }
1359 }
1360 if( a ) NEXT(ptr) = a;
1361 else NEXT(ptr) = b;
1362 }
1363 return head;
1364}
1365
1366/*
1367** Inputs:
1368** list: Pointer to a singly-linked list of structures.
1369** next: Pointer to pointer to the second element of the list.
1370** cmp: A comparison function.
1371**
1372** Return Value:
1373** A pointer to the head of a sorted list containing the elements
1374** orginally in list.
1375**
1376** Side effects:
1377** The "next" pointers for elements in list are changed.
1378*/
1379#define LISTSIZE 30
1380char *msort(list,next,cmp)
1381char *list;
1382char **next;
1383int (*cmp)();
1384{
drhba99af52001-10-25 20:37:16 +00001385 unsigned long offset;
drh75897232000-05-29 14:26:00 +00001386 char *ep;
1387 char *set[LISTSIZE];
1388 int i;
drhba99af52001-10-25 20:37:16 +00001389 offset = (unsigned long)next - (unsigned long)list;
drh75897232000-05-29 14:26:00 +00001390 for(i=0; i<LISTSIZE; i++) set[i] = 0;
1391 while( list ){
1392 ep = list;
1393 list = NEXT(list);
1394 NEXT(ep) = 0;
1395 for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
1396 ep = merge(ep,set[i],cmp,offset);
1397 set[i] = 0;
1398 }
1399 set[i] = ep;
1400 }
1401 ep = 0;
1402 for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset);
1403 return ep;
1404}
1405/************************ From the file "option.c" **************************/
1406static char **argv;
1407static struct s_options *op;
1408static FILE *errstream;
1409
1410#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
1411
1412/*
1413** Print the command line with a carrot pointing to the k-th character
1414** of the n-th field.
1415*/
1416static void errline(n,k,err)
1417int n;
1418int k;
1419FILE *err;
1420{
1421 int spcnt, i;
1422 spcnt = 0;
1423 if( argv[0] ) fprintf(err,"%s",argv[0]);
1424 spcnt = strlen(argv[0]) + 1;
1425 for(i=1; i<n && argv[i]; i++){
1426 fprintf(err," %s",argv[i]);
1427 spcnt += strlen(argv[i]+1);
1428 }
1429 spcnt += k;
1430 for(; argv[i]; i++) fprintf(err," %s",argv[i]);
1431 if( spcnt<20 ){
1432 fprintf(err,"\n%*s^-- here\n",spcnt,"");
1433 }else{
1434 fprintf(err,"\n%*shere --^\n",spcnt-7,"");
1435 }
1436}
1437
1438/*
1439** Return the index of the N-th non-switch argument. Return -1
1440** if N is out of range.
1441*/
1442static int argindex(n)
1443int n;
1444{
1445 int i;
1446 int dashdash = 0;
1447 if( argv!=0 && *argv!=0 ){
1448 for(i=1; argv[i]; i++){
1449 if( dashdash || !ISOPT(argv[i]) ){
1450 if( n==0 ) return i;
1451 n--;
1452 }
1453 if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1454 }
1455 }
1456 return -1;
1457}
1458
1459static char emsg[] = "Command line syntax error: ";
1460
1461/*
1462** Process a flag command line argument.
1463*/
1464static int handleflags(i,err)
1465int i;
1466FILE *err;
1467{
1468 int v;
1469 int errcnt = 0;
1470 int j;
1471 for(j=0; op[j].label; j++){
1472 if( strcmp(&argv[i][1],op[j].label)==0 ) break;
1473 }
1474 v = argv[i][0]=='-' ? 1 : 0;
1475 if( op[j].label==0 ){
1476 if( err ){
1477 fprintf(err,"%sundefined option.\n",emsg);
1478 errline(i,1,err);
1479 }
1480 errcnt++;
1481 }else if( op[j].type==OPT_FLAG ){
1482 *((int*)op[j].arg) = v;
1483 }else if( op[j].type==OPT_FFLAG ){
1484 (*(void(*)())(op[j].arg))(v);
1485 }else{
1486 if( err ){
1487 fprintf(err,"%smissing argument on switch.\n",emsg);
1488 errline(i,1,err);
1489 }
1490 errcnt++;
1491 }
1492 return errcnt;
1493}
1494
1495/*
1496** Process a command line switch which has an argument.
1497*/
1498static int handleswitch(i,err)
1499int i;
1500FILE *err;
1501{
1502 int lv = 0;
1503 double dv = 0.0;
1504 char *sv = 0, *end;
1505 char *cp;
1506 int j;
1507 int errcnt = 0;
1508 cp = strchr(argv[i],'=');
1509 *cp = 0;
1510 for(j=0; op[j].label; j++){
1511 if( strcmp(argv[i],op[j].label)==0 ) break;
1512 }
1513 *cp = '=';
1514 if( op[j].label==0 ){
1515 if( err ){
1516 fprintf(err,"%sundefined option.\n",emsg);
1517 errline(i,0,err);
1518 }
1519 errcnt++;
1520 }else{
1521 cp++;
1522 switch( op[j].type ){
1523 case OPT_FLAG:
1524 case OPT_FFLAG:
1525 if( err ){
1526 fprintf(err,"%soption requires an argument.\n",emsg);
1527 errline(i,0,err);
1528 }
1529 errcnt++;
1530 break;
1531 case OPT_DBL:
1532 case OPT_FDBL:
1533 dv = strtod(cp,&end);
1534 if( *end ){
1535 if( err ){
1536 fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
drhba99af52001-10-25 20:37:16 +00001537 errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
drh75897232000-05-29 14:26:00 +00001538 }
1539 errcnt++;
1540 }
1541 break;
1542 case OPT_INT:
1543 case OPT_FINT:
1544 lv = strtol(cp,&end,0);
1545 if( *end ){
1546 if( err ){
1547 fprintf(err,"%sillegal character in integer argument.\n",emsg);
drhba99af52001-10-25 20:37:16 +00001548 errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
drh75897232000-05-29 14:26:00 +00001549 }
1550 errcnt++;
1551 }
1552 break;
1553 case OPT_STR:
1554 case OPT_FSTR:
1555 sv = cp;
1556 break;
1557 }
1558 switch( op[j].type ){
1559 case OPT_FLAG:
1560 case OPT_FFLAG:
1561 break;
1562 case OPT_DBL:
1563 *(double*)(op[j].arg) = dv;
1564 break;
1565 case OPT_FDBL:
1566 (*(void(*)())(op[j].arg))(dv);
1567 break;
1568 case OPT_INT:
1569 *(int*)(op[j].arg) = lv;
1570 break;
1571 case OPT_FINT:
1572 (*(void(*)())(op[j].arg))((int)lv);
1573 break;
1574 case OPT_STR:
1575 *(char**)(op[j].arg) = sv;
1576 break;
1577 case OPT_FSTR:
1578 (*(void(*)())(op[j].arg))(sv);
1579 break;
1580 }
1581 }
1582 return errcnt;
1583}
1584
drhb0c86772000-06-02 23:21:26 +00001585int OptInit(a,o,err)
drh75897232000-05-29 14:26:00 +00001586char **a;
1587struct s_options *o;
1588FILE *err;
1589{
1590 int errcnt = 0;
1591 argv = a;
1592 op = o;
1593 errstream = err;
1594 if( argv && *argv && op ){
1595 int i;
1596 for(i=1; argv[i]; i++){
1597 if( argv[i][0]=='+' || argv[i][0]=='-' ){
1598 errcnt += handleflags(i,err);
1599 }else if( strchr(argv[i],'=') ){
1600 errcnt += handleswitch(i,err);
1601 }
1602 }
1603 }
1604 if( errcnt>0 ){
1605 fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
drhb0c86772000-06-02 23:21:26 +00001606 OptPrint();
drh75897232000-05-29 14:26:00 +00001607 exit(1);
1608 }
1609 return 0;
1610}
1611
drhb0c86772000-06-02 23:21:26 +00001612int OptNArgs(){
drh75897232000-05-29 14:26:00 +00001613 int cnt = 0;
1614 int dashdash = 0;
1615 int i;
1616 if( argv!=0 && argv[0]!=0 ){
1617 for(i=1; argv[i]; i++){
1618 if( dashdash || !ISOPT(argv[i]) ) cnt++;
1619 if( strcmp(argv[i],"--")==0 ) dashdash = 1;
1620 }
1621 }
1622 return cnt;
1623}
1624
drhb0c86772000-06-02 23:21:26 +00001625char *OptArg(n)
drh75897232000-05-29 14:26:00 +00001626int n;
1627{
1628 int i;
1629 i = argindex(n);
1630 return i>=0 ? argv[i] : 0;
1631}
1632
drhb0c86772000-06-02 23:21:26 +00001633void OptErr(n)
drh75897232000-05-29 14:26:00 +00001634int n;
1635{
1636 int i;
1637 i = argindex(n);
1638 if( i>=0 ) errline(i,0,errstream);
1639}
1640
drhb0c86772000-06-02 23:21:26 +00001641void OptPrint(){
drh75897232000-05-29 14:26:00 +00001642 int i;
1643 int max, len;
1644 max = 0;
1645 for(i=0; op[i].label; i++){
1646 len = strlen(op[i].label) + 1;
1647 switch( op[i].type ){
1648 case OPT_FLAG:
1649 case OPT_FFLAG:
1650 break;
1651 case OPT_INT:
1652 case OPT_FINT:
1653 len += 9; /* length of "<integer>" */
1654 break;
1655 case OPT_DBL:
1656 case OPT_FDBL:
1657 len += 6; /* length of "<real>" */
1658 break;
1659 case OPT_STR:
1660 case OPT_FSTR:
1661 len += 8; /* length of "<string>" */
1662 break;
1663 }
1664 if( len>max ) max = len;
1665 }
1666 for(i=0; op[i].label; i++){
1667 switch( op[i].type ){
1668 case OPT_FLAG:
1669 case OPT_FFLAG:
1670 fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message);
1671 break;
1672 case OPT_INT:
1673 case OPT_FINT:
1674 fprintf(errstream," %s=<integer>%*s %s\n",op[i].label,
1675 max-strlen(op[i].label)-9,"",op[i].message);
1676 break;
1677 case OPT_DBL:
1678 case OPT_FDBL:
1679 fprintf(errstream," %s=<real>%*s %s\n",op[i].label,
1680 max-strlen(op[i].label)-6,"",op[i].message);
1681 break;
1682 case OPT_STR:
1683 case OPT_FSTR:
1684 fprintf(errstream," %s=<string>%*s %s\n",op[i].label,
1685 max-strlen(op[i].label)-8,"",op[i].message);
1686 break;
1687 }
1688 }
1689}
1690/*********************** From the file "parse.c" ****************************/
1691/*
1692** Input file parser for the LEMON parser generator.
1693*/
1694
1695/* The state of the parser */
1696struct pstate {
1697 char *filename; /* Name of the input file */
1698 int tokenlineno; /* Linenumber at which current token starts */
1699 int errorcnt; /* Number of errors so far */
1700 char *tokenstart; /* Text of current token */
1701 struct lemon *gp; /* Global state vector */
1702 enum e_state {
1703 INITIALIZE,
1704 WAITING_FOR_DECL_OR_RULE,
1705 WAITING_FOR_DECL_KEYWORD,
1706 WAITING_FOR_DECL_ARG,
1707 WAITING_FOR_PRECEDENCE_SYMBOL,
1708 WAITING_FOR_ARROW,
1709 IN_RHS,
1710 LHS_ALIAS_1,
1711 LHS_ALIAS_2,
1712 LHS_ALIAS_3,
1713 RHS_ALIAS_1,
1714 RHS_ALIAS_2,
1715 PRECEDENCE_MARK_1,
1716 PRECEDENCE_MARK_2,
1717 RESYNC_AFTER_RULE_ERROR,
1718 RESYNC_AFTER_DECL_ERROR,
1719 WAITING_FOR_DESTRUCTOR_SYMBOL,
drh0bd1f4e2002-06-06 18:54:39 +00001720 WAITING_FOR_DATATYPE_SYMBOL,
1721 WAITING_FOR_FALLBACK_ID
drh75897232000-05-29 14:26:00 +00001722 } state; /* The state of the parser */
drh0bd1f4e2002-06-06 18:54:39 +00001723 struct symbol *fallback; /* The fallback token */
drh75897232000-05-29 14:26:00 +00001724 struct symbol *lhs; /* Left-hand side of current rule */
1725 char *lhsalias; /* Alias for the LHS */
1726 int nrhs; /* Number of right-hand side symbols seen */
1727 struct symbol *rhs[MAXRHS]; /* RHS symbols */
1728 char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
1729 struct rule *prevrule; /* Previous rule parsed */
1730 char *declkeyword; /* Keyword of a declaration */
1731 char **declargslot; /* Where the declaration argument should be put */
1732 int *decllnslot; /* Where the declaration linenumber is put */
1733 enum e_assoc declassoc; /* Assign this association to decl arguments */
1734 int preccounter; /* Assign this precedence to decl arguments */
1735 struct rule *firstrule; /* Pointer to first rule in the grammar */
1736 struct rule *lastrule; /* Pointer to the most recently parsed rule */
1737};
1738
1739/* Parse a single token */
1740static void parseonetoken(psp)
1741struct pstate *psp;
1742{
1743 char *x;
1744 x = Strsafe(psp->tokenstart); /* Save the token permanently */
1745#if 0
1746 printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
1747 x,psp->state);
1748#endif
1749 switch( psp->state ){
1750 case INITIALIZE:
1751 psp->prevrule = 0;
1752 psp->preccounter = 0;
1753 psp->firstrule = psp->lastrule = 0;
1754 psp->gp->nrule = 0;
1755 /* Fall thru to next case */
1756 case WAITING_FOR_DECL_OR_RULE:
1757 if( x[0]=='%' ){
1758 psp->state = WAITING_FOR_DECL_KEYWORD;
1759 }else if( islower(x[0]) ){
1760 psp->lhs = Symbol_new(x);
1761 psp->nrhs = 0;
1762 psp->lhsalias = 0;
1763 psp->state = WAITING_FOR_ARROW;
1764 }else if( x[0]=='{' ){
1765 if( psp->prevrule==0 ){
1766 ErrorMsg(psp->filename,psp->tokenlineno,
1767"There is not prior rule opon which to attach the code \
1768fragment which begins on this line.");
1769 psp->errorcnt++;
1770 }else if( psp->prevrule->code!=0 ){
1771 ErrorMsg(psp->filename,psp->tokenlineno,
1772"Code fragment beginning on this line is not the first \
1773to follow the previous rule.");
1774 psp->errorcnt++;
1775 }else{
1776 psp->prevrule->line = psp->tokenlineno;
1777 psp->prevrule->code = &x[1];
1778 }
1779 }else if( x[0]=='[' ){
1780 psp->state = PRECEDENCE_MARK_1;
1781 }else{
1782 ErrorMsg(psp->filename,psp->tokenlineno,
1783 "Token \"%s\" should be either \"%%\" or a nonterminal name.",
1784 x);
1785 psp->errorcnt++;
1786 }
1787 break;
1788 case PRECEDENCE_MARK_1:
1789 if( !isupper(x[0]) ){
1790 ErrorMsg(psp->filename,psp->tokenlineno,
1791 "The precedence symbol must be a terminal.");
1792 psp->errorcnt++;
1793 }else if( psp->prevrule==0 ){
1794 ErrorMsg(psp->filename,psp->tokenlineno,
1795 "There is no prior rule to assign precedence \"[%s]\".",x);
1796 psp->errorcnt++;
1797 }else if( psp->prevrule->precsym!=0 ){
1798 ErrorMsg(psp->filename,psp->tokenlineno,
1799"Precedence mark on this line is not the first \
1800to follow the previous rule.");
1801 psp->errorcnt++;
1802 }else{
1803 psp->prevrule->precsym = Symbol_new(x);
1804 }
1805 psp->state = PRECEDENCE_MARK_2;
1806 break;
1807 case PRECEDENCE_MARK_2:
1808 if( x[0]!=']' ){
1809 ErrorMsg(psp->filename,psp->tokenlineno,
1810 "Missing \"]\" on precedence mark.");
1811 psp->errorcnt++;
1812 }
1813 psp->state = WAITING_FOR_DECL_OR_RULE;
1814 break;
1815 case WAITING_FOR_ARROW:
1816 if( x[0]==':' && x[1]==':' && x[2]=='=' ){
1817 psp->state = IN_RHS;
1818 }else if( x[0]=='(' ){
1819 psp->state = LHS_ALIAS_1;
1820 }else{
1821 ErrorMsg(psp->filename,psp->tokenlineno,
1822 "Expected to see a \":\" following the LHS symbol \"%s\".",
1823 psp->lhs->name);
1824 psp->errorcnt++;
1825 psp->state = RESYNC_AFTER_RULE_ERROR;
1826 }
1827 break;
1828 case LHS_ALIAS_1:
1829 if( isalpha(x[0]) ){
1830 psp->lhsalias = x;
1831 psp->state = LHS_ALIAS_2;
1832 }else{
1833 ErrorMsg(psp->filename,psp->tokenlineno,
1834 "\"%s\" is not a valid alias for the LHS \"%s\"\n",
1835 x,psp->lhs->name);
1836 psp->errorcnt++;
1837 psp->state = RESYNC_AFTER_RULE_ERROR;
1838 }
1839 break;
1840 case LHS_ALIAS_2:
1841 if( x[0]==')' ){
1842 psp->state = LHS_ALIAS_3;
1843 }else{
1844 ErrorMsg(psp->filename,psp->tokenlineno,
1845 "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
1846 psp->errorcnt++;
1847 psp->state = RESYNC_AFTER_RULE_ERROR;
1848 }
1849 break;
1850 case LHS_ALIAS_3:
1851 if( x[0]==':' && x[1]==':' && x[2]=='=' ){
1852 psp->state = IN_RHS;
1853 }else{
1854 ErrorMsg(psp->filename,psp->tokenlineno,
1855 "Missing \"->\" following: \"%s(%s)\".",
1856 psp->lhs->name,psp->lhsalias);
1857 psp->errorcnt++;
1858 psp->state = RESYNC_AFTER_RULE_ERROR;
1859 }
1860 break;
1861 case IN_RHS:
1862 if( x[0]=='.' ){
1863 struct rule *rp;
1864 rp = (struct rule *)malloc( sizeof(struct rule) +
1865 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
1866 if( rp==0 ){
1867 ErrorMsg(psp->filename,psp->tokenlineno,
1868 "Can't allocate enough memory for this rule.");
1869 psp->errorcnt++;
1870 psp->prevrule = 0;
1871 }else{
1872 int i;
1873 rp->ruleline = psp->tokenlineno;
1874 rp->rhs = (struct symbol**)&rp[1];
1875 rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]);
1876 for(i=0; i<psp->nrhs; i++){
1877 rp->rhs[i] = psp->rhs[i];
1878 rp->rhsalias[i] = psp->alias[i];
1879 }
1880 rp->lhs = psp->lhs;
1881 rp->lhsalias = psp->lhsalias;
1882 rp->nrhs = psp->nrhs;
1883 rp->code = 0;
1884 rp->precsym = 0;
1885 rp->index = psp->gp->nrule++;
1886 rp->nextlhs = rp->lhs->rule;
1887 rp->lhs->rule = rp;
1888 rp->next = 0;
1889 if( psp->firstrule==0 ){
1890 psp->firstrule = psp->lastrule = rp;
1891 }else{
1892 psp->lastrule->next = rp;
1893 psp->lastrule = rp;
1894 }
1895 psp->prevrule = rp;
1896 }
1897 psp->state = WAITING_FOR_DECL_OR_RULE;
1898 }else if( isalpha(x[0]) ){
1899 if( psp->nrhs>=MAXRHS ){
1900 ErrorMsg(psp->filename,psp->tokenlineno,
1901 "Too many symbol on RHS or rule beginning at \"%s\".",
1902 x);
1903 psp->errorcnt++;
1904 psp->state = RESYNC_AFTER_RULE_ERROR;
1905 }else{
1906 psp->rhs[psp->nrhs] = Symbol_new(x);
1907 psp->alias[psp->nrhs] = 0;
1908 psp->nrhs++;
1909 }
1910 }else if( x[0]=='(' && psp->nrhs>0 ){
1911 psp->state = RHS_ALIAS_1;
1912 }else{
1913 ErrorMsg(psp->filename,psp->tokenlineno,
1914 "Illegal character on RHS of rule: \"%s\".",x);
1915 psp->errorcnt++;
1916 psp->state = RESYNC_AFTER_RULE_ERROR;
1917 }
1918 break;
1919 case RHS_ALIAS_1:
1920 if( isalpha(x[0]) ){
1921 psp->alias[psp->nrhs-1] = x;
1922 psp->state = RHS_ALIAS_2;
1923 }else{
1924 ErrorMsg(psp->filename,psp->tokenlineno,
1925 "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
1926 x,psp->rhs[psp->nrhs-1]->name);
1927 psp->errorcnt++;
1928 psp->state = RESYNC_AFTER_RULE_ERROR;
1929 }
1930 break;
1931 case RHS_ALIAS_2:
1932 if( x[0]==')' ){
1933 psp->state = IN_RHS;
1934 }else{
1935 ErrorMsg(psp->filename,psp->tokenlineno,
1936 "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
1937 psp->errorcnt++;
1938 psp->state = RESYNC_AFTER_RULE_ERROR;
1939 }
1940 break;
1941 case WAITING_FOR_DECL_KEYWORD:
1942 if( isalpha(x[0]) ){
1943 psp->declkeyword = x;
1944 psp->declargslot = 0;
1945 psp->decllnslot = 0;
1946 psp->state = WAITING_FOR_DECL_ARG;
1947 if( strcmp(x,"name")==0 ){
1948 psp->declargslot = &(psp->gp->name);
1949 }else if( strcmp(x,"include")==0 ){
1950 psp->declargslot = &(psp->gp->include);
1951 psp->decllnslot = &psp->gp->includeln;
1952 }else if( strcmp(x,"code")==0 ){
1953 psp->declargslot = &(psp->gp->extracode);
1954 psp->decllnslot = &psp->gp->extracodeln;
1955 }else if( strcmp(x,"token_destructor")==0 ){
1956 psp->declargslot = &psp->gp->tokendest;
1957 psp->decllnslot = &psp->gp->tokendestln;
drh960e8c62001-04-03 16:53:21 +00001958 }else if( strcmp(x,"default_destructor")==0 ){
1959 psp->declargslot = &psp->gp->vardest;
1960 psp->decllnslot = &psp->gp->vardestln;
drh75897232000-05-29 14:26:00 +00001961 }else if( strcmp(x,"token_prefix")==0 ){
1962 psp->declargslot = &psp->gp->tokenprefix;
1963 }else if( strcmp(x,"syntax_error")==0 ){
1964 psp->declargslot = &(psp->gp->error);
1965 psp->decllnslot = &psp->gp->errorln;
1966 }else if( strcmp(x,"parse_accept")==0 ){
1967 psp->declargslot = &(psp->gp->accept);
1968 psp->decllnslot = &psp->gp->acceptln;
1969 }else if( strcmp(x,"parse_failure")==0 ){
1970 psp->declargslot = &(psp->gp->failure);
1971 psp->decllnslot = &psp->gp->failureln;
1972 }else if( strcmp(x,"stack_overflow")==0 ){
1973 psp->declargslot = &(psp->gp->overflow);
1974 psp->decllnslot = &psp->gp->overflowln;
1975 }else if( strcmp(x,"extra_argument")==0 ){
1976 psp->declargslot = &(psp->gp->arg);
1977 }else if( strcmp(x,"token_type")==0 ){
1978 psp->declargslot = &(psp->gp->tokentype);
drh960e8c62001-04-03 16:53:21 +00001979 }else if( strcmp(x,"default_type")==0 ){
1980 psp->declargslot = &(psp->gp->vartype);
drh75897232000-05-29 14:26:00 +00001981 }else if( strcmp(x,"stack_size")==0 ){
1982 psp->declargslot = &(psp->gp->stacksize);
1983 }else if( strcmp(x,"start_symbol")==0 ){
1984 psp->declargslot = &(psp->gp->start);
1985 }else if( strcmp(x,"left")==0 ){
1986 psp->preccounter++;
1987 psp->declassoc = LEFT;
1988 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
1989 }else if( strcmp(x,"right")==0 ){
1990 psp->preccounter++;
1991 psp->declassoc = RIGHT;
1992 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
1993 }else if( strcmp(x,"nonassoc")==0 ){
1994 psp->preccounter++;
1995 psp->declassoc = NONE;
1996 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
1997 }else if( strcmp(x,"destructor")==0 ){
1998 psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
1999 }else if( strcmp(x,"type")==0 ){
2000 psp->state = WAITING_FOR_DATATYPE_SYMBOL;
drh0bd1f4e2002-06-06 18:54:39 +00002001 }else if( strcmp(x,"fallback")==0 ){
2002 psp->fallback = 0;
2003 psp->state = WAITING_FOR_FALLBACK_ID;
drh75897232000-05-29 14:26:00 +00002004 }else{
2005 ErrorMsg(psp->filename,psp->tokenlineno,
2006 "Unknown declaration keyword: \"%%%s\".",x);
2007 psp->errorcnt++;
2008 psp->state = RESYNC_AFTER_DECL_ERROR;
2009 }
2010 }else{
2011 ErrorMsg(psp->filename,psp->tokenlineno,
2012 "Illegal declaration keyword: \"%s\".",x);
2013 psp->errorcnt++;
2014 psp->state = RESYNC_AFTER_DECL_ERROR;
2015 }
2016 break;
2017 case WAITING_FOR_DESTRUCTOR_SYMBOL:
2018 if( !isalpha(x[0]) ){
2019 ErrorMsg(psp->filename,psp->tokenlineno,
2020 "Symbol name missing after %destructor keyword");
2021 psp->errorcnt++;
2022 psp->state = RESYNC_AFTER_DECL_ERROR;
2023 }else{
2024 struct symbol *sp = Symbol_new(x);
2025 psp->declargslot = &sp->destructor;
2026 psp->decllnslot = &sp->destructorln;
2027 psp->state = WAITING_FOR_DECL_ARG;
2028 }
2029 break;
2030 case WAITING_FOR_DATATYPE_SYMBOL:
2031 if( !isalpha(x[0]) ){
2032 ErrorMsg(psp->filename,psp->tokenlineno,
2033 "Symbol name missing after %destructor keyword");
2034 psp->errorcnt++;
2035 psp->state = RESYNC_AFTER_DECL_ERROR;
2036 }else{
2037 struct symbol *sp = Symbol_new(x);
2038 psp->declargslot = &sp->datatype;
2039 psp->decllnslot = 0;
2040 psp->state = WAITING_FOR_DECL_ARG;
2041 }
2042 break;
2043 case WAITING_FOR_PRECEDENCE_SYMBOL:
2044 if( x[0]=='.' ){
2045 psp->state = WAITING_FOR_DECL_OR_RULE;
2046 }else if( isupper(x[0]) ){
2047 struct symbol *sp;
2048 sp = Symbol_new(x);
2049 if( sp->prec>=0 ){
2050 ErrorMsg(psp->filename,psp->tokenlineno,
2051 "Symbol \"%s\" has already be given a precedence.",x);
2052 psp->errorcnt++;
2053 }else{
2054 sp->prec = psp->preccounter;
2055 sp->assoc = psp->declassoc;
2056 }
2057 }else{
2058 ErrorMsg(psp->filename,psp->tokenlineno,
2059 "Can't assign a precedence to \"%s\".",x);
2060 psp->errorcnt++;
2061 }
2062 break;
2063 case WAITING_FOR_DECL_ARG:
2064 if( (x[0]=='{' || x[0]=='\"' || isalnum(x[0])) ){
2065 if( *(psp->declargslot)!=0 ){
2066 ErrorMsg(psp->filename,psp->tokenlineno,
2067 "The argument \"%s\" to declaration \"%%%s\" is not the first.",
2068 x[0]=='\"' ? &x[1] : x,psp->declkeyword);
2069 psp->errorcnt++;
2070 psp->state = RESYNC_AFTER_DECL_ERROR;
2071 }else{
2072 *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x;
2073 if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno;
2074 psp->state = WAITING_FOR_DECL_OR_RULE;
2075 }
2076 }else{
2077 ErrorMsg(psp->filename,psp->tokenlineno,
2078 "Illegal argument to %%%s: %s",psp->declkeyword,x);
2079 psp->errorcnt++;
2080 psp->state = RESYNC_AFTER_DECL_ERROR;
2081 }
2082 break;
drh0bd1f4e2002-06-06 18:54:39 +00002083 case WAITING_FOR_FALLBACK_ID:
2084 if( x[0]=='.' ){
2085 psp->state = WAITING_FOR_DECL_OR_RULE;
2086 }else if( !isupper(x[0]) ){
2087 ErrorMsg(psp->filename, psp->tokenlineno,
2088 "%%fallback argument \"%s\" should be a token", x);
2089 psp->errorcnt++;
2090 }else{
2091 struct symbol *sp = Symbol_new(x);
2092 if( psp->fallback==0 ){
2093 psp->fallback = sp;
2094 }else if( sp->fallback ){
2095 ErrorMsg(psp->filename, psp->tokenlineno,
2096 "More than one fallback assigned to token %s", x);
2097 psp->errorcnt++;
2098 }else{
2099 sp->fallback = psp->fallback;
2100 psp->gp->has_fallback = 1;
2101 }
2102 }
2103 break;
drh75897232000-05-29 14:26:00 +00002104 case RESYNC_AFTER_RULE_ERROR:
2105/* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2106** break; */
2107 case RESYNC_AFTER_DECL_ERROR:
2108 if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
2109 if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
2110 break;
2111 }
2112}
2113
2114/* In spite of its name, this function is really a scanner. It read
2115** in the entire input file (all at once) then tokenizes it. Each
2116** token is passed to the function "parseonetoken" which builds all
2117** the appropriate data structures in the global state vector "gp".
2118*/
2119void Parse(gp)
2120struct lemon *gp;
2121{
2122 struct pstate ps;
2123 FILE *fp;
2124 char *filebuf;
2125 int filesize;
2126 int lineno;
2127 int c;
2128 char *cp, *nextcp;
2129 int startline = 0;
2130
2131 ps.gp = gp;
2132 ps.filename = gp->filename;
2133 ps.errorcnt = 0;
2134 ps.state = INITIALIZE;
2135
2136 /* Begin by reading the input file */
2137 fp = fopen(ps.filename,"rb");
2138 if( fp==0 ){
2139 ErrorMsg(ps.filename,0,"Can't open this file for reading.");
2140 gp->errorcnt++;
2141 return;
2142 }
2143 fseek(fp,0,2);
2144 filesize = ftell(fp);
2145 rewind(fp);
2146 filebuf = (char *)malloc( filesize+1 );
2147 if( filebuf==0 ){
2148 ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.",
2149 filesize+1);
2150 gp->errorcnt++;
2151 return;
2152 }
2153 if( fread(filebuf,1,filesize,fp)!=filesize ){
2154 ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
2155 filesize);
2156 free(filebuf);
2157 gp->errorcnt++;
2158 return;
2159 }
2160 fclose(fp);
2161 filebuf[filesize] = 0;
2162
2163 /* Now scan the text of the input file */
2164 lineno = 1;
2165 for(cp=filebuf; (c= *cp)!=0; ){
2166 if( c=='\n' ) lineno++; /* Keep track of the line number */
2167 if( isspace(c) ){ cp++; continue; } /* Skip all white space */
2168 if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */
2169 cp+=2;
2170 while( (c= *cp)!=0 && c!='\n' ) cp++;
2171 continue;
2172 }
2173 if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */
2174 cp+=2;
2175 while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
2176 if( c=='\n' ) lineno++;
2177 cp++;
2178 }
2179 if( c ) cp++;
2180 continue;
2181 }
2182 ps.tokenstart = cp; /* Mark the beginning of the token */
2183 ps.tokenlineno = lineno; /* Linenumber on which token begins */
2184 if( c=='\"' ){ /* String literals */
2185 cp++;
2186 while( (c= *cp)!=0 && c!='\"' ){
2187 if( c=='\n' ) lineno++;
2188 cp++;
2189 }
2190 if( c==0 ){
2191 ErrorMsg(ps.filename,startline,
2192"String starting on this line is not terminated before the end of the file.");
2193 ps.errorcnt++;
2194 nextcp = cp;
2195 }else{
2196 nextcp = cp+1;
2197 }
2198 }else if( c=='{' ){ /* A block of C code */
2199 int level;
2200 cp++;
2201 for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
2202 if( c=='\n' ) lineno++;
2203 else if( c=='{' ) level++;
2204 else if( c=='}' ) level--;
2205 else if( c=='/' && cp[1]=='*' ){ /* Skip comments */
2206 int prevc;
2207 cp = &cp[2];
2208 prevc = 0;
2209 while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
2210 if( c=='\n' ) lineno++;
2211 prevc = c;
2212 cp++;
2213 }
2214 }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
2215 cp = &cp[2];
2216 while( (c= *cp)!=0 && c!='\n' ) cp++;
2217 if( c ) lineno++;
2218 }else if( c=='\'' || c=='\"' ){ /* String a character literals */
2219 int startchar, prevc;
2220 startchar = c;
2221 prevc = 0;
2222 for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
2223 if( c=='\n' ) lineno++;
2224 if( prevc=='\\' ) prevc = 0;
2225 else prevc = c;
2226 }
2227 }
2228 }
2229 if( c==0 ){
drh960e8c62001-04-03 16:53:21 +00002230 ErrorMsg(ps.filename,ps.tokenlineno,
drh75897232000-05-29 14:26:00 +00002231"C code starting on this line is not terminated before the end of the file.");
2232 ps.errorcnt++;
2233 nextcp = cp;
2234 }else{
2235 nextcp = cp+1;
2236 }
2237 }else if( isalnum(c) ){ /* Identifiers */
2238 while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
2239 nextcp = cp;
2240 }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
2241 cp += 3;
2242 nextcp = cp;
2243 }else{ /* All other (one character) operators */
2244 cp++;
2245 nextcp = cp;
2246 }
2247 c = *cp;
2248 *cp = 0; /* Null terminate the token */
2249 parseonetoken(&ps); /* Parse the token */
2250 *cp = c; /* Restore the buffer */
2251 cp = nextcp;
2252 }
2253 free(filebuf); /* Release the buffer after parsing */
2254 gp->rule = ps.firstrule;
2255 gp->errorcnt = ps.errorcnt;
2256}
2257/*************************** From the file "plink.c" *********************/
2258/*
2259** Routines processing configuration follow-set propagation links
2260** in the LEMON parser generator.
2261*/
2262static struct plink *plink_freelist = 0;
2263
2264/* Allocate a new plink */
2265struct plink *Plink_new(){
2266 struct plink *new;
2267
2268 if( plink_freelist==0 ){
2269 int i;
2270 int amt = 100;
2271 plink_freelist = (struct plink *)malloc( sizeof(struct plink)*amt );
2272 if( plink_freelist==0 ){
2273 fprintf(stderr,
2274 "Unable to allocate memory for a new follow-set propagation link.\n");
2275 exit(1);
2276 }
2277 for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
2278 plink_freelist[amt-1].next = 0;
2279 }
2280 new = plink_freelist;
2281 plink_freelist = plink_freelist->next;
2282 return new;
2283}
2284
2285/* Add a plink to a plink list */
2286void Plink_add(plpp,cfp)
2287struct plink **plpp;
2288struct config *cfp;
2289{
2290 struct plink *new;
2291 new = Plink_new();
2292 new->next = *plpp;
2293 *plpp = new;
2294 new->cfp = cfp;
2295}
2296
2297/* Transfer every plink on the list "from" to the list "to" */
2298void Plink_copy(to,from)
2299struct plink **to;
2300struct plink *from;
2301{
2302 struct plink *nextpl;
2303 while( from ){
2304 nextpl = from->next;
2305 from->next = *to;
2306 *to = from;
2307 from = nextpl;
2308 }
2309}
2310
2311/* Delete every plink on the list */
2312void Plink_delete(plp)
2313struct plink *plp;
2314{
2315 struct plink *nextpl;
2316
2317 while( plp ){
2318 nextpl = plp->next;
2319 plp->next = plink_freelist;
2320 plink_freelist = plp;
2321 plp = nextpl;
2322 }
2323}
2324/*********************** From the file "report.c" **************************/
2325/*
2326** Procedures for generating reports and tables in the LEMON parser generator.
2327*/
2328
2329/* Generate a filename with the given suffix. Space to hold the
2330** name comes from malloc() and must be freed by the calling
2331** function.
2332*/
2333PRIVATE char *file_makename(lemp,suffix)
2334struct lemon *lemp;
2335char *suffix;
2336{
2337 char *name;
2338 char *cp;
2339
2340 name = malloc( strlen(lemp->filename) + strlen(suffix) + 5 );
2341 if( name==0 ){
2342 fprintf(stderr,"Can't allocate space for a filename.\n");
2343 exit(1);
2344 }
2345 strcpy(name,lemp->filename);
2346 cp = strrchr(name,'.');
2347 if( cp ) *cp = 0;
2348 strcat(name,suffix);
2349 return name;
2350}
2351
2352/* Open a file with a name based on the name of the input file,
2353** but with a different (specified) suffix, and return a pointer
2354** to the stream */
2355PRIVATE FILE *file_open(lemp,suffix,mode)
2356struct lemon *lemp;
2357char *suffix;
2358char *mode;
2359{
2360 FILE *fp;
2361
2362 if( lemp->outname ) free(lemp->outname);
2363 lemp->outname = file_makename(lemp, suffix);
2364 fp = fopen(lemp->outname,mode);
2365 if( fp==0 && *mode=='w' ){
2366 fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
2367 lemp->errorcnt++;
2368 return 0;
2369 }
2370 return fp;
2371}
2372
2373/* Duplicate the input file without comments and without actions
2374** on rules */
2375void Reprint(lemp)
2376struct lemon *lemp;
2377{
2378 struct rule *rp;
2379 struct symbol *sp;
2380 int i, j, maxlen, len, ncolumns, skip;
2381 printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
2382 maxlen = 10;
2383 for(i=0; i<lemp->nsymbol; i++){
2384 sp = lemp->symbols[i];
2385 len = strlen(sp->name);
2386 if( len>maxlen ) maxlen = len;
2387 }
2388 ncolumns = 76/(maxlen+5);
2389 if( ncolumns<1 ) ncolumns = 1;
2390 skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
2391 for(i=0; i<skip; i++){
2392 printf("//");
2393 for(j=i; j<lemp->nsymbol; j+=skip){
2394 sp = lemp->symbols[j];
2395 assert( sp->index==j );
2396 printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
2397 }
2398 printf("\n");
2399 }
2400 for(rp=lemp->rule; rp; rp=rp->next){
2401 printf("%s",rp->lhs->name);
2402/* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
2403 printf(" ::=");
2404 for(i=0; i<rp->nrhs; i++){
2405 printf(" %s",rp->rhs[i]->name);
2406/* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
2407 }
2408 printf(".");
2409 if( rp->precsym ) printf(" [%s]",rp->precsym->name);
2410/* if( rp->code ) printf("\n %s",rp->code); */
2411 printf("\n");
2412 }
2413}
2414
2415void ConfigPrint(fp,cfp)
2416FILE *fp;
2417struct config *cfp;
2418{
2419 struct rule *rp;
2420 int i;
2421 rp = cfp->rp;
2422 fprintf(fp,"%s ::=",rp->lhs->name);
2423 for(i=0; i<=rp->nrhs; i++){
2424 if( i==cfp->dot ) fprintf(fp," *");
2425 if( i==rp->nrhs ) break;
2426 fprintf(fp," %s",rp->rhs[i]->name);
2427 }
2428}
2429
2430/* #define TEST */
2431#ifdef TEST
2432/* Print a set */
2433PRIVATE void SetPrint(out,set,lemp)
2434FILE *out;
2435char *set;
2436struct lemon *lemp;
2437{
2438 int i;
2439 char *spacer;
2440 spacer = "";
2441 fprintf(out,"%12s[","");
2442 for(i=0; i<lemp->nterminal; i++){
2443 if( SetFind(set,i) ){
2444 fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
2445 spacer = " ";
2446 }
2447 }
2448 fprintf(out,"]\n");
2449}
2450
2451/* Print a plink chain */
2452PRIVATE void PlinkPrint(out,plp,tag)
2453FILE *out;
2454struct plink *plp;
2455char *tag;
2456{
2457 while( plp ){
2458 fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->index);
2459 ConfigPrint(out,plp->cfp);
2460 fprintf(out,"\n");
2461 plp = plp->next;
2462 }
2463}
2464#endif
2465
2466/* Print an action to the given file descriptor. Return FALSE if
2467** nothing was actually printed.
2468*/
2469int PrintAction(struct action *ap, FILE *fp, int indent){
2470 int result = 1;
2471 switch( ap->type ){
2472 case SHIFT:
2473 fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->index);
2474 break;
2475 case REDUCE:
2476 fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
2477 break;
2478 case ACCEPT:
2479 fprintf(fp,"%*s accept",indent,ap->sp->name);
2480 break;
2481 case ERROR:
2482 fprintf(fp,"%*s error",indent,ap->sp->name);
2483 break;
2484 case CONFLICT:
2485 fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
2486 indent,ap->sp->name,ap->x.rp->index);
2487 break;
2488 case SH_RESOLVED:
2489 case RD_RESOLVED:
2490 case NOT_USED:
2491 result = 0;
2492 break;
2493 }
2494 return result;
2495}
2496
2497/* Generate the "y.output" log file */
2498void ReportOutput(lemp)
2499struct lemon *lemp;
2500{
2501 int i;
2502 struct state *stp;
2503 struct config *cfp;
2504 struct action *ap;
2505 FILE *fp;
2506
2507 fp = file_open(lemp,".out","w");
2508 if( fp==0 ) return;
2509 fprintf(fp," \b");
2510 for(i=0; i<lemp->nstate; i++){
2511 stp = lemp->sorted[i];
2512 fprintf(fp,"State %d:\n",stp->index);
2513 if( lemp->basisflag ) cfp=stp->bp;
2514 else cfp=stp->cfp;
2515 while( cfp ){
2516 char buf[20];
2517 if( cfp->dot==cfp->rp->nrhs ){
2518 sprintf(buf,"(%d)",cfp->rp->index);
2519 fprintf(fp," %5s ",buf);
2520 }else{
2521 fprintf(fp," ");
2522 }
2523 ConfigPrint(fp,cfp);
2524 fprintf(fp,"\n");
2525#ifdef TEST
2526 SetPrint(fp,cfp->fws,lemp);
2527 PlinkPrint(fp,cfp->fplp,"To ");
2528 PlinkPrint(fp,cfp->bplp,"From");
2529#endif
2530 if( lemp->basisflag ) cfp=cfp->bp;
2531 else cfp=cfp->next;
2532 }
2533 fprintf(fp,"\n");
2534 for(ap=stp->ap; ap; ap=ap->next){
2535 if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
2536 }
2537 fprintf(fp,"\n");
2538 }
2539 fclose(fp);
2540 return;
2541}
2542
2543/* Search for the file "name" which is in the same directory as
2544** the exacutable */
2545PRIVATE char *pathsearch(argv0,name,modemask)
2546char *argv0;
2547char *name;
2548int modemask;
2549{
2550 char *pathlist;
2551 char *path,*cp;
2552 char c;
2553 extern int access();
2554
2555#ifdef __WIN32__
2556 cp = strrchr(argv0,'\\');
2557#else
2558 cp = strrchr(argv0,'/');
2559#endif
2560 if( cp ){
2561 c = *cp;
2562 *cp = 0;
2563 path = (char *)malloc( strlen(argv0) + strlen(name) + 2 );
2564 if( path ) sprintf(path,"%s/%s",argv0,name);
2565 *cp = c;
2566 }else{
2567 extern char *getenv();
2568 pathlist = getenv("PATH");
2569 if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
2570 path = (char *)malloc( strlen(pathlist)+strlen(name)+2 );
2571 if( path!=0 ){
2572 while( *pathlist ){
2573 cp = strchr(pathlist,':');
2574 if( cp==0 ) cp = &pathlist[strlen(pathlist)];
2575 c = *cp;
2576 *cp = 0;
2577 sprintf(path,"%s/%s",pathlist,name);
2578 *cp = c;
2579 if( c==0 ) pathlist = "";
2580 else pathlist = &cp[1];
2581 if( access(path,modemask)==0 ) break;
2582 }
2583 }
2584 }
2585 return path;
2586}
2587
2588/* Given an action, compute the integer value for that action
2589** which is to be put in the action table of the generated machine.
2590** Return negative if no action should be generated.
2591*/
2592PRIVATE int compute_action(lemp,ap)
2593struct lemon *lemp;
2594struct action *ap;
2595{
2596 int act;
2597 switch( ap->type ){
2598 case SHIFT: act = ap->x.stp->index; break;
2599 case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
2600 case ERROR: act = lemp->nstate + lemp->nrule; break;
2601 case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
2602 default: act = -1; break;
2603 }
2604 return act;
2605}
2606
2607#define LINESIZE 1000
2608/* The next cluster of routines are for reading the template file
2609** and writing the results to the generated parser */
2610/* The first function transfers data from "in" to "out" until
2611** a line is seen which begins with "%%". The line number is
2612** tracked.
2613**
2614** if name!=0, then any word that begin with "Parse" is changed to
2615** begin with *name instead.
2616*/
2617PRIVATE void tplt_xfer(name,in,out,lineno)
2618char *name;
2619FILE *in;
2620FILE *out;
2621int *lineno;
2622{
2623 int i, iStart;
2624 char line[LINESIZE];
2625 while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
2626 (*lineno)++;
2627 iStart = 0;
2628 if( name ){
2629 for(i=0; line[i]; i++){
2630 if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
2631 && (i==0 || !isalpha(line[i-1]))
2632 ){
2633 if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
2634 fprintf(out,"%s",name);
2635 i += 4;
2636 iStart = i+1;
2637 }
2638 }
2639 }
2640 fprintf(out,"%s",&line[iStart]);
2641 }
2642}
2643
2644/* The next function finds the template file and opens it, returning
2645** a pointer to the opened file. */
2646PRIVATE FILE *tplt_open(lemp)
2647struct lemon *lemp;
2648{
2649 static char templatename[] = "lempar.c";
2650 char buf[1000];
2651 FILE *in;
2652 char *tpltname;
2653 char *cp;
2654
2655 cp = strrchr(lemp->filename,'.');
2656 if( cp ){
drhba99af52001-10-25 20:37:16 +00002657 sprintf(buf,"%.*s.lt",(unsigned long)cp-(unsigned long)lemp->filename,lemp->filename);
drh75897232000-05-29 14:26:00 +00002658 }else{
2659 sprintf(buf,"%s.lt",lemp->filename);
2660 }
2661 if( access(buf,004)==0 ){
2662 tpltname = buf;
drh960e8c62001-04-03 16:53:21 +00002663 }else if( access(templatename,004)==0 ){
2664 tpltname = templatename;
drh75897232000-05-29 14:26:00 +00002665 }else{
2666 tpltname = pathsearch(lemp->argv0,templatename,0);
2667 }
2668 if( tpltname==0 ){
2669 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
2670 templatename);
2671 lemp->errorcnt++;
2672 return 0;
2673 }
2674 in = fopen(tpltname,"r");
2675 if( in==0 ){
2676 fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
2677 lemp->errorcnt++;
2678 return 0;
2679 }
2680 return in;
2681}
2682
2683/* Print a string to the file and keep the linenumber up to date */
2684PRIVATE void tplt_print(out,lemp,str,strln,lineno)
2685FILE *out;
2686struct lemon *lemp;
2687char *str;
2688int strln;
2689int *lineno;
2690{
2691 if( str==0 ) return;
2692 fprintf(out,"#line %d \"%s\"\n",strln,lemp->filename); (*lineno)++;
2693 while( *str ){
2694 if( *str=='\n' ) (*lineno)++;
2695 putc(*str,out);
2696 str++;
2697 }
2698 fprintf(out,"\n#line %d \"%s\"\n",*lineno+2,lemp->outname); (*lineno)+=2;
2699 return;
2700}
2701
2702/*
2703** The following routine emits code for the destructor for the
2704** symbol sp
2705*/
2706void emit_destructor_code(out,sp,lemp,lineno)
2707FILE *out;
2708struct symbol *sp;
2709struct lemon *lemp;
2710int *lineno;
2711{
2712 char *cp;
2713
2714 int linecnt = 0;
2715 if( sp->type==TERMINAL ){
2716 cp = lemp->tokendest;
2717 if( cp==0 ) return;
2718 fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
drh960e8c62001-04-03 16:53:21 +00002719 }else if( sp->destructor ){
drh75897232000-05-29 14:26:00 +00002720 cp = sp->destructor;
drh75897232000-05-29 14:26:00 +00002721 fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
drh960e8c62001-04-03 16:53:21 +00002722 }else if( lemp->vardest ){
2723 cp = lemp->vardest;
2724 if( cp==0 ) return;
2725 fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
drh75897232000-05-29 14:26:00 +00002726 }
2727 for(; *cp; cp++){
2728 if( *cp=='$' && cp[1]=='$' ){
2729 fprintf(out,"(yypminor->yy%d)",sp->dtnum);
2730 cp++;
2731 continue;
2732 }
2733 if( *cp=='\n' ) linecnt++;
2734 fputc(*cp,out);
2735 }
2736 (*lineno) += 3 + linecnt;
2737 fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
2738 return;
2739}
2740
2741/*
drh960e8c62001-04-03 16:53:21 +00002742** Return TRUE (non-zero) if the given symbol has a destructor.
drh75897232000-05-29 14:26:00 +00002743*/
2744int has_destructor(sp, lemp)
2745struct symbol *sp;
2746struct lemon *lemp;
2747{
2748 int ret;
2749 if( sp->type==TERMINAL ){
2750 ret = lemp->tokendest!=0;
2751 }else{
drh960e8c62001-04-03 16:53:21 +00002752 ret = lemp->vardest!=0 || sp->destructor!=0;
drh75897232000-05-29 14:26:00 +00002753 }
2754 return ret;
2755}
2756
2757/*
2758** Generate code which executes when the rule "rp" is reduced. Write
2759** the code to "out". Make sure lineno stays up-to-date.
2760*/
2761PRIVATE void emit_code(out,rp,lemp,lineno)
2762FILE *out;
2763struct rule *rp;
2764struct lemon *lemp;
2765int *lineno;
2766{
2767 char *cp, *xp;
2768 int linecnt = 0;
2769 int i;
2770 char lhsused = 0; /* True if the LHS element has been used */
2771 char used[MAXRHS]; /* True for each RHS element which is used */
2772
2773 for(i=0; i<rp->nrhs; i++) used[i] = 0;
2774 lhsused = 0;
2775
2776 /* Generate code to do the reduce action */
2777 if( rp->code ){
2778 fprintf(out,"#line %d \"%s\"\n{",rp->line,lemp->filename);
2779 for(cp=rp->code; *cp; cp++){
drh7218ac72002-03-10 21:21:00 +00002780 if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
drh75897232000-05-29 14:26:00 +00002781 char saved;
drh7218ac72002-03-10 21:21:00 +00002782 for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
drh75897232000-05-29 14:26:00 +00002783 saved = *xp;
2784 *xp = 0;
2785 if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
2786 fprintf(out,"yygotominor.yy%d",rp->lhs->dtnum);
2787 cp = xp;
2788 lhsused = 1;
2789 }else{
2790 for(i=0; i<rp->nrhs; i++){
2791 if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
2792 fprintf(out,"yymsp[%d].minor.yy%d",i-rp->nrhs+1,rp->rhs[i]->dtnum);
2793 cp = xp;
2794 used[i] = 1;
2795 break;
2796 }
2797 }
2798 }
2799 *xp = saved;
2800 }
2801 if( *cp=='\n' ) linecnt++;
2802 fputc(*cp,out);
2803 } /* End loop */
2804 (*lineno) += 3 + linecnt;
2805 fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname);
2806 } /* End if( rp->code ) */
2807
2808 /* Check to make sure the LHS has been used */
2809 if( rp->lhsalias && !lhsused ){
2810 ErrorMsg(lemp->filename,rp->ruleline,
2811 "Label \"%s\" for \"%s(%s)\" is never used.",
2812 rp->lhsalias,rp->lhs->name,rp->lhsalias);
2813 lemp->errorcnt++;
2814 }
2815
2816 /* Generate destructor code for RHS symbols which are not used in the
2817 ** reduce code */
2818 for(i=0; i<rp->nrhs; i++){
2819 if( rp->rhsalias[i] && !used[i] ){
2820 ErrorMsg(lemp->filename,rp->ruleline,
drh960e8c62001-04-03 16:53:21 +00002821 "Label %s for \"%s(%s)\" is never used.",
drh75897232000-05-29 14:26:00 +00002822 rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
2823 lemp->errorcnt++;
2824 }else if( rp->rhsalias[i]==0 ){
2825 if( has_destructor(rp->rhs[i],lemp) ){
2826 fprintf(out," yy_destructor(%d,&yymsp[%d].minor);\n",
2827 rp->rhs[i]->index,i-rp->nrhs+1); (*lineno)++;
2828 }else{
2829 fprintf(out," /* No destructor defined for %s */\n",
2830 rp->rhs[i]->name);
2831 (*lineno)++;
2832 }
2833 }
2834 }
2835 return;
2836}
2837
2838/*
2839** Print the definition of the union used for the parser's data stack.
2840** This union contains fields for every possible data type for tokens
2841** and nonterminals. In the process of computing and printing this
2842** union, also set the ".dtnum" field of every terminal and nonterminal
2843** symbol.
2844*/
2845void print_stack_union(out,lemp,plineno,mhflag)
2846FILE *out; /* The output stream */
2847struct lemon *lemp; /* The main info structure for this parser */
2848int *plineno; /* Pointer to the line number */
2849int mhflag; /* True if generating makeheaders output */
2850{
2851 int lineno = *plineno; /* The line number of the output */
2852 char **types; /* A hash table of datatypes */
2853 int arraysize; /* Size of the "types" array */
2854 int maxdtlength; /* Maximum length of any ".datatype" field. */
2855 char *stddt; /* Standardized name for a datatype */
2856 int i,j; /* Loop counters */
2857 int hash; /* For hashing the name of a type */
2858 char *name; /* Name of the parser */
2859
2860 /* Allocate and initialize types[] and allocate stddt[] */
2861 arraysize = lemp->nsymbol * 2;
2862 types = (char**)malloc( arraysize * sizeof(char*) );
2863 for(i=0; i<arraysize; i++) types[i] = 0;
2864 maxdtlength = 0;
drh960e8c62001-04-03 16:53:21 +00002865 if( lemp->vartype ){
2866 maxdtlength = strlen(lemp->vartype);
2867 }
drh75897232000-05-29 14:26:00 +00002868 for(i=0; i<lemp->nsymbol; i++){
2869 int len;
2870 struct symbol *sp = lemp->symbols[i];
2871 if( sp->datatype==0 ) continue;
2872 len = strlen(sp->datatype);
2873 if( len>maxdtlength ) maxdtlength = len;
2874 }
2875 stddt = (char*)malloc( maxdtlength*2 + 1 );
2876 if( types==0 || stddt==0 ){
2877 fprintf(stderr,"Out of memory.\n");
2878 exit(1);
2879 }
2880
2881 /* Build a hash table of datatypes. The ".dtnum" field of each symbol
2882 ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
drh960e8c62001-04-03 16:53:21 +00002883 ** used for terminal symbols. If there is no %default_type defined then
2884 ** 0 is also used as the .dtnum value for nonterminals which do not specify
2885 ** a datatype using the %type directive.
2886 */
drh75897232000-05-29 14:26:00 +00002887 for(i=0; i<lemp->nsymbol; i++){
2888 struct symbol *sp = lemp->symbols[i];
2889 char *cp;
2890 if( sp==lemp->errsym ){
2891 sp->dtnum = arraysize+1;
2892 continue;
2893 }
drh960e8c62001-04-03 16:53:21 +00002894 if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
drh75897232000-05-29 14:26:00 +00002895 sp->dtnum = 0;
2896 continue;
2897 }
2898 cp = sp->datatype;
drh960e8c62001-04-03 16:53:21 +00002899 if( cp==0 ) cp = lemp->vartype;
drh75897232000-05-29 14:26:00 +00002900 j = 0;
2901 while( isspace(*cp) ) cp++;
2902 while( *cp ) stddt[j++] = *cp++;
2903 while( j>0 && isspace(stddt[j-1]) ) j--;
2904 stddt[j] = 0;
2905 hash = 0;
2906 for(j=0; stddt[j]; j++){
2907 hash = hash*53 + stddt[j];
2908 }
2909 if( hash<0 ) hash = -hash;
2910 hash = hash%arraysize;
2911 while( types[hash] ){
2912 if( strcmp(types[hash],stddt)==0 ){
2913 sp->dtnum = hash + 1;
2914 break;
2915 }
2916 hash++;
2917 if( hash>=arraysize ) hash = 0;
2918 }
2919 if( types[hash]==0 ){
2920 sp->dtnum = hash + 1;
2921 types[hash] = (char*)malloc( strlen(stddt)+1 );
2922 if( types[hash]==0 ){
2923 fprintf(stderr,"Out of memory.\n");
2924 exit(1);
2925 }
2926 strcpy(types[hash],stddt);
2927 }
2928 }
2929
2930 /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
2931 name = lemp->name ? lemp->name : "Parse";
2932 lineno = *plineno;
2933 if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
2934 fprintf(out,"#define %sTOKENTYPE %s\n",name,
2935 lemp->tokentype?lemp->tokentype:"void*"); lineno++;
2936 if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
2937 fprintf(out,"typedef union {\n"); lineno++;
2938 fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++;
2939 for(i=0; i<arraysize; i++){
2940 if( types[i]==0 ) continue;
2941 fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
2942 free(types[i]);
2943 }
2944 fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
2945 free(stddt);
2946 free(types);
2947 fprintf(out,"} YYMINORTYPE;\n"); lineno++;
2948 *plineno = lineno;
2949}
2950
drhb29b0a52002-02-23 19:39:46 +00002951/*
2952** Return the name of a C datatype able to represent values between
2953** 0 and N, inclusive.
2954*/
2955static const char *minimum_size_type(int N){
2956 if( N<=255 ){
2957 return "unsigned char";
2958 }else if( N<65535 ){
2959 return "unsigned short int";
2960 }else{
2961 return "unsigned int";
2962 }
2963}
2964
drh75897232000-05-29 14:26:00 +00002965/* Generate C source code for the parser */
2966void ReportTable(lemp, mhflag)
2967struct lemon *lemp;
2968int mhflag; /* Output in makeheaders format if true */
2969{
2970 FILE *out, *in;
2971 char line[LINESIZE];
2972 int lineno;
2973 struct state *stp;
2974 struct action *ap;
2975 struct rule *rp;
drh0bd1f4e2002-06-06 18:54:39 +00002976 int i, j;
drh75897232000-05-29 14:26:00 +00002977 int tablecnt;
2978 char *name;
2979
2980 in = tplt_open(lemp);
2981 if( in==0 ) return;
2982 out = file_open(lemp,".c","w");
2983 if( out==0 ){
2984 fclose(in);
2985 return;
2986 }
2987 lineno = 1;
2988 tplt_xfer(lemp->name,in,out,&lineno);
2989
2990 /* Generate the include code, if any */
2991 tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno);
2992 if( mhflag ){
2993 char *name = file_makename(lemp, ".h");
2994 fprintf(out,"#include \"%s\"\n", name); lineno++;
2995 free(name);
2996 }
2997 tplt_xfer(lemp->name,in,out,&lineno);
2998
2999 /* Generate #defines for all tokens */
3000 if( mhflag ){
3001 char *prefix;
3002 fprintf(out,"#if INTERFACE\n"); lineno++;
3003 if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3004 else prefix = "";
3005 for(i=1; i<lemp->nterminal; i++){
3006 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3007 lineno++;
3008 }
3009 fprintf(out,"#endif\n"); lineno++;
3010 }
3011 tplt_xfer(lemp->name,in,out,&lineno);
3012
3013 /* Generate the defines */
3014 fprintf(out,"/* \001 */\n");
3015 fprintf(out,"#define YYCODETYPE %s\n",
drhb29b0a52002-02-23 19:39:46 +00003016 minimum_size_type(lemp->nsymbol+5)); lineno++;
drh75897232000-05-29 14:26:00 +00003017 fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
3018 fprintf(out,"#define YYACTIONTYPE %s\n",
drhb29b0a52002-02-23 19:39:46 +00003019 minimum_size_type(lemp->nstate+lemp->nrule+5)); lineno++;
drh75897232000-05-29 14:26:00 +00003020 print_stack_union(out,lemp,&lineno,mhflag);
3021 if( lemp->stacksize ){
3022 if( atoi(lemp->stacksize)<=0 ){
3023 ErrorMsg(lemp->filename,0,
3024"Illegal stack size: [%s]. The stack size should be an integer constant.",
3025 lemp->stacksize);
3026 lemp->errorcnt++;
3027 lemp->stacksize = "100";
3028 }
3029 fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
3030 }else{
3031 fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
3032 }
3033 if( mhflag ){
3034 fprintf(out,"#if INTERFACE\n"); lineno++;
3035 }
3036 name = lemp->name ? lemp->name : "Parse";
3037 if( lemp->arg && lemp->arg[0] ){
3038 int i;
3039 i = strlen(lemp->arg);
drhb1edd012000-06-02 18:52:12 +00003040 while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
3041 while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
drh1f245e42002-03-11 13:55:50 +00003042 fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
3043 fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
3044 fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
3045 name,lemp->arg,&lemp->arg[i]); lineno++;
3046 fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
3047 name,&lemp->arg[i],&lemp->arg[i]); lineno++;
drh75897232000-05-29 14:26:00 +00003048 }else{
drh1f245e42002-03-11 13:55:50 +00003049 fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
3050 fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
3051 fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
3052 fprintf(out,"#define %sARG_STORE\n",name); lineno++;
drh75897232000-05-29 14:26:00 +00003053 }
3054 if( mhflag ){
3055 fprintf(out,"#endif\n"); lineno++;
3056 }
3057 fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++;
3058 fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
3059 fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
3060 fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
drh0bd1f4e2002-06-06 18:54:39 +00003061 if( lemp->has_fallback ){
3062 fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
3063 }
drh75897232000-05-29 14:26:00 +00003064 tplt_xfer(lemp->name,in,out,&lineno);
3065
3066 /* Generate the action table.
3067 **
3068 ** Each entry in the action table is an element of the following
3069 ** structure:
3070 ** struct yyActionEntry {
3071 ** YYCODETYPE lookahead;
drhb29b0a52002-02-23 19:39:46 +00003072 ** YYCODETYPE next;
drh75897232000-05-29 14:26:00 +00003073 ** YYACTIONTYPE action;
drh75897232000-05-29 14:26:00 +00003074 ** }
3075 **
3076 ** The entries are grouped into hash tables, one hash table for each
drhb29b0a52002-02-23 19:39:46 +00003077 ** parser state. The hash table has a size which is the number of
3078 ** entries in that table. In case of a collision, the "next" value
3079 ** contains one more than the index into the hash table of the next
3080 ** entry in the collision chain. A "next" value of 0 means the end
3081 ** of the chain has been reached.
drh75897232000-05-29 14:26:00 +00003082 */
3083 tablecnt = 0;
3084
3085 /* Loop over parser states */
3086 for(i=0; i<lemp->nstate; i++){
3087 int tablesize; /* size of the hash table */
3088 int j,k; /* Loop counter */
3089 int collide[2048]; /* The collision chain for the table */
3090 struct action *table[2048]; /* Build the hash table here */
3091
3092 /* Find the number of actions and initialize the hash table */
3093 stp = lemp->sorted[i];
3094 stp->tabstart = tablecnt;
3095 stp->naction = 0;
3096 for(ap=stp->ap; ap; ap=ap->next){
3097 if( ap->sp->index!=lemp->nsymbol && compute_action(lemp,ap)>=0 ){
3098 stp->naction++;
3099 }
3100 }
drhb29b0a52002-02-23 19:39:46 +00003101 tablesize = stp->naction;
drh75897232000-05-29 14:26:00 +00003102 assert( tablesize<= sizeof(table)/sizeof(table[0]) );
3103 for(j=0; j<tablesize; j++){
3104 table[j] = 0;
3105 collide[j] = -1;
3106 }
3107
3108 /* Hash the actions into the hash table */
3109 stp->tabdfltact = lemp->nstate + lemp->nrule;
3110 for(ap=stp->ap; ap; ap=ap->next){
3111 int action = compute_action(lemp,ap);
3112 int h;
3113 if( ap->sp->index==lemp->nsymbol ){
3114 stp->tabdfltact = action;
3115 }else if( action>=0 ){
drhb29b0a52002-02-23 19:39:46 +00003116 h = ap->sp->index % tablesize;
drh75897232000-05-29 14:26:00 +00003117 ap->collide = table[h];
3118 table[h] = ap;
3119 }
3120 }
3121
3122 /* Resolve collisions */
3123 for(j=k=0; j<tablesize; j++){
3124 if( table[j] && table[j]->collide ){
3125 while( table[k] ) k++;
3126 table[k] = table[j]->collide;
3127 collide[j] = k;
3128 table[j]->collide = 0;
3129 if( k<j ) j = k-1;
3130 }
3131 }
3132
3133 /* Print the hash table */
drh1b2e0322002-03-03 02:49:51 +00003134 if( tablesize>0 ){
3135 fprintf(out,"/* State %d */\n",stp->index); lineno++;
3136 }
drh75897232000-05-29 14:26:00 +00003137 for(j=0; j<tablesize; j++){
drhb29b0a52002-02-23 19:39:46 +00003138 assert( table[j]!=0 );
drh1b2e0322002-03-03 02:49:51 +00003139 fprintf(out," {%4d,%4d,%4d}, /* %2d: ",
drh75897232000-05-29 14:26:00 +00003140 table[j]->sp->index,
drhb29b0a52002-02-23 19:39:46 +00003141 collide[j]+1,
drh1b2e0322002-03-03 02:49:51 +00003142 compute_action(lemp,table[j]),
3143 j+1);
drhb29b0a52002-02-23 19:39:46 +00003144 PrintAction(table[j],out,22);
3145 fprintf(out," */\n");
drh75897232000-05-29 14:26:00 +00003146 lineno++;
3147 }
3148
3149 /* Update the table count */
3150 tablecnt += tablesize;
3151 }
3152 tplt_xfer(lemp->name,in,out,&lineno);
3153 lemp->tablesize = tablecnt;
3154
3155 /* Generate the state table
3156 **
3157 ** Each entry is an element of the following structure:
3158 ** struct yyStateEntry {
3159 ** struct yyActionEntry *hashtbl;
drhb29b0a52002-02-23 19:39:46 +00003160 ** YYCODETYPE nEntry;
drh75897232000-05-29 14:26:00 +00003161 ** YYACTIONTYPE actionDefault;
3162 ** }
3163 */
3164 for(i=0; i<lemp->nstate; i++){
drh75897232000-05-29 14:26:00 +00003165 stp = lemp->sorted[i];
drhb29b0a52002-02-23 19:39:46 +00003166 fprintf(out," { &yyActionTable[%d],%4d,%4d },\n",
drh75897232000-05-29 14:26:00 +00003167 stp->tabstart,
drhb29b0a52002-02-23 19:39:46 +00003168 stp->naction,
drh75897232000-05-29 14:26:00 +00003169 stp->tabdfltact); lineno++;
3170 }
3171 tplt_xfer(lemp->name,in,out,&lineno);
3172
drh0bd1f4e2002-06-06 18:54:39 +00003173 /* Generate the table of fallback tokens.
3174 */
3175 if( lemp->has_fallback ){
3176 for(i=0; i<lemp->nterminal; i++){
3177 struct symbol *p = lemp->symbols[i];
3178 if( p->fallback==0 ){
3179 fprintf(out, " 0, /* %10s => nothing */\n", p->name);
3180 }else{
3181 fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index,
3182 p->name, p->fallback->name);
3183 }
3184 lineno++;
3185 }
3186 }
3187 tplt_xfer(lemp->name, in, out, &lineno);
3188
3189 /* Generate a table containing the symbolic name of every symbol
3190 */
drh75897232000-05-29 14:26:00 +00003191 for(i=0; i<lemp->nsymbol; i++){
3192 sprintf(line,"\"%s\",",lemp->symbols[i]->name);
3193 fprintf(out," %-15s",line);
3194 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
3195 }
3196 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
3197 tplt_xfer(lemp->name,in,out,&lineno);
3198
drh0bd1f4e2002-06-06 18:54:39 +00003199 /* Generate a table containing a text string that describes every
3200 ** rule in the rule set of the grammer. This information is used
3201 ** when tracing REDUCE actions.
3202 */
3203 for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
3204 assert( rp->index==i );
3205 fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
3206 for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name);
3207 fprintf(out,"\",\n"); lineno++;
3208 }
3209 tplt_xfer(lemp->name,in,out,&lineno);
3210
drh75897232000-05-29 14:26:00 +00003211 /* Generate code which executes every time a symbol is popped from
3212 ** the stack while processing errors or while destroying the parser.
drh0bd1f4e2002-06-06 18:54:39 +00003213 ** (In other words, generate the %destructor actions)
3214 */
drh75897232000-05-29 14:26:00 +00003215 if( lemp->tokendest ){
3216 for(i=0; i<lemp->nsymbol; i++){
3217 struct symbol *sp = lemp->symbols[i];
3218 if( sp==0 || sp->type!=TERMINAL ) continue;
3219 fprintf(out," case %d:\n",sp->index); lineno++;
3220 }
3221 for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
3222 if( i<lemp->nsymbol ){
3223 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3224 fprintf(out," break;\n"); lineno++;
3225 }
3226 }
3227 for(i=0; i<lemp->nsymbol; i++){
3228 struct symbol *sp = lemp->symbols[i];
3229 if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
3230 fprintf(out," case %d:\n",sp->index); lineno++;
3231 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3232 fprintf(out," break;\n"); lineno++;
3233 }
drh960e8c62001-04-03 16:53:21 +00003234 if( lemp->vardest ){
3235 struct symbol *dflt_sp = 0;
3236 for(i=0; i<lemp->nsymbol; i++){
3237 struct symbol *sp = lemp->symbols[i];
3238 if( sp==0 || sp->type==TERMINAL ||
3239 sp->index<=0 || sp->destructor!=0 ) continue;
3240 fprintf(out," case %d:\n",sp->index); lineno++;
3241 dflt_sp = sp;
3242 }
3243 if( dflt_sp!=0 ){
3244 emit_destructor_code(out,dflt_sp,lemp,&lineno);
3245 fprintf(out," break;\n"); lineno++;
3246 }
3247 }
drh75897232000-05-29 14:26:00 +00003248 tplt_xfer(lemp->name,in,out,&lineno);
3249
3250 /* Generate code which executes whenever the parser stack overflows */
3251 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
3252 tplt_xfer(lemp->name,in,out,&lineno);
3253
3254 /* Generate the table of rule information
3255 **
3256 ** Note: This code depends on the fact that rules are number
3257 ** sequentually beginning with 0.
3258 */
3259 for(rp=lemp->rule; rp; rp=rp->next){
3260 fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
3261 }
3262 tplt_xfer(lemp->name,in,out,&lineno);
3263
3264 /* Generate code which execution during each REDUCE action */
3265 for(rp=lemp->rule; rp; rp=rp->next){
3266 fprintf(out," case %d:\n",rp->index); lineno++;
drh75897232000-05-29 14:26:00 +00003267 emit_code(out,rp,lemp,&lineno);
3268 fprintf(out," break;\n"); lineno++;
3269 }
3270 tplt_xfer(lemp->name,in,out,&lineno);
3271
3272 /* Generate code which executes if a parse fails */
3273 tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);
3274 tplt_xfer(lemp->name,in,out,&lineno);
3275
3276 /* Generate code which executes when a syntax error occurs */
3277 tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno);
3278 tplt_xfer(lemp->name,in,out,&lineno);
3279
3280 /* Generate code which executes when the parser accepts its input */
3281 tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno);
3282 tplt_xfer(lemp->name,in,out,&lineno);
3283
3284 /* Append any addition code the user desires */
3285 tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno);
3286
3287 fclose(in);
3288 fclose(out);
3289 return;
3290}
3291
3292/* Generate a header file for the parser */
3293void ReportHeader(lemp)
3294struct lemon *lemp;
3295{
3296 FILE *out, *in;
3297 char *prefix;
3298 char line[LINESIZE];
3299 char pattern[LINESIZE];
3300 int i;
3301
3302 if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3303 else prefix = "";
3304 in = file_open(lemp,".h","r");
3305 if( in ){
3306 for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
3307 sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3308 if( strcmp(line,pattern) ) break;
3309 }
3310 fclose(in);
3311 if( i==lemp->nterminal ){
3312 /* No change in the file. Don't rewrite it. */
3313 return;
3314 }
3315 }
3316 out = file_open(lemp,".h","w");
3317 if( out ){
3318 for(i=1; i<lemp->nterminal; i++){
3319 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3320 }
3321 fclose(out);
3322 }
3323 return;
3324}
3325
3326/* Reduce the size of the action tables, if possible, by making use
3327** of defaults.
3328**
drhb59499c2002-02-23 18:45:13 +00003329** In this version, we take the most frequent REDUCE action and make
3330** it the default. Only default a reduce if there are more than one.
drh75897232000-05-29 14:26:00 +00003331*/
3332void CompressTables(lemp)
3333struct lemon *lemp;
3334{
3335 struct state *stp;
drhb59499c2002-02-23 18:45:13 +00003336 struct action *ap, *ap2;
3337 struct rule *rp, *rp2, *rbest;
3338 int nbest, n;
drh75897232000-05-29 14:26:00 +00003339 int i;
3340 int cnt;
3341
3342 for(i=0; i<lemp->nstate; i++){
3343 stp = lemp->sorted[i];
drhb59499c2002-02-23 18:45:13 +00003344 nbest = 0;
3345 rbest = 0;
drh75897232000-05-29 14:26:00 +00003346
drhb59499c2002-02-23 18:45:13 +00003347 for(ap=stp->ap; ap; ap=ap->next){
3348 if( ap->type!=REDUCE ) continue;
3349 rp = ap->x.rp;
3350 if( rp==rbest ) continue;
3351 n = 1;
3352 for(ap2=ap->next; ap2; ap2=ap2->next){
3353 if( ap2->type!=REDUCE ) continue;
3354 rp2 = ap2->x.rp;
3355 if( rp2==rbest ) continue;
3356 if( rp2==rp ) n++;
3357 }
3358 if( n>nbest ){
3359 nbest = n;
3360 rbest = rp;
drh75897232000-05-29 14:26:00 +00003361 }
3362 }
drhb59499c2002-02-23 18:45:13 +00003363
3364 /* Do not make a default if the number of rules to default
3365 ** is not at least 2 */
3366 if( nbest<2 ) continue;
drh75897232000-05-29 14:26:00 +00003367
drhb59499c2002-02-23 18:45:13 +00003368
3369 /* Combine matching REDUCE actions into a single default */
3370 for(ap=stp->ap; ap; ap=ap->next){
3371 if( ap->type==REDUCE && ap->x.rp==rbest ) break;
3372 }
drh75897232000-05-29 14:26:00 +00003373 assert( ap );
3374 ap->sp = Symbol_new("{default}");
3375 for(ap=ap->next; ap; ap=ap->next){
drhb59499c2002-02-23 18:45:13 +00003376 if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
drh75897232000-05-29 14:26:00 +00003377 }
3378 stp->ap = Action_sort(stp->ap);
3379 }
3380}
drhb59499c2002-02-23 18:45:13 +00003381
drh75897232000-05-29 14:26:00 +00003382/***************** From the file "set.c" ************************************/
3383/*
3384** Set manipulation routines for the LEMON parser generator.
3385*/
3386
3387static int size = 0;
3388
3389/* Set the set size */
3390void SetSize(n)
3391int n;
3392{
3393 size = n+1;
3394}
3395
3396/* Allocate a new set */
3397char *SetNew(){
3398 char *s;
3399 int i;
3400 s = (char*)malloc( size );
3401 if( s==0 ){
3402 extern void memory_error();
3403 memory_error();
3404 }
3405 for(i=0; i<size; i++) s[i] = 0;
3406 return s;
3407}
3408
3409/* Deallocate a set */
3410void SetFree(s)
3411char *s;
3412{
3413 free(s);
3414}
3415
3416/* Add a new element to the set. Return TRUE if the element was added
3417** and FALSE if it was already there. */
3418int SetAdd(s,e)
3419char *s;
3420int e;
3421{
3422 int rv;
3423 rv = s[e];
3424 s[e] = 1;
3425 return !rv;
3426}
3427
3428/* Add every element of s2 to s1. Return TRUE if s1 changes. */
3429int SetUnion(s1,s2)
3430char *s1;
3431char *s2;
3432{
3433 int i, progress;
3434 progress = 0;
3435 for(i=0; i<size; i++){
3436 if( s2[i]==0 ) continue;
3437 if( s1[i]==0 ){
3438 progress = 1;
3439 s1[i] = 1;
3440 }
3441 }
3442 return progress;
3443}
3444/********************** From the file "table.c" ****************************/
3445/*
3446** All code in this file has been automatically generated
3447** from a specification in the file
3448** "table.q"
3449** by the associative array code building program "aagen".
3450** Do not edit this file! Instead, edit the specification
3451** file, then rerun aagen.
3452*/
3453/*
3454** Code for processing tables in the LEMON parser generator.
3455*/
3456
3457PRIVATE int strhash(x)
3458char *x;
3459{
3460 int h = 0;
3461 while( *x) h = h*13 + *(x++);
3462 return h;
3463}
3464
3465/* Works like strdup, sort of. Save a string in malloced memory, but
3466** keep strings in a table so that the same string is not in more
3467** than one place.
3468*/
3469char *Strsafe(y)
3470char *y;
3471{
3472 char *z;
3473
3474 z = Strsafe_find(y);
3475 if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
3476 strcpy(z,y);
3477 Strsafe_insert(z);
3478 }
3479 MemoryCheck(z);
3480 return z;
3481}
3482
3483/* There is one instance of the following structure for each
3484** associative array of type "x1".
3485*/
3486struct s_x1 {
3487 int size; /* The number of available slots. */
3488 /* Must be a power of 2 greater than or */
3489 /* equal to 1 */
3490 int count; /* Number of currently slots filled */
3491 struct s_x1node *tbl; /* The data stored here */
3492 struct s_x1node **ht; /* Hash table for lookups */
3493};
3494
3495/* There is one instance of this structure for every data element
3496** in an associative array of type "x1".
3497*/
3498typedef struct s_x1node {
3499 char *data; /* The data */
3500 struct s_x1node *next; /* Next entry with the same hash */
3501 struct s_x1node **from; /* Previous link */
3502} x1node;
3503
3504/* There is only one instance of the array, which is the following */
3505static struct s_x1 *x1a;
3506
3507/* Allocate a new associative array */
3508void Strsafe_init(){
3509 if( x1a ) return;
3510 x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
3511 if( x1a ){
3512 x1a->size = 1024;
3513 x1a->count = 0;
3514 x1a->tbl = (x1node*)malloc(
3515 (sizeof(x1node) + sizeof(x1node*))*1024 );
3516 if( x1a->tbl==0 ){
3517 free(x1a);
3518 x1a = 0;
3519 }else{
3520 int i;
3521 x1a->ht = (x1node**)&(x1a->tbl[1024]);
3522 for(i=0; i<1024; i++) x1a->ht[i] = 0;
3523 }
3524 }
3525}
3526/* Insert a new record into the array. Return TRUE if successful.
3527** Prior data with the same key is NOT overwritten */
3528int Strsafe_insert(data)
3529char *data;
3530{
3531 x1node *np;
3532 int h;
3533 int ph;
3534
3535 if( x1a==0 ) return 0;
3536 ph = strhash(data);
3537 h = ph & (x1a->size-1);
3538 np = x1a->ht[h];
3539 while( np ){
3540 if( strcmp(np->data,data)==0 ){
3541 /* An existing entry with the same key is found. */
3542 /* Fail because overwrite is not allows. */
3543 return 0;
3544 }
3545 np = np->next;
3546 }
3547 if( x1a->count>=x1a->size ){
3548 /* Need to make the hash table bigger */
3549 int i,size;
3550 struct s_x1 array;
3551 array.size = size = x1a->size*2;
3552 array.count = x1a->count;
3553 array.tbl = (x1node*)malloc(
3554 (sizeof(x1node) + sizeof(x1node*))*size );
3555 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3556 array.ht = (x1node**)&(array.tbl[size]);
3557 for(i=0; i<size; i++) array.ht[i] = 0;
3558 for(i=0; i<x1a->count; i++){
3559 x1node *oldnp, *newnp;
3560 oldnp = &(x1a->tbl[i]);
3561 h = strhash(oldnp->data) & (size-1);
3562 newnp = &(array.tbl[i]);
3563 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3564 newnp->next = array.ht[h];
3565 newnp->data = oldnp->data;
3566 newnp->from = &(array.ht[h]);
3567 array.ht[h] = newnp;
3568 }
3569 free(x1a->tbl);
3570 *x1a = array;
3571 }
3572 /* Insert the new data */
3573 h = ph & (x1a->size-1);
3574 np = &(x1a->tbl[x1a->count++]);
3575 np->data = data;
3576 if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
3577 np->next = x1a->ht[h];
3578 x1a->ht[h] = np;
3579 np->from = &(x1a->ht[h]);
3580 return 1;
3581}
3582
3583/* Return a pointer to data assigned to the given key. Return NULL
3584** if no such key. */
3585char *Strsafe_find(key)
3586char *key;
3587{
3588 int h;
3589 x1node *np;
3590
3591 if( x1a==0 ) return 0;
3592 h = strhash(key) & (x1a->size-1);
3593 np = x1a->ht[h];
3594 while( np ){
3595 if( strcmp(np->data,key)==0 ) break;
3596 np = np->next;
3597 }
3598 return np ? np->data : 0;
3599}
3600
3601/* Return a pointer to the (terminal or nonterminal) symbol "x".
3602** Create a new symbol if this is the first time "x" has been seen.
3603*/
3604struct symbol *Symbol_new(x)
3605char *x;
3606{
3607 struct symbol *sp;
3608
3609 sp = Symbol_find(x);
3610 if( sp==0 ){
3611 sp = (struct symbol *)malloc( sizeof(struct symbol) );
3612 MemoryCheck(sp);
3613 sp->name = Strsafe(x);
3614 sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
3615 sp->rule = 0;
drh0bd1f4e2002-06-06 18:54:39 +00003616 sp->fallback = 0;
drh75897232000-05-29 14:26:00 +00003617 sp->prec = -1;
3618 sp->assoc = UNK;
3619 sp->firstset = 0;
drhb27b83a2002-08-14 23:18:57 +00003620 sp->lambda = B_FALSE;
drh75897232000-05-29 14:26:00 +00003621 sp->destructor = 0;
3622 sp->datatype = 0;
3623 Symbol_insert(sp,sp->name);
3624 }
3625 return sp;
3626}
3627
3628/* Compare two symbols */
3629int Symbolcmpp(a,b)
3630struct symbol **a;
3631struct symbol **b;
3632{
3633 return strcmp((**a).name,(**b).name);
3634}
3635
3636/* There is one instance of the following structure for each
3637** associative array of type "x2".
3638*/
3639struct s_x2 {
3640 int size; /* The number of available slots. */
3641 /* Must be a power of 2 greater than or */
3642 /* equal to 1 */
3643 int count; /* Number of currently slots filled */
3644 struct s_x2node *tbl; /* The data stored here */
3645 struct s_x2node **ht; /* Hash table for lookups */
3646};
3647
3648/* There is one instance of this structure for every data element
3649** in an associative array of type "x2".
3650*/
3651typedef struct s_x2node {
3652 struct symbol *data; /* The data */
3653 char *key; /* The key */
3654 struct s_x2node *next; /* Next entry with the same hash */
3655 struct s_x2node **from; /* Previous link */
3656} x2node;
3657
3658/* There is only one instance of the array, which is the following */
3659static struct s_x2 *x2a;
3660
3661/* Allocate a new associative array */
3662void Symbol_init(){
3663 if( x2a ) return;
3664 x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
3665 if( x2a ){
3666 x2a->size = 128;
3667 x2a->count = 0;
3668 x2a->tbl = (x2node*)malloc(
3669 (sizeof(x2node) + sizeof(x2node*))*128 );
3670 if( x2a->tbl==0 ){
3671 free(x2a);
3672 x2a = 0;
3673 }else{
3674 int i;
3675 x2a->ht = (x2node**)&(x2a->tbl[128]);
3676 for(i=0; i<128; i++) x2a->ht[i] = 0;
3677 }
3678 }
3679}
3680/* Insert a new record into the array. Return TRUE if successful.
3681** Prior data with the same key is NOT overwritten */
3682int Symbol_insert(data,key)
3683struct symbol *data;
3684char *key;
3685{
3686 x2node *np;
3687 int h;
3688 int ph;
3689
3690 if( x2a==0 ) return 0;
3691 ph = strhash(key);
3692 h = ph & (x2a->size-1);
3693 np = x2a->ht[h];
3694 while( np ){
3695 if( strcmp(np->key,key)==0 ){
3696 /* An existing entry with the same key is found. */
3697 /* Fail because overwrite is not allows. */
3698 return 0;
3699 }
3700 np = np->next;
3701 }
3702 if( x2a->count>=x2a->size ){
3703 /* Need to make the hash table bigger */
3704 int i,size;
3705 struct s_x2 array;
3706 array.size = size = x2a->size*2;
3707 array.count = x2a->count;
3708 array.tbl = (x2node*)malloc(
3709 (sizeof(x2node) + sizeof(x2node*))*size );
3710 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3711 array.ht = (x2node**)&(array.tbl[size]);
3712 for(i=0; i<size; i++) array.ht[i] = 0;
3713 for(i=0; i<x2a->count; i++){
3714 x2node *oldnp, *newnp;
3715 oldnp = &(x2a->tbl[i]);
3716 h = strhash(oldnp->key) & (size-1);
3717 newnp = &(array.tbl[i]);
3718 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3719 newnp->next = array.ht[h];
3720 newnp->key = oldnp->key;
3721 newnp->data = oldnp->data;
3722 newnp->from = &(array.ht[h]);
3723 array.ht[h] = newnp;
3724 }
3725 free(x2a->tbl);
3726 *x2a = array;
3727 }
3728 /* Insert the new data */
3729 h = ph & (x2a->size-1);
3730 np = &(x2a->tbl[x2a->count++]);
3731 np->key = key;
3732 np->data = data;
3733 if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
3734 np->next = x2a->ht[h];
3735 x2a->ht[h] = np;
3736 np->from = &(x2a->ht[h]);
3737 return 1;
3738}
3739
3740/* Return a pointer to data assigned to the given key. Return NULL
3741** if no such key. */
3742struct symbol *Symbol_find(key)
3743char *key;
3744{
3745 int h;
3746 x2node *np;
3747
3748 if( x2a==0 ) return 0;
3749 h = strhash(key) & (x2a->size-1);
3750 np = x2a->ht[h];
3751 while( np ){
3752 if( strcmp(np->key,key)==0 ) break;
3753 np = np->next;
3754 }
3755 return np ? np->data : 0;
3756}
3757
3758/* Return the n-th data. Return NULL if n is out of range. */
3759struct symbol *Symbol_Nth(n)
3760int n;
3761{
3762 struct symbol *data;
3763 if( x2a && n>0 && n<=x2a->count ){
3764 data = x2a->tbl[n-1].data;
3765 }else{
3766 data = 0;
3767 }
3768 return data;
3769}
3770
3771/* Return the size of the array */
3772int Symbol_count()
3773{
3774 return x2a ? x2a->count : 0;
3775}
3776
3777/* Return an array of pointers to all data in the table.
3778** The array is obtained from malloc. Return NULL if memory allocation
3779** problems, or if the array is empty. */
3780struct symbol **Symbol_arrayof()
3781{
3782 struct symbol **array;
3783 int i,size;
3784 if( x2a==0 ) return 0;
3785 size = x2a->count;
3786 array = (struct symbol **)malloc( sizeof(struct symbol *)*size );
3787 if( array ){
3788 for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
3789 }
3790 return array;
3791}
3792
3793/* Compare two configurations */
3794int Configcmp(a,b)
3795struct config *a;
3796struct config *b;
3797{
3798 int x;
3799 x = a->rp->index - b->rp->index;
3800 if( x==0 ) x = a->dot - b->dot;
3801 return x;
3802}
3803
3804/* Compare two states */
3805PRIVATE int statecmp(a,b)
3806struct config *a;
3807struct config *b;
3808{
3809 int rc;
3810 for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
3811 rc = a->rp->index - b->rp->index;
3812 if( rc==0 ) rc = a->dot - b->dot;
3813 }
3814 if( rc==0 ){
3815 if( a ) rc = 1;
3816 if( b ) rc = -1;
3817 }
3818 return rc;
3819}
3820
3821/* Hash a state */
3822PRIVATE int statehash(a)
3823struct config *a;
3824{
3825 int h=0;
3826 while( a ){
3827 h = h*571 + a->rp->index*37 + a->dot;
3828 a = a->bp;
3829 }
3830 return h;
3831}
3832
3833/* Allocate a new state structure */
3834struct state *State_new()
3835{
3836 struct state *new;
3837 new = (struct state *)malloc( sizeof(struct state) );
3838 MemoryCheck(new);
3839 return new;
3840}
3841
3842/* There is one instance of the following structure for each
3843** associative array of type "x3".
3844*/
3845struct s_x3 {
3846 int size; /* The number of available slots. */
3847 /* Must be a power of 2 greater than or */
3848 /* equal to 1 */
3849 int count; /* Number of currently slots filled */
3850 struct s_x3node *tbl; /* The data stored here */
3851 struct s_x3node **ht; /* Hash table for lookups */
3852};
3853
3854/* There is one instance of this structure for every data element
3855** in an associative array of type "x3".
3856*/
3857typedef struct s_x3node {
3858 struct state *data; /* The data */
3859 struct config *key; /* The key */
3860 struct s_x3node *next; /* Next entry with the same hash */
3861 struct s_x3node **from; /* Previous link */
3862} x3node;
3863
3864/* There is only one instance of the array, which is the following */
3865static struct s_x3 *x3a;
3866
3867/* Allocate a new associative array */
3868void State_init(){
3869 if( x3a ) return;
3870 x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
3871 if( x3a ){
3872 x3a->size = 128;
3873 x3a->count = 0;
3874 x3a->tbl = (x3node*)malloc(
3875 (sizeof(x3node) + sizeof(x3node*))*128 );
3876 if( x3a->tbl==0 ){
3877 free(x3a);
3878 x3a = 0;
3879 }else{
3880 int i;
3881 x3a->ht = (x3node**)&(x3a->tbl[128]);
3882 for(i=0; i<128; i++) x3a->ht[i] = 0;
3883 }
3884 }
3885}
3886/* Insert a new record into the array. Return TRUE if successful.
3887** Prior data with the same key is NOT overwritten */
3888int State_insert(data,key)
3889struct state *data;
3890struct config *key;
3891{
3892 x3node *np;
3893 int h;
3894 int ph;
3895
3896 if( x3a==0 ) return 0;
3897 ph = statehash(key);
3898 h = ph & (x3a->size-1);
3899 np = x3a->ht[h];
3900 while( np ){
3901 if( statecmp(np->key,key)==0 ){
3902 /* An existing entry with the same key is found. */
3903 /* Fail because overwrite is not allows. */
3904 return 0;
3905 }
3906 np = np->next;
3907 }
3908 if( x3a->count>=x3a->size ){
3909 /* Need to make the hash table bigger */
3910 int i,size;
3911 struct s_x3 array;
3912 array.size = size = x3a->size*2;
3913 array.count = x3a->count;
3914 array.tbl = (x3node*)malloc(
3915 (sizeof(x3node) + sizeof(x3node*))*size );
3916 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3917 array.ht = (x3node**)&(array.tbl[size]);
3918 for(i=0; i<size; i++) array.ht[i] = 0;
3919 for(i=0; i<x3a->count; i++){
3920 x3node *oldnp, *newnp;
3921 oldnp = &(x3a->tbl[i]);
3922 h = statehash(oldnp->key) & (size-1);
3923 newnp = &(array.tbl[i]);
3924 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3925 newnp->next = array.ht[h];
3926 newnp->key = oldnp->key;
3927 newnp->data = oldnp->data;
3928 newnp->from = &(array.ht[h]);
3929 array.ht[h] = newnp;
3930 }
3931 free(x3a->tbl);
3932 *x3a = array;
3933 }
3934 /* Insert the new data */
3935 h = ph & (x3a->size-1);
3936 np = &(x3a->tbl[x3a->count++]);
3937 np->key = key;
3938 np->data = data;
3939 if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
3940 np->next = x3a->ht[h];
3941 x3a->ht[h] = np;
3942 np->from = &(x3a->ht[h]);
3943 return 1;
3944}
3945
3946/* Return a pointer to data assigned to the given key. Return NULL
3947** if no such key. */
3948struct state *State_find(key)
3949struct config *key;
3950{
3951 int h;
3952 x3node *np;
3953
3954 if( x3a==0 ) return 0;
3955 h = statehash(key) & (x3a->size-1);
3956 np = x3a->ht[h];
3957 while( np ){
3958 if( statecmp(np->key,key)==0 ) break;
3959 np = np->next;
3960 }
3961 return np ? np->data : 0;
3962}
3963
3964/* Return an array of pointers to all data in the table.
3965** The array is obtained from malloc. Return NULL if memory allocation
3966** problems, or if the array is empty. */
3967struct state **State_arrayof()
3968{
3969 struct state **array;
3970 int i,size;
3971 if( x3a==0 ) return 0;
3972 size = x3a->count;
3973 array = (struct state **)malloc( sizeof(struct state *)*size );
3974 if( array ){
3975 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
3976 }
3977 return array;
3978}
3979
3980/* Hash a configuration */
3981PRIVATE int confighash(a)
3982struct config *a;
3983{
3984 int h=0;
3985 h = h*571 + a->rp->index*37 + a->dot;
3986 return h;
3987}
3988
3989/* There is one instance of the following structure for each
3990** associative array of type "x4".
3991*/
3992struct s_x4 {
3993 int size; /* The number of available slots. */
3994 /* Must be a power of 2 greater than or */
3995 /* equal to 1 */
3996 int count; /* Number of currently slots filled */
3997 struct s_x4node *tbl; /* The data stored here */
3998 struct s_x4node **ht; /* Hash table for lookups */
3999};
4000
4001/* There is one instance of this structure for every data element
4002** in an associative array of type "x4".
4003*/
4004typedef struct s_x4node {
4005 struct config *data; /* The data */
4006 struct s_x4node *next; /* Next entry with the same hash */
4007 struct s_x4node **from; /* Previous link */
4008} x4node;
4009
4010/* There is only one instance of the array, which is the following */
4011static struct s_x4 *x4a;
4012
4013/* Allocate a new associative array */
4014void Configtable_init(){
4015 if( x4a ) return;
4016 x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
4017 if( x4a ){
4018 x4a->size = 64;
4019 x4a->count = 0;
4020 x4a->tbl = (x4node*)malloc(
4021 (sizeof(x4node) + sizeof(x4node*))*64 );
4022 if( x4a->tbl==0 ){
4023 free(x4a);
4024 x4a = 0;
4025 }else{
4026 int i;
4027 x4a->ht = (x4node**)&(x4a->tbl[64]);
4028 for(i=0; i<64; i++) x4a->ht[i] = 0;
4029 }
4030 }
4031}
4032/* Insert a new record into the array. Return TRUE if successful.
4033** Prior data with the same key is NOT overwritten */
4034int Configtable_insert(data)
4035struct config *data;
4036{
4037 x4node *np;
4038 int h;
4039 int ph;
4040
4041 if( x4a==0 ) return 0;
4042 ph = confighash(data);
4043 h = ph & (x4a->size-1);
4044 np = x4a->ht[h];
4045 while( np ){
4046 if( Configcmp(np->data,data)==0 ){
4047 /* An existing entry with the same key is found. */
4048 /* Fail because overwrite is not allows. */
4049 return 0;
4050 }
4051 np = np->next;
4052 }
4053 if( x4a->count>=x4a->size ){
4054 /* Need to make the hash table bigger */
4055 int i,size;
4056 struct s_x4 array;
4057 array.size = size = x4a->size*2;
4058 array.count = x4a->count;
4059 array.tbl = (x4node*)malloc(
4060 (sizeof(x4node) + sizeof(x4node*))*size );
4061 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
4062 array.ht = (x4node**)&(array.tbl[size]);
4063 for(i=0; i<size; i++) array.ht[i] = 0;
4064 for(i=0; i<x4a->count; i++){
4065 x4node *oldnp, *newnp;
4066 oldnp = &(x4a->tbl[i]);
4067 h = confighash(oldnp->data) & (size-1);
4068 newnp = &(array.tbl[i]);
4069 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4070 newnp->next = array.ht[h];
4071 newnp->data = oldnp->data;
4072 newnp->from = &(array.ht[h]);
4073 array.ht[h] = newnp;
4074 }
4075 free(x4a->tbl);
4076 *x4a = array;
4077 }
4078 /* Insert the new data */
4079 h = ph & (x4a->size-1);
4080 np = &(x4a->tbl[x4a->count++]);
4081 np->data = data;
4082 if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
4083 np->next = x4a->ht[h];
4084 x4a->ht[h] = np;
4085 np->from = &(x4a->ht[h]);
4086 return 1;
4087}
4088
4089/* Return a pointer to data assigned to the given key. Return NULL
4090** if no such key. */
4091struct config *Configtable_find(key)
4092struct config *key;
4093{
4094 int h;
4095 x4node *np;
4096
4097 if( x4a==0 ) return 0;
4098 h = confighash(key) & (x4a->size-1);
4099 np = x4a->ht[h];
4100 while( np ){
4101 if( Configcmp(np->data,key)==0 ) break;
4102 np = np->next;
4103 }
4104 return np ? np->data : 0;
4105}
4106
4107/* Remove all data from the table. Pass each data to the function "f"
4108** as it is removed. ("f" may be null to avoid this step.) */
4109void Configtable_clear(f)
4110int(*f)(/* struct config * */);
4111{
4112 int i;
4113 if( x4a==0 || x4a->count==0 ) return;
4114 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
4115 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
4116 x4a->count = 0;
4117 return;
4118}