blob: b801e6b39e9d02a65135962c0dfde2793971b11c [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 }
drh3b2129c2003-05-13 00:34:21 +00002909 hash = (hash & 0x7fffffff)%arraysize;
drh75897232000-05-29 14:26:00 +00002910 while( types[hash] ){
2911 if( strcmp(types[hash],stddt)==0 ){
2912 sp->dtnum = hash + 1;
2913 break;
2914 }
2915 hash++;
2916 if( hash>=arraysize ) hash = 0;
2917 }
2918 if( types[hash]==0 ){
2919 sp->dtnum = hash + 1;
2920 types[hash] = (char*)malloc( strlen(stddt)+1 );
2921 if( types[hash]==0 ){
2922 fprintf(stderr,"Out of memory.\n");
2923 exit(1);
2924 }
2925 strcpy(types[hash],stddt);
2926 }
2927 }
2928
2929 /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
2930 name = lemp->name ? lemp->name : "Parse";
2931 lineno = *plineno;
2932 if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
2933 fprintf(out,"#define %sTOKENTYPE %s\n",name,
2934 lemp->tokentype?lemp->tokentype:"void*"); lineno++;
2935 if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
2936 fprintf(out,"typedef union {\n"); lineno++;
2937 fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++;
2938 for(i=0; i<arraysize; i++){
2939 if( types[i]==0 ) continue;
2940 fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
2941 free(types[i]);
2942 }
2943 fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
2944 free(stddt);
2945 free(types);
2946 fprintf(out,"} YYMINORTYPE;\n"); lineno++;
2947 *plineno = lineno;
2948}
2949
drhb29b0a52002-02-23 19:39:46 +00002950/*
2951** Return the name of a C datatype able to represent values between
2952** 0 and N, inclusive.
2953*/
2954static const char *minimum_size_type(int N){
2955 if( N<=255 ){
2956 return "unsigned char";
2957 }else if( N<65535 ){
2958 return "unsigned short int";
2959 }else{
2960 return "unsigned int";
2961 }
2962}
2963
drh75897232000-05-29 14:26:00 +00002964/* Generate C source code for the parser */
2965void ReportTable(lemp, mhflag)
2966struct lemon *lemp;
2967int mhflag; /* Output in makeheaders format if true */
2968{
2969 FILE *out, *in;
2970 char line[LINESIZE];
2971 int lineno;
2972 struct state *stp;
2973 struct action *ap;
2974 struct rule *rp;
drh0bd1f4e2002-06-06 18:54:39 +00002975 int i, j;
drh75897232000-05-29 14:26:00 +00002976 int tablecnt;
2977 char *name;
2978
2979 in = tplt_open(lemp);
2980 if( in==0 ) return;
2981 out = file_open(lemp,".c","w");
2982 if( out==0 ){
2983 fclose(in);
2984 return;
2985 }
2986 lineno = 1;
2987 tplt_xfer(lemp->name,in,out,&lineno);
2988
2989 /* Generate the include code, if any */
2990 tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno);
2991 if( mhflag ){
2992 char *name = file_makename(lemp, ".h");
2993 fprintf(out,"#include \"%s\"\n", name); lineno++;
2994 free(name);
2995 }
2996 tplt_xfer(lemp->name,in,out,&lineno);
2997
2998 /* Generate #defines for all tokens */
2999 if( mhflag ){
3000 char *prefix;
3001 fprintf(out,"#if INTERFACE\n"); lineno++;
3002 if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3003 else prefix = "";
3004 for(i=1; i<lemp->nterminal; i++){
3005 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3006 lineno++;
3007 }
3008 fprintf(out,"#endif\n"); lineno++;
3009 }
3010 tplt_xfer(lemp->name,in,out,&lineno);
3011
3012 /* Generate the defines */
3013 fprintf(out,"/* \001 */\n");
3014 fprintf(out,"#define YYCODETYPE %s\n",
drhb29b0a52002-02-23 19:39:46 +00003015 minimum_size_type(lemp->nsymbol+5)); lineno++;
drh75897232000-05-29 14:26:00 +00003016 fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
3017 fprintf(out,"#define YYACTIONTYPE %s\n",
drhb29b0a52002-02-23 19:39:46 +00003018 minimum_size_type(lemp->nstate+lemp->nrule+5)); lineno++;
drh75897232000-05-29 14:26:00 +00003019 print_stack_union(out,lemp,&lineno,mhflag);
3020 if( lemp->stacksize ){
3021 if( atoi(lemp->stacksize)<=0 ){
3022 ErrorMsg(lemp->filename,0,
3023"Illegal stack size: [%s]. The stack size should be an integer constant.",
3024 lemp->stacksize);
3025 lemp->errorcnt++;
3026 lemp->stacksize = "100";
3027 }
3028 fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++;
3029 }else{
3030 fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++;
3031 }
3032 if( mhflag ){
3033 fprintf(out,"#if INTERFACE\n"); lineno++;
3034 }
3035 name = lemp->name ? lemp->name : "Parse";
3036 if( lemp->arg && lemp->arg[0] ){
3037 int i;
3038 i = strlen(lemp->arg);
drhb1edd012000-06-02 18:52:12 +00003039 while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
3040 while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
drh1f245e42002-03-11 13:55:50 +00003041 fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
3042 fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
3043 fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
3044 name,lemp->arg,&lemp->arg[i]); lineno++;
3045 fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
3046 name,&lemp->arg[i],&lemp->arg[i]); lineno++;
drh75897232000-05-29 14:26:00 +00003047 }else{
drh1f245e42002-03-11 13:55:50 +00003048 fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
3049 fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
3050 fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
3051 fprintf(out,"#define %sARG_STORE\n",name); lineno++;
drh75897232000-05-29 14:26:00 +00003052 }
3053 if( mhflag ){
3054 fprintf(out,"#endif\n"); lineno++;
3055 }
3056 fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++;
3057 fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
3058 fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
3059 fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
drh0bd1f4e2002-06-06 18:54:39 +00003060 if( lemp->has_fallback ){
3061 fprintf(out,"#define YYFALLBACK 1\n"); lineno++;
3062 }
drh75897232000-05-29 14:26:00 +00003063 tplt_xfer(lemp->name,in,out,&lineno);
3064
3065 /* Generate the action table.
3066 **
3067 ** Each entry in the action table is an element of the following
3068 ** structure:
3069 ** struct yyActionEntry {
3070 ** YYCODETYPE lookahead;
drhb29b0a52002-02-23 19:39:46 +00003071 ** YYCODETYPE next;
drh75897232000-05-29 14:26:00 +00003072 ** YYACTIONTYPE action;
drh75897232000-05-29 14:26:00 +00003073 ** }
3074 **
3075 ** The entries are grouped into hash tables, one hash table for each
drhb29b0a52002-02-23 19:39:46 +00003076 ** parser state. The hash table has a size which is the number of
3077 ** entries in that table. In case of a collision, the "next" value
3078 ** contains one more than the index into the hash table of the next
3079 ** entry in the collision chain. A "next" value of 0 means the end
3080 ** of the chain has been reached.
drh75897232000-05-29 14:26:00 +00003081 */
3082 tablecnt = 0;
3083
3084 /* Loop over parser states */
3085 for(i=0; i<lemp->nstate; i++){
3086 int tablesize; /* size of the hash table */
3087 int j,k; /* Loop counter */
3088 int collide[2048]; /* The collision chain for the table */
3089 struct action *table[2048]; /* Build the hash table here */
3090
3091 /* Find the number of actions and initialize the hash table */
3092 stp = lemp->sorted[i];
3093 stp->tabstart = tablecnt;
3094 stp->naction = 0;
3095 for(ap=stp->ap; ap; ap=ap->next){
3096 if( ap->sp->index!=lemp->nsymbol && compute_action(lemp,ap)>=0 ){
3097 stp->naction++;
3098 }
3099 }
drhb29b0a52002-02-23 19:39:46 +00003100 tablesize = stp->naction;
drh75897232000-05-29 14:26:00 +00003101 assert( tablesize<= sizeof(table)/sizeof(table[0]) );
3102 for(j=0; j<tablesize; j++){
3103 table[j] = 0;
3104 collide[j] = -1;
3105 }
3106
3107 /* Hash the actions into the hash table */
3108 stp->tabdfltact = lemp->nstate + lemp->nrule;
3109 for(ap=stp->ap; ap; ap=ap->next){
3110 int action = compute_action(lemp,ap);
3111 int h;
3112 if( ap->sp->index==lemp->nsymbol ){
3113 stp->tabdfltact = action;
3114 }else if( action>=0 ){
drhb29b0a52002-02-23 19:39:46 +00003115 h = ap->sp->index % tablesize;
drh75897232000-05-29 14:26:00 +00003116 ap->collide = table[h];
3117 table[h] = ap;
3118 }
3119 }
3120
3121 /* Resolve collisions */
3122 for(j=k=0; j<tablesize; j++){
3123 if( table[j] && table[j]->collide ){
3124 while( table[k] ) k++;
3125 table[k] = table[j]->collide;
3126 collide[j] = k;
3127 table[j]->collide = 0;
3128 if( k<j ) j = k-1;
3129 }
3130 }
3131
3132 /* Print the hash table */
drh1b2e0322002-03-03 02:49:51 +00003133 if( tablesize>0 ){
3134 fprintf(out,"/* State %d */\n",stp->index); lineno++;
3135 }
drh75897232000-05-29 14:26:00 +00003136 for(j=0; j<tablesize; j++){
drhb29b0a52002-02-23 19:39:46 +00003137 assert( table[j]!=0 );
drh1b2e0322002-03-03 02:49:51 +00003138 fprintf(out," {%4d,%4d,%4d}, /* %2d: ",
drh75897232000-05-29 14:26:00 +00003139 table[j]->sp->index,
drhb29b0a52002-02-23 19:39:46 +00003140 collide[j]+1,
drh1b2e0322002-03-03 02:49:51 +00003141 compute_action(lemp,table[j]),
3142 j+1);
drhb29b0a52002-02-23 19:39:46 +00003143 PrintAction(table[j],out,22);
3144 fprintf(out," */\n");
drh75897232000-05-29 14:26:00 +00003145 lineno++;
3146 }
3147
3148 /* Update the table count */
3149 tablecnt += tablesize;
3150 }
3151 tplt_xfer(lemp->name,in,out,&lineno);
3152 lemp->tablesize = tablecnt;
3153
3154 /* Generate the state table
3155 **
3156 ** Each entry is an element of the following structure:
3157 ** struct yyStateEntry {
3158 ** struct yyActionEntry *hashtbl;
drhb29b0a52002-02-23 19:39:46 +00003159 ** YYCODETYPE nEntry;
drh75897232000-05-29 14:26:00 +00003160 ** YYACTIONTYPE actionDefault;
3161 ** }
3162 */
3163 for(i=0; i<lemp->nstate; i++){
drh75897232000-05-29 14:26:00 +00003164 stp = lemp->sorted[i];
drhb29b0a52002-02-23 19:39:46 +00003165 fprintf(out," { &yyActionTable[%d],%4d,%4d },\n",
drh75897232000-05-29 14:26:00 +00003166 stp->tabstart,
drhb29b0a52002-02-23 19:39:46 +00003167 stp->naction,
drh75897232000-05-29 14:26:00 +00003168 stp->tabdfltact); lineno++;
3169 }
3170 tplt_xfer(lemp->name,in,out,&lineno);
3171
drh0bd1f4e2002-06-06 18:54:39 +00003172 /* Generate the table of fallback tokens.
3173 */
3174 if( lemp->has_fallback ){
3175 for(i=0; i<lemp->nterminal; i++){
3176 struct symbol *p = lemp->symbols[i];
3177 if( p->fallback==0 ){
3178 fprintf(out, " 0, /* %10s => nothing */\n", p->name);
3179 }else{
3180 fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index,
3181 p->name, p->fallback->name);
3182 }
3183 lineno++;
3184 }
3185 }
3186 tplt_xfer(lemp->name, in, out, &lineno);
3187
3188 /* Generate a table containing the symbolic name of every symbol
3189 */
drh75897232000-05-29 14:26:00 +00003190 for(i=0; i<lemp->nsymbol; i++){
3191 sprintf(line,"\"%s\",",lemp->symbols[i]->name);
3192 fprintf(out," %-15s",line);
3193 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
3194 }
3195 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
3196 tplt_xfer(lemp->name,in,out,&lineno);
3197
drh0bd1f4e2002-06-06 18:54:39 +00003198 /* Generate a table containing a text string that describes every
3199 ** rule in the rule set of the grammer. This information is used
3200 ** when tracing REDUCE actions.
3201 */
3202 for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
3203 assert( rp->index==i );
3204 fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
3205 for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name);
3206 fprintf(out,"\",\n"); lineno++;
3207 }
3208 tplt_xfer(lemp->name,in,out,&lineno);
3209
drh75897232000-05-29 14:26:00 +00003210 /* Generate code which executes every time a symbol is popped from
3211 ** the stack while processing errors or while destroying the parser.
drh0bd1f4e2002-06-06 18:54:39 +00003212 ** (In other words, generate the %destructor actions)
3213 */
drh75897232000-05-29 14:26:00 +00003214 if( lemp->tokendest ){
3215 for(i=0; i<lemp->nsymbol; i++){
3216 struct symbol *sp = lemp->symbols[i];
3217 if( sp==0 || sp->type!=TERMINAL ) continue;
3218 fprintf(out," case %d:\n",sp->index); lineno++;
3219 }
3220 for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
3221 if( i<lemp->nsymbol ){
3222 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3223 fprintf(out," break;\n"); lineno++;
3224 }
3225 }
3226 for(i=0; i<lemp->nsymbol; i++){
3227 struct symbol *sp = lemp->symbols[i];
3228 if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
3229 fprintf(out," case %d:\n",sp->index); lineno++;
3230 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
3231 fprintf(out," break;\n"); lineno++;
3232 }
drh960e8c62001-04-03 16:53:21 +00003233 if( lemp->vardest ){
3234 struct symbol *dflt_sp = 0;
3235 for(i=0; i<lemp->nsymbol; i++){
3236 struct symbol *sp = lemp->symbols[i];
3237 if( sp==0 || sp->type==TERMINAL ||
3238 sp->index<=0 || sp->destructor!=0 ) continue;
3239 fprintf(out," case %d:\n",sp->index); lineno++;
3240 dflt_sp = sp;
3241 }
3242 if( dflt_sp!=0 ){
3243 emit_destructor_code(out,dflt_sp,lemp,&lineno);
3244 fprintf(out," break;\n"); lineno++;
3245 }
3246 }
drh75897232000-05-29 14:26:00 +00003247 tplt_xfer(lemp->name,in,out,&lineno);
3248
3249 /* Generate code which executes whenever the parser stack overflows */
3250 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
3251 tplt_xfer(lemp->name,in,out,&lineno);
3252
3253 /* Generate the table of rule information
3254 **
3255 ** Note: This code depends on the fact that rules are number
3256 ** sequentually beginning with 0.
3257 */
3258 for(rp=lemp->rule; rp; rp=rp->next){
3259 fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
3260 }
3261 tplt_xfer(lemp->name,in,out,&lineno);
3262
3263 /* Generate code which execution during each REDUCE action */
3264 for(rp=lemp->rule; rp; rp=rp->next){
3265 fprintf(out," case %d:\n",rp->index); lineno++;
drh75897232000-05-29 14:26:00 +00003266 emit_code(out,rp,lemp,&lineno);
3267 fprintf(out," break;\n"); lineno++;
3268 }
3269 tplt_xfer(lemp->name,in,out,&lineno);
3270
3271 /* Generate code which executes if a parse fails */
3272 tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);
3273 tplt_xfer(lemp->name,in,out,&lineno);
3274
3275 /* Generate code which executes when a syntax error occurs */
3276 tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno);
3277 tplt_xfer(lemp->name,in,out,&lineno);
3278
3279 /* Generate code which executes when the parser accepts its input */
3280 tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno);
3281 tplt_xfer(lemp->name,in,out,&lineno);
3282
3283 /* Append any addition code the user desires */
3284 tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno);
3285
3286 fclose(in);
3287 fclose(out);
3288 return;
3289}
3290
3291/* Generate a header file for the parser */
3292void ReportHeader(lemp)
3293struct lemon *lemp;
3294{
3295 FILE *out, *in;
3296 char *prefix;
3297 char line[LINESIZE];
3298 char pattern[LINESIZE];
3299 int i;
3300
3301 if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
3302 else prefix = "";
3303 in = file_open(lemp,".h","r");
3304 if( in ){
3305 for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
3306 sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3307 if( strcmp(line,pattern) ) break;
3308 }
3309 fclose(in);
3310 if( i==lemp->nterminal ){
3311 /* No change in the file. Don't rewrite it. */
3312 return;
3313 }
3314 }
3315 out = file_open(lemp,".h","w");
3316 if( out ){
3317 for(i=1; i<lemp->nterminal; i++){
3318 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
3319 }
3320 fclose(out);
3321 }
3322 return;
3323}
3324
3325/* Reduce the size of the action tables, if possible, by making use
3326** of defaults.
3327**
drhb59499c2002-02-23 18:45:13 +00003328** In this version, we take the most frequent REDUCE action and make
3329** it the default. Only default a reduce if there are more than one.
drh75897232000-05-29 14:26:00 +00003330*/
3331void CompressTables(lemp)
3332struct lemon *lemp;
3333{
3334 struct state *stp;
drhb59499c2002-02-23 18:45:13 +00003335 struct action *ap, *ap2;
3336 struct rule *rp, *rp2, *rbest;
3337 int nbest, n;
drh75897232000-05-29 14:26:00 +00003338 int i;
3339 int cnt;
3340
3341 for(i=0; i<lemp->nstate; i++){
3342 stp = lemp->sorted[i];
drhb59499c2002-02-23 18:45:13 +00003343 nbest = 0;
3344 rbest = 0;
drh75897232000-05-29 14:26:00 +00003345
drhb59499c2002-02-23 18:45:13 +00003346 for(ap=stp->ap; ap; ap=ap->next){
3347 if( ap->type!=REDUCE ) continue;
3348 rp = ap->x.rp;
3349 if( rp==rbest ) continue;
3350 n = 1;
3351 for(ap2=ap->next; ap2; ap2=ap2->next){
3352 if( ap2->type!=REDUCE ) continue;
3353 rp2 = ap2->x.rp;
3354 if( rp2==rbest ) continue;
3355 if( rp2==rp ) n++;
3356 }
3357 if( n>nbest ){
3358 nbest = n;
3359 rbest = rp;
drh75897232000-05-29 14:26:00 +00003360 }
3361 }
drhb59499c2002-02-23 18:45:13 +00003362
3363 /* Do not make a default if the number of rules to default
3364 ** is not at least 2 */
3365 if( nbest<2 ) continue;
drh75897232000-05-29 14:26:00 +00003366
drhb59499c2002-02-23 18:45:13 +00003367
3368 /* Combine matching REDUCE actions into a single default */
3369 for(ap=stp->ap; ap; ap=ap->next){
3370 if( ap->type==REDUCE && ap->x.rp==rbest ) break;
3371 }
drh75897232000-05-29 14:26:00 +00003372 assert( ap );
3373 ap->sp = Symbol_new("{default}");
3374 for(ap=ap->next; ap; ap=ap->next){
drhb59499c2002-02-23 18:45:13 +00003375 if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
drh75897232000-05-29 14:26:00 +00003376 }
3377 stp->ap = Action_sort(stp->ap);
3378 }
3379}
drhb59499c2002-02-23 18:45:13 +00003380
drh75897232000-05-29 14:26:00 +00003381/***************** From the file "set.c" ************************************/
3382/*
3383** Set manipulation routines for the LEMON parser generator.
3384*/
3385
3386static int size = 0;
3387
3388/* Set the set size */
3389void SetSize(n)
3390int n;
3391{
3392 size = n+1;
3393}
3394
3395/* Allocate a new set */
3396char *SetNew(){
3397 char *s;
3398 int i;
3399 s = (char*)malloc( size );
3400 if( s==0 ){
3401 extern void memory_error();
3402 memory_error();
3403 }
3404 for(i=0; i<size; i++) s[i] = 0;
3405 return s;
3406}
3407
3408/* Deallocate a set */
3409void SetFree(s)
3410char *s;
3411{
3412 free(s);
3413}
3414
3415/* Add a new element to the set. Return TRUE if the element was added
3416** and FALSE if it was already there. */
3417int SetAdd(s,e)
3418char *s;
3419int e;
3420{
3421 int rv;
3422 rv = s[e];
3423 s[e] = 1;
3424 return !rv;
3425}
3426
3427/* Add every element of s2 to s1. Return TRUE if s1 changes. */
3428int SetUnion(s1,s2)
3429char *s1;
3430char *s2;
3431{
3432 int i, progress;
3433 progress = 0;
3434 for(i=0; i<size; i++){
3435 if( s2[i]==0 ) continue;
3436 if( s1[i]==0 ){
3437 progress = 1;
3438 s1[i] = 1;
3439 }
3440 }
3441 return progress;
3442}
3443/********************** From the file "table.c" ****************************/
3444/*
3445** All code in this file has been automatically generated
3446** from a specification in the file
3447** "table.q"
3448** by the associative array code building program "aagen".
3449** Do not edit this file! Instead, edit the specification
3450** file, then rerun aagen.
3451*/
3452/*
3453** Code for processing tables in the LEMON parser generator.
3454*/
3455
3456PRIVATE int strhash(x)
3457char *x;
3458{
3459 int h = 0;
3460 while( *x) h = h*13 + *(x++);
3461 return h;
3462}
3463
3464/* Works like strdup, sort of. Save a string in malloced memory, but
3465** keep strings in a table so that the same string is not in more
3466** than one place.
3467*/
3468char *Strsafe(y)
3469char *y;
3470{
3471 char *z;
3472
3473 z = Strsafe_find(y);
3474 if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
3475 strcpy(z,y);
3476 Strsafe_insert(z);
3477 }
3478 MemoryCheck(z);
3479 return z;
3480}
3481
3482/* There is one instance of the following structure for each
3483** associative array of type "x1".
3484*/
3485struct s_x1 {
3486 int size; /* The number of available slots. */
3487 /* Must be a power of 2 greater than or */
3488 /* equal to 1 */
3489 int count; /* Number of currently slots filled */
3490 struct s_x1node *tbl; /* The data stored here */
3491 struct s_x1node **ht; /* Hash table for lookups */
3492};
3493
3494/* There is one instance of this structure for every data element
3495** in an associative array of type "x1".
3496*/
3497typedef struct s_x1node {
3498 char *data; /* The data */
3499 struct s_x1node *next; /* Next entry with the same hash */
3500 struct s_x1node **from; /* Previous link */
3501} x1node;
3502
3503/* There is only one instance of the array, which is the following */
3504static struct s_x1 *x1a;
3505
3506/* Allocate a new associative array */
3507void Strsafe_init(){
3508 if( x1a ) return;
3509 x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
3510 if( x1a ){
3511 x1a->size = 1024;
3512 x1a->count = 0;
3513 x1a->tbl = (x1node*)malloc(
3514 (sizeof(x1node) + sizeof(x1node*))*1024 );
3515 if( x1a->tbl==0 ){
3516 free(x1a);
3517 x1a = 0;
3518 }else{
3519 int i;
3520 x1a->ht = (x1node**)&(x1a->tbl[1024]);
3521 for(i=0; i<1024; i++) x1a->ht[i] = 0;
3522 }
3523 }
3524}
3525/* Insert a new record into the array. Return TRUE if successful.
3526** Prior data with the same key is NOT overwritten */
3527int Strsafe_insert(data)
3528char *data;
3529{
3530 x1node *np;
3531 int h;
3532 int ph;
3533
3534 if( x1a==0 ) return 0;
3535 ph = strhash(data);
3536 h = ph & (x1a->size-1);
3537 np = x1a->ht[h];
3538 while( np ){
3539 if( strcmp(np->data,data)==0 ){
3540 /* An existing entry with the same key is found. */
3541 /* Fail because overwrite is not allows. */
3542 return 0;
3543 }
3544 np = np->next;
3545 }
3546 if( x1a->count>=x1a->size ){
3547 /* Need to make the hash table bigger */
3548 int i,size;
3549 struct s_x1 array;
3550 array.size = size = x1a->size*2;
3551 array.count = x1a->count;
3552 array.tbl = (x1node*)malloc(
3553 (sizeof(x1node) + sizeof(x1node*))*size );
3554 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3555 array.ht = (x1node**)&(array.tbl[size]);
3556 for(i=0; i<size; i++) array.ht[i] = 0;
3557 for(i=0; i<x1a->count; i++){
3558 x1node *oldnp, *newnp;
3559 oldnp = &(x1a->tbl[i]);
3560 h = strhash(oldnp->data) & (size-1);
3561 newnp = &(array.tbl[i]);
3562 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3563 newnp->next = array.ht[h];
3564 newnp->data = oldnp->data;
3565 newnp->from = &(array.ht[h]);
3566 array.ht[h] = newnp;
3567 }
3568 free(x1a->tbl);
3569 *x1a = array;
3570 }
3571 /* Insert the new data */
3572 h = ph & (x1a->size-1);
3573 np = &(x1a->tbl[x1a->count++]);
3574 np->data = data;
3575 if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
3576 np->next = x1a->ht[h];
3577 x1a->ht[h] = np;
3578 np->from = &(x1a->ht[h]);
3579 return 1;
3580}
3581
3582/* Return a pointer to data assigned to the given key. Return NULL
3583** if no such key. */
3584char *Strsafe_find(key)
3585char *key;
3586{
3587 int h;
3588 x1node *np;
3589
3590 if( x1a==0 ) return 0;
3591 h = strhash(key) & (x1a->size-1);
3592 np = x1a->ht[h];
3593 while( np ){
3594 if( strcmp(np->data,key)==0 ) break;
3595 np = np->next;
3596 }
3597 return np ? np->data : 0;
3598}
3599
3600/* Return a pointer to the (terminal or nonterminal) symbol "x".
3601** Create a new symbol if this is the first time "x" has been seen.
3602*/
3603struct symbol *Symbol_new(x)
3604char *x;
3605{
3606 struct symbol *sp;
3607
3608 sp = Symbol_find(x);
3609 if( sp==0 ){
3610 sp = (struct symbol *)malloc( sizeof(struct symbol) );
3611 MemoryCheck(sp);
3612 sp->name = Strsafe(x);
3613 sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
3614 sp->rule = 0;
drh0bd1f4e2002-06-06 18:54:39 +00003615 sp->fallback = 0;
drh75897232000-05-29 14:26:00 +00003616 sp->prec = -1;
3617 sp->assoc = UNK;
3618 sp->firstset = 0;
drhb27b83a2002-08-14 23:18:57 +00003619 sp->lambda = B_FALSE;
drh75897232000-05-29 14:26:00 +00003620 sp->destructor = 0;
3621 sp->datatype = 0;
3622 Symbol_insert(sp,sp->name);
3623 }
3624 return sp;
3625}
3626
3627/* Compare two symbols */
3628int Symbolcmpp(a,b)
3629struct symbol **a;
3630struct symbol **b;
3631{
3632 return strcmp((**a).name,(**b).name);
3633}
3634
3635/* There is one instance of the following structure for each
3636** associative array of type "x2".
3637*/
3638struct s_x2 {
3639 int size; /* The number of available slots. */
3640 /* Must be a power of 2 greater than or */
3641 /* equal to 1 */
3642 int count; /* Number of currently slots filled */
3643 struct s_x2node *tbl; /* The data stored here */
3644 struct s_x2node **ht; /* Hash table for lookups */
3645};
3646
3647/* There is one instance of this structure for every data element
3648** in an associative array of type "x2".
3649*/
3650typedef struct s_x2node {
3651 struct symbol *data; /* The data */
3652 char *key; /* The key */
3653 struct s_x2node *next; /* Next entry with the same hash */
3654 struct s_x2node **from; /* Previous link */
3655} x2node;
3656
3657/* There is only one instance of the array, which is the following */
3658static struct s_x2 *x2a;
3659
3660/* Allocate a new associative array */
3661void Symbol_init(){
3662 if( x2a ) return;
3663 x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
3664 if( x2a ){
3665 x2a->size = 128;
3666 x2a->count = 0;
3667 x2a->tbl = (x2node*)malloc(
3668 (sizeof(x2node) + sizeof(x2node*))*128 );
3669 if( x2a->tbl==0 ){
3670 free(x2a);
3671 x2a = 0;
3672 }else{
3673 int i;
3674 x2a->ht = (x2node**)&(x2a->tbl[128]);
3675 for(i=0; i<128; i++) x2a->ht[i] = 0;
3676 }
3677 }
3678}
3679/* Insert a new record into the array. Return TRUE if successful.
3680** Prior data with the same key is NOT overwritten */
3681int Symbol_insert(data,key)
3682struct symbol *data;
3683char *key;
3684{
3685 x2node *np;
3686 int h;
3687 int ph;
3688
3689 if( x2a==0 ) return 0;
3690 ph = strhash(key);
3691 h = ph & (x2a->size-1);
3692 np = x2a->ht[h];
3693 while( np ){
3694 if( strcmp(np->key,key)==0 ){
3695 /* An existing entry with the same key is found. */
3696 /* Fail because overwrite is not allows. */
3697 return 0;
3698 }
3699 np = np->next;
3700 }
3701 if( x2a->count>=x2a->size ){
3702 /* Need to make the hash table bigger */
3703 int i,size;
3704 struct s_x2 array;
3705 array.size = size = x2a->size*2;
3706 array.count = x2a->count;
3707 array.tbl = (x2node*)malloc(
3708 (sizeof(x2node) + sizeof(x2node*))*size );
3709 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3710 array.ht = (x2node**)&(array.tbl[size]);
3711 for(i=0; i<size; i++) array.ht[i] = 0;
3712 for(i=0; i<x2a->count; i++){
3713 x2node *oldnp, *newnp;
3714 oldnp = &(x2a->tbl[i]);
3715 h = strhash(oldnp->key) & (size-1);
3716 newnp = &(array.tbl[i]);
3717 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3718 newnp->next = array.ht[h];
3719 newnp->key = oldnp->key;
3720 newnp->data = oldnp->data;
3721 newnp->from = &(array.ht[h]);
3722 array.ht[h] = newnp;
3723 }
3724 free(x2a->tbl);
3725 *x2a = array;
3726 }
3727 /* Insert the new data */
3728 h = ph & (x2a->size-1);
3729 np = &(x2a->tbl[x2a->count++]);
3730 np->key = key;
3731 np->data = data;
3732 if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
3733 np->next = x2a->ht[h];
3734 x2a->ht[h] = np;
3735 np->from = &(x2a->ht[h]);
3736 return 1;
3737}
3738
3739/* Return a pointer to data assigned to the given key. Return NULL
3740** if no such key. */
3741struct symbol *Symbol_find(key)
3742char *key;
3743{
3744 int h;
3745 x2node *np;
3746
3747 if( x2a==0 ) return 0;
3748 h = strhash(key) & (x2a->size-1);
3749 np = x2a->ht[h];
3750 while( np ){
3751 if( strcmp(np->key,key)==0 ) break;
3752 np = np->next;
3753 }
3754 return np ? np->data : 0;
3755}
3756
3757/* Return the n-th data. Return NULL if n is out of range. */
3758struct symbol *Symbol_Nth(n)
3759int n;
3760{
3761 struct symbol *data;
3762 if( x2a && n>0 && n<=x2a->count ){
3763 data = x2a->tbl[n-1].data;
3764 }else{
3765 data = 0;
3766 }
3767 return data;
3768}
3769
3770/* Return the size of the array */
3771int Symbol_count()
3772{
3773 return x2a ? x2a->count : 0;
3774}
3775
3776/* Return an array of pointers to all data in the table.
3777** The array is obtained from malloc. Return NULL if memory allocation
3778** problems, or if the array is empty. */
3779struct symbol **Symbol_arrayof()
3780{
3781 struct symbol **array;
3782 int i,size;
3783 if( x2a==0 ) return 0;
3784 size = x2a->count;
3785 array = (struct symbol **)malloc( sizeof(struct symbol *)*size );
3786 if( array ){
3787 for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
3788 }
3789 return array;
3790}
3791
3792/* Compare two configurations */
3793int Configcmp(a,b)
3794struct config *a;
3795struct config *b;
3796{
3797 int x;
3798 x = a->rp->index - b->rp->index;
3799 if( x==0 ) x = a->dot - b->dot;
3800 return x;
3801}
3802
3803/* Compare two states */
3804PRIVATE int statecmp(a,b)
3805struct config *a;
3806struct config *b;
3807{
3808 int rc;
3809 for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
3810 rc = a->rp->index - b->rp->index;
3811 if( rc==0 ) rc = a->dot - b->dot;
3812 }
3813 if( rc==0 ){
3814 if( a ) rc = 1;
3815 if( b ) rc = -1;
3816 }
3817 return rc;
3818}
3819
3820/* Hash a state */
3821PRIVATE int statehash(a)
3822struct config *a;
3823{
3824 int h=0;
3825 while( a ){
3826 h = h*571 + a->rp->index*37 + a->dot;
3827 a = a->bp;
3828 }
3829 return h;
3830}
3831
3832/* Allocate a new state structure */
3833struct state *State_new()
3834{
3835 struct state *new;
3836 new = (struct state *)malloc( sizeof(struct state) );
3837 MemoryCheck(new);
3838 return new;
3839}
3840
3841/* There is one instance of the following structure for each
3842** associative array of type "x3".
3843*/
3844struct s_x3 {
3845 int size; /* The number of available slots. */
3846 /* Must be a power of 2 greater than or */
3847 /* equal to 1 */
3848 int count; /* Number of currently slots filled */
3849 struct s_x3node *tbl; /* The data stored here */
3850 struct s_x3node **ht; /* Hash table for lookups */
3851};
3852
3853/* There is one instance of this structure for every data element
3854** in an associative array of type "x3".
3855*/
3856typedef struct s_x3node {
3857 struct state *data; /* The data */
3858 struct config *key; /* The key */
3859 struct s_x3node *next; /* Next entry with the same hash */
3860 struct s_x3node **from; /* Previous link */
3861} x3node;
3862
3863/* There is only one instance of the array, which is the following */
3864static struct s_x3 *x3a;
3865
3866/* Allocate a new associative array */
3867void State_init(){
3868 if( x3a ) return;
3869 x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
3870 if( x3a ){
3871 x3a->size = 128;
3872 x3a->count = 0;
3873 x3a->tbl = (x3node*)malloc(
3874 (sizeof(x3node) + sizeof(x3node*))*128 );
3875 if( x3a->tbl==0 ){
3876 free(x3a);
3877 x3a = 0;
3878 }else{
3879 int i;
3880 x3a->ht = (x3node**)&(x3a->tbl[128]);
3881 for(i=0; i<128; i++) x3a->ht[i] = 0;
3882 }
3883 }
3884}
3885/* Insert a new record into the array. Return TRUE if successful.
3886** Prior data with the same key is NOT overwritten */
3887int State_insert(data,key)
3888struct state *data;
3889struct config *key;
3890{
3891 x3node *np;
3892 int h;
3893 int ph;
3894
3895 if( x3a==0 ) return 0;
3896 ph = statehash(key);
3897 h = ph & (x3a->size-1);
3898 np = x3a->ht[h];
3899 while( np ){
3900 if( statecmp(np->key,key)==0 ){
3901 /* An existing entry with the same key is found. */
3902 /* Fail because overwrite is not allows. */
3903 return 0;
3904 }
3905 np = np->next;
3906 }
3907 if( x3a->count>=x3a->size ){
3908 /* Need to make the hash table bigger */
3909 int i,size;
3910 struct s_x3 array;
3911 array.size = size = x3a->size*2;
3912 array.count = x3a->count;
3913 array.tbl = (x3node*)malloc(
3914 (sizeof(x3node) + sizeof(x3node*))*size );
3915 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
3916 array.ht = (x3node**)&(array.tbl[size]);
3917 for(i=0; i<size; i++) array.ht[i] = 0;
3918 for(i=0; i<x3a->count; i++){
3919 x3node *oldnp, *newnp;
3920 oldnp = &(x3a->tbl[i]);
3921 h = statehash(oldnp->key) & (size-1);
3922 newnp = &(array.tbl[i]);
3923 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
3924 newnp->next = array.ht[h];
3925 newnp->key = oldnp->key;
3926 newnp->data = oldnp->data;
3927 newnp->from = &(array.ht[h]);
3928 array.ht[h] = newnp;
3929 }
3930 free(x3a->tbl);
3931 *x3a = array;
3932 }
3933 /* Insert the new data */
3934 h = ph & (x3a->size-1);
3935 np = &(x3a->tbl[x3a->count++]);
3936 np->key = key;
3937 np->data = data;
3938 if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
3939 np->next = x3a->ht[h];
3940 x3a->ht[h] = np;
3941 np->from = &(x3a->ht[h]);
3942 return 1;
3943}
3944
3945/* Return a pointer to data assigned to the given key. Return NULL
3946** if no such key. */
3947struct state *State_find(key)
3948struct config *key;
3949{
3950 int h;
3951 x3node *np;
3952
3953 if( x3a==0 ) return 0;
3954 h = statehash(key) & (x3a->size-1);
3955 np = x3a->ht[h];
3956 while( np ){
3957 if( statecmp(np->key,key)==0 ) break;
3958 np = np->next;
3959 }
3960 return np ? np->data : 0;
3961}
3962
3963/* Return an array of pointers to all data in the table.
3964** The array is obtained from malloc. Return NULL if memory allocation
3965** problems, or if the array is empty. */
3966struct state **State_arrayof()
3967{
3968 struct state **array;
3969 int i,size;
3970 if( x3a==0 ) return 0;
3971 size = x3a->count;
3972 array = (struct state **)malloc( sizeof(struct state *)*size );
3973 if( array ){
3974 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
3975 }
3976 return array;
3977}
3978
3979/* Hash a configuration */
3980PRIVATE int confighash(a)
3981struct config *a;
3982{
3983 int h=0;
3984 h = h*571 + a->rp->index*37 + a->dot;
3985 return h;
3986}
3987
3988/* There is one instance of the following structure for each
3989** associative array of type "x4".
3990*/
3991struct s_x4 {
3992 int size; /* The number of available slots. */
3993 /* Must be a power of 2 greater than or */
3994 /* equal to 1 */
3995 int count; /* Number of currently slots filled */
3996 struct s_x4node *tbl; /* The data stored here */
3997 struct s_x4node **ht; /* Hash table for lookups */
3998};
3999
4000/* There is one instance of this structure for every data element
4001** in an associative array of type "x4".
4002*/
4003typedef struct s_x4node {
4004 struct config *data; /* The data */
4005 struct s_x4node *next; /* Next entry with the same hash */
4006 struct s_x4node **from; /* Previous link */
4007} x4node;
4008
4009/* There is only one instance of the array, which is the following */
4010static struct s_x4 *x4a;
4011
4012/* Allocate a new associative array */
4013void Configtable_init(){
4014 if( x4a ) return;
4015 x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
4016 if( x4a ){
4017 x4a->size = 64;
4018 x4a->count = 0;
4019 x4a->tbl = (x4node*)malloc(
4020 (sizeof(x4node) + sizeof(x4node*))*64 );
4021 if( x4a->tbl==0 ){
4022 free(x4a);
4023 x4a = 0;
4024 }else{
4025 int i;
4026 x4a->ht = (x4node**)&(x4a->tbl[64]);
4027 for(i=0; i<64; i++) x4a->ht[i] = 0;
4028 }
4029 }
4030}
4031/* Insert a new record into the array. Return TRUE if successful.
4032** Prior data with the same key is NOT overwritten */
4033int Configtable_insert(data)
4034struct config *data;
4035{
4036 x4node *np;
4037 int h;
4038 int ph;
4039
4040 if( x4a==0 ) return 0;
4041 ph = confighash(data);
4042 h = ph & (x4a->size-1);
4043 np = x4a->ht[h];
4044 while( np ){
4045 if( Configcmp(np->data,data)==0 ){
4046 /* An existing entry with the same key is found. */
4047 /* Fail because overwrite is not allows. */
4048 return 0;
4049 }
4050 np = np->next;
4051 }
4052 if( x4a->count>=x4a->size ){
4053 /* Need to make the hash table bigger */
4054 int i,size;
4055 struct s_x4 array;
4056 array.size = size = x4a->size*2;
4057 array.count = x4a->count;
4058 array.tbl = (x4node*)malloc(
4059 (sizeof(x4node) + sizeof(x4node*))*size );
4060 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
4061 array.ht = (x4node**)&(array.tbl[size]);
4062 for(i=0; i<size; i++) array.ht[i] = 0;
4063 for(i=0; i<x4a->count; i++){
4064 x4node *oldnp, *newnp;
4065 oldnp = &(x4a->tbl[i]);
4066 h = confighash(oldnp->data) & (size-1);
4067 newnp = &(array.tbl[i]);
4068 if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
4069 newnp->next = array.ht[h];
4070 newnp->data = oldnp->data;
4071 newnp->from = &(array.ht[h]);
4072 array.ht[h] = newnp;
4073 }
4074 free(x4a->tbl);
4075 *x4a = array;
4076 }
4077 /* Insert the new data */
4078 h = ph & (x4a->size-1);
4079 np = &(x4a->tbl[x4a->count++]);
4080 np->data = data;
4081 if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
4082 np->next = x4a->ht[h];
4083 x4a->ht[h] = np;
4084 np->from = &(x4a->ht[h]);
4085 return 1;
4086}
4087
4088/* Return a pointer to data assigned to the given key. Return NULL
4089** if no such key. */
4090struct config *Configtable_find(key)
4091struct config *key;
4092{
4093 int h;
4094 x4node *np;
4095
4096 if( x4a==0 ) return 0;
4097 h = confighash(key) & (x4a->size-1);
4098 np = x4a->ht[h];
4099 while( np ){
4100 if( Configcmp(np->data,key)==0 ) break;
4101 np = np->next;
4102 }
4103 return np ? np->data : 0;
4104}
4105
4106/* Remove all data from the table. Pass each data to the function "f"
4107** as it is removed. ("f" may be null to avoid this step.) */
4108void Configtable_clear(f)
4109int(*f)(/* struct config * */);
4110{
4111 int i;
4112 if( x4a==0 || x4a->count==0 ) return;
4113 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
4114 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
4115 x4a->count = 0;
4116 return;
4117}