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