| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** This file contains all sources (including headers) to the LEMON | 2 ** This file contains all sources (including headers) to the LEMON |
| 3 ** LALR(1) parser generator. The sources have been combined into a | 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 | 4 ** single file to make it easy to include LEMON in the source tree |
| 5 ** and Makefile of another program. | 5 ** and Makefile of another program. |
| 6 ** | 6 ** |
| 7 ** The author of this program disclaims copyright. | 7 ** The author of this program disclaims copyright. |
| 8 */ | 8 */ |
| 9 #include <stdio.h> | 9 #include <stdio.h> |
| 10 #include <stdarg.h> | 10 #include <stdarg.h> |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 enum symbol_type type; /* Symbols are all either TERMINALS or NTs */ | 256 enum symbol_type type; /* Symbols are all either TERMINALS or NTs */ |
| 257 struct rule *rule; /* Linked list of rules of this (if an NT) */ | 257 struct rule *rule; /* Linked list of rules of this (if an NT) */ |
| 258 struct symbol *fallback; /* fallback token in case this token doesn't parse */ | 258 struct symbol *fallback; /* fallback token in case this token doesn't parse */ |
| 259 int prec; /* Precedence if defined (-1 otherwise) */ | 259 int prec; /* Precedence if defined (-1 otherwise) */ |
| 260 enum e_assoc assoc; /* Associativity if precedence is defined */ | 260 enum e_assoc assoc; /* Associativity if precedence is defined */ |
| 261 char *firstset; /* First-set for all rules of this symbol */ | 261 char *firstset; /* First-set for all rules of this symbol */ |
| 262 Boolean lambda; /* True if NT and can generate an empty string */ | 262 Boolean lambda; /* True if NT and can generate an empty string */ |
| 263 int useCnt; /* Number of times used */ | 263 int useCnt; /* Number of times used */ |
| 264 char *destructor; /* Code which executes whenever this symbol is | 264 char *destructor; /* Code which executes whenever this symbol is |
| 265 ** popped from the stack during error processing */ | 265 ** popped from the stack during error processing */ |
| 266 int destLineno; /* Line number for start of destructor */ | 266 int destLineno; /* Line number for start of destructor. Set to |
| 267 ** -1 for duplicate destructors. */ |
| 267 char *datatype; /* The data type of information held by this | 268 char *datatype; /* The data type of information held by this |
| 268 ** object. Only used if type==NONTERMINAL */ | 269 ** object. Only used if type==NONTERMINAL */ |
| 269 int dtnum; /* The data type number. In the parser, the value | 270 int dtnum; /* The data type number. In the parser, the value |
| 270 ** stack is a union. The .yy%d element of this | 271 ** stack is a union. The .yy%d element of this |
| 271 ** union is the correct data type for this object */ | 272 ** union is the correct data type for this object */ |
| 272 /* The following fields are used by MULTITERMINALs only */ | 273 /* The following fields are used by MULTITERMINALs only */ |
| 273 int nsubsym; /* Number of constituent symbols in the MULTI */ | 274 int nsubsym; /* Number of constituent symbols in the MULTI */ |
| 274 struct symbol **subsym; /* Array of constituent symbols */ | 275 struct symbol **subsym; /* Array of constituent symbols */ |
| 275 }; | 276 }; |
| 276 | 277 |
| 277 /* Each production rule in the grammar is stored in the following | 278 /* Each production rule in the grammar is stored in the following |
| 278 ** structure. */ | 279 ** structure. */ |
| 279 struct rule { | 280 struct rule { |
| 280 struct symbol *lhs; /* Left-hand side of the rule */ | 281 struct symbol *lhs; /* Left-hand side of the rule */ |
| 281 const char *lhsalias; /* Alias for the LHS (NULL if none) */ | 282 const char *lhsalias; /* Alias for the LHS (NULL if none) */ |
| 282 int lhsStart; /* True if left-hand side is the start symbol */ | 283 int lhsStart; /* True if left-hand side is the start symbol */ |
| 283 int ruleline; /* Line number for the rule */ | 284 int ruleline; /* Line number for the rule */ |
| 284 int nrhs; /* Number of RHS symbols */ | 285 int nrhs; /* Number of RHS symbols */ |
| 285 struct symbol **rhs; /* The RHS symbols */ | 286 struct symbol **rhs; /* The RHS symbols */ |
| 286 const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */ | 287 const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */ |
| 287 int line; /* Line number at which code begins */ | 288 int line; /* Line number at which code begins */ |
| 288 const char *code; /* The code executed when this rule is reduced */ | 289 const char *code; /* The code executed when this rule is reduced */ |
| 290 const char *codePrefix; /* Setup code before code[] above */ |
| 291 const char *codeSuffix; /* Breakdown code after code[] above */ |
| 292 int noCode; /* True if this rule has no associated C code */ |
| 293 int codeEmitted; /* True if the code has been emitted already */ |
| 289 struct symbol *precsym; /* Precedence symbol for this rule */ | 294 struct symbol *precsym; /* Precedence symbol for this rule */ |
| 290 int index; /* An index number for this rule */ | 295 int index; /* An index number for this rule */ |
| 296 int iRule; /* Rule number as used in the generated tables */ |
| 291 Boolean canReduce; /* True if this rule is ever reduced */ | 297 Boolean canReduce; /* True if this rule is ever reduced */ |
| 298 Boolean doesReduce; /* Reduce actions occur after optimization */ |
| 292 struct rule *nextlhs; /* Next rule with the same LHS */ | 299 struct rule *nextlhs; /* Next rule with the same LHS */ |
| 293 struct rule *next; /* Next rule in the global list */ | 300 struct rule *next; /* Next rule in the global list */ |
| 294 }; | 301 }; |
| 295 | 302 |
| 296 /* A configuration is a production rule of the grammar together with | 303 /* A configuration is a production rule of the grammar together with |
| 297 ** a mark (dot) showing how much of that rule has been processed so far. | 304 ** a mark (dot) showing how much of that rule has been processed so far. |
| 298 ** Configurations also contain a follow-set which is a list of terminal | 305 ** Configurations also contain a follow-set which is a list of terminal |
| 299 ** symbols which are allowed to immediately follow the end of the rule. | 306 ** symbols which are allowed to immediately follow the end of the rule. |
| 300 ** Every configuration is recorded as an instance of the following: */ | 307 ** Every configuration is recorded as an instance of the following: */ |
| 301 enum cfgstatus { | 308 enum cfgstatus { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 329 }; | 336 }; |
| 330 | 337 |
| 331 /* Every shift or reduce operation is stored as one of the following */ | 338 /* Every shift or reduce operation is stored as one of the following */ |
| 332 struct action { | 339 struct action { |
| 333 struct symbol *sp; /* The look-ahead symbol */ | 340 struct symbol *sp; /* The look-ahead symbol */ |
| 334 enum e_action type; | 341 enum e_action type; |
| 335 union { | 342 union { |
| 336 struct state *stp; /* The new state, if a shift */ | 343 struct state *stp; /* The new state, if a shift */ |
| 337 struct rule *rp; /* The rule, if a reduce */ | 344 struct rule *rp; /* The rule, if a reduce */ |
| 338 } x; | 345 } x; |
| 346 struct symbol *spOpt; /* SHIFTREDUCE optimization to this symbol */ |
| 339 struct action *next; /* Next action for this state */ | 347 struct action *next; /* Next action for this state */ |
| 340 struct action *collide; /* Next action with the same hash */ | 348 struct action *collide; /* Next action with the same hash */ |
| 341 }; | 349 }; |
| 342 | 350 |
| 343 /* Each state of the generated parser's finite state machine | 351 /* Each state of the generated parser's finite state machine |
| 344 ** is encoded as an instance of the following structure. */ | 352 ** is encoded as an instance of the following structure. */ |
| 345 struct state { | 353 struct state { |
| 346 struct config *bp; /* The basis configurations for this state */ | 354 struct config *bp; /* The basis configurations for this state */ |
| 347 struct config *cfp; /* All configurations in this set */ | 355 struct config *cfp; /* All configurations in this set */ |
| 348 int statenum; /* Sequential number for this state */ | 356 int statenum; /* Sequential number for this state */ |
| 349 struct action *ap; /* Array of actions for this state */ | 357 struct action *ap; /* List of actions for this state */ |
| 350 int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */ | 358 int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */ |
| 351 int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */ | 359 int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */ |
| 352 int iDfltReduce; /* Default action is to REDUCE by this rule */ | 360 int iDfltReduce; /* Default action is to REDUCE by this rule */ |
| 353 struct rule *pDfltReduce;/* The default REDUCE rule. */ | 361 struct rule *pDfltReduce;/* The default REDUCE rule. */ |
| 354 int autoReduce; /* True if this is an auto-reduce state */ | 362 int autoReduce; /* True if this is an auto-reduce state */ |
| 355 }; | 363 }; |
| 356 #define NO_OFFSET (-2147483647) | 364 #define NO_OFFSET (-2147483647) |
| 357 | 365 |
| 358 /* A followset propagation link indicates that the contents of one | 366 /* A followset propagation link indicates that the contents of one |
| 359 ** configuration followset should be propagated to another whenever | 367 ** configuration followset should be propagated to another whenever |
| 360 ** the first changes. */ | 368 ** the first changes. */ |
| 361 struct plink { | 369 struct plink { |
| 362 struct config *cfp; /* The configuration to which linked */ | 370 struct config *cfp; /* The configuration to which linked */ |
| 363 struct plink *next; /* The next propagate link */ | 371 struct plink *next; /* The next propagate link */ |
| 364 }; | 372 }; |
| 365 | 373 |
| 366 /* The state vector for the entire parser generator is recorded as | 374 /* The state vector for the entire parser generator is recorded as |
| 367 ** follows. (LEMON uses no global variables and makes little use of | 375 ** follows. (LEMON uses no global variables and makes little use of |
| 368 ** static variables. Fields in the following structure can be thought | 376 ** static variables. Fields in the following structure can be thought |
| 369 ** of as begin global variables in the program.) */ | 377 ** of as begin global variables in the program.) */ |
| 370 struct lemon { | 378 struct lemon { |
| 371 struct state **sorted; /* Table of states sorted by state number */ | 379 struct state **sorted; /* Table of states sorted by state number */ |
| 372 struct rule *rule; /* List of all rules */ | 380 struct rule *rule; /* List of all rules */ |
| 381 struct rule *startRule; /* First rule */ |
| 373 int nstate; /* Number of states */ | 382 int nstate; /* Number of states */ |
| 374 int nxstate; /* nstate with tail degenerate states removed */ | 383 int nxstate; /* nstate with tail degenerate states removed */ |
| 375 int nrule; /* Number of rules */ | 384 int nrule; /* Number of rules */ |
| 376 int nsymbol; /* Number of terminal and nonterminal symbols */ | 385 int nsymbol; /* Number of terminal and nonterminal symbols */ |
| 377 int nterminal; /* Number of terminal symbols */ | 386 int nterminal; /* Number of terminal symbols */ |
| 378 struct symbol **symbols; /* Sorted array of pointers to symbols */ | 387 struct symbol **symbols; /* Sorted array of pointers to symbols */ |
| 379 int errorcnt; /* Number of errors */ | 388 int errorcnt; /* Number of errors */ |
| 380 struct symbol *errsym; /* The error symbol */ | 389 struct symbol *errsym; /* The error symbol */ |
| 381 struct symbol *wildcard; /* Token that matches anything */ | 390 struct symbol *wildcard; /* Token that matches anything */ |
| 382 char *name; /* Name of the generated parser */ | 391 char *name; /* Name of the generated parser */ |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 enum e_action type, | 528 enum e_action type, |
| 520 struct symbol *sp, | 529 struct symbol *sp, |
| 521 char *arg | 530 char *arg |
| 522 ){ | 531 ){ |
| 523 struct action *newaction; | 532 struct action *newaction; |
| 524 newaction = Action_new(); | 533 newaction = Action_new(); |
| 525 newaction->next = *app; | 534 newaction->next = *app; |
| 526 *app = newaction; | 535 *app = newaction; |
| 527 newaction->type = type; | 536 newaction->type = type; |
| 528 newaction->sp = sp; | 537 newaction->sp = sp; |
| 538 newaction->spOpt = 0; |
| 529 if( type==SHIFT ){ | 539 if( type==SHIFT ){ |
| 530 newaction->x.stp = (struct state *)arg; | 540 newaction->x.stp = (struct state *)arg; |
| 531 }else{ | 541 }else{ |
| 532 newaction->x.rp = (struct rule *)arg; | 542 newaction->x.rp = (struct rule *)arg; |
| 533 } | 543 } |
| 534 } | 544 } |
| 535 /********************** New code to implement the "acttab" module ***********/ | 545 /********************** New code to implement the "acttab" module ***********/ |
| 536 /* | 546 /* |
| 537 ** This module implements routines use to construct the yy_action[] table. | 547 ** This module implements routines use to construct the yy_action[] table. |
| 538 */ | 548 */ |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 | 859 |
| 850 Configlist_init(); | 860 Configlist_init(); |
| 851 | 861 |
| 852 /* Find the start symbol */ | 862 /* Find the start symbol */ |
| 853 if( lemp->start ){ | 863 if( lemp->start ){ |
| 854 sp = Symbol_find(lemp->start); | 864 sp = Symbol_find(lemp->start); |
| 855 if( sp==0 ){ | 865 if( sp==0 ){ |
| 856 ErrorMsg(lemp->filename,0, | 866 ErrorMsg(lemp->filename,0, |
| 857 "The specified start symbol \"%s\" is not \ | 867 "The specified start symbol \"%s\" is not \ |
| 858 in a nonterminal of the grammar. \"%s\" will be used as the start \ | 868 in a nonterminal of the grammar. \"%s\" will be used as the start \ |
| 859 symbol instead.",lemp->start,lemp->rule->lhs->name); | 869 symbol instead.",lemp->start,lemp->startRule->lhs->name); |
| 860 lemp->errorcnt++; | 870 lemp->errorcnt++; |
| 861 sp = lemp->rule->lhs; | 871 sp = lemp->startRule->lhs; |
| 862 } | 872 } |
| 863 }else{ | 873 }else{ |
| 864 sp = lemp->rule->lhs; | 874 sp = lemp->startRule->lhs; |
| 865 } | 875 } |
| 866 | 876 |
| 867 /* Make sure the start symbol doesn't occur on the right-hand side of | 877 /* Make sure the start symbol doesn't occur on the right-hand side of |
| 868 ** any rule. Report an error if it does. (YACC would generate a new | 878 ** any rule. Report an error if it does. (YACC would generate a new |
| 869 ** start symbol in this case.) */ | 879 ** start symbol in this case.) */ |
| 870 for(rp=lemp->rule; rp; rp=rp->next){ | 880 for(rp=lemp->rule; rp; rp=rp->next){ |
| 871 int i; | 881 int i; |
| 872 for(i=0; i<rp->nrhs; i++){ | 882 for(i=0; i<rp->nrhs; i++){ |
| 873 if( rp->rhs[i]==sp ){ /* FIX ME: Deal with multiterminals */ | 883 if( rp->rhs[i]==sp ){ /* FIX ME: Deal with multiterminals */ |
| 874 ErrorMsg(lemp->filename,0, | 884 ErrorMsg(lemp->filename,0, |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); | 1118 Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); |
| 1109 } | 1119 } |
| 1110 } | 1120 } |
| 1111 } | 1121 } |
| 1112 } | 1122 } |
| 1113 } | 1123 } |
| 1114 | 1124 |
| 1115 /* Add the accepting token */ | 1125 /* Add the accepting token */ |
| 1116 if( lemp->start ){ | 1126 if( lemp->start ){ |
| 1117 sp = Symbol_find(lemp->start); | 1127 sp = Symbol_find(lemp->start); |
| 1118 if( sp==0 ) sp = lemp->rule->lhs; | 1128 if( sp==0 ) sp = lemp->startRule->lhs; |
| 1119 }else{ | 1129 }else{ |
| 1120 sp = lemp->rule->lhs; | 1130 sp = lemp->startRule->lhs; |
| 1121 } | 1131 } |
| 1122 /* Add to the first state (which is always the starting state of the | 1132 /* Add to the first state (which is always the starting state of the |
| 1123 ** finite state machine) an action to ACCEPT if the lookahead is the | 1133 ** finite state machine) an action to ACCEPT if the lookahead is the |
| 1124 ** start nonterminal. */ | 1134 ** start nonterminal. */ |
| 1125 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); | 1135 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); |
| 1126 | 1136 |
| 1127 /* Resolve conflicts */ | 1137 /* Resolve conflicts */ |
| 1128 for(i=0; i<lemp->nstate; i++){ | 1138 for(i=0; i<lemp->nstate; i++){ |
| 1129 struct action *ap, *nap; | 1139 struct action *ap, *nap; |
| 1130 stp = lemp->sorted[i]; | 1140 stp = lemp->sorted[i]; |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1488 | 1498 |
| 1489 static char *user_templatename = NULL; | 1499 static char *user_templatename = NULL; |
| 1490 static void handle_T_option(char *z){ | 1500 static void handle_T_option(char *z){ |
| 1491 user_templatename = (char *) malloc( lemonStrlen(z)+1 ); | 1501 user_templatename = (char *) malloc( lemonStrlen(z)+1 ); |
| 1492 if( user_templatename==0 ){ | 1502 if( user_templatename==0 ){ |
| 1493 memory_error(); | 1503 memory_error(); |
| 1494 } | 1504 } |
| 1495 lemon_strcpy(user_templatename, z); | 1505 lemon_strcpy(user_templatename, z); |
| 1496 } | 1506 } |
| 1497 | 1507 |
| 1508 /* Merge together to lists of rules ordered by rule.iRule */ |
| 1509 static struct rule *Rule_merge(struct rule *pA, struct rule *pB){ |
| 1510 struct rule *pFirst = 0; |
| 1511 struct rule **ppPrev = &pFirst; |
| 1512 while( pA && pB ){ |
| 1513 if( pA->iRule<pB->iRule ){ |
| 1514 *ppPrev = pA; |
| 1515 ppPrev = &pA->next; |
| 1516 pA = pA->next; |
| 1517 }else{ |
| 1518 *ppPrev = pB; |
| 1519 ppPrev = &pB->next; |
| 1520 pB = pB->next; |
| 1521 } |
| 1522 } |
| 1523 if( pA ){ |
| 1524 *ppPrev = pA; |
| 1525 }else{ |
| 1526 *ppPrev = pB; |
| 1527 } |
| 1528 return pFirst; |
| 1529 } |
| 1530 |
| 1531 /* |
| 1532 ** Sort a list of rules in order of increasing iRule value |
| 1533 */ |
| 1534 static struct rule *Rule_sort(struct rule *rp){ |
| 1535 int i; |
| 1536 struct rule *pNext; |
| 1537 struct rule *x[32]; |
| 1538 memset(x, 0, sizeof(x)); |
| 1539 while( rp ){ |
| 1540 pNext = rp->next; |
| 1541 rp->next = 0; |
| 1542 for(i=0; i<sizeof(x)/sizeof(x[0]) && x[i]; i++){ |
| 1543 rp = Rule_merge(x[i], rp); |
| 1544 x[i] = 0; |
| 1545 } |
| 1546 x[i] = rp; |
| 1547 rp = pNext; |
| 1548 } |
| 1549 rp = 0; |
| 1550 for(i=0; i<sizeof(x)/sizeof(x[0]); i++){ |
| 1551 rp = Rule_merge(x[i], rp); |
| 1552 } |
| 1553 return rp; |
| 1554 } |
| 1555 |
| 1498 /* forward reference */ | 1556 /* forward reference */ |
| 1499 static const char *minimum_size_type(int lwr, int upr, int *pnByte); | 1557 static const char *minimum_size_type(int lwr, int upr, int *pnByte); |
| 1500 | 1558 |
| 1501 /* Print a single line of the "Parser Stats" output | 1559 /* Print a single line of the "Parser Stats" output |
| 1502 */ | 1560 */ |
| 1503 static void stats_line(const char *zLabel, int iValue){ | 1561 static void stats_line(const char *zLabel, int iValue){ |
| 1504 int nLabel = lemonStrlen(zLabel); | 1562 int nLabel = lemonStrlen(zLabel); |
| 1505 printf(" %s%.*s %5d\n", zLabel, | 1563 printf(" %s%.*s %5d\n", zLabel, |
| 1506 35-nLabel, "................................", | 1564 35-nLabel, "................................", |
| 1507 iValue); | 1565 iValue); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1536 {OPT_FLAG, "s", (char*)&statistics, | 1594 {OPT_FLAG, "s", (char*)&statistics, |
| 1537 "Print parser stats to standard output."}, | 1595 "Print parser stats to standard output."}, |
| 1538 {OPT_FLAG, "x", (char*)&version, "Print the version number."}, | 1596 {OPT_FLAG, "x", (char*)&version, "Print the version number."}, |
| 1539 {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."}, | 1597 {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."}, |
| 1540 {OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"}, | 1598 {OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"}, |
| 1541 {OPT_FLAG,0,0,0} | 1599 {OPT_FLAG,0,0,0} |
| 1542 }; | 1600 }; |
| 1543 int i; | 1601 int i; |
| 1544 int exitcode; | 1602 int exitcode; |
| 1545 struct lemon lem; | 1603 struct lemon lem; |
| 1604 struct rule *rp; |
| 1546 | 1605 |
| 1547 OptInit(argv,options,stderr); | 1606 OptInit(argv,options,stderr); |
| 1548 if( version ){ | 1607 if( version ){ |
| 1549 printf("Lemon version 1.0\n"); | 1608 printf("Lemon version 1.0\n"); |
| 1550 exit(0); | 1609 exit(0); |
| 1551 } | 1610 } |
| 1552 if( OptNArgs()!=1 ){ | 1611 if( OptNArgs()!=1 ){ |
| 1553 fprintf(stderr,"Exactly one filename argument is required.\n"); | 1612 fprintf(stderr,"Exactly one filename argument is required.\n"); |
| 1554 exit(1); | 1613 exit(1); |
| 1555 } | 1614 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1582 lem.symbols = Symbol_arrayof(); | 1641 lem.symbols = Symbol_arrayof(); |
| 1583 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; | 1642 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
| 1584 qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); | 1643 qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); |
| 1585 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; | 1644 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
| 1586 while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } | 1645 while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } |
| 1587 assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); | 1646 assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); |
| 1588 lem.nsymbol = i - 1; | 1647 lem.nsymbol = i - 1; |
| 1589 for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); | 1648 for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); |
| 1590 lem.nterminal = i; | 1649 lem.nterminal = i; |
| 1591 | 1650 |
| 1651 /* Assign sequential rule numbers. Start with 0. Put rules that have no |
| 1652 ** reduce action C-code associated with them last, so that the switch() |
| 1653 ** statement that selects reduction actions will have a smaller jump table. |
| 1654 */ |
| 1655 for(i=0, rp=lem.rule; rp; rp=rp->next){ |
| 1656 rp->iRule = rp->code ? i++ : -1; |
| 1657 } |
| 1658 for(rp=lem.rule; rp; rp=rp->next){ |
| 1659 if( rp->iRule<0 ) rp->iRule = i++; |
| 1660 } |
| 1661 lem.startRule = lem.rule; |
| 1662 lem.rule = Rule_sort(lem.rule); |
| 1663 |
| 1592 /* Generate a reprint of the grammar, if requested on the command line */ | 1664 /* Generate a reprint of the grammar, if requested on the command line */ |
| 1593 if( rpflag ){ | 1665 if( rpflag ){ |
| 1594 Reprint(&lem); | 1666 Reprint(&lem); |
| 1595 }else{ | 1667 }else{ |
| 1596 /* Initialize the size for all follow and first sets */ | 1668 /* Initialize the size for all follow and first sets */ |
| 1597 SetSize(lem.nterminal+1); | 1669 SetSize(lem.nterminal+1); |
| 1598 | 1670 |
| 1599 /* Find the precedence for every production rule (that has one) */ | 1671 /* Find the precedence for every production rule (that has one) */ |
| 1600 FindRulePrecedences(&lem); | 1672 FindRulePrecedences(&lem); |
| 1601 | 1673 |
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2141 fragment which begins on this line."); | 2213 fragment which begins on this line."); |
| 2142 psp->errorcnt++; | 2214 psp->errorcnt++; |
| 2143 }else if( psp->prevrule->code!=0 ){ | 2215 }else if( psp->prevrule->code!=0 ){ |
| 2144 ErrorMsg(psp->filename,psp->tokenlineno, | 2216 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2145 "Code fragment beginning on this line is not the first \ | 2217 "Code fragment beginning on this line is not the first \ |
| 2146 to follow the previous rule."); | 2218 to follow the previous rule."); |
| 2147 psp->errorcnt++; | 2219 psp->errorcnt++; |
| 2148 }else{ | 2220 }else{ |
| 2149 psp->prevrule->line = psp->tokenlineno; | 2221 psp->prevrule->line = psp->tokenlineno; |
| 2150 psp->prevrule->code = &x[1]; | 2222 psp->prevrule->code = &x[1]; |
| 2223 psp->prevrule->noCode = 0; |
| 2151 } | 2224 } |
| 2152 }else if( x[0]=='[' ){ | 2225 }else if( x[0]=='[' ){ |
| 2153 psp->state = PRECEDENCE_MARK_1; | 2226 psp->state = PRECEDENCE_MARK_1; |
| 2154 }else{ | 2227 }else{ |
| 2155 ErrorMsg(psp->filename,psp->tokenlineno, | 2228 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2156 "Token \"%s\" should be either \"%%\" or a nonterminal name.", | 2229 "Token \"%s\" should be either \"%%\" or a nonterminal name.", |
| 2157 x); | 2230 x); |
| 2158 psp->errorcnt++; | 2231 psp->errorcnt++; |
| 2159 } | 2232 } |
| 2160 break; | 2233 break; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2247 rp->rhs = (struct symbol**)&rp[1]; | 2320 rp->rhs = (struct symbol**)&rp[1]; |
| 2248 rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); | 2321 rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); |
| 2249 for(i=0; i<psp->nrhs; i++){ | 2322 for(i=0; i<psp->nrhs; i++){ |
| 2250 rp->rhs[i] = psp->rhs[i]; | 2323 rp->rhs[i] = psp->rhs[i]; |
| 2251 rp->rhsalias[i] = psp->alias[i]; | 2324 rp->rhsalias[i] = psp->alias[i]; |
| 2252 } | 2325 } |
| 2253 rp->lhs = psp->lhs; | 2326 rp->lhs = psp->lhs; |
| 2254 rp->lhsalias = psp->lhsalias; | 2327 rp->lhsalias = psp->lhsalias; |
| 2255 rp->nrhs = psp->nrhs; | 2328 rp->nrhs = psp->nrhs; |
| 2256 rp->code = 0; | 2329 rp->code = 0; |
| 2330 rp->noCode = 1; |
| 2257 rp->precsym = 0; | 2331 rp->precsym = 0; |
| 2258 rp->index = psp->gp->nrule++; | 2332 rp->index = psp->gp->nrule++; |
| 2259 rp->nextlhs = rp->lhs->rule; | 2333 rp->nextlhs = rp->lhs->rule; |
| 2260 rp->lhs->rule = rp; | 2334 rp->lhs->rule = rp; |
| 2261 rp->next = 0; | 2335 rp->next = 0; |
| 2262 if( psp->firstrule==0 ){ | 2336 if( psp->firstrule==0 ){ |
| 2263 psp->firstrule = psp->lastrule = rp; | 2337 psp->firstrule = psp->lastrule = rp; |
| 2264 }else{ | 2338 }else{ |
| 2265 psp->lastrule->next = rp; | 2339 psp->lastrule->next = rp; |
| 2266 psp->lastrule = rp; | 2340 psp->lastrule = rp; |
| (...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3045 ){ | 3119 ){ |
| 3046 int result = 1; | 3120 int result = 1; |
| 3047 switch( ap->type ){ | 3121 switch( ap->type ){ |
| 3048 case SHIFT: { | 3122 case SHIFT: { |
| 3049 struct state *stp = ap->x.stp; | 3123 struct state *stp = ap->x.stp; |
| 3050 fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum); | 3124 fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum); |
| 3051 break; | 3125 break; |
| 3052 } | 3126 } |
| 3053 case REDUCE: { | 3127 case REDUCE: { |
| 3054 struct rule *rp = ap->x.rp; | 3128 struct rule *rp = ap->x.rp; |
| 3055 fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->index); | 3129 fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->iRule); |
| 3056 RulePrint(fp, rp, -1); | 3130 RulePrint(fp, rp, -1); |
| 3057 break; | 3131 break; |
| 3058 } | 3132 } |
| 3059 case SHIFTREDUCE: { | 3133 case SHIFTREDUCE: { |
| 3060 struct rule *rp = ap->x.rp; | 3134 struct rule *rp = ap->x.rp; |
| 3061 fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->index); | 3135 fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->iRule); |
| 3062 RulePrint(fp, rp, -1); | 3136 RulePrint(fp, rp, -1); |
| 3063 break; | 3137 break; |
| 3064 } | 3138 } |
| 3065 case ACCEPT: | 3139 case ACCEPT: |
| 3066 fprintf(fp,"%*s accept",indent,ap->sp->name); | 3140 fprintf(fp,"%*s accept",indent,ap->sp->name); |
| 3067 break; | 3141 break; |
| 3068 case ERROR: | 3142 case ERROR: |
| 3069 fprintf(fp,"%*s error",indent,ap->sp->name); | 3143 fprintf(fp,"%*s error",indent,ap->sp->name); |
| 3070 break; | 3144 break; |
| 3071 case SRCONFLICT: | 3145 case SRCONFLICT: |
| 3072 case RRCONFLICT: | 3146 case RRCONFLICT: |
| 3073 fprintf(fp,"%*s reduce %-7d ** Parsing conflict **", | 3147 fprintf(fp,"%*s reduce %-7d ** Parsing conflict **", |
| 3074 indent,ap->sp->name,ap->x.rp->index); | 3148 indent,ap->sp->name,ap->x.rp->iRule); |
| 3075 break; | 3149 break; |
| 3076 case SSCONFLICT: | 3150 case SSCONFLICT: |
| 3077 fprintf(fp,"%*s shift %-7d ** Parsing conflict **", | 3151 fprintf(fp,"%*s shift %-7d ** Parsing conflict **", |
| 3078 indent,ap->sp->name,ap->x.stp->statenum); | 3152 indent,ap->sp->name,ap->x.stp->statenum); |
| 3079 break; | 3153 break; |
| 3080 case SH_RESOLVED: | 3154 case SH_RESOLVED: |
| 3081 if( showPrecedenceConflict ){ | 3155 if( showPrecedenceConflict ){ |
| 3082 fprintf(fp,"%*s shift %-7d -- dropped by precedence", | 3156 fprintf(fp,"%*s shift %-7d -- dropped by precedence", |
| 3083 indent,ap->sp->name,ap->x.stp->statenum); | 3157 indent,ap->sp->name,ap->x.stp->statenum); |
| 3084 }else{ | 3158 }else{ |
| 3085 result = 0; | 3159 result = 0; |
| 3086 } | 3160 } |
| 3087 break; | 3161 break; |
| 3088 case RD_RESOLVED: | 3162 case RD_RESOLVED: |
| 3089 if( showPrecedenceConflict ){ | 3163 if( showPrecedenceConflict ){ |
| 3090 fprintf(fp,"%*s reduce %-7d -- dropped by precedence", | 3164 fprintf(fp,"%*s reduce %-7d -- dropped by precedence", |
| 3091 indent,ap->sp->name,ap->x.rp->index); | 3165 indent,ap->sp->name,ap->x.rp->iRule); |
| 3092 }else{ | 3166 }else{ |
| 3093 result = 0; | 3167 result = 0; |
| 3094 } | 3168 } |
| 3095 break; | 3169 break; |
| 3096 case NOT_USED: | 3170 case NOT_USED: |
| 3097 result = 0; | 3171 result = 0; |
| 3098 break; | 3172 break; |
| 3099 } | 3173 } |
| 3174 if( result && ap->spOpt ){ |
| 3175 fprintf(fp," /* because %s==%s */", ap->sp->name, ap->spOpt->name); |
| 3176 } |
| 3100 return result; | 3177 return result; |
| 3101 } | 3178 } |
| 3102 | 3179 |
| 3103 /* Generate the "*.out" log file */ | 3180 /* Generate the "*.out" log file */ |
| 3104 void ReportOutput(struct lemon *lemp) | 3181 void ReportOutput(struct lemon *lemp) |
| 3105 { | 3182 { |
| 3106 int i; | 3183 int i; |
| 3107 struct state *stp; | 3184 struct state *stp; |
| 3108 struct config *cfp; | 3185 struct config *cfp; |
| 3109 struct action *ap; | 3186 struct action *ap; |
| 3110 FILE *fp; | 3187 FILE *fp; |
| 3111 | 3188 |
| 3112 fp = file_open(lemp,".out","wb"); | 3189 fp = file_open(lemp,".out","wb"); |
| 3113 if( fp==0 ) return; | 3190 if( fp==0 ) return; |
| 3114 for(i=0; i<lemp->nxstate; i++){ | 3191 for(i=0; i<lemp->nxstate; i++){ |
| 3115 stp = lemp->sorted[i]; | 3192 stp = lemp->sorted[i]; |
| 3116 fprintf(fp,"State %d:\n",stp->statenum); | 3193 fprintf(fp,"State %d:\n",stp->statenum); |
| 3117 if( lemp->basisflag ) cfp=stp->bp; | 3194 if( lemp->basisflag ) cfp=stp->bp; |
| 3118 else cfp=stp->cfp; | 3195 else cfp=stp->cfp; |
| 3119 while( cfp ){ | 3196 while( cfp ){ |
| 3120 char buf[20]; | 3197 char buf[20]; |
| 3121 if( cfp->dot==cfp->rp->nrhs ){ | 3198 if( cfp->dot==cfp->rp->nrhs ){ |
| 3122 lemon_sprintf(buf,"(%d)",cfp->rp->index); | 3199 lemon_sprintf(buf,"(%d)",cfp->rp->iRule); |
| 3123 fprintf(fp," %5s ",buf); | 3200 fprintf(fp," %5s ",buf); |
| 3124 }else{ | 3201 }else{ |
| 3125 fprintf(fp," "); | 3202 fprintf(fp," "); |
| 3126 } | 3203 } |
| 3127 ConfigPrint(fp,cfp); | 3204 ConfigPrint(fp,cfp); |
| 3128 fprintf(fp,"\n"); | 3205 fprintf(fp,"\n"); |
| 3129 #if 0 | 3206 #if 0 |
| 3130 SetPrint(fp,cfp->fws,lemp); | 3207 SetPrint(fp,cfp->fws,lemp); |
| 3131 PlinkPrint(fp,cfp->fplp,"To "); | 3208 PlinkPrint(fp,cfp->fplp,"To "); |
| 3132 PlinkPrint(fp,cfp->bplp,"From"); | 3209 PlinkPrint(fp,cfp->bplp,"From"); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3213 | 3290 |
| 3214 /* Given an action, compute the integer value for that action | 3291 /* Given an action, compute the integer value for that action |
| 3215 ** which is to be put in the action table of the generated machine. | 3292 ** which is to be put in the action table of the generated machine. |
| 3216 ** Return negative if no action should be generated. | 3293 ** Return negative if no action should be generated. |
| 3217 */ | 3294 */ |
| 3218 PRIVATE int compute_action(struct lemon *lemp, struct action *ap) | 3295 PRIVATE int compute_action(struct lemon *lemp, struct action *ap) |
| 3219 { | 3296 { |
| 3220 int act; | 3297 int act; |
| 3221 switch( ap->type ){ | 3298 switch( ap->type ){ |
| 3222 case SHIFT: act = ap->x.stp->statenum; break; | 3299 case SHIFT: act = ap->x.stp->statenum; break; |
| 3223 case SHIFTREDUCE: act = ap->x.rp->index + lemp->nstate; break; | 3300 case SHIFTREDUCE: act = ap->x.rp->iRule + lemp->nstate; break; |
| 3224 case REDUCE: act = ap->x.rp->index + lemp->nstate+lemp->nrule; break; | 3301 case REDUCE: act = ap->x.rp->iRule + lemp->nstate+lemp->nrule; break; |
| 3225 case ERROR: act = lemp->nstate + lemp->nrule*2; break; | 3302 case ERROR: act = lemp->nstate + lemp->nrule*2; break; |
| 3226 case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break; | 3303 case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break; |
| 3227 default: act = -1; break; | 3304 default: act = -1; break; |
| 3228 } | 3305 } |
| 3229 return act; | 3306 return act; |
| 3230 } | 3307 } |
| 3231 | 3308 |
| 3232 #define LINESIZE 1000 | 3309 #define LINESIZE 1000 |
| 3233 /* The next cluster of routines are for reading the template file | 3310 /* The next cluster of routines are for reading the template file |
| 3234 ** and writing the results to the generated parser */ | 3311 ** and writing the results to the generated parser */ |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3423 ** If n==-1, then the previous character is overwritten. | 3500 ** If n==-1, then the previous character is overwritten. |
| 3424 */ | 3501 */ |
| 3425 PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ | 3502 PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ |
| 3426 static char empty[1] = { 0 }; | 3503 static char empty[1] = { 0 }; |
| 3427 static char *z = 0; | 3504 static char *z = 0; |
| 3428 static int alloced = 0; | 3505 static int alloced = 0; |
| 3429 static int used = 0; | 3506 static int used = 0; |
| 3430 int c; | 3507 int c; |
| 3431 char zInt[40]; | 3508 char zInt[40]; |
| 3432 if( zText==0 ){ | 3509 if( zText==0 ){ |
| 3510 if( used==0 && z!=0 ) z[0] = 0; |
| 3433 used = 0; | 3511 used = 0; |
| 3434 return z; | 3512 return z; |
| 3435 } | 3513 } |
| 3436 if( n<=0 ){ | 3514 if( n<=0 ){ |
| 3437 if( n<0 ){ | 3515 if( n<0 ){ |
| 3438 used += n; | 3516 used += n; |
| 3439 assert( used>=0 ); | 3517 assert( used>=0 ); |
| 3440 } | 3518 } |
| 3441 n = lemonStrlen(zText); | 3519 n = lemonStrlen(zText); |
| 3442 } | 3520 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3456 n--; | 3534 n--; |
| 3457 }else{ | 3535 }else{ |
| 3458 z[used++] = (char)c; | 3536 z[used++] = (char)c; |
| 3459 } | 3537 } |
| 3460 } | 3538 } |
| 3461 z[used] = 0; | 3539 z[used] = 0; |
| 3462 return z; | 3540 return z; |
| 3463 } | 3541 } |
| 3464 | 3542 |
| 3465 /* | 3543 /* |
| 3466 ** zCode is a string that is the action associated with a rule. Expand | 3544 ** Write and transform the rp->code string so that symbols are expanded. |
| 3467 ** the symbols in this string so that the refer to elements of the parser | 3545 ** Populate the rp->codePrefix and rp->codeSuffix strings, as appropriate. |
| 3468 ** stack. | 3546 ** |
| 3547 ** Return 1 if the expanded code requires that "yylhsminor" local variable |
| 3548 ** to be defined. |
| 3469 */ | 3549 */ |
| 3470 PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ | 3550 PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){ |
| 3471 char *cp, *xp; | 3551 char *cp, *xp; |
| 3472 int i; | 3552 int i; |
| 3473 char lhsused = 0; /* True if the LHS element has been used */ | 3553 int rc = 0; /* True if yylhsminor is used */ |
| 3474 char used[MAXRHS]; /* True for each RHS element which is used */ | 3554 int dontUseRhs0 = 0; /* If true, use of left-most RHS label is illegal */ |
| 3555 const char *zSkip = 0; /* The zOvwrt comment within rp->code, or NULL */ |
| 3556 char lhsused = 0; /* True if the LHS element has been used */ |
| 3557 char lhsdirect; /* True if LHS writes directly into stack */ |
| 3558 char used[MAXRHS]; /* True for each RHS element which is used */ |
| 3559 char zLhs[50]; /* Convert the LHS symbol into this string */ |
| 3560 char zOvwrt[900]; /* Comment that to allow LHS to overwrite RHS */ |
| 3475 | 3561 |
| 3476 for(i=0; i<rp->nrhs; i++) used[i] = 0; | 3562 for(i=0; i<rp->nrhs; i++) used[i] = 0; |
| 3477 lhsused = 0; | 3563 lhsused = 0; |
| 3478 | 3564 |
| 3479 if( rp->code==0 ){ | 3565 if( rp->code==0 ){ |
| 3480 static char newlinestr[2] = { '\n', '\0' }; | 3566 static char newlinestr[2] = { '\n', '\0' }; |
| 3481 rp->code = newlinestr; | 3567 rp->code = newlinestr; |
| 3482 rp->line = rp->ruleline; | 3568 rp->line = rp->ruleline; |
| 3569 rp->noCode = 1; |
| 3570 }else{ |
| 3571 rp->noCode = 0; |
| 3572 } |
| 3573 |
| 3574 |
| 3575 if( rp->nrhs==0 ){ |
| 3576 /* If there are no RHS symbols, then writing directly to the LHS is ok */ |
| 3577 lhsdirect = 1; |
| 3578 }else if( rp->rhsalias[0]==0 ){ |
| 3579 /* The left-most RHS symbol has no value. LHS direct is ok. But |
| 3580 ** we have to call the distructor on the RHS symbol first. */ |
| 3581 lhsdirect = 1; |
| 3582 if( has_destructor(rp->rhs[0],lemp) ){ |
| 3583 append_str(0,0,0,0); |
| 3584 append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, |
| 3585 rp->rhs[0]->index,1-rp->nrhs); |
| 3586 rp->codePrefix = Strsafe(append_str(0,0,0,0)); |
| 3587 rp->noCode = 0; |
| 3588 } |
| 3589 }else if( rp->lhsalias==0 ){ |
| 3590 /* There is no LHS value symbol. */ |
| 3591 lhsdirect = 1; |
| 3592 }else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){ |
| 3593 /* The LHS symbol and the left-most RHS symbol are the same, so |
| 3594 ** direct writing is allowed */ |
| 3595 lhsdirect = 1; |
| 3596 lhsused = 1; |
| 3597 used[0] = 1; |
| 3598 if( rp->lhs->dtnum!=rp->rhs[0]->dtnum ){ |
| 3599 ErrorMsg(lemp->filename,rp->ruleline, |
| 3600 "%s(%s) and %s(%s) share the same label but have " |
| 3601 "different datatypes.", |
| 3602 rp->lhs->name, rp->lhsalias, rp->rhs[0]->name, rp->rhsalias[0]); |
| 3603 lemp->errorcnt++; |
| 3604 } |
| 3605 }else{ |
| 3606 lemon_sprintf(zOvwrt, "/*%s-overwrites-%s*/", |
| 3607 rp->lhsalias, rp->rhsalias[0]); |
| 3608 zSkip = strstr(rp->code, zOvwrt); |
| 3609 if( zSkip!=0 ){ |
| 3610 /* The code contains a special comment that indicates that it is safe |
| 3611 ** for the LHS label to overwrite left-most RHS label. */ |
| 3612 lhsdirect = 1; |
| 3613 }else{ |
| 3614 lhsdirect = 0; |
| 3615 } |
| 3616 } |
| 3617 if( lhsdirect ){ |
| 3618 sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum); |
| 3619 }else{ |
| 3620 rc = 1; |
| 3621 sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum); |
| 3483 } | 3622 } |
| 3484 | 3623 |
| 3485 append_str(0,0,0,0); | 3624 append_str(0,0,0,0); |
| 3486 | 3625 |
| 3487 /* This const cast is wrong but harmless, if we're careful. */ | 3626 /* This const cast is wrong but harmless, if we're careful. */ |
| 3488 for(cp=(char *)rp->code; *cp; cp++){ | 3627 for(cp=(char *)rp->code; *cp; cp++){ |
| 3628 if( cp==zSkip ){ |
| 3629 append_str(zOvwrt,0,0,0); |
| 3630 cp += lemonStrlen(zOvwrt)-1; |
| 3631 dontUseRhs0 = 1; |
| 3632 continue; |
| 3633 } |
| 3489 if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){ | 3634 if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){ |
| 3490 char saved; | 3635 char saved; |
| 3491 for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++); | 3636 for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++); |
| 3492 saved = *xp; | 3637 saved = *xp; |
| 3493 *xp = 0; | 3638 *xp = 0; |
| 3494 if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ | 3639 if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ |
| 3495 append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0); | 3640 append_str(zLhs,0,0,0); |
| 3496 cp = xp; | 3641 cp = xp; |
| 3497 lhsused = 1; | 3642 lhsused = 1; |
| 3498 }else{ | 3643 }else{ |
| 3499 for(i=0; i<rp->nrhs; i++){ | 3644 for(i=0; i<rp->nrhs; i++){ |
| 3500 if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ | 3645 if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ |
| 3501 if( cp!=rp->code && cp[-1]=='@' ){ | 3646 if( i==0 && dontUseRhs0 ){ |
| 3647 ErrorMsg(lemp->filename,rp->ruleline, |
| 3648 "Label %s used after '%s'.", |
| 3649 rp->rhsalias[0], zOvwrt); |
| 3650 lemp->errorcnt++; |
| 3651 }else if( cp!=rp->code && cp[-1]=='@' ){ |
| 3502 /* If the argument is of the form @X then substituted | 3652 /* If the argument is of the form @X then substituted |
| 3503 ** the token number of X, not the value of X */ | 3653 ** the token number of X, not the value of X */ |
| 3504 append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0); | 3654 append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0); |
| 3505 }else{ | 3655 }else{ |
| 3506 struct symbol *sp = rp->rhs[i]; | 3656 struct symbol *sp = rp->rhs[i]; |
| 3507 int dtnum; | 3657 int dtnum; |
| 3508 if( sp->type==MULTITERMINAL ){ | 3658 if( sp->type==MULTITERMINAL ){ |
| 3509 dtnum = sp->subsym[0]->dtnum; | 3659 dtnum = sp->subsym[0]->dtnum; |
| 3510 }else{ | 3660 }else{ |
| 3511 dtnum = sp->dtnum; | 3661 dtnum = sp->dtnum; |
| 3512 } | 3662 } |
| 3513 append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum); | 3663 append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum); |
| 3514 } | 3664 } |
| 3515 cp = xp; | 3665 cp = xp; |
| 3516 used[i] = 1; | 3666 used[i] = 1; |
| 3517 break; | 3667 break; |
| 3518 } | 3668 } |
| 3519 } | 3669 } |
| 3520 } | 3670 } |
| 3521 *xp = saved; | 3671 *xp = saved; |
| 3522 } | 3672 } |
| 3523 append_str(cp, 1, 0, 0); | 3673 append_str(cp, 1, 0, 0); |
| 3524 } /* End loop */ | 3674 } /* End loop */ |
| 3525 | 3675 |
| 3676 /* Main code generation completed */ |
| 3677 cp = append_str(0,0,0,0); |
| 3678 if( cp && cp[0] ) rp->code = Strsafe(cp); |
| 3679 append_str(0,0,0,0); |
| 3680 |
| 3526 /* Check to make sure the LHS has been used */ | 3681 /* Check to make sure the LHS has been used */ |
| 3527 if( rp->lhsalias && !lhsused ){ | 3682 if( rp->lhsalias && !lhsused ){ |
| 3528 ErrorMsg(lemp->filename,rp->ruleline, | 3683 ErrorMsg(lemp->filename,rp->ruleline, |
| 3529 "Label \"%s\" for \"%s(%s)\" is never used.", | 3684 "Label \"%s\" for \"%s(%s)\" is never used.", |
| 3530 rp->lhsalias,rp->lhs->name,rp->lhsalias); | 3685 rp->lhsalias,rp->lhs->name,rp->lhsalias); |
| 3531 lemp->errorcnt++; | 3686 lemp->errorcnt++; |
| 3532 } | 3687 } |
| 3533 | 3688 |
| 3534 /* Generate destructor code for RHS symbols which are not used in the | 3689 /* Generate destructor code for RHS minor values which are not referenced. |
| 3535 ** reduce code */ | 3690 ** Generate error messages for unused labels and duplicate labels. |
| 3691 */ |
| 3536 for(i=0; i<rp->nrhs; i++){ | 3692 for(i=0; i<rp->nrhs; i++){ |
| 3537 if( rp->rhsalias[i] && !used[i] ){ | 3693 if( rp->rhsalias[i] ){ |
| 3538 ErrorMsg(lemp->filename,rp->ruleline, | 3694 if( i>0 ){ |
| 3539 "Label %s for \"%s(%s)\" is never used.", | 3695 int j; |
| 3540 rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); | 3696 if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){ |
| 3541 lemp->errorcnt++; | 3697 ErrorMsg(lemp->filename,rp->ruleline, |
| 3542 }else if( rp->rhsalias[i]==0 ){ | 3698 "%s(%s) has the same label as the LHS but is not the left-most " |
| 3543 if( has_destructor(rp->rhs[i],lemp) ){ | 3699 "symbol on the RHS.", |
| 3544 append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, | 3700 rp->rhs[i]->name, rp->rhsalias); |
| 3545 rp->rhs[i]->index,i-rp->nrhs+1); | 3701 lemp->errorcnt++; |
| 3546 }else{ | 3702 } |
| 3547 /* No destructor defined for this term */ | 3703 for(j=0; j<i; j++){ |
| 3704 if( rp->rhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){ |
| 3705 ErrorMsg(lemp->filename,rp->ruleline, |
| 3706 "Label %s used for multiple symbols on the RHS of a rule.", |
| 3707 rp->rhsalias[i]); |
| 3708 lemp->errorcnt++; |
| 3709 break; |
| 3710 } |
| 3711 } |
| 3548 } | 3712 } |
| 3713 if( !used[i] ){ |
| 3714 ErrorMsg(lemp->filename,rp->ruleline, |
| 3715 "Label %s for \"%s(%s)\" is never used.", |
| 3716 rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); |
| 3717 lemp->errorcnt++; |
| 3718 } |
| 3719 }else if( i>0 && has_destructor(rp->rhs[i],lemp) ){ |
| 3720 append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, |
| 3721 rp->rhs[i]->index,i-rp->nrhs+1); |
| 3549 } | 3722 } |
| 3550 } | 3723 } |
| 3551 if( rp->code ){ | 3724 |
| 3552 cp = append_str(0,0,0,0); | 3725 /* If unable to write LHS values directly into the stack, write the |
| 3553 rp->code = Strsafe(cp?cp:""); | 3726 ** saved LHS value now. */ |
| 3727 if( lhsdirect==0 ){ |
| 3728 append_str(" yymsp[%d].minor.yy%d = ", 0, 1-rp->nrhs, rp->lhs->dtnum); |
| 3729 append_str(zLhs, 0, 0, 0); |
| 3730 append_str(";\n", 0, 0, 0); |
| 3554 } | 3731 } |
| 3732 |
| 3733 /* Suffix code generation complete */ |
| 3734 cp = append_str(0,0,0,0); |
| 3735 if( cp && cp[0] ){ |
| 3736 rp->codeSuffix = Strsafe(cp); |
| 3737 rp->noCode = 0; |
| 3738 } |
| 3739 |
| 3740 return rc; |
| 3555 } | 3741 } |
| 3556 | 3742 |
| 3557 /* | 3743 /* |
| 3558 ** Generate code which executes when the rule "rp" is reduced. Write | 3744 ** Generate code which executes when the rule "rp" is reduced. Write |
| 3559 ** the code to "out". Make sure lineno stays up-to-date. | 3745 ** the code to "out". Make sure lineno stays up-to-date. |
| 3560 */ | 3746 */ |
| 3561 PRIVATE void emit_code( | 3747 PRIVATE void emit_code( |
| 3562 FILE *out, | 3748 FILE *out, |
| 3563 struct rule *rp, | 3749 struct rule *rp, |
| 3564 struct lemon *lemp, | 3750 struct lemon *lemp, |
| 3565 int *lineno | 3751 int *lineno |
| 3566 ){ | 3752 ){ |
| 3567 const char *cp; | 3753 const char *cp; |
| 3568 | 3754 |
| 3755 /* Setup code prior to the #line directive */ |
| 3756 if( rp->codePrefix && rp->codePrefix[0] ){ |
| 3757 fprintf(out, "{%s", rp->codePrefix); |
| 3758 for(cp=rp->codePrefix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; } |
| 3759 } |
| 3760 |
| 3569 /* Generate code to do the reduce action */ | 3761 /* Generate code to do the reduce action */ |
| 3570 if( rp->code ){ | 3762 if( rp->code ){ |
| 3571 if( !lemp->nolinenosflag ){ | 3763 if( !lemp->nolinenosflag ){ |
| 3572 (*lineno)++; | 3764 (*lineno)++; |
| 3573 tplt_linedir(out,rp->line,lemp->filename); | 3765 tplt_linedir(out,rp->line,lemp->filename); |
| 3574 } | 3766 } |
| 3575 fprintf(out,"{%s",rp->code); | 3767 fprintf(out,"{%s",rp->code); |
| 3576 for(cp=rp->code; *cp; cp++){ | 3768 for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; } |
| 3577 if( *cp=='\n' ) (*lineno)++; | |
| 3578 } /* End loop */ | |
| 3579 fprintf(out,"}\n"); (*lineno)++; | 3769 fprintf(out,"}\n"); (*lineno)++; |
| 3580 if( !lemp->nolinenosflag ){ | 3770 if( !lemp->nolinenosflag ){ |
| 3581 (*lineno)++; | 3771 (*lineno)++; |
| 3582 tplt_linedir(out,*lineno,lemp->outname); | 3772 tplt_linedir(out,*lineno,lemp->outname); |
| 3583 } | 3773 } |
| 3584 } /* End if( rp->code ) */ | 3774 } |
| 3775 |
| 3776 /* Generate breakdown code that occurs after the #line directive */ |
| 3777 if( rp->codeSuffix && rp->codeSuffix[0] ){ |
| 3778 fprintf(out, "%s", rp->codeSuffix); |
| 3779 for(cp=rp->codeSuffix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; } |
| 3780 } |
| 3781 |
| 3782 if( rp->codePrefix ){ |
| 3783 fprintf(out, "}\n"); (*lineno)++; |
| 3784 } |
| 3585 | 3785 |
| 3586 return; | 3786 return; |
| 3587 } | 3787 } |
| 3588 | 3788 |
| 3589 /* | 3789 /* |
| 3590 ** Print the definition of the union used for the parser's data stack. | 3790 ** Print the definition of the union used for the parser's data stack. |
| 3591 ** This union contains fields for every possible data type for tokens | 3791 ** This union contains fields for every possible data type for tokens |
| 3592 ** and nonterminals. In the process of computing and printing this | 3792 ** and nonterminals. In the process of computing and printing this |
| 3593 ** union, also set the ".dtnum" field of every terminal and nonterminal | 3793 ** union, also set the ".dtnum" field of every terminal and nonterminal |
| 3594 ** symbol. | 3794 ** symbol. |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3947 if( pActtab->aAction[jj].action<0 ) nn++; | 4147 if( pActtab->aAction[jj].action<0 ) nn++; |
| 3948 } | 4148 } |
| 3949 printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n", | 4149 printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n", |
| 3950 i, stp->statenum, ax[i].isTkn ? "Token" : "Var ", | 4150 i, stp->statenum, ax[i].isTkn ? "Token" : "Var ", |
| 3951 ax[i].nAction, pActtab->nAction, nn); | 4151 ax[i].nAction, pActtab->nAction, nn); |
| 3952 } | 4152 } |
| 3953 #endif | 4153 #endif |
| 3954 } | 4154 } |
| 3955 free(ax); | 4155 free(ax); |
| 3956 | 4156 |
| 4157 /* Mark rules that are actually used for reduce actions after all |
| 4158 ** optimizations have been applied |
| 4159 */ |
| 4160 for(rp=lemp->rule; rp; rp=rp->next) rp->doesReduce = LEMON_FALSE; |
| 4161 for(i=0; i<lemp->nxstate; i++){ |
| 4162 for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ |
| 4163 if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){ |
| 4164 ap->x.rp->doesReduce = i; |
| 4165 } |
| 4166 } |
| 4167 } |
| 4168 |
| 3957 /* Finish rendering the constants now that the action table has | 4169 /* Finish rendering the constants now that the action table has |
| 3958 ** been computed */ | 4170 ** been computed */ |
| 3959 fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++; | 4171 fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++; |
| 3960 fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; | 4172 fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; |
| 3961 fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++; | 4173 fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++; |
| 3962 fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",lemp->nstate); lineno++; | 4174 fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",lemp->nstate); lineno++; |
| 3963 i = lemp->nstate + lemp->nrule; | 4175 i = lemp->nstate + lemp->nrule; |
| 3964 fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++; | 4176 fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++; |
| 3965 fprintf(out,"#define YY_MIN_REDUCE %d\n", i); lineno++; | 4177 fprintf(out,"#define YY_MIN_REDUCE %d\n", i); lineno++; |
| 3966 i = lemp->nstate + lemp->nrule*2; | 4178 i = lemp->nstate + lemp->nrule*2; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4012 if( j==9 || i==n-1 ){ | 4224 if( j==9 || i==n-1 ){ |
| 4013 fprintf(out, "\n"); lineno++; | 4225 fprintf(out, "\n"); lineno++; |
| 4014 j = 0; | 4226 j = 0; |
| 4015 }else{ | 4227 }else{ |
| 4016 j++; | 4228 j++; |
| 4017 } | 4229 } |
| 4018 } | 4230 } |
| 4019 fprintf(out, "};\n"); lineno++; | 4231 fprintf(out, "};\n"); lineno++; |
| 4020 | 4232 |
| 4021 /* Output the yy_shift_ofst[] table */ | 4233 /* Output the yy_shift_ofst[] table */ |
| 4022 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; | |
| 4023 n = lemp->nxstate; | 4234 n = lemp->nxstate; |
| 4024 while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; | 4235 while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; |
| 4025 fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; | 4236 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", lemp->nactiontab); lineno++; |
| 4026 fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; | 4237 fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; |
| 4027 fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; | 4238 fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; |
| 4239 fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; |
| 4028 fprintf(out, "static const %s yy_shift_ofst[] = {\n", | 4240 fprintf(out, "static const %s yy_shift_ofst[] = {\n", |
| 4029 minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++; | 4241 minimum_size_type(mnTknOfst, lemp->nterminal+lemp->nactiontab, &sz)); |
| 4242 lineno++; |
| 4030 lemp->tablesize += n*sz; | 4243 lemp->tablesize += n*sz; |
| 4031 for(i=j=0; i<n; i++){ | 4244 for(i=j=0; i<n; i++){ |
| 4032 int ofst; | 4245 int ofst; |
| 4033 stp = lemp->sorted[i]; | 4246 stp = lemp->sorted[i]; |
| 4034 ofst = stp->iTknOfst; | 4247 ofst = stp->iTknOfst; |
| 4035 if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1; | 4248 if( ofst==NO_OFFSET ) ofst = lemp->nactiontab; |
| 4036 if( j==0 ) fprintf(out," /* %5d */ ", i); | 4249 if( j==0 ) fprintf(out," /* %5d */ ", i); |
| 4037 fprintf(out, " %4d,", ofst); | 4250 fprintf(out, " %4d,", ofst); |
| 4038 if( j==9 || i==n-1 ){ | 4251 if( j==9 || i==n-1 ){ |
| 4039 fprintf(out, "\n"); lineno++; | 4252 fprintf(out, "\n"); lineno++; |
| 4040 j = 0; | 4253 j = 0; |
| 4041 }else{ | 4254 }else{ |
| 4042 j++; | 4255 j++; |
| 4043 } | 4256 } |
| 4044 } | 4257 } |
| 4045 fprintf(out, "};\n"); lineno++; | 4258 fprintf(out, "};\n"); lineno++; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4115 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } | 4328 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } |
| 4116 } | 4329 } |
| 4117 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } | 4330 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } |
| 4118 tplt_xfer(lemp->name,in,out,&lineno); | 4331 tplt_xfer(lemp->name,in,out,&lineno); |
| 4119 | 4332 |
| 4120 /* Generate a table containing a text string that describes every | 4333 /* Generate a table containing a text string that describes every |
| 4121 ** rule in the rule set of the grammar. This information is used | 4334 ** rule in the rule set of the grammar. This information is used |
| 4122 ** when tracing REDUCE actions. | 4335 ** when tracing REDUCE actions. |
| 4123 */ | 4336 */ |
| 4124 for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ | 4337 for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ |
| 4125 assert( rp->index==i ); | 4338 assert( rp->iRule==i ); |
| 4126 fprintf(out," /* %3d */ \"", i); | 4339 fprintf(out," /* %3d */ \"", i); |
| 4127 writeRuleText(out, rp); | 4340 writeRuleText(out, rp); |
| 4128 fprintf(out,"\",\n"); lineno++; | 4341 fprintf(out,"\",\n"); lineno++; |
| 4129 } | 4342 } |
| 4130 tplt_xfer(lemp->name,in,out,&lineno); | 4343 tplt_xfer(lemp->name,in,out,&lineno); |
| 4131 | 4344 |
| 4132 /* Generate code which executes every time a symbol is popped from | 4345 /* Generate code which executes every time a symbol is popped from |
| 4133 ** the stack while processing errors or while destroying the parser. | 4346 ** the stack while processing errors or while destroying the parser. |
| 4134 ** (In other words, generate the %destructor actions) | 4347 ** (In other words, generate the %destructor actions) |
| 4135 */ | 4348 */ |
| (...skipping 29 matching lines...) Expand all Loading... |
| 4165 dflt_sp = sp; | 4378 dflt_sp = sp; |
| 4166 } | 4379 } |
| 4167 if( dflt_sp!=0 ){ | 4380 if( dflt_sp!=0 ){ |
| 4168 emit_destructor_code(out,dflt_sp,lemp,&lineno); | 4381 emit_destructor_code(out,dflt_sp,lemp,&lineno); |
| 4169 } | 4382 } |
| 4170 fprintf(out," break;\n"); lineno++; | 4383 fprintf(out," break;\n"); lineno++; |
| 4171 } | 4384 } |
| 4172 for(i=0; i<lemp->nsymbol; i++){ | 4385 for(i=0; i<lemp->nsymbol; i++){ |
| 4173 struct symbol *sp = lemp->symbols[i]; | 4386 struct symbol *sp = lemp->symbols[i]; |
| 4174 if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; | 4387 if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; |
| 4388 if( sp->destLineno<0 ) continue; /* Already emitted */ |
| 4175 fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; | 4389 fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; |
| 4176 | 4390 |
| 4177 /* Combine duplicate destructors into a single case */ | 4391 /* Combine duplicate destructors into a single case */ |
| 4178 for(j=i+1; j<lemp->nsymbol; j++){ | 4392 for(j=i+1; j<lemp->nsymbol; j++){ |
| 4179 struct symbol *sp2 = lemp->symbols[j]; | 4393 struct symbol *sp2 = lemp->symbols[j]; |
| 4180 if( sp2 && sp2->type!=TERMINAL && sp2->destructor | 4394 if( sp2 && sp2->type!=TERMINAL && sp2->destructor |
| 4181 && sp2->dtnum==sp->dtnum | 4395 && sp2->dtnum==sp->dtnum |
| 4182 && strcmp(sp->destructor,sp2->destructor)==0 ){ | 4396 && strcmp(sp->destructor,sp2->destructor)==0 ){ |
| 4183 fprintf(out," case %d: /* %s */\n", | 4397 fprintf(out," case %d: /* %s */\n", |
| 4184 sp2->index, sp2->name); lineno++; | 4398 sp2->index, sp2->name); lineno++; |
| 4185 sp2->destructor = 0; | 4399 sp2->destLineno = -1; /* Avoid emitting this destructor again */ |
| 4186 } | 4400 } |
| 4187 } | 4401 } |
| 4188 | 4402 |
| 4189 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); | 4403 emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); |
| 4190 fprintf(out," break;\n"); lineno++; | 4404 fprintf(out," break;\n"); lineno++; |
| 4191 } | 4405 } |
| 4192 tplt_xfer(lemp->name,in,out,&lineno); | 4406 tplt_xfer(lemp->name,in,out,&lineno); |
| 4193 | 4407 |
| 4194 /* Generate code which executes whenever the parser stack overflows */ | 4408 /* Generate code which executes whenever the parser stack overflows */ |
| 4195 tplt_print(out,lemp,lemp->overflow,&lineno); | 4409 tplt_print(out,lemp,lemp->overflow,&lineno); |
| 4196 tplt_xfer(lemp->name,in,out,&lineno); | 4410 tplt_xfer(lemp->name,in,out,&lineno); |
| 4197 | 4411 |
| 4198 /* Generate the table of rule information | 4412 /* Generate the table of rule information |
| 4199 ** | 4413 ** |
| 4200 ** Note: This code depends on the fact that rules are number | 4414 ** Note: This code depends on the fact that rules are number |
| 4201 ** sequentually beginning with 0. | 4415 ** sequentually beginning with 0. |
| 4202 */ | 4416 */ |
| 4203 for(rp=lemp->rule; rp; rp=rp->next){ | 4417 for(rp=lemp->rule; rp; rp=rp->next){ |
| 4204 fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++; | 4418 fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++; |
| 4205 } | 4419 } |
| 4206 tplt_xfer(lemp->name,in,out,&lineno); | 4420 tplt_xfer(lemp->name,in,out,&lineno); |
| 4207 | 4421 |
| 4208 /* Generate code which execution during each REDUCE action */ | 4422 /* Generate code which execution during each REDUCE action */ |
| 4423 i = 0; |
| 4209 for(rp=lemp->rule; rp; rp=rp->next){ | 4424 for(rp=lemp->rule; rp; rp=rp->next){ |
| 4210 translate_code(lemp, rp); | 4425 i += translate_code(lemp, rp); |
| 4426 } |
| 4427 if( i ){ |
| 4428 fprintf(out," YYMINORTYPE yylhsminor;\n"); lineno++; |
| 4211 } | 4429 } |
| 4212 /* First output rules other than the default: rule */ | 4430 /* First output rules other than the default: rule */ |
| 4213 for(rp=lemp->rule; rp; rp=rp->next){ | 4431 for(rp=lemp->rule; rp; rp=rp->next){ |
| 4214 struct rule *rp2; /* Other rules with the same action */ | 4432 struct rule *rp2; /* Other rules with the same action */ |
| 4215 if( rp->code==0 ) continue; | 4433 if( rp->codeEmitted ) continue; |
| 4216 if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */ | 4434 if( rp->noCode ){ |
| 4217 fprintf(out," case %d: /* ", rp->index); | 4435 /* No C code actions, so this will be part of the "default:" rule */ |
| 4436 continue; |
| 4437 } |
| 4438 fprintf(out," case %d: /* ", rp->iRule); |
| 4218 writeRuleText(out, rp); | 4439 writeRuleText(out, rp); |
| 4219 fprintf(out, " */\n"); lineno++; | 4440 fprintf(out, " */\n"); lineno++; |
| 4220 for(rp2=rp->next; rp2; rp2=rp2->next){ | 4441 for(rp2=rp->next; rp2; rp2=rp2->next){ |
| 4221 if( rp2->code==rp->code ){ | 4442 if( rp2->code==rp->code && rp2->codePrefix==rp->codePrefix |
| 4222 fprintf(out," case %d: /* ", rp2->index); | 4443 && rp2->codeSuffix==rp->codeSuffix ){ |
| 4444 fprintf(out," case %d: /* ", rp2->iRule); |
| 4223 writeRuleText(out, rp2); | 4445 writeRuleText(out, rp2); |
| 4224 fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->index); lineno++; | 4446 fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->iRule); lineno++; |
| 4225 rp2->code = 0; | 4447 rp2->codeEmitted = 1; |
| 4226 } | 4448 } |
| 4227 } | 4449 } |
| 4228 emit_code(out,rp,lemp,&lineno); | 4450 emit_code(out,rp,lemp,&lineno); |
| 4229 fprintf(out," break;\n"); lineno++; | 4451 fprintf(out," break;\n"); lineno++; |
| 4230 rp->code = 0; | 4452 rp->codeEmitted = 1; |
| 4231 } | 4453 } |
| 4232 /* Finally, output the default: rule. We choose as the default: all | 4454 /* Finally, output the default: rule. We choose as the default: all |
| 4233 ** empty actions. */ | 4455 ** empty actions. */ |
| 4234 fprintf(out," default:\n"); lineno++; | 4456 fprintf(out," default:\n"); lineno++; |
| 4235 for(rp=lemp->rule; rp; rp=rp->next){ | 4457 for(rp=lemp->rule; rp; rp=rp->next){ |
| 4236 if( rp->code==0 ) continue; | 4458 if( rp->codeEmitted ) continue; |
| 4237 assert( rp->code[0]=='\n' && rp->code[1]==0 ); | 4459 assert( rp->noCode ); |
| 4238 fprintf(out," /* (%d) ", rp->index); | 4460 fprintf(out," /* (%d) ", rp->iRule); |
| 4239 writeRuleText(out, rp); | 4461 writeRuleText(out, rp); |
| 4240 fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->index); lineno++; | 4462 if( rp->doesReduce ){ |
| 4463 fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->iRule); lineno++; |
| 4464 }else{ |
| 4465 fprintf(out, " (OPTIMIZED OUT) */ assert(yyruleno!=%d);\n", |
| 4466 rp->iRule); lineno++; |
| 4467 } |
| 4241 } | 4468 } |
| 4242 fprintf(out," break;\n"); lineno++; | 4469 fprintf(out," break;\n"); lineno++; |
| 4243 tplt_xfer(lemp->name,in,out,&lineno); | 4470 tplt_xfer(lemp->name,in,out,&lineno); |
| 4244 | 4471 |
| 4245 /* Generate code which executes if a parse fails */ | 4472 /* Generate code which executes if a parse fails */ |
| 4246 tplt_print(out,lemp,lemp->failure,&lineno); | 4473 tplt_print(out,lemp,lemp->failure,&lineno); |
| 4247 tplt_xfer(lemp->name,in,out,&lineno); | 4474 tplt_xfer(lemp->name,in,out,&lineno); |
| 4248 | 4475 |
| 4249 /* Generate code which executes when a syntax error occurs */ | 4476 /* Generate code which executes when a syntax error occurs */ |
| 4250 tplt_print(out,lemp,lemp->error,&lineno); | 4477 tplt_print(out,lemp,lemp->error,&lineno); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4301 /* Reduce the size of the action tables, if possible, by making use | 4528 /* Reduce the size of the action tables, if possible, by making use |
| 4302 ** of defaults. | 4529 ** of defaults. |
| 4303 ** | 4530 ** |
| 4304 ** In this version, we take the most frequent REDUCE action and make | 4531 ** In this version, we take the most frequent REDUCE action and make |
| 4305 ** it the default. Except, there is no default if the wildcard token | 4532 ** it the default. Except, there is no default if the wildcard token |
| 4306 ** is a possible look-ahead. | 4533 ** is a possible look-ahead. |
| 4307 */ | 4534 */ |
| 4308 void CompressTables(struct lemon *lemp) | 4535 void CompressTables(struct lemon *lemp) |
| 4309 { | 4536 { |
| 4310 struct state *stp; | 4537 struct state *stp; |
| 4311 struct action *ap, *ap2; | 4538 struct action *ap, *ap2, *nextap; |
| 4312 struct rule *rp, *rp2, *rbest; | 4539 struct rule *rp, *rp2, *rbest; |
| 4313 int nbest, n; | 4540 int nbest, n; |
| 4314 int i; | 4541 int i; |
| 4315 int usesWildcard; | 4542 int usesWildcard; |
| 4316 | 4543 |
| 4317 for(i=0; i<lemp->nstate; i++){ | 4544 for(i=0; i<lemp->nstate; i++){ |
| 4318 stp = lemp->sorted[i]; | 4545 stp = lemp->sorted[i]; |
| 4319 nbest = 0; | 4546 nbest = 0; |
| 4320 rbest = 0; | 4547 rbest = 0; |
| 4321 usesWildcard = 0; | 4548 usesWildcard = 0; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4378 for(ap=stp->ap; ap; ap=ap->next){ | 4605 for(ap=stp->ap; ap; ap=ap->next){ |
| 4379 struct state *pNextState; | 4606 struct state *pNextState; |
| 4380 if( ap->type!=SHIFT ) continue; | 4607 if( ap->type!=SHIFT ) continue; |
| 4381 pNextState = ap->x.stp; | 4608 pNextState = ap->x.stp; |
| 4382 if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){ | 4609 if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){ |
| 4383 ap->type = SHIFTREDUCE; | 4610 ap->type = SHIFTREDUCE; |
| 4384 ap->x.rp = pNextState->pDfltReduce; | 4611 ap->x.rp = pNextState->pDfltReduce; |
| 4385 } | 4612 } |
| 4386 } | 4613 } |
| 4387 } | 4614 } |
| 4615 |
| 4616 /* If a SHIFTREDUCE action specifies a rule that has a single RHS term |
| 4617 ** (meaning that the SHIFTREDUCE will land back in the state where it |
| 4618 ** started) and if there is no C-code associated with the reduce action, |
| 4619 ** then we can go ahead and convert the action to be the same as the |
| 4620 ** action for the RHS of the rule. |
| 4621 */ |
| 4622 for(i=0; i<lemp->nstate; i++){ |
| 4623 stp = lemp->sorted[i]; |
| 4624 for(ap=stp->ap; ap; ap=nextap){ |
| 4625 nextap = ap->next; |
| 4626 if( ap->type!=SHIFTREDUCE ) continue; |
| 4627 rp = ap->x.rp; |
| 4628 if( rp->noCode==0 ) continue; |
| 4629 if( rp->nrhs!=1 ) continue; |
| 4630 #if 1 |
| 4631 /* Only apply this optimization to non-terminals. It would be OK to |
| 4632 ** apply it to terminal symbols too, but that makes the parser tables |
| 4633 ** larger. */ |
| 4634 if( ap->sp->index<lemp->nterminal ) continue; |
| 4635 #endif |
| 4636 /* If we reach this point, it means the optimization can be applied */ |
| 4637 nextap = ap; |
| 4638 for(ap2=stp->ap; ap2 && (ap2==ap || ap2->sp!=rp->lhs); ap2=ap2->next){} |
| 4639 assert( ap2!=0 ); |
| 4640 ap->spOpt = ap2->sp; |
| 4641 ap->type = ap2->type; |
| 4642 ap->x = ap2->x; |
| 4643 } |
| 4644 } |
| 4388 } | 4645 } |
| 4389 | 4646 |
| 4390 | 4647 |
| 4391 /* | 4648 /* |
| 4392 ** Compare two states for sorting purposes. The smaller state is the | 4649 ** Compare two states for sorting purposes. The smaller state is the |
| 4393 ** one with the most non-terminal actions. If they have the same number | 4650 ** one with the most non-terminal actions. If they have the same number |
| 4394 ** of non-terminal actions, then the smaller is the one with the most | 4651 ** of non-terminal actions, then the smaller is the one with the most |
| 4395 ** token actions. | 4652 ** token actions. |
| 4396 */ | 4653 */ |
| 4397 static int stateResortCompare(const void *a, const void *b){ | 4654 static int stateResortCompare(const void *a, const void *b){ |
| (...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5170 ** as it is removed. ("f" may be null to avoid this step.) */ | 5427 ** as it is removed. ("f" may be null to avoid this step.) */ |
| 5171 void Configtable_clear(int(*f)(struct config *)) | 5428 void Configtable_clear(int(*f)(struct config *)) |
| 5172 { | 5429 { |
| 5173 int i; | 5430 int i; |
| 5174 if( x4a==0 || x4a->count==0 ) return; | 5431 if( x4a==0 || x4a->count==0 ) return; |
| 5175 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); | 5432 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); |
| 5176 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; | 5433 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; |
| 5177 x4a->count = 0; | 5434 x4a->count = 0; |
| 5178 return; | 5435 return; |
| 5179 } | 5436 } |
| OLD | NEW |