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