/ Check-in [d8bab8cf]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added %expect directive, to consider a certain number of conflicts "correct."

This has the side effect of changing the process exit code to never overflow.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | lemon-update-2010
Files: files | file ages | folders
SHA1: d8bab8cf0bc3fbd4c489c31a65d724dda2944d83
User & Date: icculus 2010-02-14 05:19:56
Context
2010-02-14
05:34
Delete output files if this is a failed run.

Otherwise, the fail will stop a Makefile from progressing, but if you immediately run the build again, Make will think the output files are up to date, since they are newer (albeit incomplete/incorrect). check-in: e38c08d9 user: icculus tags: lemon-update-2010

05:19
Added %expect directive, to consider a certain number of conflicts "correct."

This has the side effect of changing the process exit code to never overflow. check-in: d8bab8cf user: icculus tags: lemon-update-2010

00:48
Added -T option, to specify a template filename on the command line.

The default is still "lempar.c", though. check-in: e6cbe1e5 user: icculus tags: lemon-update-2010

Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to tool/lemon.c.

   264    264     char *extracode;         /* Code appended to the generated file */
   265    265     char *tokendest;         /* Code to execute to destroy token data */
   266    266     char *vardest;           /* Code for the default non-terminal destructor */
   267    267     char *filename;          /* Name of the input file */
   268    268     char *outname;           /* Name of the current output file */
   269    269     char *tokenprefix;       /* A prefix added to token names in the .h file */
   270    270     int nconflict;           /* Number of parsing conflicts */
          271  +  int nexpected;           /* Number of expected parsing conflicts */
   271    272     int tablesize;           /* Size of the parse tables */
   272    273     int basisflag;           /* Print only basis configurations */
   273    274     int has_fallback;        /* True if any %fallback is seen in the grammar */
   274    275     int nolinenosflag;       /* True if #line statements should not be printed */
   275    276     char *argv0;             /* Name of the program */
   276    277   };
   277    278   
................................................................................
  1462   1463       {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
  1463   1464       {OPT_FLAG, "s", (char*)&statistics,
  1464   1465                                      "Print parser stats to standard output."},
  1465   1466       {OPT_FLAG, "x", (char*)&version, "Print the version number."},
  1466   1467       {OPT_FLAG,0,0,0}
  1467   1468     };
  1468   1469     int i;
         1470  +  int exitcode;
  1469   1471     struct lemon lem;
  1470   1472   
  1471   1473     OptInit(argv,options,stderr);
  1472   1474     if( version ){
  1473   1475        printf("Lemon version 1.0\n");
  1474   1476        exit(0); 
  1475   1477     }
  1476   1478     if( OptNArgs()!=1 ){
  1477   1479       fprintf(stderr,"Exactly one filename argument is required.\n");
  1478   1480       exit(1);
  1479   1481     }
  1480   1482     memset(&lem, 0, sizeof(lem));
  1481   1483     lem.errorcnt = 0;
         1484  +  lem.nexpected = -1;
  1482   1485   
  1483   1486     /* Initialize the machine */
  1484   1487     Strsafe_init();
  1485   1488     Symbol_init();
  1486   1489     State_init();
  1487   1490     lem.argv0 = argv[0];
  1488   1491     lem.filename = OptArg(0);
................................................................................
  1560   1563     }
  1561   1564     if( statistics ){
  1562   1565       printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
  1563   1566         lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
  1564   1567       printf("                   %d states, %d parser table entries, %d conflicts\n",
  1565   1568         lem.nstate, lem.tablesize, lem.nconflict);
  1566   1569     }
  1567         -  if( lem.nconflict ){
  1568         -    fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
         1570  +  if( lem.nexpected < 0 ) {
         1571  +    lem.nexpected = 0;  /* grammar didn't have an %expect declaration. */
  1569   1572     }
  1570         -  exit(lem.errorcnt + lem.nconflict);
  1571         -  return (lem.errorcnt + lem.nconflict);
         1573  +  if( lem.nconflict != lem.nexpected ){
         1574  +    fprintf(stderr,"%d parsing conflicts (%d expected).\n",lem.nconflict,lem.nexpected);
         1575  +  }
         1576  +
         1577  +  /* return 0 on success, 1 on failure. */
         1578  +  exitcode = ((lem.errorcnt > 0) || (lem.nconflict != lem.nexpected)) ? 1 : 0;
         1579  +  exit(exitcode);
         1580  +  return (exitcode);
  1572   1581   }
  1573   1582   /******************** From the file "msort.c" *******************************/
  1574   1583   /*
  1575   1584   ** A generic merge-sort program.
  1576   1585   **
  1577   1586   ** USAGE:
  1578   1587   ** Let "ptr" be a pointer to some structure which is at the head of
................................................................................
  2006   2015       PRECEDENCE_MARK_1,
  2007   2016       PRECEDENCE_MARK_2,
  2008   2017       RESYNC_AFTER_RULE_ERROR,
  2009   2018       RESYNC_AFTER_DECL_ERROR,
  2010   2019       WAITING_FOR_DESTRUCTOR_SYMBOL,
  2011   2020       WAITING_FOR_DATATYPE_SYMBOL,
  2012   2021       WAITING_FOR_FALLBACK_ID,
         2022  +    WAITING_FOR_EXPECT_VALUE,
  2013   2023       WAITING_FOR_WILDCARD_ID
  2014   2024     } state;                   /* The state of the parser */
  2015   2025     struct symbol *fallback;   /* The fallback token */
  2016   2026     struct symbol *lhs;        /* Left-hand side of current rule */
  2017   2027     char *lhsalias;            /* Alias for the LHS */
  2018   2028     int nrhs;                  /* Number of right-hand side symbols seen */
  2019   2029     struct symbol *rhs[MAXRHS];  /* RHS symbols */
................................................................................
  2029   2039     struct rule *lastrule;     /* Pointer to the most recently parsed rule */
  2030   2040   };
  2031   2041   
  2032   2042   /* Parse a single token */
  2033   2043   static void parseonetoken(psp)
  2034   2044   struct pstate *psp;
  2035   2045   {
         2046  +  char *endptr;
  2036   2047     char *x;
  2037   2048     x = Strsafe(psp->tokenstart);     /* Save the token permanently */
  2038   2049   #if 0
  2039   2050     printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
  2040   2051       x,psp->state);
  2041   2052   #endif
  2042   2053     switch( psp->state ){
................................................................................
  2313   2324   	}else if( strcmp(x,"type")==0 ){
  2314   2325             psp->state = WAITING_FOR_DATATYPE_SYMBOL;
  2315   2326           }else if( strcmp(x,"fallback")==0 ){
  2316   2327             psp->fallback = 0;
  2317   2328             psp->state = WAITING_FOR_FALLBACK_ID;
  2318   2329           }else if( strcmp(x,"wildcard")==0 ){
  2319   2330             psp->state = WAITING_FOR_WILDCARD_ID;
         2331  +        }else if( strcmp(x,"expect")==0 ){
         2332  +          if (psp->gp->nexpected >= 0) {
         2333  +            ErrorMsg(psp->filename,psp->tokenlineno, "Multiple %expect declarations.");
         2334  +            psp->errorcnt++;
         2335  +            psp->state = RESYNC_AFTER_DECL_ERROR;
         2336  +          } else {
         2337  +            psp->state = WAITING_FOR_EXPECT_VALUE;
         2338  +          }
  2320   2339           }else{
  2321   2340             ErrorMsg(psp->filename,psp->tokenlineno,
  2322   2341               "Unknown declaration keyword: \"%%%s\".",x);
  2323   2342             psp->errorcnt++;
  2324   2343             psp->state = RESYNC_AFTER_DECL_ERROR;
  2325   2344   	}
  2326   2345         }else{
................................................................................
  2340   2359           struct symbol *sp = Symbol_new(x);
  2341   2360           psp->declargslot = &sp->destructor;
  2342   2361           psp->decllinenoslot = &sp->destLineno;
  2343   2362           psp->insertLineMacro = 1;
  2344   2363           psp->state = WAITING_FOR_DECL_ARG;
  2345   2364         }
  2346   2365         break;
         2366  +    case WAITING_FOR_EXPECT_VALUE:
         2367  +        psp->gp->nexpected = (int) strtol(x, &endptr, 10);
         2368  +        if( (*endptr != '\0') || (endptr == x) ) {
         2369  +          ErrorMsg(psp->filename,psp->tokenlineno,
         2370  +            "Integer expected after %%expect keyword");
         2371  +          psp->errorcnt++;
         2372  +        } else if (psp->gp->nexpected < 0) {
         2373  +          ErrorMsg(psp->filename,psp->tokenlineno,
         2374  +            "Integer can't be negative after %%expect keyword");
         2375  +          psp->errorcnt++;
         2376  +        }
         2377  +        psp->state = WAITING_FOR_DECL_OR_RULE;
         2378  +        break;
  2347   2379       case WAITING_FOR_DATATYPE_SYMBOL:
  2348   2380         if( !isalpha(x[0]) ){
  2349   2381           ErrorMsg(psp->filename,psp->tokenlineno,
  2350   2382             "Symbol name missing after %destructor keyword");
  2351   2383           psp->errorcnt++;
  2352   2384           psp->state = RESYNC_AFTER_DECL_ERROR;
  2353   2385         }else{