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