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