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 |