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> |
11 #include <string.h> | 11 #include <string.h> |
12 #include <ctype.h> | 12 #include <ctype.h> |
13 #include <stdlib.h> | 13 #include <stdlib.h> |
14 #include <assert.h> | 14 #include <assert.h> |
15 | 15 |
| 16 #define ISSPACE(X) isspace((unsigned char)(X)) |
| 17 #define ISDIGIT(X) isdigit((unsigned char)(X)) |
| 18 #define ISALNUM(X) isalnum((unsigned char)(X)) |
| 19 #define ISALPHA(X) isalpha((unsigned char)(X)) |
| 20 #define ISUPPER(X) isupper((unsigned char)(X)) |
| 21 #define ISLOWER(X) islower((unsigned char)(X)) |
| 22 |
| 23 |
16 #ifndef __WIN32__ | 24 #ifndef __WIN32__ |
17 # if defined(_WIN32) || defined(WIN32) | 25 # if defined(_WIN32) || defined(WIN32) |
18 # define __WIN32__ | 26 # define __WIN32__ |
19 # endif | 27 # endif |
20 #endif | 28 #endif |
21 | 29 |
22 #ifdef __WIN32__ | 30 #ifdef __WIN32__ |
23 #ifdef __cplusplus | 31 #ifdef __cplusplus |
24 extern "C" { | 32 extern "C" { |
25 #endif | 33 #endif |
(...skipping 22 matching lines...) Expand all Loading... |
48 ** as C evolves ever closer to Ada.... To work around the latest problems | 56 ** as C evolves ever closer to Ada.... To work around the latest problems |
49 ** we have to define the following variant of strlen(). | 57 ** we have to define the following variant of strlen(). |
50 */ | 58 */ |
51 #define lemonStrlen(X) ((int)strlen(X)) | 59 #define lemonStrlen(X) ((int)strlen(X)) |
52 | 60 |
53 /* | 61 /* |
54 ** Compilers are starting to complain about the use of sprintf() and strcpy(), | 62 ** Compilers are starting to complain about the use of sprintf() and strcpy(), |
55 ** saying they are unsafe. So we define our own versions of those routines too. | 63 ** saying they are unsafe. So we define our own versions of those routines too. |
56 ** | 64 ** |
57 ** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and | 65 ** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and |
58 ** lemon_addtext(). The first two are replacements for sprintf() and vsprintf()
. | 66 ** lemon_addtext(). The first two are replacements for sprintf() and vsprintf(). |
59 ** The third is a helper routine for vsnprintf() that adds texts to the end of a | 67 ** The third is a helper routine for vsnprintf() that adds texts to the end of a |
60 ** buffer, making sure the buffer is always zero-terminated. | 68 ** buffer, making sure the buffer is always zero-terminated. |
61 ** | 69 ** |
62 ** The string formatter is a minimal subset of stdlib sprintf() supporting only | 70 ** The string formatter is a minimal subset of stdlib sprintf() supporting only |
63 ** a few simply conversions: | 71 ** a few simply conversions: |
64 ** | 72 ** |
65 ** %d | 73 ** %d |
66 ** %s | 74 ** %s |
67 ** %.*s | 75 ** %.*s |
68 ** | 76 ** |
(...skipping 17 matching lines...) Expand all Loading... |
86 int i, j, k, c; | 94 int i, j, k, c; |
87 int nUsed = 0; | 95 int nUsed = 0; |
88 const char *z; | 96 const char *z; |
89 char zTemp[50]; | 97 char zTemp[50]; |
90 str[0] = 0; | 98 str[0] = 0; |
91 for(i=j=0; (c = zFormat[i])!=0; i++){ | 99 for(i=j=0; (c = zFormat[i])!=0; i++){ |
92 if( c=='%' ){ | 100 if( c=='%' ){ |
93 int iWidth = 0; | 101 int iWidth = 0; |
94 lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); | 102 lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); |
95 c = zFormat[++i]; | 103 c = zFormat[++i]; |
96 if( isdigit(c) || (c=='-' && isdigit(zFormat[i+1])) ){ | 104 if( ISDIGIT(c) || (c=='-' && ISDIGIT(zFormat[i+1])) ){ |
97 if( c=='-' ) i++; | 105 if( c=='-' ) i++; |
98 while( isdigit(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; | 106 while( ISDIGIT(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; |
99 if( c=='-' ) iWidth = -iWidth; | 107 if( c=='-' ) iWidth = -iWidth; |
100 c = zFormat[i]; | 108 c = zFormat[i]; |
101 } | 109 } |
102 if( c=='d' ){ | 110 if( c=='d' ){ |
103 int v = va_arg(ap, int); | 111 int v = va_arg(ap, int); |
104 if( v<0 ){ | 112 if( v<0 ){ |
105 lemon_addtext(str, &nUsed, "-", 1, iWidth); | 113 lemon_addtext(str, &nUsed, "-", 1, iWidth); |
106 v = -v; | 114 v = -v; |
107 }else if( v==0 ){ | 115 }else if( v==0 ){ |
108 lemon_addtext(str, &nUsed, "0", 1, iWidth); | 116 lemon_addtext(str, &nUsed, "0", 1, iWidth); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 enum e_action { | 317 enum e_action { |
310 SHIFT, | 318 SHIFT, |
311 ACCEPT, | 319 ACCEPT, |
312 REDUCE, | 320 REDUCE, |
313 ERROR, | 321 ERROR, |
314 SSCONFLICT, /* A shift/shift conflict */ | 322 SSCONFLICT, /* A shift/shift conflict */ |
315 SRCONFLICT, /* Was a reduce, but part of a conflict */ | 323 SRCONFLICT, /* Was a reduce, but part of a conflict */ |
316 RRCONFLICT, /* Was a reduce, but part of a conflict */ | 324 RRCONFLICT, /* Was a reduce, but part of a conflict */ |
317 SH_RESOLVED, /* Was a shift. Precedence resolved conflict */ | 325 SH_RESOLVED, /* Was a shift. Precedence resolved conflict */ |
318 RD_RESOLVED, /* Was reduce. Precedence resolved conflict */ | 326 RD_RESOLVED, /* Was reduce. Precedence resolved conflict */ |
319 NOT_USED /* Deleted by compression */ | 327 NOT_USED, /* Deleted by compression */ |
| 328 SHIFTREDUCE /* Shift first, then reduce */ |
320 }; | 329 }; |
321 | 330 |
322 /* Every shift or reduce operation is stored as one of the following */ | 331 /* Every shift or reduce operation is stored as one of the following */ |
323 struct action { | 332 struct action { |
324 struct symbol *sp; /* The look-ahead symbol */ | 333 struct symbol *sp; /* The look-ahead symbol */ |
325 enum e_action type; | 334 enum e_action type; |
326 union { | 335 union { |
327 struct state *stp; /* The new state, if a shift */ | 336 struct state *stp; /* The new state, if a shift */ |
328 struct rule *rp; /* The rule, if a reduce */ | 337 struct rule *rp; /* The rule, if a reduce */ |
329 } x; | 338 } x; |
330 struct action *next; /* Next action for this state */ | 339 struct action *next; /* Next action for this state */ |
331 struct action *collide; /* Next action with the same hash */ | 340 struct action *collide; /* Next action with the same hash */ |
332 }; | 341 }; |
333 | 342 |
334 /* Each state of the generated parser's finite state machine | 343 /* Each state of the generated parser's finite state machine |
335 ** is encoded as an instance of the following structure. */ | 344 ** is encoded as an instance of the following structure. */ |
336 struct state { | 345 struct state { |
337 struct config *bp; /* The basis configurations for this state */ | 346 struct config *bp; /* The basis configurations for this state */ |
338 struct config *cfp; /* All configurations in this set */ | 347 struct config *cfp; /* All configurations in this set */ |
339 int statenum; /* Sequential number for this state */ | 348 int statenum; /* Sequential number for this state */ |
340 struct action *ap; /* Array of actions for this state */ | 349 struct action *ap; /* Array of actions for this state */ |
341 int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */ | 350 int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */ |
342 int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */ | 351 int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */ |
343 int iDflt; /* Default action */ | 352 int iDfltReduce; /* Default action is to REDUCE by this rule */ |
| 353 struct rule *pDfltReduce;/* The default REDUCE rule. */ |
| 354 int autoReduce; /* True if this is an auto-reduce state */ |
344 }; | 355 }; |
345 #define NO_OFFSET (-2147483647) | 356 #define NO_OFFSET (-2147483647) |
346 | 357 |
347 /* A followset propagation link indicates that the contents of one | 358 /* A followset propagation link indicates that the contents of one |
348 ** configuration followset should be propagated to another whenever | 359 ** configuration followset should be propagated to another whenever |
349 ** the first changes. */ | 360 ** the first changes. */ |
350 struct plink { | 361 struct plink { |
351 struct config *cfp; /* The configuration to which linked */ | 362 struct config *cfp; /* The configuration to which linked */ |
352 struct plink *next; /* The next propagate link */ | 363 struct plink *next; /* The next propagate link */ |
353 }; | 364 }; |
354 | 365 |
355 /* The state vector for the entire parser generator is recorded as | 366 /* The state vector for the entire parser generator is recorded as |
356 ** follows. (LEMON uses no global variables and makes little use of | 367 ** follows. (LEMON uses no global variables and makes little use of |
357 ** static variables. Fields in the following structure can be thought | 368 ** static variables. Fields in the following structure can be thought |
358 ** of as begin global variables in the program.) */ | 369 ** of as begin global variables in the program.) */ |
359 struct lemon { | 370 struct lemon { |
360 struct state **sorted; /* Table of states sorted by state number */ | 371 struct state **sorted; /* Table of states sorted by state number */ |
361 struct rule *rule; /* List of all rules */ | 372 struct rule *rule; /* List of all rules */ |
362 int nstate; /* Number of states */ | 373 int nstate; /* Number of states */ |
| 374 int nxstate; /* nstate with tail degenerate states removed */ |
363 int nrule; /* Number of rules */ | 375 int nrule; /* Number of rules */ |
364 int nsymbol; /* Number of terminal and nonterminal symbols */ | 376 int nsymbol; /* Number of terminal and nonterminal symbols */ |
365 int nterminal; /* Number of terminal symbols */ | 377 int nterminal; /* Number of terminal symbols */ |
366 struct symbol **symbols; /* Sorted array of pointers to symbols */ | 378 struct symbol **symbols; /* Sorted array of pointers to symbols */ |
367 int errorcnt; /* Number of errors */ | 379 int errorcnt; /* Number of errors */ |
368 struct symbol *errsym; /* The error symbol */ | 380 struct symbol *errsym; /* The error symbol */ |
369 struct symbol *wildcard; /* Token that matches anything */ | 381 struct symbol *wildcard; /* Token that matches anything */ |
370 char *name; /* Name of the generated parser */ | 382 char *name; /* Name of the generated parser */ |
371 char *arg; /* Declaration of the 3th argument to parser */ | 383 char *arg; /* Declaration of the 3th argument to parser */ |
372 char *tokentype; /* Type of terminal symbols in the parser stack */ | 384 char *tokentype; /* Type of terminal symbols in the parser stack */ |
373 char *vartype; /* The default type of non-terminal symbols */ | 385 char *vartype; /* The default type of non-terminal symbols */ |
374 char *start; /* Name of the start symbol for the grammar */ | 386 char *start; /* Name of the start symbol for the grammar */ |
375 char *stacksize; /* Size of the parser stack */ | 387 char *stacksize; /* Size of the parser stack */ |
376 char *include; /* Code to put at the start of the C file */ | 388 char *include; /* Code to put at the start of the C file */ |
377 char *error; /* Code to execute when an error is seen */ | 389 char *error; /* Code to execute when an error is seen */ |
378 char *overflow; /* Code to execute on a stack overflow */ | 390 char *overflow; /* Code to execute on a stack overflow */ |
379 char *failure; /* Code to execute on parser failure */ | 391 char *failure; /* Code to execute on parser failure */ |
380 char *accept; /* Code to execute when the parser excepts */ | 392 char *accept; /* Code to execute when the parser excepts */ |
381 char *extracode; /* Code appended to the generated file */ | 393 char *extracode; /* Code appended to the generated file */ |
382 char *tokendest; /* Code to execute to destroy token data */ | 394 char *tokendest; /* Code to execute to destroy token data */ |
383 char *vardest; /* Code for the default non-terminal destructor */ | 395 char *vardest; /* Code for the default non-terminal destructor */ |
384 char *filename; /* Name of the input file */ | 396 char *filename; /* Name of the input file */ |
385 char *outname; /* Name of the current output file */ | 397 char *outname; /* Name of the current output file */ |
386 char *tokenprefix; /* A prefix added to token names in the .h file */ | 398 char *tokenprefix; /* A prefix added to token names in the .h file */ |
387 int nconflict; /* Number of parsing conflicts */ | 399 int nconflict; /* Number of parsing conflicts */ |
388 int tablesize; /* Size of the parse tables */ | 400 int nactiontab; /* Number of entries in the yy_action[] table */ |
| 401 int tablesize; /* Total table size of all tables in bytes */ |
389 int basisflag; /* Print only basis configurations */ | 402 int basisflag; /* Print only basis configurations */ |
390 int has_fallback; /* True if any %fallback is seen in the grammar */ | 403 int has_fallback; /* True if any %fallback is seen in the grammar */ |
391 int nolinenosflag; /* True if #line statements should not be printed */ | 404 int nolinenosflag; /* True if #line statements should not be printed */ |
392 char *argv0; /* Name of the program */ | 405 char *argv0; /* Name of the program */ |
393 }; | 406 }; |
394 | 407 |
395 #define MemoryCheck(X) if((X)==0){ \ | 408 #define MemoryCheck(X) if((X)==0){ \ |
396 extern void memory_error(); \ | 409 extern void memory_error(); \ |
397 memory_error(); \ | 410 memory_error(); \ |
398 } | 411 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 */ | 489 */ |
477 static int actioncmp( | 490 static int actioncmp( |
478 struct action *ap1, | 491 struct action *ap1, |
479 struct action *ap2 | 492 struct action *ap2 |
480 ){ | 493 ){ |
481 int rc; | 494 int rc; |
482 rc = ap1->sp->index - ap2->sp->index; | 495 rc = ap1->sp->index - ap2->sp->index; |
483 if( rc==0 ){ | 496 if( rc==0 ){ |
484 rc = (int)ap1->type - (int)ap2->type; | 497 rc = (int)ap1->type - (int)ap2->type; |
485 } | 498 } |
486 if( rc==0 && ap1->type==REDUCE ){ | 499 if( rc==0 && (ap1->type==REDUCE || ap1->type==SHIFTREDUCE) ){ |
487 rc = ap1->x.rp->index - ap2->x.rp->index; | 500 rc = ap1->x.rp->index - ap2->x.rp->index; |
488 } | 501 } |
489 if( rc==0 ){ | 502 if( rc==0 ){ |
490 rc = (int) (ap2 - ap1); | 503 rc = (int) (ap2 - ap1); |
491 } | 504 } |
492 return rc; | 505 return rc; |
493 } | 506 } |
494 | 507 |
495 /* Sort parser actions */ | 508 /* Sort parser actions */ |
496 static struct action *Action_sort( | 509 static struct action *Action_sort( |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1107 sp = lemp->rule->lhs; | 1120 sp = lemp->rule->lhs; |
1108 } | 1121 } |
1109 /* Add to the first state (which is always the starting state of the | 1122 /* Add to the first state (which is always the starting state of the |
1110 ** finite state machine) an action to ACCEPT if the lookahead is the | 1123 ** finite state machine) an action to ACCEPT if the lookahead is the |
1111 ** start nonterminal. */ | 1124 ** start nonterminal. */ |
1112 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); | 1125 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); |
1113 | 1126 |
1114 /* Resolve conflicts */ | 1127 /* Resolve conflicts */ |
1115 for(i=0; i<lemp->nstate; i++){ | 1128 for(i=0; i<lemp->nstate; i++){ |
1116 struct action *ap, *nap; | 1129 struct action *ap, *nap; |
1117 struct state *stp; | |
1118 stp = lemp->sorted[i]; | 1130 stp = lemp->sorted[i]; |
1119 /* assert( stp->ap ); */ | 1131 /* assert( stp->ap ); */ |
1120 stp->ap = Action_sort(stp->ap); | 1132 stp->ap = Action_sort(stp->ap); |
1121 for(ap=stp->ap; ap && ap->next; ap=ap->next){ | 1133 for(ap=stp->ap; ap && ap->next; ap=ap->next){ |
1122 for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ | 1134 for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ |
1123 /* The two actions "ap" and "nap" have the same lookahead. | 1135 /* The two actions "ap" and "nap" have the same lookahead. |
1124 ** Figure out which one should be used */ | 1136 ** Figure out which one should be used */ |
1125 lemp->nconflict += resolve_conflict(ap,nap); | 1137 lemp->nconflict += resolve_conflict(ap,nap); |
1126 } | 1138 } |
1127 } | 1139 } |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1369 } | 1381 } |
1370 if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); | 1382 if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); |
1371 } | 1383 } |
1372 } | 1384 } |
1373 } | 1385 } |
1374 return; | 1386 return; |
1375 } | 1387 } |
1376 | 1388 |
1377 /* Sort the configuration list */ | 1389 /* Sort the configuration list */ |
1378 void Configlist_sort(){ | 1390 void Configlist_sort(){ |
1379 current = (struct config *)msort((char *)current,(char **)&(current->next),Con
figcmp); | 1391 current = (struct config*)msort((char*)current,(char**)&(current->next), |
| 1392 Configcmp); |
1380 currentend = 0; | 1393 currentend = 0; |
1381 return; | 1394 return; |
1382 } | 1395 } |
1383 | 1396 |
1384 /* Sort the basis configuration list */ | 1397 /* Sort the basis configuration list */ |
1385 void Configlist_sortbasis(){ | 1398 void Configlist_sortbasis(){ |
1386 basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configc
mp); | 1399 basis = (struct config*)msort((char*)current,(char**)&(current->bp), |
| 1400 Configcmp); |
1387 basisend = 0; | 1401 basisend = 0; |
1388 return; | 1402 return; |
1389 } | 1403 } |
1390 | 1404 |
1391 /* Return a pointer to the head of the configuration list and | 1405 /* Return a pointer to the head of the configuration list and |
1392 ** reset the list */ | 1406 ** reset the list */ |
1393 struct config *Configlist_return(){ | 1407 struct config *Configlist_return(){ |
1394 struct config *old; | 1408 struct config *old; |
1395 old = current; | 1409 old = current; |
1396 current = 0; | 1410 current = 0; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1474 | 1488 |
1475 static char *user_templatename = NULL; | 1489 static char *user_templatename = NULL; |
1476 static void handle_T_option(char *z){ | 1490 static void handle_T_option(char *z){ |
1477 user_templatename = (char *) malloc( lemonStrlen(z)+1 ); | 1491 user_templatename = (char *) malloc( lemonStrlen(z)+1 ); |
1478 if( user_templatename==0 ){ | 1492 if( user_templatename==0 ){ |
1479 memory_error(); | 1493 memory_error(); |
1480 } | 1494 } |
1481 lemon_strcpy(user_templatename, z); | 1495 lemon_strcpy(user_templatename, z); |
1482 } | 1496 } |
1483 | 1497 |
| 1498 /* forward reference */ |
| 1499 static const char *minimum_size_type(int lwr, int upr, int *pnByte); |
| 1500 |
| 1501 /* Print a single line of the "Parser Stats" output |
| 1502 */ |
| 1503 static void stats_line(const char *zLabel, int iValue){ |
| 1504 int nLabel = lemonStrlen(zLabel); |
| 1505 printf(" %s%.*s %5d\n", zLabel, |
| 1506 35-nLabel, "................................", |
| 1507 iValue); |
| 1508 } |
| 1509 |
1484 /* The main program. Parse the command line and do it... */ | 1510 /* The main program. Parse the command line and do it... */ |
1485 int main(int argc, char **argv) | 1511 int main(int argc, char **argv) |
1486 { | 1512 { |
1487 static int version = 0; | 1513 static int version = 0; |
1488 static int rpflag = 0; | 1514 static int rpflag = 0; |
1489 static int basisflag = 0; | 1515 static int basisflag = 0; |
1490 static int compress = 0; | 1516 static int compress = 0; |
1491 static int quiet = 0; | 1517 static int quiet = 0; |
1492 static int statistics = 0; | 1518 static int statistics = 0; |
1493 static int mhflag = 0; | 1519 static int mhflag = 0; |
1494 static int nolinenosflag = 0; | 1520 static int nolinenosflag = 0; |
1495 static int noResort = 0; | 1521 static int noResort = 0; |
1496 static struct s_options options[] = { | 1522 static struct s_options options[] = { |
1497 {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, | 1523 {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, |
1498 {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, | 1524 {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, |
1499 {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, | 1525 {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, |
1500 {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."}, | 1526 {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"}, |
1501 {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, | 1527 {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, |
| 1528 {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"}, |
1502 {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."}, | 1529 {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."}, |
1503 {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."}, | 1530 {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."}, |
| 1531 {OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)"}, |
1504 {OPT_FLAG, "p", (char*)&showPrecedenceConflict, | 1532 {OPT_FLAG, "p", (char*)&showPrecedenceConflict, |
1505 "Show conflicts resolved by precedence rules"}, | 1533 "Show conflicts resolved by precedence rules"}, |
1506 {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."}, | 1534 {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."}, |
1507 {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"}, | 1535 {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"}, |
1508 {OPT_FLAG, "s", (char*)&statistics, | 1536 {OPT_FLAG, "s", (char*)&statistics, |
1509 "Print parser stats to standard output."}, | 1537 "Print parser stats to standard output."}, |
1510 {OPT_FLAG, "x", (char*)&version, "Print the version number."}, | 1538 {OPT_FLAG, "x", (char*)&version, "Print the version number."}, |
| 1539 {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."}, |
| 1540 {OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"}, |
1511 {OPT_FLAG,0,0,0} | 1541 {OPT_FLAG,0,0,0} |
1512 }; | 1542 }; |
1513 int i; | 1543 int i; |
1514 int exitcode; | 1544 int exitcode; |
1515 struct lemon lem; | 1545 struct lemon lem; |
1516 | 1546 |
1517 OptInit(argv,options,stderr); | 1547 OptInit(argv,options,stderr); |
1518 if( version ){ | 1548 if( version ){ |
1519 printf("Lemon version 1.0\n"); | 1549 printf("Lemon version 1.0\n"); |
1520 exit(0); | 1550 exit(0); |
(...skipping 28 matching lines...) Expand all Loading... |
1549 /* Count and index the symbols of the grammar */ | 1579 /* Count and index the symbols of the grammar */ |
1550 Symbol_new("{default}"); | 1580 Symbol_new("{default}"); |
1551 lem.nsymbol = Symbol_count(); | 1581 lem.nsymbol = Symbol_count(); |
1552 lem.symbols = Symbol_arrayof(); | 1582 lem.symbols = Symbol_arrayof(); |
1553 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; | 1583 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
1554 qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); | 1584 qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); |
1555 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; | 1585 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
1556 while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } | 1586 while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } |
1557 assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); | 1587 assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); |
1558 lem.nsymbol = i - 1; | 1588 lem.nsymbol = i - 1; |
1559 for(i=1; isupper(lem.symbols[i]->name[0]); i++); | 1589 for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); |
1560 lem.nterminal = i; | 1590 lem.nterminal = i; |
1561 | 1591 |
1562 /* Generate a reprint of the grammar, if requested on the command line */ | 1592 /* Generate a reprint of the grammar, if requested on the command line */ |
1563 if( rpflag ){ | 1593 if( rpflag ){ |
1564 Reprint(&lem); | 1594 Reprint(&lem); |
1565 }else{ | 1595 }else{ |
1566 /* Initialize the size for all follow and first sets */ | 1596 /* Initialize the size for all follow and first sets */ |
1567 SetSize(lem.nterminal+1); | 1597 SetSize(lem.nterminal+1); |
1568 | 1598 |
1569 /* Find the precedence for every production rule (that has one) */ | 1599 /* Find the precedence for every production rule (that has one) */ |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1601 | 1631 |
1602 /* Generate the source code for the parser */ | 1632 /* Generate the source code for the parser */ |
1603 ReportTable(&lem, mhflag); | 1633 ReportTable(&lem, mhflag); |
1604 | 1634 |
1605 /* Produce a header file for use by the scanner. (This step is | 1635 /* Produce a header file for use by the scanner. (This step is |
1606 ** omitted if the "-m" option is used because makeheaders will | 1636 ** omitted if the "-m" option is used because makeheaders will |
1607 ** generate the file for us.) */ | 1637 ** generate the file for us.) */ |
1608 if( !mhflag ) ReportHeader(&lem); | 1638 if( !mhflag ) ReportHeader(&lem); |
1609 } | 1639 } |
1610 if( statistics ){ | 1640 if( statistics ){ |
1611 printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n", | 1641 printf("Parser statistics:\n"); |
1612 lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule); | 1642 stats_line("terminal symbols", lem.nterminal); |
1613 printf(" %d states, %d parser table entries, %d conflicts\
n", | 1643 stats_line("non-terminal symbols", lem.nsymbol - lem.nterminal); |
1614 lem.nstate, lem.tablesize, lem.nconflict); | 1644 stats_line("total symbols", lem.nsymbol); |
| 1645 stats_line("rules", lem.nrule); |
| 1646 stats_line("states", lem.nxstate); |
| 1647 stats_line("conflicts", lem.nconflict); |
| 1648 stats_line("action table entries", lem.nactiontab); |
| 1649 stats_line("total table size (bytes)", lem.tablesize); |
1615 } | 1650 } |
1616 if( lem.nconflict > 0 ){ | 1651 if( lem.nconflict > 0 ){ |
1617 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); | 1652 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); |
1618 } | 1653 } |
1619 | 1654 |
1620 /* return 0 on success, 1 on failure. */ | 1655 /* return 0 on success, 1 on failure. */ |
1621 exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; | 1656 exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; |
1622 exit(exitcode); | 1657 exit(exitcode); |
1623 return (exitcode); | 1658 return (exitcode); |
1624 } | 1659 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 #define LISTSIZE 30 | 1755 #define LISTSIZE 30 |
1721 static char *msort( | 1756 static char *msort( |
1722 char *list, | 1757 char *list, |
1723 char **next, | 1758 char **next, |
1724 int (*cmp)(const char*,const char*) | 1759 int (*cmp)(const char*,const char*) |
1725 ){ | 1760 ){ |
1726 unsigned long offset; | 1761 unsigned long offset; |
1727 char *ep; | 1762 char *ep; |
1728 char *set[LISTSIZE]; | 1763 char *set[LISTSIZE]; |
1729 int i; | 1764 int i; |
1730 offset = (unsigned long)next - (unsigned long)list; | 1765 offset = (unsigned long)((char*)next - (char*)list); |
1731 for(i=0; i<LISTSIZE; i++) set[i] = 0; | 1766 for(i=0; i<LISTSIZE; i++) set[i] = 0; |
1732 while( list ){ | 1767 while( list ){ |
1733 ep = list; | 1768 ep = list; |
1734 list = NEXT(list); | 1769 list = NEXT(list); |
1735 NEXT(ep) = 0; | 1770 NEXT(ep) = 0; |
1736 for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){ | 1771 for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){ |
1737 ep = merge(ep,set[i],cmp,offset); | 1772 ep = merge(ep,set[i],cmp,offset); |
1738 set[i] = 0; | 1773 set[i] = 0; |
1739 } | 1774 } |
1740 set[i] = ep; | 1775 set[i] = ep; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1805 for(j=0; op[j].label; j++){ | 1840 for(j=0; op[j].label; j++){ |
1806 if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break; | 1841 if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break; |
1807 } | 1842 } |
1808 v = argv[i][0]=='-' ? 1 : 0; | 1843 v = argv[i][0]=='-' ? 1 : 0; |
1809 if( op[j].label==0 ){ | 1844 if( op[j].label==0 ){ |
1810 if( err ){ | 1845 if( err ){ |
1811 fprintf(err,"%sundefined option.\n",emsg); | 1846 fprintf(err,"%sundefined option.\n",emsg); |
1812 errline(i,1,err); | 1847 errline(i,1,err); |
1813 } | 1848 } |
1814 errcnt++; | 1849 errcnt++; |
| 1850 }else if( op[j].arg==0 ){ |
| 1851 /* Ignore this option */ |
1815 }else if( op[j].type==OPT_FLAG ){ | 1852 }else if( op[j].type==OPT_FLAG ){ |
1816 *((int*)op[j].arg) = v; | 1853 *((int*)op[j].arg) = v; |
1817 }else if( op[j].type==OPT_FFLAG ){ | 1854 }else if( op[j].type==OPT_FFLAG ){ |
1818 (*(void(*)(int))(op[j].arg))(v); | 1855 (*(void(*)(int))(op[j].arg))(v); |
1819 }else if( op[j].type==OPT_FSTR ){ | 1856 }else if( op[j].type==OPT_FSTR ){ |
1820 (*(void(*)(char *))(op[j].arg))(&argv[i][2]); | 1857 (*(void(*)(char *))(op[j].arg))(&argv[i][2]); |
1821 }else{ | 1858 }else{ |
1822 if( err ){ | 1859 if( err ){ |
1823 fprintf(err,"%smissing argument on switch.\n",emsg); | 1860 fprintf(err,"%smissing argument on switch.\n",emsg); |
1824 errline(i,1,err); | 1861 errline(i,1,err); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1861 fprintf(err,"%soption requires an argument.\n",emsg); | 1898 fprintf(err,"%soption requires an argument.\n",emsg); |
1862 errline(i,0,err); | 1899 errline(i,0,err); |
1863 } | 1900 } |
1864 errcnt++; | 1901 errcnt++; |
1865 break; | 1902 break; |
1866 case OPT_DBL: | 1903 case OPT_DBL: |
1867 case OPT_FDBL: | 1904 case OPT_FDBL: |
1868 dv = strtod(cp,&end); | 1905 dv = strtod(cp,&end); |
1869 if( *end ){ | 1906 if( *end ){ |
1870 if( err ){ | 1907 if( err ){ |
1871 fprintf(err,"%sillegal character in floating-point argument.\n",emsg
); | 1908 fprintf(err, |
1872 errline(i,((unsigned long)end)-(unsigned long)argv[i],err); | 1909 "%sillegal character in floating-point argument.\n",emsg); |
| 1910 errline(i,(int)((char*)end-(char*)argv[i]),err); |
1873 } | 1911 } |
1874 errcnt++; | 1912 errcnt++; |
1875 } | 1913 } |
1876 break; | 1914 break; |
1877 case OPT_INT: | 1915 case OPT_INT: |
1878 case OPT_FINT: | 1916 case OPT_FINT: |
1879 lv = strtol(cp,&end,0); | 1917 lv = strtol(cp,&end,0); |
1880 if( *end ){ | 1918 if( *end ){ |
1881 if( err ){ | 1919 if( err ){ |
1882 fprintf(err,"%sillegal character in integer argument.\n",emsg); | 1920 fprintf(err,"%sillegal character in integer argument.\n",emsg); |
1883 errline(i,((unsigned long)end)-(unsigned long)argv[i],err); | 1921 errline(i,(int)((char*)end-(char*)argv[i]),err); |
1884 } | 1922 } |
1885 errcnt++; | 1923 errcnt++; |
1886 } | 1924 } |
1887 break; | 1925 break; |
1888 case OPT_STR: | 1926 case OPT_STR: |
1889 case OPT_FSTR: | 1927 case OPT_FSTR: |
1890 sv = cp; | 1928 sv = cp; |
1891 break; | 1929 break; |
1892 } | 1930 } |
1893 switch( op[j].type ){ | 1931 switch( op[j].type ){ |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1994 if( len>max ) max = len; | 2032 if( len>max ) max = len; |
1995 } | 2033 } |
1996 for(i=0; op[i].label; i++){ | 2034 for(i=0; op[i].label; i++){ |
1997 switch( op[i].type ){ | 2035 switch( op[i].type ){ |
1998 case OPT_FLAG: | 2036 case OPT_FLAG: |
1999 case OPT_FFLAG: | 2037 case OPT_FFLAG: |
2000 fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message); | 2038 fprintf(errstream," -%-*s %s\n",max,op[i].label,op[i].message); |
2001 break; | 2039 break; |
2002 case OPT_INT: | 2040 case OPT_INT: |
2003 case OPT_FINT: | 2041 case OPT_FINT: |
2004 fprintf(errstream," %s=<integer>%*s %s\n",op[i].label, | 2042 fprintf(errstream," -%s<integer>%*s %s\n",op[i].label, |
2005 (int)(max-lemonStrlen(op[i].label)-9),"",op[i].message); | 2043 (int)(max-lemonStrlen(op[i].label)-9),"",op[i].message); |
2006 break; | 2044 break; |
2007 case OPT_DBL: | 2045 case OPT_DBL: |
2008 case OPT_FDBL: | 2046 case OPT_FDBL: |
2009 fprintf(errstream," %s=<real>%*s %s\n",op[i].label, | 2047 fprintf(errstream," -%s<real>%*s %s\n",op[i].label, |
2010 (int)(max-lemonStrlen(op[i].label)-6),"",op[i].message); | 2048 (int)(max-lemonStrlen(op[i].label)-6),"",op[i].message); |
2011 break; | 2049 break; |
2012 case OPT_STR: | 2050 case OPT_STR: |
2013 case OPT_FSTR: | 2051 case OPT_FSTR: |
2014 fprintf(errstream," %s=<string>%*s %s\n",op[i].label, | 2052 fprintf(errstream," -%s<string>%*s %s\n",op[i].label, |
2015 (int)(max-lemonStrlen(op[i].label)-8),"",op[i].message); | 2053 (int)(max-lemonStrlen(op[i].label)-8),"",op[i].message); |
2016 break; | 2054 break; |
2017 } | 2055 } |
2018 } | 2056 } |
2019 } | 2057 } |
2020 /*********************** From the file "parse.c" ****************************/ | 2058 /*********************** From the file "parse.c" ****************************/ |
2021 /* | 2059 /* |
2022 ** Input file parser for the LEMON parser generator. | 2060 ** Input file parser for the LEMON parser generator. |
2023 */ | 2061 */ |
2024 | 2062 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2084 switch( psp->state ){ | 2122 switch( psp->state ){ |
2085 case INITIALIZE: | 2123 case INITIALIZE: |
2086 psp->prevrule = 0; | 2124 psp->prevrule = 0; |
2087 psp->preccounter = 0; | 2125 psp->preccounter = 0; |
2088 psp->firstrule = psp->lastrule = 0; | 2126 psp->firstrule = psp->lastrule = 0; |
2089 psp->gp->nrule = 0; | 2127 psp->gp->nrule = 0; |
2090 /* Fall thru to next case */ | 2128 /* Fall thru to next case */ |
2091 case WAITING_FOR_DECL_OR_RULE: | 2129 case WAITING_FOR_DECL_OR_RULE: |
2092 if( x[0]=='%' ){ | 2130 if( x[0]=='%' ){ |
2093 psp->state = WAITING_FOR_DECL_KEYWORD; | 2131 psp->state = WAITING_FOR_DECL_KEYWORD; |
2094 }else if( islower(x[0]) ){ | 2132 }else if( ISLOWER(x[0]) ){ |
2095 psp->lhs = Symbol_new(x); | 2133 psp->lhs = Symbol_new(x); |
2096 psp->nrhs = 0; | 2134 psp->nrhs = 0; |
2097 psp->lhsalias = 0; | 2135 psp->lhsalias = 0; |
2098 psp->state = WAITING_FOR_ARROW; | 2136 psp->state = WAITING_FOR_ARROW; |
2099 }else if( x[0]=='{' ){ | 2137 }else if( x[0]=='{' ){ |
2100 if( psp->prevrule==0 ){ | 2138 if( psp->prevrule==0 ){ |
2101 ErrorMsg(psp->filename,psp->tokenlineno, | 2139 ErrorMsg(psp->filename,psp->tokenlineno, |
2102 "There is no prior rule upon which to attach the code \ | 2140 "There is no prior rule upon which to attach the code \ |
2103 fragment which begins on this line."); | 2141 fragment which begins on this line."); |
2104 psp->errorcnt++; | 2142 psp->errorcnt++; |
2105 }else if( psp->prevrule->code!=0 ){ | 2143 }else if( psp->prevrule->code!=0 ){ |
2106 ErrorMsg(psp->filename,psp->tokenlineno, | 2144 ErrorMsg(psp->filename,psp->tokenlineno, |
2107 "Code fragment beginning on this line is not the first \ | 2145 "Code fragment beginning on this line is not the first \ |
2108 to follow the previous rule."); | 2146 to follow the previous rule."); |
2109 psp->errorcnt++; | 2147 psp->errorcnt++; |
2110 }else{ | 2148 }else{ |
2111 psp->prevrule->line = psp->tokenlineno; | 2149 psp->prevrule->line = psp->tokenlineno; |
2112 psp->prevrule->code = &x[1]; | 2150 psp->prevrule->code = &x[1]; |
2113 } | 2151 } |
2114 }else if( x[0]=='[' ){ | 2152 }else if( x[0]=='[' ){ |
2115 psp->state = PRECEDENCE_MARK_1; | 2153 psp->state = PRECEDENCE_MARK_1; |
2116 }else{ | 2154 }else{ |
2117 ErrorMsg(psp->filename,psp->tokenlineno, | 2155 ErrorMsg(psp->filename,psp->tokenlineno, |
2118 "Token \"%s\" should be either \"%%\" or a nonterminal name.", | 2156 "Token \"%s\" should be either \"%%\" or a nonterminal name.", |
2119 x); | 2157 x); |
2120 psp->errorcnt++; | 2158 psp->errorcnt++; |
2121 } | 2159 } |
2122 break; | 2160 break; |
2123 case PRECEDENCE_MARK_1: | 2161 case PRECEDENCE_MARK_1: |
2124 if( !isupper(x[0]) ){ | 2162 if( !ISUPPER(x[0]) ){ |
2125 ErrorMsg(psp->filename,psp->tokenlineno, | 2163 ErrorMsg(psp->filename,psp->tokenlineno, |
2126 "The precedence symbol must be a terminal."); | 2164 "The precedence symbol must be a terminal."); |
2127 psp->errorcnt++; | 2165 psp->errorcnt++; |
2128 }else if( psp->prevrule==0 ){ | 2166 }else if( psp->prevrule==0 ){ |
2129 ErrorMsg(psp->filename,psp->tokenlineno, | 2167 ErrorMsg(psp->filename,psp->tokenlineno, |
2130 "There is no prior rule to assign precedence \"[%s]\".",x); | 2168 "There is no prior rule to assign precedence \"[%s]\".",x); |
2131 psp->errorcnt++; | 2169 psp->errorcnt++; |
2132 }else if( psp->prevrule->precsym!=0 ){ | 2170 }else if( psp->prevrule->precsym!=0 ){ |
2133 ErrorMsg(psp->filename,psp->tokenlineno, | 2171 ErrorMsg(psp->filename,psp->tokenlineno, |
2134 "Precedence mark on this line is not the first \ | 2172 "Precedence mark on this line is not the first \ |
(...skipping 19 matching lines...) Expand all Loading... |
2154 psp->state = LHS_ALIAS_1; | 2192 psp->state = LHS_ALIAS_1; |
2155 }else{ | 2193 }else{ |
2156 ErrorMsg(psp->filename,psp->tokenlineno, | 2194 ErrorMsg(psp->filename,psp->tokenlineno, |
2157 "Expected to see a \":\" following the LHS symbol \"%s\".", | 2195 "Expected to see a \":\" following the LHS symbol \"%s\".", |
2158 psp->lhs->name); | 2196 psp->lhs->name); |
2159 psp->errorcnt++; | 2197 psp->errorcnt++; |
2160 psp->state = RESYNC_AFTER_RULE_ERROR; | 2198 psp->state = RESYNC_AFTER_RULE_ERROR; |
2161 } | 2199 } |
2162 break; | 2200 break; |
2163 case LHS_ALIAS_1: | 2201 case LHS_ALIAS_1: |
2164 if( isalpha(x[0]) ){ | 2202 if( ISALPHA(x[0]) ){ |
2165 psp->lhsalias = x; | 2203 psp->lhsalias = x; |
2166 psp->state = LHS_ALIAS_2; | 2204 psp->state = LHS_ALIAS_2; |
2167 }else{ | 2205 }else{ |
2168 ErrorMsg(psp->filename,psp->tokenlineno, | 2206 ErrorMsg(psp->filename,psp->tokenlineno, |
2169 "\"%s\" is not a valid alias for the LHS \"%s\"\n", | 2207 "\"%s\" is not a valid alias for the LHS \"%s\"\n", |
2170 x,psp->lhs->name); | 2208 x,psp->lhs->name); |
2171 psp->errorcnt++; | 2209 psp->errorcnt++; |
2172 psp->state = RESYNC_AFTER_RULE_ERROR; | 2210 psp->state = RESYNC_AFTER_RULE_ERROR; |
2173 } | 2211 } |
2174 break; | 2212 break; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2223 rp->next = 0; | 2261 rp->next = 0; |
2224 if( psp->firstrule==0 ){ | 2262 if( psp->firstrule==0 ){ |
2225 psp->firstrule = psp->lastrule = rp; | 2263 psp->firstrule = psp->lastrule = rp; |
2226 }else{ | 2264 }else{ |
2227 psp->lastrule->next = rp; | 2265 psp->lastrule->next = rp; |
2228 psp->lastrule = rp; | 2266 psp->lastrule = rp; |
2229 } | 2267 } |
2230 psp->prevrule = rp; | 2268 psp->prevrule = rp; |
2231 } | 2269 } |
2232 psp->state = WAITING_FOR_DECL_OR_RULE; | 2270 psp->state = WAITING_FOR_DECL_OR_RULE; |
2233 }else if( isalpha(x[0]) ){ | 2271 }else if( ISALPHA(x[0]) ){ |
2234 if( psp->nrhs>=MAXRHS ){ | 2272 if( psp->nrhs>=MAXRHS ){ |
2235 ErrorMsg(psp->filename,psp->tokenlineno, | 2273 ErrorMsg(psp->filename,psp->tokenlineno, |
2236 "Too many symbols on RHS of rule beginning at \"%s\".", | 2274 "Too many symbols on RHS of rule beginning at \"%s\".", |
2237 x); | 2275 x); |
2238 psp->errorcnt++; | 2276 psp->errorcnt++; |
2239 psp->state = RESYNC_AFTER_RULE_ERROR; | 2277 psp->state = RESYNC_AFTER_RULE_ERROR; |
2240 }else{ | 2278 }else{ |
2241 psp->rhs[psp->nrhs] = Symbol_new(x); | 2279 psp->rhs[psp->nrhs] = Symbol_new(x); |
2242 psp->alias[psp->nrhs] = 0; | 2280 psp->alias[psp->nrhs] = 0; |
2243 psp->nrhs++; | 2281 psp->nrhs++; |
2244 } | 2282 } |
2245 }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ | 2283 }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ |
2246 struct symbol *msp = psp->rhs[psp->nrhs-1]; | 2284 struct symbol *msp = psp->rhs[psp->nrhs-1]; |
2247 if( msp->type!=MULTITERMINAL ){ | 2285 if( msp->type!=MULTITERMINAL ){ |
2248 struct symbol *origsp = msp; | 2286 struct symbol *origsp = msp; |
2249 msp = (struct symbol *) calloc(1,sizeof(*msp)); | 2287 msp = (struct symbol *) calloc(1,sizeof(*msp)); |
2250 memset(msp, 0, sizeof(*msp)); | 2288 memset(msp, 0, sizeof(*msp)); |
2251 msp->type = MULTITERMINAL; | 2289 msp->type = MULTITERMINAL; |
2252 msp->nsubsym = 1; | 2290 msp->nsubsym = 1; |
2253 msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); | 2291 msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); |
2254 msp->subsym[0] = origsp; | 2292 msp->subsym[0] = origsp; |
2255 msp->name = origsp->name; | 2293 msp->name = origsp->name; |
2256 psp->rhs[psp->nrhs-1] = msp; | 2294 psp->rhs[psp->nrhs-1] = msp; |
2257 } | 2295 } |
2258 msp->nsubsym++; | 2296 msp->nsubsym++; |
2259 msp->subsym = (struct symbol **) realloc(msp->subsym, | 2297 msp->subsym = (struct symbol **) realloc(msp->subsym, |
2260 sizeof(struct symbol*)*msp->nsubsym); | 2298 sizeof(struct symbol*)*msp->nsubsym); |
2261 msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); | 2299 msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); |
2262 if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){ | 2300 if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){ |
2263 ErrorMsg(psp->filename,psp->tokenlineno, | 2301 ErrorMsg(psp->filename,psp->tokenlineno, |
2264 "Cannot form a compound containing a non-terminal"); | 2302 "Cannot form a compound containing a non-terminal"); |
2265 psp->errorcnt++; | 2303 psp->errorcnt++; |
2266 } | 2304 } |
2267 }else if( x[0]=='(' && psp->nrhs>0 ){ | 2305 }else if( x[0]=='(' && psp->nrhs>0 ){ |
2268 psp->state = RHS_ALIAS_1; | 2306 psp->state = RHS_ALIAS_1; |
2269 }else{ | 2307 }else{ |
2270 ErrorMsg(psp->filename,psp->tokenlineno, | 2308 ErrorMsg(psp->filename,psp->tokenlineno, |
2271 "Illegal character on RHS of rule: \"%s\".",x); | 2309 "Illegal character on RHS of rule: \"%s\".",x); |
2272 psp->errorcnt++; | 2310 psp->errorcnt++; |
2273 psp->state = RESYNC_AFTER_RULE_ERROR; | 2311 psp->state = RESYNC_AFTER_RULE_ERROR; |
2274 } | 2312 } |
2275 break; | 2313 break; |
2276 case RHS_ALIAS_1: | 2314 case RHS_ALIAS_1: |
2277 if( isalpha(x[0]) ){ | 2315 if( ISALPHA(x[0]) ){ |
2278 psp->alias[psp->nrhs-1] = x; | 2316 psp->alias[psp->nrhs-1] = x; |
2279 psp->state = RHS_ALIAS_2; | 2317 psp->state = RHS_ALIAS_2; |
2280 }else{ | 2318 }else{ |
2281 ErrorMsg(psp->filename,psp->tokenlineno, | 2319 ErrorMsg(psp->filename,psp->tokenlineno, |
2282 "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n", | 2320 "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n", |
2283 x,psp->rhs[psp->nrhs-1]->name); | 2321 x,psp->rhs[psp->nrhs-1]->name); |
2284 psp->errorcnt++; | 2322 psp->errorcnt++; |
2285 psp->state = RESYNC_AFTER_RULE_ERROR; | 2323 psp->state = RESYNC_AFTER_RULE_ERROR; |
2286 } | 2324 } |
2287 break; | 2325 break; |
2288 case RHS_ALIAS_2: | 2326 case RHS_ALIAS_2: |
2289 if( x[0]==')' ){ | 2327 if( x[0]==')' ){ |
2290 psp->state = IN_RHS; | 2328 psp->state = IN_RHS; |
2291 }else{ | 2329 }else{ |
2292 ErrorMsg(psp->filename,psp->tokenlineno, | 2330 ErrorMsg(psp->filename,psp->tokenlineno, |
2293 "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias); | 2331 "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias); |
2294 psp->errorcnt++; | 2332 psp->errorcnt++; |
2295 psp->state = RESYNC_AFTER_RULE_ERROR; | 2333 psp->state = RESYNC_AFTER_RULE_ERROR; |
2296 } | 2334 } |
2297 break; | 2335 break; |
2298 case WAITING_FOR_DECL_KEYWORD: | 2336 case WAITING_FOR_DECL_KEYWORD: |
2299 if( isalpha(x[0]) ){ | 2337 if( ISALPHA(x[0]) ){ |
2300 psp->declkeyword = x; | 2338 psp->declkeyword = x; |
2301 psp->declargslot = 0; | 2339 psp->declargslot = 0; |
2302 psp->decllinenoslot = 0; | 2340 psp->decllinenoslot = 0; |
2303 psp->insertLineMacro = 1; | 2341 psp->insertLineMacro = 1; |
2304 psp->state = WAITING_FOR_DECL_ARG; | 2342 psp->state = WAITING_FOR_DECL_ARG; |
2305 if( strcmp(x,"name")==0 ){ | 2343 if( strcmp(x,"name")==0 ){ |
2306 psp->declargslot = &(psp->gp->name); | 2344 psp->declargslot = &(psp->gp->name); |
2307 psp->insertLineMacro = 0; | 2345 psp->insertLineMacro = 0; |
2308 }else if( strcmp(x,"include")==0 ){ | 2346 }else if( strcmp(x,"include")==0 ){ |
2309 psp->declargslot = &(psp->gp->include); | 2347 psp->declargslot = &(psp->gp->include); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2369 psp->state = RESYNC_AFTER_DECL_ERROR; | 2407 psp->state = RESYNC_AFTER_DECL_ERROR; |
2370 } | 2408 } |
2371 }else{ | 2409 }else{ |
2372 ErrorMsg(psp->filename,psp->tokenlineno, | 2410 ErrorMsg(psp->filename,psp->tokenlineno, |
2373 "Illegal declaration keyword: \"%s\".",x); | 2411 "Illegal declaration keyword: \"%s\".",x); |
2374 psp->errorcnt++; | 2412 psp->errorcnt++; |
2375 psp->state = RESYNC_AFTER_DECL_ERROR; | 2413 psp->state = RESYNC_AFTER_DECL_ERROR; |
2376 } | 2414 } |
2377 break; | 2415 break; |
2378 case WAITING_FOR_DESTRUCTOR_SYMBOL: | 2416 case WAITING_FOR_DESTRUCTOR_SYMBOL: |
2379 if( !isalpha(x[0]) ){ | 2417 if( !ISALPHA(x[0]) ){ |
2380 ErrorMsg(psp->filename,psp->tokenlineno, | 2418 ErrorMsg(psp->filename,psp->tokenlineno, |
2381 "Symbol name missing after %%destructor keyword"); | 2419 "Symbol name missing after %%destructor keyword"); |
2382 psp->errorcnt++; | 2420 psp->errorcnt++; |
2383 psp->state = RESYNC_AFTER_DECL_ERROR; | 2421 psp->state = RESYNC_AFTER_DECL_ERROR; |
2384 }else{ | 2422 }else{ |
2385 struct symbol *sp = Symbol_new(x); | 2423 struct symbol *sp = Symbol_new(x); |
2386 psp->declargslot = &sp->destructor; | 2424 psp->declargslot = &sp->destructor; |
2387 psp->decllinenoslot = &sp->destLineno; | 2425 psp->decllinenoslot = &sp->destLineno; |
2388 psp->insertLineMacro = 1; | 2426 psp->insertLineMacro = 1; |
2389 psp->state = WAITING_FOR_DECL_ARG; | 2427 psp->state = WAITING_FOR_DECL_ARG; |
2390 } | 2428 } |
2391 break; | 2429 break; |
2392 case WAITING_FOR_DATATYPE_SYMBOL: | 2430 case WAITING_FOR_DATATYPE_SYMBOL: |
2393 if( !isalpha(x[0]) ){ | 2431 if( !ISALPHA(x[0]) ){ |
2394 ErrorMsg(psp->filename,psp->tokenlineno, | 2432 ErrorMsg(psp->filename,psp->tokenlineno, |
2395 "Symbol name missing after %%type keyword"); | 2433 "Symbol name missing after %%type keyword"); |
2396 psp->errorcnt++; | 2434 psp->errorcnt++; |
2397 psp->state = RESYNC_AFTER_DECL_ERROR; | 2435 psp->state = RESYNC_AFTER_DECL_ERROR; |
2398 }else{ | 2436 }else{ |
2399 struct symbol *sp = Symbol_find(x); | 2437 struct symbol *sp = Symbol_find(x); |
2400 if((sp) && (sp->datatype)){ | 2438 if((sp) && (sp->datatype)){ |
2401 ErrorMsg(psp->filename,psp->tokenlineno, | 2439 ErrorMsg(psp->filename,psp->tokenlineno, |
2402 "Symbol %%type \"%s\" already defined", x); | 2440 "Symbol %%type \"%s\" already defined", x); |
2403 psp->errorcnt++; | 2441 psp->errorcnt++; |
2404 psp->state = RESYNC_AFTER_DECL_ERROR; | 2442 psp->state = RESYNC_AFTER_DECL_ERROR; |
2405 }else{ | 2443 }else{ |
2406 if (!sp){ | 2444 if (!sp){ |
2407 sp = Symbol_new(x); | 2445 sp = Symbol_new(x); |
2408 } | 2446 } |
2409 psp->declargslot = &sp->datatype; | 2447 psp->declargslot = &sp->datatype; |
2410 psp->insertLineMacro = 0; | 2448 psp->insertLineMacro = 0; |
2411 psp->state = WAITING_FOR_DECL_ARG; | 2449 psp->state = WAITING_FOR_DECL_ARG; |
2412 } | 2450 } |
2413 } | 2451 } |
2414 break; | 2452 break; |
2415 case WAITING_FOR_PRECEDENCE_SYMBOL: | 2453 case WAITING_FOR_PRECEDENCE_SYMBOL: |
2416 if( x[0]=='.' ){ | 2454 if( x[0]=='.' ){ |
2417 psp->state = WAITING_FOR_DECL_OR_RULE; | 2455 psp->state = WAITING_FOR_DECL_OR_RULE; |
2418 }else if( isupper(x[0]) ){ | 2456 }else if( ISUPPER(x[0]) ){ |
2419 struct symbol *sp; | 2457 struct symbol *sp; |
2420 sp = Symbol_new(x); | 2458 sp = Symbol_new(x); |
2421 if( sp->prec>=0 ){ | 2459 if( sp->prec>=0 ){ |
2422 ErrorMsg(psp->filename,psp->tokenlineno, | 2460 ErrorMsg(psp->filename,psp->tokenlineno, |
2423 "Symbol \"%s\" has already be given a precedence.",x); | 2461 "Symbol \"%s\" has already be given a precedence.",x); |
2424 psp->errorcnt++; | 2462 psp->errorcnt++; |
2425 }else{ | 2463 }else{ |
2426 sp->prec = psp->preccounter; | 2464 sp->prec = psp->preccounter; |
2427 sp->assoc = psp->declassoc; | 2465 sp->assoc = psp->declassoc; |
2428 } | 2466 } |
2429 }else{ | 2467 }else{ |
2430 ErrorMsg(psp->filename,psp->tokenlineno, | 2468 ErrorMsg(psp->filename,psp->tokenlineno, |
2431 "Can't assign a precedence to \"%s\".",x); | 2469 "Can't assign a precedence to \"%s\".",x); |
2432 psp->errorcnt++; | 2470 psp->errorcnt++; |
2433 } | 2471 } |
2434 break; | 2472 break; |
2435 case WAITING_FOR_DECL_ARG: | 2473 case WAITING_FOR_DECL_ARG: |
2436 if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){ | 2474 if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) ){ |
2437 const char *zOld, *zNew; | 2475 const char *zOld, *zNew; |
2438 char *zBuf, *z; | 2476 char *zBuf, *z; |
2439 int nOld, n, nLine, nNew, nBack; | 2477 int nOld, n, nLine = 0, nNew, nBack; |
2440 int addLineMacro; | 2478 int addLineMacro; |
2441 char zLine[50]; | 2479 char zLine[50]; |
2442 zNew = x; | 2480 zNew = x; |
2443 if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; | 2481 if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; |
2444 nNew = lemonStrlen(zNew); | 2482 nNew = lemonStrlen(zNew); |
2445 if( *psp->declargslot ){ | 2483 if( *psp->declargslot ){ |
2446 zOld = *psp->declargslot; | 2484 zOld = *psp->declargslot; |
2447 }else{ | 2485 }else{ |
2448 zOld = ""; | 2486 zOld = ""; |
2449 } | 2487 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2487 }else{ | 2525 }else{ |
2488 ErrorMsg(psp->filename,psp->tokenlineno, | 2526 ErrorMsg(psp->filename,psp->tokenlineno, |
2489 "Illegal argument to %%%s: %s",psp->declkeyword,x); | 2527 "Illegal argument to %%%s: %s",psp->declkeyword,x); |
2490 psp->errorcnt++; | 2528 psp->errorcnt++; |
2491 psp->state = RESYNC_AFTER_DECL_ERROR; | 2529 psp->state = RESYNC_AFTER_DECL_ERROR; |
2492 } | 2530 } |
2493 break; | 2531 break; |
2494 case WAITING_FOR_FALLBACK_ID: | 2532 case WAITING_FOR_FALLBACK_ID: |
2495 if( x[0]=='.' ){ | 2533 if( x[0]=='.' ){ |
2496 psp->state = WAITING_FOR_DECL_OR_RULE; | 2534 psp->state = WAITING_FOR_DECL_OR_RULE; |
2497 }else if( !isupper(x[0]) ){ | 2535 }else if( !ISUPPER(x[0]) ){ |
2498 ErrorMsg(psp->filename, psp->tokenlineno, | 2536 ErrorMsg(psp->filename, psp->tokenlineno, |
2499 "%%fallback argument \"%s\" should be a token", x); | 2537 "%%fallback argument \"%s\" should be a token", x); |
2500 psp->errorcnt++; | 2538 psp->errorcnt++; |
2501 }else{ | 2539 }else{ |
2502 struct symbol *sp = Symbol_new(x); | 2540 struct symbol *sp = Symbol_new(x); |
2503 if( psp->fallback==0 ){ | 2541 if( psp->fallback==0 ){ |
2504 psp->fallback = sp; | 2542 psp->fallback = sp; |
2505 }else if( sp->fallback ){ | 2543 }else if( sp->fallback ){ |
2506 ErrorMsg(psp->filename, psp->tokenlineno, | 2544 ErrorMsg(psp->filename, psp->tokenlineno, |
2507 "More than one fallback assigned to token %s", x); | 2545 "More than one fallback assigned to token %s", x); |
2508 psp->errorcnt++; | 2546 psp->errorcnt++; |
2509 }else{ | 2547 }else{ |
2510 sp->fallback = psp->fallback; | 2548 sp->fallback = psp->fallback; |
2511 psp->gp->has_fallback = 1; | 2549 psp->gp->has_fallback = 1; |
2512 } | 2550 } |
2513 } | 2551 } |
2514 break; | 2552 break; |
2515 case WAITING_FOR_WILDCARD_ID: | 2553 case WAITING_FOR_WILDCARD_ID: |
2516 if( x[0]=='.' ){ | 2554 if( x[0]=='.' ){ |
2517 psp->state = WAITING_FOR_DECL_OR_RULE; | 2555 psp->state = WAITING_FOR_DECL_OR_RULE; |
2518 }else if( !isupper(x[0]) ){ | 2556 }else if( !ISUPPER(x[0]) ){ |
2519 ErrorMsg(psp->filename, psp->tokenlineno, | 2557 ErrorMsg(psp->filename, psp->tokenlineno, |
2520 "%%wildcard argument \"%s\" should be a token", x); | 2558 "%%wildcard argument \"%s\" should be a token", x); |
2521 psp->errorcnt++; | 2559 psp->errorcnt++; |
2522 }else{ | 2560 }else{ |
2523 struct symbol *sp = Symbol_new(x); | 2561 struct symbol *sp = Symbol_new(x); |
2524 if( psp->gp->wildcard==0 ){ | 2562 if( psp->gp->wildcard==0 ){ |
2525 psp->gp->wildcard = sp; | 2563 psp->gp->wildcard = sp; |
2526 }else{ | 2564 }else{ |
2527 ErrorMsg(psp->filename, psp->tokenlineno, | 2565 ErrorMsg(psp->filename, psp->tokenlineno, |
2528 "Extra wildcard to token: %s", x); | 2566 "Extra wildcard to token: %s", x); |
2529 psp->errorcnt++; | 2567 psp->errorcnt++; |
2530 } | 2568 } |
2531 } | 2569 } |
2532 break; | 2570 break; |
2533 case WAITING_FOR_CLASS_ID: | 2571 case WAITING_FOR_CLASS_ID: |
2534 if( !islower(x[0]) ){ | 2572 if( !ISLOWER(x[0]) ){ |
2535 ErrorMsg(psp->filename, psp->tokenlineno, | 2573 ErrorMsg(psp->filename, psp->tokenlineno, |
2536 "%%token_class must be followed by an identifier: ", x); | 2574 "%%token_class must be followed by an identifier: ", x); |
2537 psp->errorcnt++; | 2575 psp->errorcnt++; |
2538 psp->state = RESYNC_AFTER_DECL_ERROR; | 2576 psp->state = RESYNC_AFTER_DECL_ERROR; |
2539 }else if( Symbol_find(x) ){ | 2577 }else if( Symbol_find(x) ){ |
2540 ErrorMsg(psp->filename, psp->tokenlineno, | 2578 ErrorMsg(psp->filename, psp->tokenlineno, |
2541 "Symbol \"%s\" already used", x); | 2579 "Symbol \"%s\" already used", x); |
2542 psp->errorcnt++; | 2580 psp->errorcnt++; |
2543 psp->state = RESYNC_AFTER_DECL_ERROR; | 2581 psp->state = RESYNC_AFTER_DECL_ERROR; |
2544 }else{ | 2582 }else{ |
2545 psp->tkclass = Symbol_new(x); | 2583 psp->tkclass = Symbol_new(x); |
2546 psp->tkclass->type = MULTITERMINAL; | 2584 psp->tkclass->type = MULTITERMINAL; |
2547 psp->state = WAITING_FOR_CLASS_TOKEN; | 2585 psp->state = WAITING_FOR_CLASS_TOKEN; |
2548 } | 2586 } |
2549 break; | 2587 break; |
2550 case WAITING_FOR_CLASS_TOKEN: | 2588 case WAITING_FOR_CLASS_TOKEN: |
2551 if( x[0]=='.' ){ | 2589 if( x[0]=='.' ){ |
2552 psp->state = WAITING_FOR_DECL_OR_RULE; | 2590 psp->state = WAITING_FOR_DECL_OR_RULE; |
2553 }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){ | 2591 }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){ |
2554 struct symbol *msp = psp->tkclass; | 2592 struct symbol *msp = psp->tkclass; |
2555 msp->nsubsym++; | 2593 msp->nsubsym++; |
2556 msp->subsym = (struct symbol **) realloc(msp->subsym, | 2594 msp->subsym = (struct symbol **) realloc(msp->subsym, |
2557 sizeof(struct symbol*)*msp->nsubsym); | 2595 sizeof(struct symbol*)*msp->nsubsym); |
2558 if( !isupper(x[0]) ) x++; | 2596 if( !ISUPPER(x[0]) ) x++; |
2559 msp->subsym[msp->nsubsym-1] = Symbol_new(x); | 2597 msp->subsym[msp->nsubsym-1] = Symbol_new(x); |
2560 }else{ | 2598 }else{ |
2561 ErrorMsg(psp->filename, psp->tokenlineno, | 2599 ErrorMsg(psp->filename, psp->tokenlineno, |
2562 "%%token_class argument \"%s\" should be a token", x); | 2600 "%%token_class argument \"%s\" should be a token", x); |
2563 psp->errorcnt++; | 2601 psp->errorcnt++; |
2564 psp->state = RESYNC_AFTER_DECL_ERROR; | 2602 psp->state = RESYNC_AFTER_DECL_ERROR; |
2565 } | 2603 } |
2566 break; | 2604 break; |
2567 case RESYNC_AFTER_RULE_ERROR: | 2605 case RESYNC_AFTER_RULE_ERROR: |
2568 /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; | 2606 /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; |
(...skipping 12 matching lines...) Expand all Loading... |
2581 */ | 2619 */ |
2582 static void preprocess_input(char *z){ | 2620 static void preprocess_input(char *z){ |
2583 int i, j, k, n; | 2621 int i, j, k, n; |
2584 int exclude = 0; | 2622 int exclude = 0; |
2585 int start = 0; | 2623 int start = 0; |
2586 int lineno = 1; | 2624 int lineno = 1; |
2587 int start_lineno = 1; | 2625 int start_lineno = 1; |
2588 for(i=0; z[i]; i++){ | 2626 for(i=0; z[i]; i++){ |
2589 if( z[i]=='\n' ) lineno++; | 2627 if( z[i]=='\n' ) lineno++; |
2590 if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue; | 2628 if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue; |
2591 if( strncmp(&z[i],"%endif",6)==0 && isspace(z[i+6]) ){ | 2629 if( strncmp(&z[i],"%endif",6)==0 && ISSPACE(z[i+6]) ){ |
2592 if( exclude ){ | 2630 if( exclude ){ |
2593 exclude--; | 2631 exclude--; |
2594 if( exclude==0 ){ | 2632 if( exclude==0 ){ |
2595 for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' '; | 2633 for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' '; |
2596 } | 2634 } |
2597 } | 2635 } |
2598 for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' '; | 2636 for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' '; |
2599 }else if( (strncmp(&z[i],"%ifdef",6)==0 && isspace(z[i+6])) | 2637 }else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6])) |
2600 || (strncmp(&z[i],"%ifndef",7)==0 && isspace(z[i+7])) ){ | 2638 || (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){ |
2601 if( exclude ){ | 2639 if( exclude ){ |
2602 exclude++; | 2640 exclude++; |
2603 }else{ | 2641 }else{ |
2604 for(j=i+7; isspace(z[j]); j++){} | 2642 for(j=i+7; ISSPACE(z[j]); j++){} |
2605 for(n=0; z[j+n] && !isspace(z[j+n]); n++){} | 2643 for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){} |
2606 exclude = 1; | 2644 exclude = 1; |
2607 for(k=0; k<nDefine; k++){ | 2645 for(k=0; k<nDefine; k++){ |
2608 if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){ | 2646 if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){ |
2609 exclude = 0; | 2647 exclude = 0; |
2610 break; | 2648 break; |
2611 } | 2649 } |
2612 } | 2650 } |
2613 if( z[i+3]=='n' ) exclude = !exclude; | 2651 if( z[i+3]=='n' ) exclude = !exclude; |
2614 if( exclude ){ | 2652 if( exclude ){ |
2615 start = i; | 2653 start = i; |
(...skipping 12 matching lines...) Expand all Loading... |
2628 /* In spite of its name, this function is really a scanner. It read | 2666 /* In spite of its name, this function is really a scanner. It read |
2629 ** in the entire input file (all at once) then tokenizes it. Each | 2667 ** in the entire input file (all at once) then tokenizes it. Each |
2630 ** token is passed to the function "parseonetoken" which builds all | 2668 ** token is passed to the function "parseonetoken" which builds all |
2631 ** the appropriate data structures in the global state vector "gp". | 2669 ** the appropriate data structures in the global state vector "gp". |
2632 */ | 2670 */ |
2633 void Parse(struct lemon *gp) | 2671 void Parse(struct lemon *gp) |
2634 { | 2672 { |
2635 struct pstate ps; | 2673 struct pstate ps; |
2636 FILE *fp; | 2674 FILE *fp; |
2637 char *filebuf; | 2675 char *filebuf; |
2638 int filesize; | 2676 unsigned int filesize; |
2639 int lineno; | 2677 int lineno; |
2640 int c; | 2678 int c; |
2641 char *cp, *nextcp; | 2679 char *cp, *nextcp; |
2642 int startline = 0; | 2680 int startline = 0; |
2643 | 2681 |
2644 memset(&ps, '\0', sizeof(ps)); | 2682 memset(&ps, '\0', sizeof(ps)); |
2645 ps.gp = gp; | 2683 ps.gp = gp; |
2646 ps.filename = gp->filename; | 2684 ps.filename = gp->filename; |
2647 ps.errorcnt = 0; | 2685 ps.errorcnt = 0; |
2648 ps.state = INITIALIZE; | 2686 ps.state = INITIALIZE; |
(...skipping 26 matching lines...) Expand all Loading... |
2675 fclose(fp); | 2713 fclose(fp); |
2676 filebuf[filesize] = 0; | 2714 filebuf[filesize] = 0; |
2677 | 2715 |
2678 /* Make an initial pass through the file to handle %ifdef and %ifndef */ | 2716 /* Make an initial pass through the file to handle %ifdef and %ifndef */ |
2679 preprocess_input(filebuf); | 2717 preprocess_input(filebuf); |
2680 | 2718 |
2681 /* Now scan the text of the input file */ | 2719 /* Now scan the text of the input file */ |
2682 lineno = 1; | 2720 lineno = 1; |
2683 for(cp=filebuf; (c= *cp)!=0; ){ | 2721 for(cp=filebuf; (c= *cp)!=0; ){ |
2684 if( c=='\n' ) lineno++; /* Keep track of the line number */ | 2722 if( c=='\n' ) lineno++; /* Keep track of the line number */ |
2685 if( isspace(c) ){ cp++; continue; } /* Skip all white space */ | 2723 if( ISSPACE(c) ){ cp++; continue; } /* Skip all white space */ |
2686 if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */ | 2724 if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */ |
2687 cp+=2; | 2725 cp+=2; |
2688 while( (c= *cp)!=0 && c!='\n' ) cp++; | 2726 while( (c= *cp)!=0 && c!='\n' ) cp++; |
2689 continue; | 2727 continue; |
2690 } | 2728 } |
2691 if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */ | 2729 if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */ |
2692 cp+=2; | 2730 cp+=2; |
2693 while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){ | 2731 while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){ |
2694 if( c=='\n' ) lineno++; | 2732 if( c=='\n' ) lineno++; |
2695 cp++; | 2733 cp++; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2745 } | 2783 } |
2746 } | 2784 } |
2747 if( c==0 ){ | 2785 if( c==0 ){ |
2748 ErrorMsg(ps.filename,ps.tokenlineno, | 2786 ErrorMsg(ps.filename,ps.tokenlineno, |
2749 "C code starting on this line is not terminated before the end of the file."); | 2787 "C code starting on this line is not terminated before the end of the file."); |
2750 ps.errorcnt++; | 2788 ps.errorcnt++; |
2751 nextcp = cp; | 2789 nextcp = cp; |
2752 }else{ | 2790 }else{ |
2753 nextcp = cp+1; | 2791 nextcp = cp+1; |
2754 } | 2792 } |
2755 }else if( isalnum(c) ){ /* Identifiers */ | 2793 }else if( ISALNUM(c) ){ /* Identifiers */ |
2756 while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++; | 2794 while( (c= *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++; |
2757 nextcp = cp; | 2795 nextcp = cp; |
2758 }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */ | 2796 }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */ |
2759 cp += 3; | 2797 cp += 3; |
2760 nextcp = cp; | 2798 nextcp = cp; |
2761 }else if( (c=='/' || c=='|') && isalpha(cp[1]) ){ | 2799 }else if( (c=='/' || c=='|') && ISALPHA(cp[1]) ){ |
2762 cp += 2; | 2800 cp += 2; |
2763 while( (c = *cp)!=0 && (isalnum(c) || c=='_') ) cp++; | 2801 while( (c = *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++; |
2764 nextcp = cp; | 2802 nextcp = cp; |
2765 }else{ /* All other (one character) operators */ | 2803 }else{ /* All other (one character) operators */ |
2766 cp++; | 2804 cp++; |
2767 nextcp = cp; | 2805 nextcp = cp; |
2768 } | 2806 } |
2769 c = *cp; | 2807 c = *cp; |
2770 *cp = 0; /* Null terminate the token */ | 2808 *cp = 0; /* Null terminate the token */ |
2771 parseonetoken(&ps); /* Parse the token */ | 2809 parseonetoken(&ps); /* Parse the token */ |
2772 *cp = c; /* Restore the buffer */ | 2810 *cp = (char)c; /* Restore the buffer */ |
2773 cp = nextcp; | 2811 cp = nextcp; |
2774 } | 2812 } |
2775 free(filebuf); /* Release the buffer after parsing */ | 2813 free(filebuf); /* Release the buffer after parsing */ |
2776 gp->rule = ps.firstrule; | 2814 gp->rule = ps.firstrule; |
2777 gp->errorcnt = ps.errorcnt; | 2815 gp->errorcnt = ps.errorcnt; |
2778 } | 2816 } |
2779 /*************************** From the file "plink.c" *********************/ | 2817 /*************************** From the file "plink.c" *********************/ |
2780 /* | 2818 /* |
2781 ** Routines processing configuration follow-set propagation links | 2819 ** Routines processing configuration follow-set propagation links |
2782 ** in the LEMON parser generator. | 2820 ** in the LEMON parser generator. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2927 } | 2965 } |
2928 /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ | 2966 /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ |
2929 } | 2967 } |
2930 printf("."); | 2968 printf("."); |
2931 if( rp->precsym ) printf(" [%s]",rp->precsym->name); | 2969 if( rp->precsym ) printf(" [%s]",rp->precsym->name); |
2932 /* if( rp->code ) printf("\n %s",rp->code); */ | 2970 /* if( rp->code ) printf("\n %s",rp->code); */ |
2933 printf("\n"); | 2971 printf("\n"); |
2934 } | 2972 } |
2935 } | 2973 } |
2936 | 2974 |
2937 void ConfigPrint(FILE *fp, struct config *cfp) | 2975 /* Print a single rule. |
2938 { | 2976 */ |
2939 struct rule *rp; | 2977 void RulePrint(FILE *fp, struct rule *rp, int iCursor){ |
2940 struct symbol *sp; | 2978 struct symbol *sp; |
2941 int i, j; | 2979 int i, j; |
2942 rp = cfp->rp; | |
2943 fprintf(fp,"%s ::=",rp->lhs->name); | 2980 fprintf(fp,"%s ::=",rp->lhs->name); |
2944 for(i=0; i<=rp->nrhs; i++){ | 2981 for(i=0; i<=rp->nrhs; i++){ |
2945 if( i==cfp->dot ) fprintf(fp," *"); | 2982 if( i==iCursor ) fprintf(fp," *"); |
2946 if( i==rp->nrhs ) break; | 2983 if( i==rp->nrhs ) break; |
2947 sp = rp->rhs[i]; | 2984 sp = rp->rhs[i]; |
2948 if( sp->type==MULTITERMINAL ){ | 2985 if( sp->type==MULTITERMINAL ){ |
2949 fprintf(fp," %s", sp->subsym[0]->name); | 2986 fprintf(fp," %s", sp->subsym[0]->name); |
2950 for(j=1; j<sp->nsubsym; j++){ | 2987 for(j=1; j<sp->nsubsym; j++){ |
2951 fprintf(fp,"|%s",sp->subsym[j]->name); | 2988 fprintf(fp,"|%s",sp->subsym[j]->name); |
2952 } | 2989 } |
2953 }else{ | 2990 }else{ |
2954 fprintf(fp," %s", sp->name); | 2991 fprintf(fp," %s", sp->name); |
2955 } | 2992 } |
2956 } | 2993 } |
2957 } | 2994 } |
2958 | 2995 |
| 2996 /* Print the rule for a configuration. |
| 2997 */ |
| 2998 void ConfigPrint(FILE *fp, struct config *cfp){ |
| 2999 RulePrint(fp, cfp->rp, cfp->dot); |
| 3000 } |
| 3001 |
2959 /* #define TEST */ | 3002 /* #define TEST */ |
2960 #if 0 | 3003 #if 0 |
2961 /* Print a set */ | 3004 /* Print a set */ |
2962 PRIVATE void SetPrint(out,set,lemp) | 3005 PRIVATE void SetPrint(out,set,lemp) |
2963 FILE *out; | 3006 FILE *out; |
2964 char *set; | 3007 char *set; |
2965 struct lemon *lemp; | 3008 struct lemon *lemp; |
2966 { | 3009 { |
2967 int i; | 3010 int i; |
2968 char *spacer; | 3011 char *spacer; |
(...skipping 19 matching lines...) Expand all Loading... |
2988 ConfigPrint(out,plp->cfp); | 3031 ConfigPrint(out,plp->cfp); |
2989 fprintf(out,"\n"); | 3032 fprintf(out,"\n"); |
2990 plp = plp->next; | 3033 plp = plp->next; |
2991 } | 3034 } |
2992 } | 3035 } |
2993 #endif | 3036 #endif |
2994 | 3037 |
2995 /* Print an action to the given file descriptor. Return FALSE if | 3038 /* Print an action to the given file descriptor. Return FALSE if |
2996 ** nothing was actually printed. | 3039 ** nothing was actually printed. |
2997 */ | 3040 */ |
2998 int PrintAction(struct action *ap, FILE *fp, int indent){ | 3041 int PrintAction( |
| 3042 struct action *ap, /* The action to print */ |
| 3043 FILE *fp, /* Print the action here */ |
| 3044 int indent /* Indent by this amount */ |
| 3045 ){ |
2999 int result = 1; | 3046 int result = 1; |
3000 switch( ap->type ){ | 3047 switch( ap->type ){ |
3001 case SHIFT: | 3048 case SHIFT: { |
3002 fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->statenum); | 3049 struct state *stp = ap->x.stp; |
| 3050 fprintf(fp,"%*s shift %-7d",indent,ap->sp->name,stp->statenum); |
3003 break; | 3051 break; |
3004 case REDUCE: | 3052 } |
3005 fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index); | 3053 case REDUCE: { |
| 3054 struct rule *rp = ap->x.rp; |
| 3055 fprintf(fp,"%*s reduce %-7d",indent,ap->sp->name,rp->index); |
| 3056 RulePrint(fp, rp, -1); |
3006 break; | 3057 break; |
| 3058 } |
| 3059 case SHIFTREDUCE: { |
| 3060 struct rule *rp = ap->x.rp; |
| 3061 fprintf(fp,"%*s shift-reduce %-7d",indent,ap->sp->name,rp->index); |
| 3062 RulePrint(fp, rp, -1); |
| 3063 break; |
| 3064 } |
3007 case ACCEPT: | 3065 case ACCEPT: |
3008 fprintf(fp,"%*s accept",indent,ap->sp->name); | 3066 fprintf(fp,"%*s accept",indent,ap->sp->name); |
3009 break; | 3067 break; |
3010 case ERROR: | 3068 case ERROR: |
3011 fprintf(fp,"%*s error",indent,ap->sp->name); | 3069 fprintf(fp,"%*s error",indent,ap->sp->name); |
3012 break; | 3070 break; |
3013 case SRCONFLICT: | 3071 case SRCONFLICT: |
3014 case RRCONFLICT: | 3072 case RRCONFLICT: |
3015 fprintf(fp,"%*s reduce %-3d ** Parsing conflict **", | 3073 fprintf(fp,"%*s reduce %-7d ** Parsing conflict **", |
3016 indent,ap->sp->name,ap->x.rp->index); | 3074 indent,ap->sp->name,ap->x.rp->index); |
3017 break; | 3075 break; |
3018 case SSCONFLICT: | 3076 case SSCONFLICT: |
3019 fprintf(fp,"%*s shift %-3d ** Parsing conflict **", | 3077 fprintf(fp,"%*s shift %-7d ** Parsing conflict **", |
3020 indent,ap->sp->name,ap->x.stp->statenum); | 3078 indent,ap->sp->name,ap->x.stp->statenum); |
3021 break; | 3079 break; |
3022 case SH_RESOLVED: | 3080 case SH_RESOLVED: |
3023 if( showPrecedenceConflict ){ | 3081 if( showPrecedenceConflict ){ |
3024 fprintf(fp,"%*s shift %-3d -- dropped by precedence", | 3082 fprintf(fp,"%*s shift %-7d -- dropped by precedence", |
3025 indent,ap->sp->name,ap->x.stp->statenum); | 3083 indent,ap->sp->name,ap->x.stp->statenum); |
3026 }else{ | 3084 }else{ |
3027 result = 0; | 3085 result = 0; |
3028 } | 3086 } |
3029 break; | 3087 break; |
3030 case RD_RESOLVED: | 3088 case RD_RESOLVED: |
3031 if( showPrecedenceConflict ){ | 3089 if( showPrecedenceConflict ){ |
3032 fprintf(fp,"%*s reduce %-3d -- dropped by precedence", | 3090 fprintf(fp,"%*s reduce %-7d -- dropped by precedence", |
3033 indent,ap->sp->name,ap->x.rp->index); | 3091 indent,ap->sp->name,ap->x.rp->index); |
3034 }else{ | 3092 }else{ |
3035 result = 0; | 3093 result = 0; |
3036 } | 3094 } |
3037 break; | 3095 break; |
3038 case NOT_USED: | 3096 case NOT_USED: |
3039 result = 0; | 3097 result = 0; |
3040 break; | 3098 break; |
3041 } | 3099 } |
3042 return result; | 3100 return result; |
3043 } | 3101 } |
3044 | 3102 |
3045 /* Generate the "y.output" log file */ | 3103 /* Generate the "*.out" log file */ |
3046 void ReportOutput(struct lemon *lemp) | 3104 void ReportOutput(struct lemon *lemp) |
3047 { | 3105 { |
3048 int i; | 3106 int i; |
3049 struct state *stp; | 3107 struct state *stp; |
3050 struct config *cfp; | 3108 struct config *cfp; |
3051 struct action *ap; | 3109 struct action *ap; |
3052 FILE *fp; | 3110 FILE *fp; |
3053 | 3111 |
3054 fp = file_open(lemp,".out","wb"); | 3112 fp = file_open(lemp,".out","wb"); |
3055 if( fp==0 ) return; | 3113 if( fp==0 ) return; |
3056 for(i=0; i<lemp->nstate; i++){ | 3114 for(i=0; i<lemp->nxstate; i++){ |
3057 stp = lemp->sorted[i]; | 3115 stp = lemp->sorted[i]; |
3058 fprintf(fp,"State %d:\n",stp->statenum); | 3116 fprintf(fp,"State %d:\n",stp->statenum); |
3059 if( lemp->basisflag ) cfp=stp->bp; | 3117 if( lemp->basisflag ) cfp=stp->bp; |
3060 else cfp=stp->cfp; | 3118 else cfp=stp->cfp; |
3061 while( cfp ){ | 3119 while( cfp ){ |
3062 char buf[20]; | 3120 char buf[20]; |
3063 if( cfp->dot==cfp->rp->nrhs ){ | 3121 if( cfp->dot==cfp->rp->nrhs ){ |
3064 lemon_sprintf(buf,"(%d)",cfp->rp->index); | 3122 lemon_sprintf(buf,"(%d)",cfp->rp->index); |
3065 fprintf(fp," %5s ",buf); | 3123 fprintf(fp," %5s ",buf); |
3066 }else{ | 3124 }else{ |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3154 } | 3212 } |
3155 | 3213 |
3156 /* Given an action, compute the integer value for that action | 3214 /* Given an action, compute the integer value for that action |
3157 ** which is to be put in the action table of the generated machine. | 3215 ** which is to be put in the action table of the generated machine. |
3158 ** Return negative if no action should be generated. | 3216 ** Return negative if no action should be generated. |
3159 */ | 3217 */ |
3160 PRIVATE int compute_action(struct lemon *lemp, struct action *ap) | 3218 PRIVATE int compute_action(struct lemon *lemp, struct action *ap) |
3161 { | 3219 { |
3162 int act; | 3220 int act; |
3163 switch( ap->type ){ | 3221 switch( ap->type ){ |
3164 case SHIFT: act = ap->x.stp->statenum; break; | 3222 case SHIFT: act = ap->x.stp->statenum; break; |
3165 case REDUCE: act = ap->x.rp->index + lemp->nstate; break; | 3223 case SHIFTREDUCE: act = ap->x.rp->index + lemp->nstate; break; |
3166 case ERROR: act = lemp->nstate + lemp->nrule; break; | 3224 case REDUCE: act = ap->x.rp->index + lemp->nstate+lemp->nrule; break; |
3167 case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break; | 3225 case ERROR: act = lemp->nstate + lemp->nrule*2; break; |
| 3226 case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break; |
3168 default: act = -1; break; | 3227 default: act = -1; break; |
3169 } | 3228 } |
3170 return act; | 3229 return act; |
3171 } | 3230 } |
3172 | 3231 |
3173 #define LINESIZE 1000 | 3232 #define LINESIZE 1000 |
3174 /* The next cluster of routines are for reading the template file | 3233 /* The next cluster of routines are for reading the template file |
3175 ** and writing the results to the generated parser */ | 3234 ** and writing the results to the generated parser */ |
3176 /* The first function transfers data from "in" to "out" until | 3235 /* The first function transfers data from "in" to "out" until |
3177 ** a line is seen which begins with "%%". The line number is | 3236 ** a line is seen which begins with "%%". The line number is |
3178 ** tracked. | 3237 ** tracked. |
3179 ** | 3238 ** |
3180 ** if name!=0, then any word that begin with "Parse" is changed to | 3239 ** if name!=0, then any word that begin with "Parse" is changed to |
3181 ** begin with *name instead. | 3240 ** begin with *name instead. |
3182 */ | 3241 */ |
3183 PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno) | 3242 PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno) |
3184 { | 3243 { |
3185 int i, iStart; | 3244 int i, iStart; |
3186 char line[LINESIZE]; | 3245 char line[LINESIZE]; |
3187 while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){ | 3246 while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){ |
3188 (*lineno)++; | 3247 (*lineno)++; |
3189 iStart = 0; | 3248 iStart = 0; |
3190 if( name ){ | 3249 if( name ){ |
3191 for(i=0; line[i]; i++){ | 3250 for(i=0; line[i]; i++){ |
3192 if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 | 3251 if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 |
3193 && (i==0 || !isalpha(line[i-1])) | 3252 && (i==0 || !ISALPHA(line[i-1])) |
3194 ){ | 3253 ){ |
3195 if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]); | 3254 if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]); |
3196 fprintf(out,"%s",name); | 3255 fprintf(out,"%s",name); |
3197 i += 4; | 3256 i += 4; |
3198 iStart = i+1; | 3257 iStart = i+1; |
3199 } | 3258 } |
3200 } | 3259 } |
3201 } | 3260 } |
3202 fprintf(out,"%s",&line[iStart]); | 3261 fprintf(out,"%s",&line[iStart]); |
3203 } | 3262 } |
(...skipping 12 matching lines...) Expand all Loading... |
3216 /* first, see if user specified a template filename on the command line. */ | 3275 /* first, see if user specified a template filename on the command line. */ |
3217 if (user_templatename != 0) { | 3276 if (user_templatename != 0) { |
3218 if( access(user_templatename,004)==-1 ){ | 3277 if( access(user_templatename,004)==-1 ){ |
3219 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", | 3278 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", |
3220 user_templatename); | 3279 user_templatename); |
3221 lemp->errorcnt++; | 3280 lemp->errorcnt++; |
3222 return 0; | 3281 return 0; |
3223 } | 3282 } |
3224 in = fopen(user_templatename,"rb"); | 3283 in = fopen(user_templatename,"rb"); |
3225 if( in==0 ){ | 3284 if( in==0 ){ |
3226 fprintf(stderr,"Can't open the template file \"%s\".\n",user_templatename)
; | 3285 fprintf(stderr,"Can't open the template file \"%s\".\n", |
| 3286 user_templatename); |
3227 lemp->errorcnt++; | 3287 lemp->errorcnt++; |
3228 return 0; | 3288 return 0; |
3229 } | 3289 } |
3230 return in; | 3290 return in; |
3231 } | 3291 } |
3232 | 3292 |
3233 cp = strrchr(lemp->filename,'.'); | 3293 cp = strrchr(lemp->filename,'.'); |
3234 if( cp ){ | 3294 if( cp ){ |
3235 lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); | 3295 lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); |
3236 }else{ | 3296 }else{ |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3301 ){ | 3361 ){ |
3302 char *cp = 0; | 3362 char *cp = 0; |
3303 | 3363 |
3304 if( sp->type==TERMINAL ){ | 3364 if( sp->type==TERMINAL ){ |
3305 cp = lemp->tokendest; | 3365 cp = lemp->tokendest; |
3306 if( cp==0 ) return; | 3366 if( cp==0 ) return; |
3307 fprintf(out,"{\n"); (*lineno)++; | 3367 fprintf(out,"{\n"); (*lineno)++; |
3308 }else if( sp->destructor ){ | 3368 }else if( sp->destructor ){ |
3309 cp = sp->destructor; | 3369 cp = sp->destructor; |
3310 fprintf(out,"{\n"); (*lineno)++; | 3370 fprintf(out,"{\n"); (*lineno)++; |
3311 if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,sp->destLineno,lemp
->filename); } | 3371 if( !lemp->nolinenosflag ){ |
| 3372 (*lineno)++; |
| 3373 tplt_linedir(out,sp->destLineno,lemp->filename); |
| 3374 } |
3312 }else if( lemp->vardest ){ | 3375 }else if( lemp->vardest ){ |
3313 cp = lemp->vardest; | 3376 cp = lemp->vardest; |
3314 if( cp==0 ) return; | 3377 if( cp==0 ) return; |
3315 fprintf(out,"{\n"); (*lineno)++; | 3378 fprintf(out,"{\n"); (*lineno)++; |
3316 }else{ | 3379 }else{ |
3317 assert( 0 ); /* Cannot happen */ | 3380 assert( 0 ); /* Cannot happen */ |
3318 } | 3381 } |
3319 for(; *cp; cp++){ | 3382 for(; *cp; cp++){ |
3320 if( *cp=='$' && cp[1]=='$' ){ | 3383 if( *cp=='$' && cp[1]=='$' ){ |
3321 fprintf(out,"(yypminor->yy%d)",sp->dtnum); | 3384 fprintf(out,"(yypminor->yy%d)",sp->dtnum); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3385 while( n-- > 0 ){ | 3448 while( n-- > 0 ){ |
3386 c = *(zText++); | 3449 c = *(zText++); |
3387 if( c=='%' && n>0 && zText[0]=='d' ){ | 3450 if( c=='%' && n>0 && zText[0]=='d' ){ |
3388 lemon_sprintf(zInt, "%d", p1); | 3451 lemon_sprintf(zInt, "%d", p1); |
3389 p1 = p2; | 3452 p1 = p2; |
3390 lemon_strcpy(&z[used], zInt); | 3453 lemon_strcpy(&z[used], zInt); |
3391 used += lemonStrlen(&z[used]); | 3454 used += lemonStrlen(&z[used]); |
3392 zText++; | 3455 zText++; |
3393 n--; | 3456 n--; |
3394 }else{ | 3457 }else{ |
3395 z[used++] = c; | 3458 z[used++] = (char)c; |
3396 } | 3459 } |
3397 } | 3460 } |
3398 z[used] = 0; | 3461 z[used] = 0; |
3399 return z; | 3462 return z; |
3400 } | 3463 } |
3401 | 3464 |
3402 /* | 3465 /* |
3403 ** zCode is a string that is the action associated with a rule. Expand | 3466 ** zCode is a string that is the action associated with a rule. Expand |
3404 ** the symbols in this string so that the refer to elements of the parser | 3467 ** the symbols in this string so that the refer to elements of the parser |
3405 ** stack. | 3468 ** stack. |
(...skipping 10 matching lines...) Expand all Loading... |
3416 if( rp->code==0 ){ | 3479 if( rp->code==0 ){ |
3417 static char newlinestr[2] = { '\n', '\0' }; | 3480 static char newlinestr[2] = { '\n', '\0' }; |
3418 rp->code = newlinestr; | 3481 rp->code = newlinestr; |
3419 rp->line = rp->ruleline; | 3482 rp->line = rp->ruleline; |
3420 } | 3483 } |
3421 | 3484 |
3422 append_str(0,0,0,0); | 3485 append_str(0,0,0,0); |
3423 | 3486 |
3424 /* This const cast is wrong but harmless, if we're careful. */ | 3487 /* This const cast is wrong but harmless, if we're careful. */ |
3425 for(cp=(char *)rp->code; *cp; cp++){ | 3488 for(cp=(char *)rp->code; *cp; cp++){ |
3426 if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){ | 3489 if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){ |
3427 char saved; | 3490 char saved; |
3428 for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++); | 3491 for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++); |
3429 saved = *xp; | 3492 saved = *xp; |
3430 *xp = 0; | 3493 *xp = 0; |
3431 if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ | 3494 if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ |
3432 append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0); | 3495 append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0); |
3433 cp = xp; | 3496 cp = xp; |
3434 lhsused = 1; | 3497 lhsused = 1; |
3435 }else{ | 3498 }else{ |
3436 for(i=0; i<rp->nrhs; i++){ | 3499 for(i=0; i<rp->nrhs; i++){ |
3437 if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ | 3500 if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ |
3438 if( cp!=rp->code && cp[-1]=='@' ){ | 3501 if( cp!=rp->code && cp[-1]=='@' ){ |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3498 PRIVATE void emit_code( | 3561 PRIVATE void emit_code( |
3499 FILE *out, | 3562 FILE *out, |
3500 struct rule *rp, | 3563 struct rule *rp, |
3501 struct lemon *lemp, | 3564 struct lemon *lemp, |
3502 int *lineno | 3565 int *lineno |
3503 ){ | 3566 ){ |
3504 const char *cp; | 3567 const char *cp; |
3505 | 3568 |
3506 /* Generate code to do the reduce action */ | 3569 /* Generate code to do the reduce action */ |
3507 if( rp->code ){ | 3570 if( rp->code ){ |
3508 if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,rp->line,lemp->file
name); } | 3571 if( !lemp->nolinenosflag ){ |
| 3572 (*lineno)++; |
| 3573 tplt_linedir(out,rp->line,lemp->filename); |
| 3574 } |
3509 fprintf(out,"{%s",rp->code); | 3575 fprintf(out,"{%s",rp->code); |
3510 for(cp=rp->code; *cp; cp++){ | 3576 for(cp=rp->code; *cp; cp++){ |
3511 if( *cp=='\n' ) (*lineno)++; | 3577 if( *cp=='\n' ) (*lineno)++; |
3512 } /* End loop */ | 3578 } /* End loop */ |
3513 fprintf(out,"}\n"); (*lineno)++; | 3579 fprintf(out,"}\n"); (*lineno)++; |
3514 if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,*lineno,lemp->outna
me); } | 3580 if( !lemp->nolinenosflag ){ |
| 3581 (*lineno)++; |
| 3582 tplt_linedir(out,*lineno,lemp->outname); |
| 3583 } |
3515 } /* End if( rp->code ) */ | 3584 } /* End if( rp->code ) */ |
3516 | 3585 |
3517 return; | 3586 return; |
3518 } | 3587 } |
3519 | 3588 |
3520 /* | 3589 /* |
3521 ** Print the definition of the union used for the parser's data stack. | 3590 ** Print the definition of the union used for the parser's data stack. |
3522 ** This union contains fields for every possible data type for tokens | 3591 ** This union contains fields for every possible data type for tokens |
3523 ** and nonterminals. In the process of computing and printing this | 3592 ** and nonterminals. In the process of computing and printing this |
3524 ** union, also set the ".dtnum" field of every terminal and nonterminal | 3593 ** union, also set the ".dtnum" field of every terminal and nonterminal |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3577 sp->dtnum = arraysize+1; | 3646 sp->dtnum = arraysize+1; |
3578 continue; | 3647 continue; |
3579 } | 3648 } |
3580 if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){ | 3649 if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){ |
3581 sp->dtnum = 0; | 3650 sp->dtnum = 0; |
3582 continue; | 3651 continue; |
3583 } | 3652 } |
3584 cp = sp->datatype; | 3653 cp = sp->datatype; |
3585 if( cp==0 ) cp = lemp->vartype; | 3654 if( cp==0 ) cp = lemp->vartype; |
3586 j = 0; | 3655 j = 0; |
3587 while( isspace(*cp) ) cp++; | 3656 while( ISSPACE(*cp) ) cp++; |
3588 while( *cp ) stddt[j++] = *cp++; | 3657 while( *cp ) stddt[j++] = *cp++; |
3589 while( j>0 && isspace(stddt[j-1]) ) j--; | 3658 while( j>0 && ISSPACE(stddt[j-1]) ) j--; |
3590 stddt[j] = 0; | 3659 stddt[j] = 0; |
3591 if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){ | 3660 if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){ |
3592 sp->dtnum = 0; | 3661 sp->dtnum = 0; |
3593 continue; | 3662 continue; |
3594 } | 3663 } |
3595 hash = 0; | 3664 hash = 0; |
3596 for(j=0; stddt[j]; j++){ | 3665 for(j=0; stddt[j]; j++){ |
3597 hash = hash*53 + stddt[j]; | 3666 hash = hash*53 + stddt[j]; |
3598 } | 3667 } |
3599 hash = (hash & 0x7fffffff)%arraysize; | 3668 hash = (hash & 0x7fffffff)%arraysize; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3635 fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++; | 3704 fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++; |
3636 } | 3705 } |
3637 free(stddt); | 3706 free(stddt); |
3638 free(types); | 3707 free(types); |
3639 fprintf(out,"} YYMINORTYPE;\n"); lineno++; | 3708 fprintf(out,"} YYMINORTYPE;\n"); lineno++; |
3640 *plineno = lineno; | 3709 *plineno = lineno; |
3641 } | 3710 } |
3642 | 3711 |
3643 /* | 3712 /* |
3644 ** Return the name of a C datatype able to represent values between | 3713 ** Return the name of a C datatype able to represent values between |
3645 ** lwr and upr, inclusive. | 3714 ** lwr and upr, inclusive. If pnByte!=NULL then also write the sizeof |
| 3715 ** for that type (1, 2, or 4) into *pnByte. |
3646 */ | 3716 */ |
3647 static const char *minimum_size_type(int lwr, int upr){ | 3717 static const char *minimum_size_type(int lwr, int upr, int *pnByte){ |
| 3718 const char *zType = "int"; |
| 3719 int nByte = 4; |
3648 if( lwr>=0 ){ | 3720 if( lwr>=0 ){ |
3649 if( upr<=255 ){ | 3721 if( upr<=255 ){ |
3650 return "unsigned char"; | 3722 zType = "unsigned char"; |
| 3723 nByte = 1; |
3651 }else if( upr<65535 ){ | 3724 }else if( upr<65535 ){ |
3652 return "unsigned short int"; | 3725 zType = "unsigned short int"; |
| 3726 nByte = 2; |
3653 }else{ | 3727 }else{ |
3654 return "unsigned int"; | 3728 zType = "unsigned int"; |
| 3729 nByte = 4; |
3655 } | 3730 } |
3656 }else if( lwr>=-127 && upr<=127 ){ | 3731 }else if( lwr>=-127 && upr<=127 ){ |
3657 return "signed char"; | 3732 zType = "signed char"; |
| 3733 nByte = 1; |
3658 }else if( lwr>=-32767 && upr<32767 ){ | 3734 }else if( lwr>=-32767 && upr<32767 ){ |
3659 return "short"; | 3735 zType = "short"; |
3660 }else{ | 3736 nByte = 2; |
3661 return "int"; | |
3662 } | 3737 } |
| 3738 if( pnByte ) *pnByte = nByte; |
| 3739 return zType; |
3663 } | 3740 } |
3664 | 3741 |
3665 /* | 3742 /* |
3666 ** Each state contains a set of token transaction and a set of | 3743 ** Each state contains a set of token transaction and a set of |
3667 ** nonterminal transactions. Each of these sets makes an instance | 3744 ** nonterminal transactions. Each of these sets makes an instance |
3668 ** of the following structure. An array of these structures is used | 3745 ** of the following structure. An array of these structures is used |
3669 ** to order the creation of entries in the yy_action[] table. | 3746 ** to order the creation of entries in the yy_action[] table. |
3670 */ | 3747 */ |
3671 struct axset { | 3748 struct axset { |
3672 struct state *stp; /* A pointer to a state */ | 3749 struct state *stp; /* A pointer to a state */ |
3673 int isTkn; /* True to use tokens. False for non-terminals */ | 3750 int isTkn; /* True to use tokens. False for non-terminals */ |
3674 int nAction; /* Number of actions */ | 3751 int nAction; /* Number of actions */ |
3675 int iOrder; /* Original order of action sets */ | 3752 int iOrder; /* Original order of action sets */ |
3676 }; | 3753 }; |
3677 | 3754 |
3678 /* | 3755 /* |
3679 ** Compare to axset structures for sorting purposes | 3756 ** Compare to axset structures for sorting purposes |
3680 */ | 3757 */ |
3681 static int axset_compare(const void *a, const void *b){ | 3758 static int axset_compare(const void *a, const void *b){ |
3682 struct axset *p1 = (struct axset*)a; | 3759 struct axset *p1 = (struct axset*)a; |
3683 struct axset *p2 = (struct axset*)b; | 3760 struct axset *p2 = (struct axset*)b; |
3684 int c; | 3761 int c; |
3685 c = p2->nAction - p1->nAction; | 3762 c = p2->nAction - p1->nAction; |
3686 if( c==0 ){ | 3763 if( c==0 ){ |
3687 c = p2->iOrder - p1->iOrder; | 3764 c = p1->iOrder - p2->iOrder; |
3688 } | 3765 } |
3689 assert( c!=0 || p1==p2 ); | 3766 assert( c!=0 || p1==p2 ); |
3690 return c; | 3767 return c; |
3691 } | 3768 } |
3692 | 3769 |
3693 /* | 3770 /* |
3694 ** Write text on "out" that describes the rule "rp". | 3771 ** Write text on "out" that describes the rule "rp". |
3695 */ | 3772 */ |
3696 static void writeRuleText(FILE *out, struct rule *rp){ | 3773 static void writeRuleText(FILE *out, struct rule *rp){ |
3697 int j; | 3774 int j; |
(...skipping 18 matching lines...) Expand all Loading... |
3716 struct lemon *lemp, | 3793 struct lemon *lemp, |
3717 int mhflag /* Output in makeheaders format if true */ | 3794 int mhflag /* Output in makeheaders format if true */ |
3718 ){ | 3795 ){ |
3719 FILE *out, *in; | 3796 FILE *out, *in; |
3720 char line[LINESIZE]; | 3797 char line[LINESIZE]; |
3721 int lineno; | 3798 int lineno; |
3722 struct state *stp; | 3799 struct state *stp; |
3723 struct action *ap; | 3800 struct action *ap; |
3724 struct rule *rp; | 3801 struct rule *rp; |
3725 struct acttab *pActtab; | 3802 struct acttab *pActtab; |
3726 int i, j, n; | 3803 int i, j, n, sz; |
| 3804 int szActionType; /* sizeof(YYACTIONTYPE) */ |
| 3805 int szCodeType; /* sizeof(YYCODETYPE) */ |
3727 const char *name; | 3806 const char *name; |
3728 int mnTknOfst, mxTknOfst; | 3807 int mnTknOfst, mxTknOfst; |
3729 int mnNtOfst, mxNtOfst; | 3808 int mnNtOfst, mxNtOfst; |
3730 struct axset *ax; | 3809 struct axset *ax; |
3731 | 3810 |
3732 in = tplt_open(lemp); | 3811 in = tplt_open(lemp); |
3733 if( in==0 ) return; | 3812 if( in==0 ) return; |
3734 out = file_open(lemp,".c","wb"); | 3813 out = file_open(lemp,".c","wb"); |
3735 if( out==0 ){ | 3814 if( out==0 ){ |
3736 fclose(in); | 3815 fclose(in); |
3737 return; | 3816 return; |
3738 } | 3817 } |
3739 lineno = 1; | 3818 lineno = 1; |
3740 tplt_xfer(lemp->name,in,out,&lineno); | 3819 tplt_xfer(lemp->name,in,out,&lineno); |
3741 | 3820 |
3742 /* Generate the include code, if any */ | 3821 /* Generate the include code, if any */ |
3743 tplt_print(out,lemp,lemp->include,&lineno); | 3822 tplt_print(out,lemp,lemp->include,&lineno); |
3744 if( mhflag ){ | 3823 if( mhflag ){ |
3745 char *name = file_makename(lemp, ".h"); | 3824 char *incName = file_makename(lemp, ".h"); |
3746 fprintf(out,"#include \"%s\"\n", name); lineno++; | 3825 fprintf(out,"#include \"%s\"\n", incName); lineno++; |
3747 free(name); | 3826 free(incName); |
3748 } | 3827 } |
3749 tplt_xfer(lemp->name,in,out,&lineno); | 3828 tplt_xfer(lemp->name,in,out,&lineno); |
3750 | 3829 |
3751 /* Generate #defines for all tokens */ | 3830 /* Generate #defines for all tokens */ |
3752 if( mhflag ){ | 3831 if( mhflag ){ |
3753 const char *prefix; | 3832 const char *prefix; |
3754 fprintf(out,"#if INTERFACE\n"); lineno++; | 3833 fprintf(out,"#if INTERFACE\n"); lineno++; |
3755 if( lemp->tokenprefix ) prefix = lemp->tokenprefix; | 3834 if( lemp->tokenprefix ) prefix = lemp->tokenprefix; |
3756 else prefix = ""; | 3835 else prefix = ""; |
3757 for(i=1; i<lemp->nterminal; i++){ | 3836 for(i=1; i<lemp->nterminal; i++){ |
3758 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 3837 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); |
3759 lineno++; | 3838 lineno++; |
3760 } | 3839 } |
3761 fprintf(out,"#endif\n"); lineno++; | 3840 fprintf(out,"#endif\n"); lineno++; |
3762 } | 3841 } |
3763 tplt_xfer(lemp->name,in,out,&lineno); | 3842 tplt_xfer(lemp->name,in,out,&lineno); |
3764 | 3843 |
3765 /* Generate the defines */ | 3844 /* Generate the defines */ |
3766 fprintf(out,"#define YYCODETYPE %s\n", | 3845 fprintf(out,"#define YYCODETYPE %s\n", |
3767 minimum_size_type(0, lemp->nsymbol+1)); lineno++; | 3846 minimum_size_type(0, lemp->nsymbol+1, &szCodeType)); lineno++; |
3768 fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++; | 3847 fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++; |
3769 fprintf(out,"#define YYACTIONTYPE %s\n", | 3848 fprintf(out,"#define YYACTIONTYPE %s\n", |
3770 minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++; | 3849 minimum_size_type(0,lemp->nstate+lemp->nrule*2+5,&szActionType)); lineno++; |
3771 if( lemp->wildcard ){ | 3850 if( lemp->wildcard ){ |
3772 fprintf(out,"#define YYWILDCARD %d\n", | 3851 fprintf(out,"#define YYWILDCARD %d\n", |
3773 lemp->wildcard->index); lineno++; | 3852 lemp->wildcard->index); lineno++; |
3774 } | 3853 } |
3775 print_stack_union(out,lemp,&lineno,mhflag); | 3854 print_stack_union(out,lemp,&lineno,mhflag); |
3776 fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++; | 3855 fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++; |
3777 if( lemp->stacksize ){ | 3856 if( lemp->stacksize ){ |
3778 fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++; | 3857 fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++; |
3779 }else{ | 3858 }else{ |
3780 fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++; | 3859 fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++; |
3781 } | 3860 } |
3782 fprintf(out, "#endif\n"); lineno++; | 3861 fprintf(out, "#endif\n"); lineno++; |
3783 if( mhflag ){ | 3862 if( mhflag ){ |
3784 fprintf(out,"#if INTERFACE\n"); lineno++; | 3863 fprintf(out,"#if INTERFACE\n"); lineno++; |
3785 } | 3864 } |
3786 name = lemp->name ? lemp->name : "Parse"; | 3865 name = lemp->name ? lemp->name : "Parse"; |
3787 if( lemp->arg && lemp->arg[0] ){ | 3866 if( lemp->arg && lemp->arg[0] ){ |
3788 int i; | |
3789 i = lemonStrlen(lemp->arg); | 3867 i = lemonStrlen(lemp->arg); |
3790 while( i>=1 && isspace(lemp->arg[i-1]) ) i--; | 3868 while( i>=1 && ISSPACE(lemp->arg[i-1]) ) i--; |
3791 while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; | 3869 while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; |
3792 fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++; | 3870 fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++; |
3793 fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++; | 3871 fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++; |
3794 fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n", | 3872 fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n", |
3795 name,lemp->arg,&lemp->arg[i]); lineno++; | 3873 name,lemp->arg,&lemp->arg[i]); lineno++; |
3796 fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n", | 3874 fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n", |
3797 name,&lemp->arg[i],&lemp->arg[i]); lineno++; | 3875 name,&lemp->arg[i],&lemp->arg[i]); lineno++; |
3798 }else{ | 3876 }else{ |
3799 fprintf(out,"#define %sARG_SDECL\n",name); lineno++; | 3877 fprintf(out,"#define %sARG_SDECL\n",name); lineno++; |
3800 fprintf(out,"#define %sARG_PDECL\n",name); lineno++; | 3878 fprintf(out,"#define %sARG_PDECL\n",name); lineno++; |
3801 fprintf(out,"#define %sARG_FETCH\n",name); lineno++; | 3879 fprintf(out,"#define %sARG_FETCH\n",name); lineno++; |
3802 fprintf(out,"#define %sARG_STORE\n",name); lineno++; | 3880 fprintf(out,"#define %sARG_STORE\n",name); lineno++; |
3803 } | 3881 } |
3804 if( mhflag ){ | 3882 if( mhflag ){ |
3805 fprintf(out,"#endif\n"); lineno++; | 3883 fprintf(out,"#endif\n"); lineno++; |
3806 } | 3884 } |
3807 fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++; | |
3808 fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; | |
3809 if( lemp->errsym->useCnt ){ | 3885 if( lemp->errsym->useCnt ){ |
3810 fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++; | 3886 fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++; |
3811 fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++; | 3887 fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++; |
3812 } | 3888 } |
3813 if( lemp->has_fallback ){ | 3889 if( lemp->has_fallback ){ |
3814 fprintf(out,"#define YYFALLBACK 1\n"); lineno++; | 3890 fprintf(out,"#define YYFALLBACK 1\n"); lineno++; |
3815 } | 3891 } |
3816 tplt_xfer(lemp->name,in,out,&lineno); | |
3817 | 3892 |
3818 /* Generate the action table and its associates: | 3893 /* Compute the action table, but do not output it yet. The action |
3819 ** | 3894 ** table must be computed before generating the YYNSTATE macro because |
3820 ** yy_action[] A single table containing all actions. | 3895 ** we need to know how many states can be eliminated. |
3821 ** yy_lookahead[] A table containing the lookahead for each entry in | |
3822 ** yy_action. Used to detect hash collisions. | |
3823 ** yy_shift_ofst[] For each state, the offset into yy_action for | |
3824 ** shifting terminals. | |
3825 ** yy_reduce_ofst[] For each state, the offset into yy_action for | |
3826 ** shifting non-terminals after a reduce. | |
3827 ** yy_default[] Default action for each state. | |
3828 */ | 3896 */ |
3829 | 3897 ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0])); |
3830 /* Compute the actions on all states and count them up */ | |
3831 ax = (struct axset *) calloc(lemp->nstate*2, sizeof(ax[0])); | |
3832 if( ax==0 ){ | 3898 if( ax==0 ){ |
3833 fprintf(stderr,"malloc failed\n"); | 3899 fprintf(stderr,"malloc failed\n"); |
3834 exit(1); | 3900 exit(1); |
3835 } | 3901 } |
3836 for(i=0; i<lemp->nstate; i++){ | 3902 for(i=0; i<lemp->nxstate; i++){ |
3837 stp = lemp->sorted[i]; | 3903 stp = lemp->sorted[i]; |
3838 ax[i*2].stp = stp; | 3904 ax[i*2].stp = stp; |
3839 ax[i*2].isTkn = 1; | 3905 ax[i*2].isTkn = 1; |
3840 ax[i*2].nAction = stp->nTknAct; | 3906 ax[i*2].nAction = stp->nTknAct; |
3841 ax[i*2+1].stp = stp; | 3907 ax[i*2+1].stp = stp; |
3842 ax[i*2+1].isTkn = 0; | 3908 ax[i*2+1].isTkn = 0; |
3843 ax[i*2+1].nAction = stp->nNtAct; | 3909 ax[i*2+1].nAction = stp->nNtAct; |
3844 } | 3910 } |
3845 mxTknOfst = mnTknOfst = 0; | 3911 mxTknOfst = mnTknOfst = 0; |
3846 mxNtOfst = mnNtOfst = 0; | 3912 mxNtOfst = mnNtOfst = 0; |
3847 | 3913 /* In an effort to minimize the action table size, use the heuristic |
3848 /* Compute the action table. In order to try to keep the size of the | 3914 ** of placing the largest action sets first */ |
3849 ** action table to a minimum, the heuristic of placing the largest action | 3915 for(i=0; i<lemp->nxstate*2; i++) ax[i].iOrder = i; |
3850 ** sets first is used. | 3916 qsort(ax, lemp->nxstate*2, sizeof(ax[0]), axset_compare); |
3851 */ | |
3852 for(i=0; i<lemp->nstate*2; i++) ax[i].iOrder = i; | |
3853 qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare); | |
3854 pActtab = acttab_alloc(); | 3917 pActtab = acttab_alloc(); |
3855 for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){ | 3918 for(i=0; i<lemp->nxstate*2 && ax[i].nAction>0; i++){ |
3856 stp = ax[i].stp; | 3919 stp = ax[i].stp; |
3857 if( ax[i].isTkn ){ | 3920 if( ax[i].isTkn ){ |
3858 for(ap=stp->ap; ap; ap=ap->next){ | 3921 for(ap=stp->ap; ap; ap=ap->next){ |
3859 int action; | 3922 int action; |
3860 if( ap->sp->index>=lemp->nterminal ) continue; | 3923 if( ap->sp->index>=lemp->nterminal ) continue; |
3861 action = compute_action(lemp, ap); | 3924 action = compute_action(lemp, ap); |
3862 if( action<0 ) continue; | 3925 if( action<0 ) continue; |
3863 acttab_action(pActtab, ap->sp->index, action); | 3926 acttab_action(pActtab, ap->sp->index, action); |
3864 } | 3927 } |
3865 stp->iTknOfst = acttab_insert(pActtab); | 3928 stp->iTknOfst = acttab_insert(pActtab); |
3866 if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst; | 3929 if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst; |
3867 if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst; | 3930 if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst; |
3868 }else{ | 3931 }else{ |
3869 for(ap=stp->ap; ap; ap=ap->next){ | 3932 for(ap=stp->ap; ap; ap=ap->next){ |
3870 int action; | 3933 int action; |
3871 if( ap->sp->index<lemp->nterminal ) continue; | 3934 if( ap->sp->index<lemp->nterminal ) continue; |
3872 if( ap->sp->index==lemp->nsymbol ) continue; | 3935 if( ap->sp->index==lemp->nsymbol ) continue; |
3873 action = compute_action(lemp, ap); | 3936 action = compute_action(lemp, ap); |
3874 if( action<0 ) continue; | 3937 if( action<0 ) continue; |
3875 acttab_action(pActtab, ap->sp->index, action); | 3938 acttab_action(pActtab, ap->sp->index, action); |
3876 } | 3939 } |
3877 stp->iNtOfst = acttab_insert(pActtab); | 3940 stp->iNtOfst = acttab_insert(pActtab); |
3878 if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst; | 3941 if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst; |
3879 if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst; | 3942 if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst; |
3880 } | 3943 } |
| 3944 #if 0 /* Uncomment for a trace of how the yy_action[] table fills out */ |
| 3945 { int jj, nn; |
| 3946 for(jj=nn=0; jj<pActtab->nAction; jj++){ |
| 3947 if( pActtab->aAction[jj].action<0 ) nn++; |
| 3948 } |
| 3949 printf("%4d: State %3d %s n: %2d size: %5d freespace: %d\n", |
| 3950 i, stp->statenum, ax[i].isTkn ? "Token" : "Var ", |
| 3951 ax[i].nAction, pActtab->nAction, nn); |
| 3952 } |
| 3953 #endif |
3881 } | 3954 } |
3882 free(ax); | 3955 free(ax); |
3883 | 3956 |
| 3957 /* Finish rendering the constants now that the action table has |
| 3958 ** been computed */ |
| 3959 fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++; |
| 3960 fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; |
| 3961 fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++; |
| 3962 fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",lemp->nstate); lineno++; |
| 3963 i = lemp->nstate + lemp->nrule; |
| 3964 fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++; |
| 3965 fprintf(out,"#define YY_MIN_REDUCE %d\n", i); lineno++; |
| 3966 i = lemp->nstate + lemp->nrule*2; |
| 3967 fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++; |
| 3968 fprintf(out,"#define YY_ERROR_ACTION %d\n", i); lineno++; |
| 3969 fprintf(out,"#define YY_ACCEPT_ACTION %d\n", i+1); lineno++; |
| 3970 fprintf(out,"#define YY_NO_ACTION %d\n", i+2); lineno++; |
| 3971 tplt_xfer(lemp->name,in,out,&lineno); |
| 3972 |
| 3973 /* Now output the action table and its associates: |
| 3974 ** |
| 3975 ** yy_action[] A single table containing all actions. |
| 3976 ** yy_lookahead[] A table containing the lookahead for each entry in |
| 3977 ** yy_action. Used to detect hash collisions. |
| 3978 ** yy_shift_ofst[] For each state, the offset into yy_action for |
| 3979 ** shifting terminals. |
| 3980 ** yy_reduce_ofst[] For each state, the offset into yy_action for |
| 3981 ** shifting non-terminals after a reduce. |
| 3982 ** yy_default[] Default action for each state. |
| 3983 */ |
| 3984 |
3884 /* Output the yy_action table */ | 3985 /* Output the yy_action table */ |
3885 n = acttab_size(pActtab); | 3986 lemp->nactiontab = n = acttab_size(pActtab); |
| 3987 lemp->tablesize += n*szActionType; |
3886 fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++; | 3988 fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++; |
3887 fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++; | 3989 fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++; |
3888 for(i=j=0; i<n; i++){ | 3990 for(i=j=0; i<n; i++){ |
3889 int action = acttab_yyaction(pActtab, i); | 3991 int action = acttab_yyaction(pActtab, i); |
3890 if( action<0 ) action = lemp->nstate + lemp->nrule + 2; | 3992 if( action<0 ) action = lemp->nstate + lemp->nrule + 2; |
3891 if( j==0 ) fprintf(out," /* %5d */ ", i); | 3993 if( j==0 ) fprintf(out," /* %5d */ ", i); |
3892 fprintf(out, " %4d,", action); | 3994 fprintf(out, " %4d,", action); |
3893 if( j==9 || i==n-1 ){ | 3995 if( j==9 || i==n-1 ){ |
3894 fprintf(out, "\n"); lineno++; | 3996 fprintf(out, "\n"); lineno++; |
3895 j = 0; | 3997 j = 0; |
3896 }else{ | 3998 }else{ |
3897 j++; | 3999 j++; |
3898 } | 4000 } |
3899 } | 4001 } |
3900 fprintf(out, "};\n"); lineno++; | 4002 fprintf(out, "};\n"); lineno++; |
3901 | 4003 |
3902 /* Output the yy_lookahead table */ | 4004 /* Output the yy_lookahead table */ |
| 4005 lemp->tablesize += n*szCodeType; |
3903 fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++; | 4006 fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++; |
3904 for(i=j=0; i<n; i++){ | 4007 for(i=j=0; i<n; i++){ |
3905 int la = acttab_yylookahead(pActtab, i); | 4008 int la = acttab_yylookahead(pActtab, i); |
3906 if( la<0 ) la = lemp->nsymbol; | 4009 if( la<0 ) la = lemp->nsymbol; |
3907 if( j==0 ) fprintf(out," /* %5d */ ", i); | 4010 if( j==0 ) fprintf(out," /* %5d */ ", i); |
3908 fprintf(out, " %4d,", la); | 4011 fprintf(out, " %4d,", la); |
3909 if( j==9 || i==n-1 ){ | 4012 if( j==9 || i==n-1 ){ |
3910 fprintf(out, "\n"); lineno++; | 4013 fprintf(out, "\n"); lineno++; |
3911 j = 0; | 4014 j = 0; |
3912 }else{ | 4015 }else{ |
3913 j++; | 4016 j++; |
3914 } | 4017 } |
3915 } | 4018 } |
3916 fprintf(out, "};\n"); lineno++; | 4019 fprintf(out, "};\n"); lineno++; |
3917 | 4020 |
3918 /* Output the yy_shift_ofst[] table */ | 4021 /* Output the yy_shift_ofst[] table */ |
3919 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; | 4022 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; |
3920 n = lemp->nstate; | 4023 n = lemp->nxstate; |
3921 while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; | 4024 while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; |
3922 fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; | 4025 fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; |
3923 fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; | 4026 fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; |
3924 fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; | 4027 fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; |
3925 fprintf(out, "static const %s yy_shift_ofst[] = {\n", | 4028 fprintf(out, "static const %s yy_shift_ofst[] = {\n", |
3926 minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++; | 4029 minimum_size_type(mnTknOfst-1, mxTknOfst, &sz)); lineno++; |
| 4030 lemp->tablesize += n*sz; |
3927 for(i=j=0; i<n; i++){ | 4031 for(i=j=0; i<n; i++){ |
3928 int ofst; | 4032 int ofst; |
3929 stp = lemp->sorted[i]; | 4033 stp = lemp->sorted[i]; |
3930 ofst = stp->iTknOfst; | 4034 ofst = stp->iTknOfst; |
3931 if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1; | 4035 if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1; |
3932 if( j==0 ) fprintf(out," /* %5d */ ", i); | 4036 if( j==0 ) fprintf(out," /* %5d */ ", i); |
3933 fprintf(out, " %4d,", ofst); | 4037 fprintf(out, " %4d,", ofst); |
3934 if( j==9 || i==n-1 ){ | 4038 if( j==9 || i==n-1 ){ |
3935 fprintf(out, "\n"); lineno++; | 4039 fprintf(out, "\n"); lineno++; |
3936 j = 0; | 4040 j = 0; |
3937 }else{ | 4041 }else{ |
3938 j++; | 4042 j++; |
3939 } | 4043 } |
3940 } | 4044 } |
3941 fprintf(out, "};\n"); lineno++; | 4045 fprintf(out, "};\n"); lineno++; |
3942 | 4046 |
3943 /* Output the yy_reduce_ofst[] table */ | 4047 /* Output the yy_reduce_ofst[] table */ |
3944 fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++; | 4048 fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++; |
3945 n = lemp->nstate; | 4049 n = lemp->nxstate; |
3946 while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--; | 4050 while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--; |
3947 fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++; | 4051 fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++; |
3948 fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++; | 4052 fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++; |
3949 fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++; | 4053 fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++; |
3950 fprintf(out, "static const %s yy_reduce_ofst[] = {\n", | 4054 fprintf(out, "static const %s yy_reduce_ofst[] = {\n", |
3951 minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++; | 4055 minimum_size_type(mnNtOfst-1, mxNtOfst, &sz)); lineno++; |
| 4056 lemp->tablesize += n*sz; |
3952 for(i=j=0; i<n; i++){ | 4057 for(i=j=0; i<n; i++){ |
3953 int ofst; | 4058 int ofst; |
3954 stp = lemp->sorted[i]; | 4059 stp = lemp->sorted[i]; |
3955 ofst = stp->iNtOfst; | 4060 ofst = stp->iNtOfst; |
3956 if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1; | 4061 if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1; |
3957 if( j==0 ) fprintf(out," /* %5d */ ", i); | 4062 if( j==0 ) fprintf(out," /* %5d */ ", i); |
3958 fprintf(out, " %4d,", ofst); | 4063 fprintf(out, " %4d,", ofst); |
3959 if( j==9 || i==n-1 ){ | 4064 if( j==9 || i==n-1 ){ |
3960 fprintf(out, "\n"); lineno++; | 4065 fprintf(out, "\n"); lineno++; |
3961 j = 0; | 4066 j = 0; |
3962 }else{ | 4067 }else{ |
3963 j++; | 4068 j++; |
3964 } | 4069 } |
3965 } | 4070 } |
3966 fprintf(out, "};\n"); lineno++; | 4071 fprintf(out, "};\n"); lineno++; |
3967 | 4072 |
3968 /* Output the default action table */ | 4073 /* Output the default action table */ |
3969 fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++; | 4074 fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++; |
3970 n = lemp->nstate; | 4075 n = lemp->nxstate; |
| 4076 lemp->tablesize += n*szActionType; |
3971 for(i=j=0; i<n; i++){ | 4077 for(i=j=0; i<n; i++){ |
3972 stp = lemp->sorted[i]; | 4078 stp = lemp->sorted[i]; |
3973 if( j==0 ) fprintf(out," /* %5d */ ", i); | 4079 if( j==0 ) fprintf(out," /* %5d */ ", i); |
3974 fprintf(out, " %4d,", stp->iDflt); | 4080 fprintf(out, " %4d,", stp->iDfltReduce+lemp->nstate+lemp->nrule); |
3975 if( j==9 || i==n-1 ){ | 4081 if( j==9 || i==n-1 ){ |
3976 fprintf(out, "\n"); lineno++; | 4082 fprintf(out, "\n"); lineno++; |
3977 j = 0; | 4083 j = 0; |
3978 }else{ | 4084 }else{ |
3979 j++; | 4085 j++; |
3980 } | 4086 } |
3981 } | 4087 } |
3982 fprintf(out, "};\n"); lineno++; | 4088 fprintf(out, "};\n"); lineno++; |
3983 tplt_xfer(lemp->name,in,out,&lineno); | 4089 tplt_xfer(lemp->name,in,out,&lineno); |
3984 | 4090 |
3985 /* Generate the table of fallback tokens. | 4091 /* Generate the table of fallback tokens. |
3986 */ | 4092 */ |
3987 if( lemp->has_fallback ){ | 4093 if( lemp->has_fallback ){ |
3988 int mx = lemp->nterminal - 1; | 4094 int mx = lemp->nterminal - 1; |
3989 while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } | 4095 while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } |
| 4096 lemp->tablesize += (mx+1)*szCodeType; |
3990 for(i=0; i<=mx; i++){ | 4097 for(i=0; i<=mx; i++){ |
3991 struct symbol *p = lemp->symbols[i]; | 4098 struct symbol *p = lemp->symbols[i]; |
3992 if( p->fallback==0 ){ | 4099 if( p->fallback==0 ){ |
3993 fprintf(out, " 0, /* %10s => nothing */\n", p->name); | 4100 fprintf(out, " 0, /* %10s => nothing */\n", p->name); |
3994 }else{ | 4101 }else{ |
3995 fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index, | 4102 fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index, |
3996 p->name, p->fallback->name); | 4103 p->name, p->fallback->name); |
3997 } | 4104 } |
3998 lineno++; | 4105 lineno++; |
3999 } | 4106 } |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4244 /* Combine matching REDUCE actions into a single default */ | 4351 /* Combine matching REDUCE actions into a single default */ |
4245 for(ap=stp->ap; ap; ap=ap->next){ | 4352 for(ap=stp->ap; ap; ap=ap->next){ |
4246 if( ap->type==REDUCE && ap->x.rp==rbest ) break; | 4353 if( ap->type==REDUCE && ap->x.rp==rbest ) break; |
4247 } | 4354 } |
4248 assert( ap ); | 4355 assert( ap ); |
4249 ap->sp = Symbol_new("{default}"); | 4356 ap->sp = Symbol_new("{default}"); |
4250 for(ap=ap->next; ap; ap=ap->next){ | 4357 for(ap=ap->next; ap; ap=ap->next){ |
4251 if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED; | 4358 if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED; |
4252 } | 4359 } |
4253 stp->ap = Action_sort(stp->ap); | 4360 stp->ap = Action_sort(stp->ap); |
| 4361 |
| 4362 for(ap=stp->ap; ap; ap=ap->next){ |
| 4363 if( ap->type==SHIFT ) break; |
| 4364 if( ap->type==REDUCE && ap->x.rp!=rbest ) break; |
| 4365 } |
| 4366 if( ap==0 ){ |
| 4367 stp->autoReduce = 1; |
| 4368 stp->pDfltReduce = rbest; |
| 4369 } |
| 4370 } |
| 4371 |
| 4372 /* Make a second pass over all states and actions. Convert |
| 4373 ** every action that is a SHIFT to an autoReduce state into |
| 4374 ** a SHIFTREDUCE action. |
| 4375 */ |
| 4376 for(i=0; i<lemp->nstate; i++){ |
| 4377 stp = lemp->sorted[i]; |
| 4378 for(ap=stp->ap; ap; ap=ap->next){ |
| 4379 struct state *pNextState; |
| 4380 if( ap->type!=SHIFT ) continue; |
| 4381 pNextState = ap->x.stp; |
| 4382 if( pNextState->autoReduce && pNextState->pDfltReduce!=0 ){ |
| 4383 ap->type = SHIFTREDUCE; |
| 4384 ap->x.rp = pNextState->pDfltReduce; |
| 4385 } |
| 4386 } |
4254 } | 4387 } |
4255 } | 4388 } |
4256 | 4389 |
4257 | 4390 |
4258 /* | 4391 /* |
4259 ** Compare two states for sorting purposes. The smaller state is the | 4392 ** Compare two states for sorting purposes. The smaller state is the |
4260 ** one with the most non-terminal actions. If they have the same number | 4393 ** one with the most non-terminal actions. If they have the same number |
4261 ** of non-terminal actions, then the smaller is the one with the most | 4394 ** of non-terminal actions, then the smaller is the one with the most |
4262 ** token actions. | 4395 ** token actions. |
4263 */ | 4396 */ |
(...skipping 20 matching lines...) Expand all Loading... |
4284 */ | 4417 */ |
4285 void ResortStates(struct lemon *lemp) | 4418 void ResortStates(struct lemon *lemp) |
4286 { | 4419 { |
4287 int i; | 4420 int i; |
4288 struct state *stp; | 4421 struct state *stp; |
4289 struct action *ap; | 4422 struct action *ap; |
4290 | 4423 |
4291 for(i=0; i<lemp->nstate; i++){ | 4424 for(i=0; i<lemp->nstate; i++){ |
4292 stp = lemp->sorted[i]; | 4425 stp = lemp->sorted[i]; |
4293 stp->nTknAct = stp->nNtAct = 0; | 4426 stp->nTknAct = stp->nNtAct = 0; |
4294 stp->iDflt = lemp->nstate + lemp->nrule; | 4427 stp->iDfltReduce = lemp->nrule; /* Init dflt action to "syntax error" */ |
4295 stp->iTknOfst = NO_OFFSET; | 4428 stp->iTknOfst = NO_OFFSET; |
4296 stp->iNtOfst = NO_OFFSET; | 4429 stp->iNtOfst = NO_OFFSET; |
4297 for(ap=stp->ap; ap; ap=ap->next){ | 4430 for(ap=stp->ap; ap; ap=ap->next){ |
4298 if( compute_action(lemp,ap)>=0 ){ | 4431 int iAction = compute_action(lemp,ap); |
| 4432 if( iAction>=0 ){ |
4299 if( ap->sp->index<lemp->nterminal ){ | 4433 if( ap->sp->index<lemp->nterminal ){ |
4300 stp->nTknAct++; | 4434 stp->nTknAct++; |
4301 }else if( ap->sp->index<lemp->nsymbol ){ | 4435 }else if( ap->sp->index<lemp->nsymbol ){ |
4302 stp->nNtAct++; | 4436 stp->nNtAct++; |
4303 }else{ | 4437 }else{ |
4304 stp->iDflt = compute_action(lemp, ap); | 4438 assert( stp->autoReduce==0 || stp->pDfltReduce==ap->x.rp ); |
| 4439 stp->iDfltReduce = iAction - lemp->nstate - lemp->nrule; |
4305 } | 4440 } |
4306 } | 4441 } |
4307 } | 4442 } |
4308 } | 4443 } |
4309 qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]), | 4444 qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]), |
4310 stateResortCompare); | 4445 stateResortCompare); |
4311 for(i=0; i<lemp->nstate; i++){ | 4446 for(i=0; i<lemp->nstate; i++){ |
4312 lemp->sorted[i]->statenum = i; | 4447 lemp->sorted[i]->statenum = i; |
4313 } | 4448 } |
| 4449 lemp->nxstate = lemp->nstate; |
| 4450 while( lemp->nxstate>1 && lemp->sorted[lemp->nxstate-1]->autoReduce ){ |
| 4451 lemp->nxstate--; |
| 4452 } |
4314 } | 4453 } |
4315 | 4454 |
4316 | 4455 |
4317 /***************** From the file "set.c" ************************************/ | 4456 /***************** From the file "set.c" ************************************/ |
4318 /* | 4457 /* |
4319 ** Set manipulation routines for the LEMON parser generator. | 4458 ** Set manipulation routines for the LEMON parser generator. |
4320 */ | 4459 */ |
4321 | 4460 |
4322 static int size = 0; | 4461 static int size = 0; |
4323 | 4462 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4466 while( np ){ | 4605 while( np ){ |
4467 if( strcmp(np->data,data)==0 ){ | 4606 if( strcmp(np->data,data)==0 ){ |
4468 /* An existing entry with the same key is found. */ | 4607 /* An existing entry with the same key is found. */ |
4469 /* Fail because overwrite is not allows. */ | 4608 /* Fail because overwrite is not allows. */ |
4470 return 0; | 4609 return 0; |
4471 } | 4610 } |
4472 np = np->next; | 4611 np = np->next; |
4473 } | 4612 } |
4474 if( x1a->count>=x1a->size ){ | 4613 if( x1a->count>=x1a->size ){ |
4475 /* Need to make the hash table bigger */ | 4614 /* Need to make the hash table bigger */ |
4476 int i,size; | 4615 int i,arrSize; |
4477 struct s_x1 array; | 4616 struct s_x1 array; |
4478 array.size = size = x1a->size*2; | 4617 array.size = arrSize = x1a->size*2; |
4479 array.count = x1a->count; | 4618 array.count = x1a->count; |
4480 array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*)); | 4619 array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*)); |
4481 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4620 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4482 array.ht = (x1node**)&(array.tbl[size]); | 4621 array.ht = (x1node**)&(array.tbl[arrSize]); |
4483 for(i=0; i<size; i++) array.ht[i] = 0; | 4622 for(i=0; i<arrSize; i++) array.ht[i] = 0; |
4484 for(i=0; i<x1a->count; i++){ | 4623 for(i=0; i<x1a->count; i++){ |
4485 x1node *oldnp, *newnp; | 4624 x1node *oldnp, *newnp; |
4486 oldnp = &(x1a->tbl[i]); | 4625 oldnp = &(x1a->tbl[i]); |
4487 h = strhash(oldnp->data) & (size-1); | 4626 h = strhash(oldnp->data) & (arrSize-1); |
4488 newnp = &(array.tbl[i]); | 4627 newnp = &(array.tbl[i]); |
4489 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4628 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
4490 newnp->next = array.ht[h]; | 4629 newnp->next = array.ht[h]; |
4491 newnp->data = oldnp->data; | 4630 newnp->data = oldnp->data; |
4492 newnp->from = &(array.ht[h]); | 4631 newnp->from = &(array.ht[h]); |
4493 array.ht[h] = newnp; | 4632 array.ht[h] = newnp; |
4494 } | 4633 } |
4495 free(x1a->tbl); | 4634 free(x1a->tbl); |
4496 *x1a = array; | 4635 *x1a = array; |
4497 } | 4636 } |
(...skipping 30 matching lines...) Expand all Loading... |
4528 */ | 4667 */ |
4529 struct symbol *Symbol_new(const char *x) | 4668 struct symbol *Symbol_new(const char *x) |
4530 { | 4669 { |
4531 struct symbol *sp; | 4670 struct symbol *sp; |
4532 | 4671 |
4533 sp = Symbol_find(x); | 4672 sp = Symbol_find(x); |
4534 if( sp==0 ){ | 4673 if( sp==0 ){ |
4535 sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); | 4674 sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); |
4536 MemoryCheck(sp); | 4675 MemoryCheck(sp); |
4537 sp->name = Strsafe(x); | 4676 sp->name = Strsafe(x); |
4538 sp->type = isupper(*x) ? TERMINAL : NONTERMINAL; | 4677 sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL; |
4539 sp->rule = 0; | 4678 sp->rule = 0; |
4540 sp->fallback = 0; | 4679 sp->fallback = 0; |
4541 sp->prec = -1; | 4680 sp->prec = -1; |
4542 sp->assoc = UNK; | 4681 sp->assoc = UNK; |
4543 sp->firstset = 0; | 4682 sp->firstset = 0; |
4544 sp->lambda = LEMON_FALSE; | 4683 sp->lambda = LEMON_FALSE; |
4545 sp->destructor = 0; | 4684 sp->destructor = 0; |
4546 sp->destLineno = 0; | 4685 sp->destLineno = 0; |
4547 sp->datatype = 0; | 4686 sp->datatype = 0; |
4548 sp->useCnt = 0; | 4687 sp->useCnt = 0; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4633 while( np ){ | 4772 while( np ){ |
4634 if( strcmp(np->key,key)==0 ){ | 4773 if( strcmp(np->key,key)==0 ){ |
4635 /* An existing entry with the same key is found. */ | 4774 /* An existing entry with the same key is found. */ |
4636 /* Fail because overwrite is not allows. */ | 4775 /* Fail because overwrite is not allows. */ |
4637 return 0; | 4776 return 0; |
4638 } | 4777 } |
4639 np = np->next; | 4778 np = np->next; |
4640 } | 4779 } |
4641 if( x2a->count>=x2a->size ){ | 4780 if( x2a->count>=x2a->size ){ |
4642 /* Need to make the hash table bigger */ | 4781 /* Need to make the hash table bigger */ |
4643 int i,size; | 4782 int i,arrSize; |
4644 struct s_x2 array; | 4783 struct s_x2 array; |
4645 array.size = size = x2a->size*2; | 4784 array.size = arrSize = x2a->size*2; |
4646 array.count = x2a->count; | 4785 array.count = x2a->count; |
4647 array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*)); | 4786 array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*)); |
4648 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4787 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4649 array.ht = (x2node**)&(array.tbl[size]); | 4788 array.ht = (x2node**)&(array.tbl[arrSize]); |
4650 for(i=0; i<size; i++) array.ht[i] = 0; | 4789 for(i=0; i<arrSize; i++) array.ht[i] = 0; |
4651 for(i=0; i<x2a->count; i++){ | 4790 for(i=0; i<x2a->count; i++){ |
4652 x2node *oldnp, *newnp; | 4791 x2node *oldnp, *newnp; |
4653 oldnp = &(x2a->tbl[i]); | 4792 oldnp = &(x2a->tbl[i]); |
4654 h = strhash(oldnp->key) & (size-1); | 4793 h = strhash(oldnp->key) & (arrSize-1); |
4655 newnp = &(array.tbl[i]); | 4794 newnp = &(array.tbl[i]); |
4656 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4795 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
4657 newnp->next = array.ht[h]; | 4796 newnp->next = array.ht[h]; |
4658 newnp->key = oldnp->key; | 4797 newnp->key = oldnp->key; |
4659 newnp->data = oldnp->data; | 4798 newnp->data = oldnp->data; |
4660 newnp->from = &(array.ht[h]); | 4799 newnp->from = &(array.ht[h]); |
4661 array.ht[h] = newnp; | 4800 array.ht[h] = newnp; |
4662 } | 4801 } |
4663 free(x2a->tbl); | 4802 free(x2a->tbl); |
4664 *x2a = array; | 4803 *x2a = array; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4709 { | 4848 { |
4710 return x2a ? x2a->count : 0; | 4849 return x2a ? x2a->count : 0; |
4711 } | 4850 } |
4712 | 4851 |
4713 /* Return an array of pointers to all data in the table. | 4852 /* Return an array of pointers to all data in the table. |
4714 ** The array is obtained from malloc. Return NULL if memory allocation | 4853 ** The array is obtained from malloc. Return NULL if memory allocation |
4715 ** problems, or if the array is empty. */ | 4854 ** problems, or if the array is empty. */ |
4716 struct symbol **Symbol_arrayof() | 4855 struct symbol **Symbol_arrayof() |
4717 { | 4856 { |
4718 struct symbol **array; | 4857 struct symbol **array; |
4719 int i,size; | 4858 int i,arrSize; |
4720 if( x2a==0 ) return 0; | 4859 if( x2a==0 ) return 0; |
4721 size = x2a->count; | 4860 arrSize = x2a->count; |
4722 array = (struct symbol **)calloc(size, sizeof(struct symbol *)); | 4861 array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *)); |
4723 if( array ){ | 4862 if( array ){ |
4724 for(i=0; i<size; i++) array[i] = x2a->tbl[i].data; | 4863 for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data; |
4725 } | 4864 } |
4726 return array; | 4865 return array; |
4727 } | 4866 } |
4728 | 4867 |
4729 /* Compare two configurations */ | 4868 /* Compare two configurations */ |
4730 int Configcmp(const char *_a,const char *_b) | 4869 int Configcmp(const char *_a,const char *_b) |
4731 { | 4870 { |
4732 const struct config *a = (struct config *) _a; | 4871 const struct config *a = (struct config *) _a; |
4733 const struct config *b = (struct config *) _b; | 4872 const struct config *b = (struct config *) _b; |
4734 int x; | 4873 int x; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4830 while( np ){ | 4969 while( np ){ |
4831 if( statecmp(np->key,key)==0 ){ | 4970 if( statecmp(np->key,key)==0 ){ |
4832 /* An existing entry with the same key is found. */ | 4971 /* An existing entry with the same key is found. */ |
4833 /* Fail because overwrite is not allows. */ | 4972 /* Fail because overwrite is not allows. */ |
4834 return 0; | 4973 return 0; |
4835 } | 4974 } |
4836 np = np->next; | 4975 np = np->next; |
4837 } | 4976 } |
4838 if( x3a->count>=x3a->size ){ | 4977 if( x3a->count>=x3a->size ){ |
4839 /* Need to make the hash table bigger */ | 4978 /* Need to make the hash table bigger */ |
4840 int i,size; | 4979 int i,arrSize; |
4841 struct s_x3 array; | 4980 struct s_x3 array; |
4842 array.size = size = x3a->size*2; | 4981 array.size = arrSize = x3a->size*2; |
4843 array.count = x3a->count; | 4982 array.count = x3a->count; |
4844 array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*)); | 4983 array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*)); |
4845 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4984 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4846 array.ht = (x3node**)&(array.tbl[size]); | 4985 array.ht = (x3node**)&(array.tbl[arrSize]); |
4847 for(i=0; i<size; i++) array.ht[i] = 0; | 4986 for(i=0; i<arrSize; i++) array.ht[i] = 0; |
4848 for(i=0; i<x3a->count; i++){ | 4987 for(i=0; i<x3a->count; i++){ |
4849 x3node *oldnp, *newnp; | 4988 x3node *oldnp, *newnp; |
4850 oldnp = &(x3a->tbl[i]); | 4989 oldnp = &(x3a->tbl[i]); |
4851 h = statehash(oldnp->key) & (size-1); | 4990 h = statehash(oldnp->key) & (arrSize-1); |
4852 newnp = &(array.tbl[i]); | 4991 newnp = &(array.tbl[i]); |
4853 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4992 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
4854 newnp->next = array.ht[h]; | 4993 newnp->next = array.ht[h]; |
4855 newnp->key = oldnp->key; | 4994 newnp->key = oldnp->key; |
4856 newnp->data = oldnp->data; | 4995 newnp->data = oldnp->data; |
4857 newnp->from = &(array.ht[h]); | 4996 newnp->from = &(array.ht[h]); |
4858 array.ht[h] = newnp; | 4997 array.ht[h] = newnp; |
4859 } | 4998 } |
4860 free(x3a->tbl); | 4999 free(x3a->tbl); |
4861 *x3a = array; | 5000 *x3a = array; |
(...skipping 26 matching lines...) Expand all Loading... |
4888 } | 5027 } |
4889 return np ? np->data : 0; | 5028 return np ? np->data : 0; |
4890 } | 5029 } |
4891 | 5030 |
4892 /* Return an array of pointers to all data in the table. | 5031 /* Return an array of pointers to all data in the table. |
4893 ** The array is obtained from malloc. Return NULL if memory allocation | 5032 ** The array is obtained from malloc. Return NULL if memory allocation |
4894 ** problems, or if the array is empty. */ | 5033 ** problems, or if the array is empty. */ |
4895 struct state **State_arrayof() | 5034 struct state **State_arrayof() |
4896 { | 5035 { |
4897 struct state **array; | 5036 struct state **array; |
4898 int i,size; | 5037 int i,arrSize; |
4899 if( x3a==0 ) return 0; | 5038 if( x3a==0 ) return 0; |
4900 size = x3a->count; | 5039 arrSize = x3a->count; |
4901 array = (struct state **)calloc(size, sizeof(struct state *)); | 5040 array = (struct state **)calloc(arrSize, sizeof(struct state *)); |
4902 if( array ){ | 5041 if( array ){ |
4903 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; | 5042 for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data; |
4904 } | 5043 } |
4905 return array; | 5044 return array; |
4906 } | 5045 } |
4907 | 5046 |
4908 /* Hash a configuration */ | 5047 /* Hash a configuration */ |
4909 PRIVATE unsigned confighash(struct config *a) | 5048 PRIVATE unsigned confighash(struct config *a) |
4910 { | 5049 { |
4911 unsigned h=0; | 5050 unsigned h=0; |
4912 h = h*571 + a->rp->index*37 + a->dot; | 5051 h = h*571 + a->rp->index*37 + a->dot; |
4913 return h; | 5052 return h; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4970 while( np ){ | 5109 while( np ){ |
4971 if( Configcmp((const char *) np->data,(const char *) data)==0 ){ | 5110 if( Configcmp((const char *) np->data,(const char *) data)==0 ){ |
4972 /* An existing entry with the same key is found. */ | 5111 /* An existing entry with the same key is found. */ |
4973 /* Fail because overwrite is not allows. */ | 5112 /* Fail because overwrite is not allows. */ |
4974 return 0; | 5113 return 0; |
4975 } | 5114 } |
4976 np = np->next; | 5115 np = np->next; |
4977 } | 5116 } |
4978 if( x4a->count>=x4a->size ){ | 5117 if( x4a->count>=x4a->size ){ |
4979 /* Need to make the hash table bigger */ | 5118 /* Need to make the hash table bigger */ |
4980 int i,size; | 5119 int i,arrSize; |
4981 struct s_x4 array; | 5120 struct s_x4 array; |
4982 array.size = size = x4a->size*2; | 5121 array.size = arrSize = x4a->size*2; |
4983 array.count = x4a->count; | 5122 array.count = x4a->count; |
4984 array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*)); | 5123 array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*)); |
4985 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 5124 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
4986 array.ht = (x4node**)&(array.tbl[size]); | 5125 array.ht = (x4node**)&(array.tbl[arrSize]); |
4987 for(i=0; i<size; i++) array.ht[i] = 0; | 5126 for(i=0; i<arrSize; i++) array.ht[i] = 0; |
4988 for(i=0; i<x4a->count; i++){ | 5127 for(i=0; i<x4a->count; i++){ |
4989 x4node *oldnp, *newnp; | 5128 x4node *oldnp, *newnp; |
4990 oldnp = &(x4a->tbl[i]); | 5129 oldnp = &(x4a->tbl[i]); |
4991 h = confighash(oldnp->data) & (size-1); | 5130 h = confighash(oldnp->data) & (arrSize-1); |
4992 newnp = &(array.tbl[i]); | 5131 newnp = &(array.tbl[i]); |
4993 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 5132 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
4994 newnp->next = array.ht[h]; | 5133 newnp->next = array.ht[h]; |
4995 newnp->data = oldnp->data; | 5134 newnp->data = oldnp->data; |
4996 newnp->from = &(array.ht[h]); | 5135 newnp->from = &(array.ht[h]); |
4997 array.ht[h] = newnp; | 5136 array.ht[h] = newnp; |
4998 } | 5137 } |
4999 free(x4a->tbl); | 5138 free(x4a->tbl); |
5000 *x4a = array; | 5139 *x4a = array; |
5001 } | 5140 } |
(...skipping 29 matching lines...) Expand all Loading... |
5031 ** as it is removed. ("f" may be null to avoid this step.) */ | 5170 ** as it is removed. ("f" may be null to avoid this step.) */ |
5032 void Configtable_clear(int(*f)(struct config *)) | 5171 void Configtable_clear(int(*f)(struct config *)) |
5033 { | 5172 { |
5034 int i; | 5173 int i; |
5035 if( x4a==0 || x4a->count==0 ) return; | 5174 if( x4a==0 || x4a->count==0 ) return; |
5036 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); | 5175 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); |
5037 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; | 5176 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; |
5038 x4a->count = 0; | 5177 x4a->count = 0; |
5039 return; | 5178 return; |
5040 } | 5179 } |
OLD | NEW |