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