**
** The author of this program disclaims copyright.
*/
-
-#include <config.h>
-
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
-#include "ws_attributes.h"
-
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
#define ISALNUM(X) isalnum((unsigned char)(X))
#include <unistd.h>
#endif
-#define PRIVATE static
-/* #define PRIVATE */
+/* #define PRIVATE static */
+#define PRIVATE
#ifdef TEST
#define MAXRHS 5 /* Set low to exercise exception code */
void ErrorMsg(const char *, int,const char *, ...);
/****** From the file "option.h" ******************************************/
-enum option_type {
- OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
- OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR
-};
+enum option_type { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
+ OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR};
struct s_options {
enum option_type type;
const char *label;
int OptInit(char**,struct s_options*,FILE*);
int OptNArgs(void);
char *OptArg(int);
-#if 0
void OptErr(int);
-#endif
void OptPrint(void);
/******** From the file "parse.h" *****************************************/
int dtnum; /* The data type number. In the parser, the value
** stack is a union. The .yy%d element of this
** union is the correct data type for this object */
+ int bContent; /* True if this symbol ever carries content - if
+ ** it is ever more than just syntax */
/* The following fields are used by MULTITERMINALs only */
int nsubsym; /* Number of constituent symbols in the MULTI */
struct symbol **subsym; /* Array of constituent symbols */
struct symbol *wildcard; /* Token that matches anything */
char *name; /* Name of the generated parser */
char *arg; /* Declaration of the 3th argument to parser */
+ char *ctx; /* Declaration of 2nd argument to constructor */
char *tokentype; /* Type of terminal symbols in the parser stack */
char *vartype; /* The default type of non-terminal symbols */
char *start; /* Name of the start symbol for the grammar */
char *tokendest; /* Code to execute to destroy token data */
char *vardest; /* Code for the default non-terminal destructor */
char *filename; /* Name of the input file */
- char *basename; /* Basename of inputer file (no directory or path) */
char *outname; /* Name of the current output file */
char *tokenprefix; /* A prefix added to token names in the .h file */
int nconflict; /* Number of parsing conflicts */
};
#define MemoryCheck(X) if((X)==0){ \
- fprintf(stderr,"Out of memory. Aborting...\n"); \
- exit(1); \
+ extern void memory_error(); \
+ memory_error(); \
}
/**************** From the file "table.h" *********************************/
return ap;
}
-PRIVATE void Action_add(
+void Action_add(
struct action **app,
enum e_action type,
struct symbol *sp,
char *arg
){
- assert(app);
struct action *newaction;
newaction = Action_new();
newaction->next = *app;
#define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
/* Free all memory associated with the given acttab */
-PRIVATE void acttab_free(acttab *p){
+void acttab_free(acttab *p){
free( p->aAction );
free( p->aLookahead );
free( p );
}
/* Allocate a new acttab structure */
-PRIVATE acttab *acttab_alloc(int nsymbol, int nterminal) {
- acttab *p = (acttab *)calloc(1, sizeof(*p));
- if (p == 0) {
- fprintf(stderr, "Unable to allocate memory for a new acttab.");
- exit(1);
- }
- memset(p, 0, sizeof(*p));
- p->nsymbol = nsymbol;
- p->nterminal = nterminal;
- return p;
+acttab *acttab_alloc(int nsymbol, int nterminal){
+ acttab *p = (acttab *) calloc( 1, sizeof(*p) );
+ if( p==0 ){
+ fprintf(stderr,"Unable to allocate memory for a new acttab.");
+ exit(1);
+ }
+ memset(p, 0, sizeof(*p));
+ p->nsymbol = nsymbol;
+ p->nterminal = nterminal;
+ return p;
}
/* Add a new action to the current transaction set.
** This routine is called once for each lookahead for a particular
** state.
*/
-PRIVATE void acttab_action(acttab *p, int lookahead, int action){
+void acttab_action(acttab *p, int lookahead, int action){
if( p->nLookahead>=p->nLookaheadAlloc ){
p->nLookaheadAlloc += 25;
p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead,
sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
- if (p->aLookahead == 0) {
- fprintf(stderr, "malloc failed\n");
- exit(1);
+ if( p->aLookahead==0 ){
+ fprintf(stderr,"malloc failed\n");
+ exit(1);
}
}
if( p->nLookahead==0 ){
** a smaller table. For non-terminal symbols, which are never syntax errors,
** makeItSafe can be false.
*/
-PRIVATE int acttab_insert(acttab *p, int makeItSafe) {
- int i, j, k, n, end;
- assert(p->nLookahead>0);
+int acttab_insert(acttab *p, int makeItSafe){
+ int i, j, k, n, end;
+ assert( p->nLookahead>0 );
/* Make sure we have enough space to hold the expanded action table
** in the worst case. The worst case occurs if the transaction set
p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
p->aAction = (struct lookahead_action *) realloc( p->aAction,
sizeof(p->aAction[0])*p->nActionAlloc);
- if (p->aAction == 0) {
- fprintf(stderr, "malloc failed\n");
- exit(1);
+ if( p->aAction==0 ){
+ fprintf(stderr,"malloc failed\n");
+ exit(1);
}
+ assert(oldAlloc < p->nActionAlloc); /* hint for CSA */
for(i=oldAlloc; i<p->nActionAlloc; i++){
p->aAction[i].lookahead = -1;
p->aAction[i].action = -1;
}
}
+ assert(p->aAction); /* Hint for CSA (for p->aAction[i] below) */
/* Scan the existing action table looking for an offset that is a
** duplicate of the current transaction set. Fall out of the loop
** i is the index in p->aAction[] where p->mnLookahead is inserted.
*/
end = makeItSafe ? p->mnLookahead : 0;
- for (i = p->nAction - 1; i >= end; i--) {
+ for(i=p->nAction-1; i>=end; i--){
if( p->aAction[i].lookahead==p->mnLookahead ){
/* All lookaheads and actions in the aLookahead[] transaction
** must match against the candidate aAction[i] entry. */
** an empty offset in the aAction[] table in which we can add the
** aLookahead[] transaction.
*/
- if (i<end) {
+ if( i<end ){
/* Look for holes in the aAction[] table that fit the current
** aLookahead[] transaction. Leave i set to the offset of the hole.
** If no holes are found, i is left at p->nAction, which means the
** transaction will be appended. */
- i = makeItSafe ? p->mnLookahead : 0;
- for (; i<p->nActionAlloc - p->mxLookahead; i++) {
+ i = makeItSafe ? p->mnLookahead : 0;
+ for(; i<p->nActionAlloc - p->mxLookahead; i++){
if( p->aAction[i].lookahead<0 ){
for(j=0; j<p->nLookahead; j++){
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
/* Insert transaction set at index i. */
#if 0
printf("Acttab:");
- for (j = 0; j<p->nLookahead; j++) {
- printf(" %d", p->aLookahead[j].lookahead);
+ for(j=0; j<p->nLookahead; j++){
+ printf(" %d", p->aLookahead[j].lookahead);
}
printf(" inserted at %d\n", i);
#endif
p->aAction[k] = p->aLookahead[j];
if( k>=p->nAction ) p->nAction = k+1;
}
- if (makeItSafe && i + p->nterminal >= p->nAction) p->nAction = i + p->nterminal + 1;
+ if( makeItSafe && i+p->nterminal>=p->nAction ) p->nAction = i+p->nterminal+1;
p->nLookahead = 0;
/* Return the offset that is added to the lookahead in order to get the
** Return the size of the action table without the trailing syntax error
** entries.
*/
-static int acttab_action_size(acttab *p) {
- int n = p->nAction;
- while (n>0 && p->aAction[n - 1].lookahead<0) { n--; }
- return n;
+int acttab_action_size(acttab *p){
+ int n = p->nAction;
+ while( n>0 && p->aAction[n-1].lookahead<0 ){ n--; }
+ return n;
}
/********************** From the file "build.c" *****************************/
return;
}
-#ifndef __clang_analyzer__
/* Compute all LR(0) states for the grammar. Links
** are added to between some states so that the LR(1) follow sets
** can be computed later.
(void)getstate(lemp);
return;
}
-#endif
/* Return a pointer to a state which is described by the configuration
** list which has been built from calls to Configlist_add.
stp->cfp = cfp; /* Remember the configuration closure */
stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
stp->ap = 0; /* No actions, yet. */
+#ifndef NDEBUG
+ int ret =
+#endif
State_insert(stp,stp->bp); /* Add to the state table */
+ assert(ret == 1); /* CSA hint: stp did not leak, it has escaped. */
buildshifts(lemp,stp); /* Recursively compute successor states */
}
return stp;
/*
** Return true if two symbols are the same.
*/
-PRIVATE int same_symbol(struct symbol *a, struct symbol *b)
+int same_symbol(struct symbol *a, struct symbol *b)
{
int i;
if( a==b ) return 1;
return 1;
}
-#ifndef __clang_analyzer__
/* Construct all successor states to the given state. A "successor"
** state is any state which can be reached by a shift action.
*/
** which the link is attached. */
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
- if(stp){
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- cfp->stp = stp;
- }
+ assert(stp); /* Hint for CSA */
+ for(cfp=stp->cfp; cfp; cfp=cfp->next){
+ cfp->stp = stp;
}
}
** links are used in the follow-set computation. */
for(i=0; i<lemp->nstate; i++){
stp = lemp->sorted[i];
- if(stp){
- for(cfp=stp->cfp; cfp; cfp=cfp->next){
- for(plp=cfp->bplp; plp; plp=plp->next){
- other = plp->cfp;
- Plink_add(&other->fplp,cfp);
- }
+ for(cfp=stp->cfp; cfp; cfp=cfp->next){
+ for(plp=cfp->bplp; plp; plp=plp->next){
+ other = plp->cfp;
+ Plink_add(&other->fplp,cfp);
}
}
}
}
-#endif
/* Compute all followsets.
**
int change;
for(i=0; i<lemp->nstate; i++){
- if(lemp->sorted[i]){
- for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
- cfp->status = INCOMPLETE;
- }
+ for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
+ cfp->status = INCOMPLETE;
}
}
do{
progress = 0;
for(i=0; i<lemp->nstate; i++){
- if(lemp->sorted[i]){
- for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
- if( cfp->status==COMPLETE ) continue;
- for(plp=cfp->fplp; plp; plp=plp->next){
- change = SetUnion(plp->cfp->fws,cfp->fws);
- if( change ){
- plp->cfp->status = INCOMPLETE;
- progress = 1;
- }
+ for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
+ if( cfp->status==COMPLETE ) continue;
+ for(plp=cfp->fplp; plp; plp=plp->next){
+ change = SetUnion(plp->cfp->fws,cfp->fws);
+ if( change ){
+ plp->cfp->status = INCOMPLETE;
+ progress = 1;
}
- cfp->status = COMPLETE;
}
+ cfp->status = COMPLETE;
}
}
}while( progress );
*/
for(i=0; i<lemp->nstate; i++){ /* Loop over all states */
stp = lemp->sorted[i];
- if(stp){
- for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */
- if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */
- for(j=0; j<lemp->nterminal; j++){
- if( SetFind(cfp->fws,j) ){
- /* Add a reduce action to the state "stp" which will reduce by the
- ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
- Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
- }
+ for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */
+ if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */
+ for(j=0; j<lemp->nterminal; j++){
+ if( SetFind(cfp->fws,j) ){
+ /* Add a reduce action to the state "stp" which will reduce by the
+ ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
+ Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
}
}
}
** Main program file for the LEMON parser generator.
*/
-/* Locates the basename in a string possibly containing paths,
- * including forward-slash and backward-slash delimiters on Windows,
- * and allocates a new string containing just the basename.
- * Returns the pointer to that string.
- */
-PRIVATE char*
-make_basename(char* fullname)
-{
- char *cp;
- char *new_string;
-
- /* Find the last forward slash */
- cp = strrchr(fullname, '/');
-
-#ifdef _WIN32
- /* On Windows, if no forward slash was found, look ofr
- * backslash also */
- if (!cp)
- cp = strrchr(fullname, '\\');
-#endif
-
- if (!cp) {
- new_string = (char *) malloc( strlen(fullname) + 1 );
- MemoryCheck( new_string );
- strcpy(new_string, fullname);
- }
- else {
- /* skip the slash */
- cp++;
- new_string = (char *) malloc( strlen(cp) + 1 );
- MemoryCheck( new_string );
- strcpy(new_string, cp);
- }
-
- return new_string;
-}
-
/* Report an out-of-memory condition and abort. This function
** is used mostly by the "MemoryCheck" macro in struct.h
*/
+void memory_error(void){
+ fprintf(stderr,"Out of memory. Aborting...\n");
+ exit(1);
+}
static int nDefine = 0; /* Number of -D options on the command line */
static char **azDefine = 0; /* Name of the -D macros */
/* This routine is called with the argument to each -D command-line option.
** Add the macro defined to the azDefine array.
*/
-static void handle_D_option(char *z) {
+static void handle_D_option(char *z){
char **paz;
nDefine++;
azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine);
- if (azDefine == 0) {
- fprintf(stderr, "out of memory\n");
- exit(1);
+ if( azDefine==0 ){
+ fprintf(stderr,"out of memory\n");
+ exit(1);
}
paz = &azDefine[nDefine-1];
*paz = (char *) malloc( lemonStrlen(z)+1 );
- if (*paz == 0) {
- fprintf(stderr, "out of memory\n");
- exit(1);
+ if( *paz==0 ){
+ fprintf(stderr,"out of memory\n");
+ exit(1);
}
lemon_strcpy(*paz, z);
for(z=*paz; *z && *z!='='; z++){}
*z = 0;
}
+/* Rember the name of the output directory
+*/
+static char *outputDir = NULL;
+static void handle_d_option(char *z){
+ outputDir = (char *) malloc( lemonStrlen(z)+1 );
+ if( outputDir==0 ){
+ fprintf(stderr,"out of memory\n");
+ exit(1);
+ }
+ lemon_strcpy(outputDir, z);
+}
+
static char *user_templatename = NULL;
-static void handle_T_option(char *z) {
+static void handle_T_option(char *z){
user_templatename = (char *) malloc( lemonStrlen(z)+1 );
- MemoryCheck(user_templatename);
+ if( user_templatename==0 ){
+ memory_error();
+ }
lemon_strcpy(user_templatename, z);
}
** Sort a list of rules in order of increasing iRule value
*/
static struct rule *Rule_sort(struct rule *rp){
- unsigned int i;
+ int i;
struct rule *pNext;
struct rule *x[32];
memset(x, 0, sizeof(x));
}
/* The main program. Parse the command line and do it... */
-int main(int argc _U_, char **argv)
+int main(int argc, char **argv)
{
static int version = 0;
static int rpflag = 0;
static int mhflag = 0;
static int nolinenosflag = 0;
static int noResort = 0;
+
static struct s_options options[] = {
- { OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report." },
- { OPT_FLAG, "c", (char*)&compress, "Don't compress the action table." },
- { OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro." },
- { OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)" },
- { OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions." },
- { OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)" },
- { OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file." },
- { OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements." },
- { OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)" },
- { OPT_FLAG, "p", (char*)&showPrecedenceConflict,
- "Show conflicts resolved by precedence rules" },
- { OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file." },
- { OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states" },
- { OPT_FLAG, "s", (char*)&statistics,
- "Print parser stats to standard output." },
- { OPT_FLAG, "x", (char*)&version, "Print the version number." },
- { OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file." },
- { OPT_FSTR, "W", NULL, "Ignored. (Placeholder for '-W' compiler options.)" },
- {OPT_FLAG, NULL, NULL, NULL}
+ {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
+ {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
+ {OPT_FSTR, "d", (char*)&handle_d_option, "Output directory. Default '.'"},
+ {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
+ {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"},
+ {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
+ {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"},
+ {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."},
+ {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."},
+ {OPT_FSTR, "O", 0, "Ignored. (Placeholder for '-O' compiler options.)"},
+ {OPT_FLAG, "p", (char*)&showPrecedenceConflict,
+ "Show conflicts resolved by precedence rules"},
+ {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
+ {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"},
+ {OPT_FLAG, "s", (char*)&statistics,
+ "Print parser stats to standard output."},
+ {OPT_FLAG, "x", (char*)&version, "Print the version number."},
+ {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."},
+ {OPT_FSTR, "W", 0, "Ignored. (Placeholder for '-W' compiler options.)"},
+ {OPT_FLAG,0,0,0}
};
int i;
int exitcode;
struct lemon lem;
struct rule *rp;
- struct symbol *dollar_sym;
- struct symbol *default_sym;
-
- memset(&lem, 0x0, sizeof(lem));
OptInit(argv,options,stderr);
if( version ){
lem.filename = OptArg(0);
lem.basisflag = basisflag;
lem.nolinenosflag = nolinenosflag;
- dollar_sym = Symbol_new("$");
- lem.errsym = Symbol_new("error");
- lem.errsym->useCnt = 0;
-
- lem.basename = make_basename(lem.filename);
-
+ Symbol_new("$");
/* Parse the input file */
Parse(&lem);
if( lem.errorcnt ) exit(lem.errorcnt);
- if( lem.nrule==0 || lem.rule == NULL ){
- free(dollar_sym);
+ assert(lem.rule); /* Hint for CSA (no errors => rule found). */
+ if( lem.nrule==0 ){
fprintf(stderr,"Empty grammar.\n");
exit(1);
}
+ lem.errsym = Symbol_find("error");
/* Count and index the symbols of the grammar */
- default_sym = Symbol_new("{default}");
+ Symbol_new("{default}");
lem.nsymbol = Symbol_count();
lem.symbols = Symbol_arrayof();
- if (lem.nsymbol == 0 || !lem.symbols) {
- free(dollar_sym);
- free(default_sym);
- free(lem.errsym);
- if (lem.symbols)
- free(lem.symbols);
- fprintf(stderr, "Can't find symbols\n");
- exit(1);
- }
-
for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp);
for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i;
fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
}
- free(default_sym);
- free(dollar_sym);
-
/* return 0 on success, 1 on failure. */
exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
exit(exitcode);
list = NEXT(list);
NEXT(ep) = 0;
for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
- ep = merge(ep, set[i], cmp, (int)offset);
+ ep = merge(ep,set[i],cmp,offset);
set[i] = 0;
}
set[i] = ep;
}
ep = 0;
- for (i = 0; i<LISTSIZE; i++) if (set[i]) ep = merge(set[i], ep, cmp, (int)offset);
+ for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset);
return ep;
}
/************************ From the file "option.c" **************************/
*/
static void errline(int n, int k, FILE *err)
{
- int spcnt = 0, i;
- if( argv[0] ) {
- fprintf(err,"%s",argv[0]);
- spcnt = lemonStrlen(argv[0]) + 1;
- }
+ int spcnt, i;
+ if( argv[0] ) fprintf(err,"%s",argv[0]);
+ spcnt = lemonStrlen(argv[0]) + 1;
for(i=1; i<n && argv[i]; i++){
fprintf(err," %s",argv[i]);
spcnt += lemonStrlen(argv[i])+1;
*/
static int handleflags(int i, FILE *err)
{
- int v;
- int errcnt = 0;
- int j;
- for (j = 0; op[j].label; j++) {
- if (strncmp(&argv[i][1], op[j].label, lemonStrlen(op[j].label)) == 0) break;
+ int v;
+ int errcnt = 0;
+ int j;
+ for(j=0; op[j].label; j++){
+ if( strncmp(&argv[i][1],op[j].label,lemonStrlen(op[j].label))==0 ) break;
+ }
+ v = argv[i][0]=='-' ? 1 : 0;
+ if( op[j].label==0 ){
+ if( err ){
+ fprintf(err,"%sundefined option.\n",emsg);
+ errline(i,1,err);
}
- v = argv[i][0] == '-' ? 1 : 0;
- if (op[j].label == 0) {
- if (err) {
- fprintf(err, "%sundefined option.\n", emsg);
- errline(i, 1, err);
- }
- errcnt++;
- } else if (op[j].arg == 0) {
- /* Ignore this option */
- } else if (op[j].type == OPT_FLAG) {
- *((int*)op[j].arg) = v;
- } else if (op[j].type == OPT_FFLAG) {
- (*(void(*)(int))(op[j].arg))(v);
- } else if (op[j].type == OPT_FSTR) {
- (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
- } else {
- if (err) {
- fprintf(err, "%smissing argument on switch.\n", emsg);
- errline(i, 1, err);
- }
- errcnt++;
+ errcnt++;
+ }else if( op[j].arg==0 ){
+ /* Ignore this option */
+ }else if( op[j].type==OPT_FLAG ){
+ *((int*)op[j].arg) = v;
+ }else if( op[j].type==OPT_FFLAG ){
+ (*(void(*)(int))(op[j].arg))(v);
+ }else if( op[j].type==OPT_FSTR ){
+ (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
+ }else{
+ if( err ){
+ fprintf(err,"%smissing argument on switch.\n",emsg);
+ errline(i,1,err);
}
- return errcnt;
+ errcnt++;
+ }
+ return errcnt;
}
/*
*/
static int handleswitch(int i, FILE *err)
{
- int errcnt = 0;
-#ifndef __clang_analyzer__
int lv = 0;
double dv = 0.0;
char *sv = 0, *end;
char *cp;
int j;
+ int errcnt = 0;
cp = strchr(argv[i],'=');
assert( cp!=0 );
*cp = 0;
break;
case OPT_INT:
case OPT_FINT:
- lv = (int)strtol(cp,&end,0);
+ lv = strtol(cp,&end,0);
if( *end ){
if( err ){
fprintf(err,"%sillegal character in integer argument.\n",emsg);
*(double*)(op[j].arg) = dv;
break;
case OPT_FDBL:
- (*(void(*)(double))(op[j].arg))(dv);
- break;
+ (*(void(*)(double))(op[j].arg))(dv);
+ break;
case OPT_INT:
- *(int*)(op[j].arg) = lv;
- break;
+ *(int*)(op[j].arg) = lv;
+ break;
case OPT_FINT:
- (*(void(*)(int))(op[j].arg))((int)lv);
- break;
+ (*(void(*)(int))(op[j].arg))((int)lv);
+ break;
case OPT_STR:
- *(char**)(op[j].arg) = sv;
- break;
+ *(char**)(op[j].arg) = sv;
+ break;
case OPT_FSTR:
- (*(void(*)(char *))(op[j].arg))(sv);
- break;
+ (*(void(*)(char *))(op[j].arg))(sv);
+ break;
}
}
-#endif
return errcnt;
}
return i>=0 ? argv[i] : 0;
}
-#if 0
void OptErr(int n)
{
int i;
i = argindex(n);
if( i>=0 ) errline(i,0,errstream);
}
-#endif
void OptPrint(void){
int i;
psp->preccounter = 0;
psp->firstrule = psp->lastrule = 0;
psp->gp->nrule = 0;
- /* FALL THROUGH */
+ /* Fall thru to next case */
case WAITING_FOR_DECL_OR_RULE:
if( x[0]=='%' ){
psp->state = WAITING_FOR_DECL_KEYWORD;
for(i=0; i<psp->nrhs; i++){
rp->rhs[i] = psp->rhs[i];
rp->rhsalias[i] = psp->alias[i];
+ if( rp->rhsalias[i]!=0 ){ rp->rhs[i]->bContent = 1; }
}
rp->lhs = psp->lhs;
rp->lhsalias = psp->lhsalias;
msp->nsubsym++;
msp->subsym = (struct symbol **) realloc(msp->subsym,
sizeof(struct symbol*)*msp->nsubsym);
- MemoryCheck( msp->subsym );
msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){
ErrorMsg(psp->filename,psp->tokenlineno,
}else if( strcmp(x,"extra_argument")==0 ){
psp->declargslot = &(psp->gp->arg);
psp->insertLineMacro = 0;
+ }else if( strcmp(x,"extra_context")==0 ){
+ psp->declargslot = &(psp->gp->ctx);
+ psp->insertLineMacro = 0;
}else if( strcmp(x,"token_type")==0 ){
psp->declargslot = &(psp->gp->tokentype);
psp->insertLineMacro = 0;
}else if( strcmp(x,"fallback")==0 ){
psp->fallback = 0;
psp->state = WAITING_FOR_FALLBACK_ID;
- } else if (strcmp(x, "token") == 0) {
- psp->state = WAITING_FOR_TOKEN_NAME;
+ }else if( strcmp(x,"token")==0 ){
+ psp->state = WAITING_FOR_TOKEN_NAME;
}else if( strcmp(x,"wildcard")==0 ){
psp->state = WAITING_FOR_WILDCARD_ID;
}else if( strcmp(x,"token_class")==0 ){
n += nLine + lemonStrlen(psp->filename) + nBack;
}
*psp->declargslot = (char *) realloc(*psp->declargslot, n);
- MemoryCheck( *psp->declargslot );
zBuf = *psp->declargslot + nOld;
if( addLineMacro ){
if( nOld && zBuf[-1]!='\n' ){
}
break;
case WAITING_FOR_TOKEN_NAME:
- /* Tokens do not have to be declared before use. But they can be
- ** in order to control their assigned integer number. The number for
- ** each token is assigned when it is first seen. So by including
- **
- ** %token ONE TWO THREE
- **
- ** early in the grammar file, that assigns small consecutive values
- ** to each of the tokens ONE TWO and THREE.
- */
- if (x[0] == '.') {
- psp->state = WAITING_FOR_DECL_OR_RULE;
- } else if (!ISUPPER(x[0])) {
- ErrorMsg(psp->filename, psp->tokenlineno,
- "%%token argument \"%s\" should be a token", x);
- psp->errorcnt++;
- } else {
- (void)Symbol_new(x);
- }
- break;
+ /* Tokens do not have to be declared before use. But they can be
+ ** in order to control their assigned integer number. The number for
+ ** each token is assigned when it is first seen. So by including
+ **
+ ** %token ONE TWO THREE
+ **
+ ** early in the grammar file, that assigns small consecutive values
+ ** to each of the tokens ONE TWO and THREE.
+ */
+ if( x[0]=='.' ){
+ psp->state = WAITING_FOR_DECL_OR_RULE;
+ }else if( !ISUPPER(x[0]) ){
+ ErrorMsg(psp->filename, psp->tokenlineno,
+ "%%token argument \"%s\" should be a token", x);
+ psp->errorcnt++;
+ }else{
+ (void)Symbol_new(x);
+ }
+ break;
case WAITING_FOR_WILDCARD_ID:
if( x[0]=='.' ){
psp->state = WAITING_FOR_DECL_OR_RULE;
msp->nsubsym++;
msp->subsym = (struct symbol **) realloc(msp->subsym,
sizeof(struct symbol*)*msp->nsubsym);
- MemoryCheck( msp->subsym );
if( !ISUPPER(x[0]) ) x++;
msp->subsym[msp->nsubsym-1] = Symbol_new(x);
}else{
struct pstate ps;
FILE *fp;
char *filebuf;
- unsigned long int filesize;
+ unsigned int filesize;
int lineno;
int c;
char *cp, *nextcp;
gp->errorcnt++;
return;
}
- fseek(fp, 0, SEEK_END);
+ fseek(fp,0,2);
filesize = ftell(fp);
rewind(fp);
filebuf = (char *)malloc( filesize+1 );
if( filesize>100000000 || filebuf==0 ){
ErrorMsg(ps.filename,0,"Input file too large.");
- gp->errorcnt++;
free(filebuf);
+ gp->errorcnt++;
fclose(fp);
return;
}
{
char *name;
char *cp;
-
- name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 );
+ char *filename = lemp->filename;
+ int sz;
+
+ if( outputDir ){
+ cp = strrchr(filename, '/');
+ if( cp ) filename = cp + 1;
+ }
+ sz = lemonStrlen(filename);
+ sz += lemonStrlen(suffix);
+ if( outputDir ) sz += lemonStrlen(outputDir) + 1;
+ sz += 5;
+ name = (char*)malloc( sz );
if( name==0 ){
fprintf(stderr,"Can't allocate space for a filename.\n");
exit(1);
}
- lemon_strcpy(name,lemp->filename);
+ name[0] = 0;
+ if( outputDir ){
+ lemon_strcpy(name, outputDir);
+ lemon_strcat(name, "/");
+ }
+ lemon_strcat(name,filename);
cp = strrchr(name,'.');
if( cp ) *cp = 0;
lemon_strcat(name,suffix);
return name;
}
-/* Generate a filename with the given suffix. Uses only
-** the basename of the input file, not the entire path. This
-** is useful for creating output files when using outdirname.
-** Space to hold this name comes from malloc() and must be
-** freed by the calling function.
-*/
-PRIVATE char *file_makename_using_basename(struct lemon *lemp, const char *suffix)
-{
- lemp->filename = lemp->basename;
- return file_makename(lemp, suffix);
-}
-
/* Open a file with a name based on the name of the input file,
** but with a different (specified) suffix, and return a pointer
** to the stream */
){
FILE *fp;
- if (lemp->outname) free(lemp->outname);
- lemp->outname = file_makename_using_basename(lemp, suffix);
+ if( lemp->outname ) free(lemp->outname);
+ lemp->outname = file_makename(lemp, suffix);
fp = fopen(lemp->outname,mode);
if( fp==0 && *mode=='w' ){
fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
/* Print the text of a rule
*/
-static void rule_print(FILE *out, struct rule *rp) {
- int i, j;
- fprintf(out, "%s", rp->lhs->name);
- /* if( rp->lhsalias ) fprintf(out,"(%s)",rp->lhsalias); */
- fprintf(out, " ::=");
- for (i = 0; i<rp->nrhs; i++) {
- struct symbol *sp = rp->rhs[i];
- if (sp->type == MULTITERMINAL) {
- fprintf(out, " %s", sp->subsym[0]->name);
- for (j = 1; j<sp->nsubsym; j++) {
- fprintf(out, "|%s", sp->subsym[j]->name);
- }
- } else {
- fprintf(out, " %s", sp->name);
- }
- /* if( rp->rhsalias[i] ) fprintf(out,"(%s)",rp->rhsalias[i]); */
+void rule_print(FILE *out, struct rule *rp){
+ int i, j;
+ fprintf(out, "%s",rp->lhs->name);
+ /* if( rp->lhsalias ) fprintf(out,"(%s)",rp->lhsalias); */
+ fprintf(out," ::=");
+ for(i=0; i<rp->nrhs; i++){
+ struct symbol *sp = rp->rhs[i];
+ if( sp->type==MULTITERMINAL ){
+ fprintf(out," %s", sp->subsym[0]->name);
+ for(j=1; j<sp->nsubsym; j++){
+ fprintf(out,"|%s", sp->subsym[j]->name);
+ }
+ }else{
+ fprintf(out," %s", sp->name);
}
+ /* if( rp->rhsalias[i] ) fprintf(out,"(%s)",rp->rhsalias[i]); */
+ }
}
/* Duplicate the input file without comments and without actions
/* Print a single rule.
*/
-PRIVATE void RulePrint(FILE *fp, struct rule *rp, int iCursor){
+void RulePrint(FILE *fp, struct rule *rp, int iCursor){
struct symbol *sp;
int i, j;
fprintf(fp,"%s ::=",rp->lhs->name);
/* Print the rule for a configuration.
*/
-PRIVATE void ConfigPrint(FILE *fp, struct config *cfp){
+void ConfigPrint(FILE *fp, struct config *cfp){
RulePrint(fp, cfp->rp, cfp->dot);
}
/* Print an action to the given file descriptor. Return FALSE if
** nothing was actually printed.
*/
-PRIVATE int PrintAction(
+int PrintAction(
struct action *ap, /* The action to print */
FILE *fp, /* Print the action here */
int indent /* Indent by this amount */
/* Generate the "*.out" log file */
void ReportOutput(struct lemon *lemp)
{
- int i;
+ int i, n;
struct state *stp;
struct config *cfp;
struct action *ap;
+ struct rule *rp;
FILE *fp;
fp = file_open(lemp,".out","wb");
if( fp==0 ) return;
for(i=0; i<lemp->nxstate; i++){
stp = lemp->sorted[i];
- if(stp){
- fprintf(fp,"State %d:\n",stp->statenum);
- if( lemp->basisflag ) cfp=stp->bp;
- else cfp=stp->cfp;
- while( cfp ){
- char buf[20];
- if( cfp->dot==cfp->rp->nrhs ){
- lemon_sprintf(buf,"(%d)",cfp->rp->iRule);
- fprintf(fp," %5s ",buf);
- }else{
- fprintf(fp," ");
- }
- ConfigPrint(fp,cfp);
- fprintf(fp,"\n");
-#if 0
- SetPrint(fp,cfp->fws,lemp);
- PlinkPrint(fp,cfp->fplp,"To ");
- PlinkPrint(fp,cfp->bplp,"From");
-#endif
- if( lemp->basisflag ) cfp=cfp->bp;
- else cfp=cfp->next;
-
+ fprintf(fp,"State %d:\n",stp->statenum);
+ if( lemp->basisflag ) cfp=stp->bp;
+ else cfp=stp->cfp;
+ while( cfp ){
+ char buf[20];
+ if( cfp->dot==cfp->rp->nrhs ){
+ lemon_sprintf(buf,"(%d)",cfp->rp->iRule);
+ fprintf(fp," %5s ",buf);
+ }else{
+ fprintf(fp," ");
}
+ ConfigPrint(fp,cfp);
fprintf(fp,"\n");
- for(ap=stp->ap; ap; ap=ap->next){
- if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
- }
+#if 0
+ SetPrint(fp,cfp->fws,lemp);
+ PlinkPrint(fp,cfp->fplp,"To ");
+ PlinkPrint(fp,cfp->bplp,"From");
+#endif
+ if( lemp->basisflag ) cfp=cfp->bp;
+ else cfp=cfp->next;
+ }
+ fprintf(fp,"\n");
+ for(ap=stp->ap; ap; ap=ap->next){
+ if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
}
fprintf(fp,"\n");
}
fprintf(fp, "----------------------------------------------------\n");
fprintf(fp, "Symbols:\n");
+ fprintf(fp, "The first-set of non-terminals is shown after the name.\n\n");
for(i=0; i<lemp->nsymbol; i++){
int j;
struct symbol *sp;
}
}
}
+ if( sp->prec>=0 ) fprintf(fp," (precedence=%d)", sp->prec);
fprintf(fp, "\n");
}
+ fprintf(fp, "----------------------------------------------------\n");
+ fprintf(fp, "Syntax-only Symbols:\n");
+ fprintf(fp, "The following symbols never carry semantic content.\n\n");
+ for(i=n=0; i<lemp->nsymbol; i++){
+ int w;
+ struct symbol *sp = lemp->symbols[i];
+ if( sp->bContent ) continue;
+ w = (int)strlen(sp->name);
+ if( n>0 && n+w>75 ){
+ fprintf(fp,"\n");
+ n = 0;
+ }
+ if( n>0 ){
+ fprintf(fp, " ");
+ n++;
+ }
+ fprintf(fp, "%s", sp->name);
+ n += w;
+ }
+ if( n>0 ) fprintf(fp, "\n");
+ fprintf(fp, "----------------------------------------------------\n");
+ fprintf(fp, "Rules:\n");
+ for(rp=lemp->rule; rp; rp=rp->next){
+ fprintf(fp, "%4d: ", rp->iRule);
+ rule_print(fp, rp);
+ fprintf(fp,".");
+ if( rp->precsym ){
+ fprintf(fp," [%s precedence=%d]",
+ rp->precsym->name, rp->precsym->prec);
+ }
+ fprintf(fp,"\n");
+ }
fclose(fp);
return;
}
pathlist = getenv("PATH");
if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
- if( pathbuf == 0 )
- return NULL;
- pathbufptr = pathbuf;
path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
- if( (path!=0) ){
+ MemoryCheck(pathbuf); MemoryCheck(path); /* Fail on allocation failure. */
+ if( (pathbuf != 0) && (path!=0) ){
+ pathbufptr = pathbuf;
lemon_strcpy(pathbuf, pathlist);
while( *pathbuf ){
cp = strchr(pathbuf,':');
else pathbuf = &cp[1];
if( access(path,modemask)==0 ) break;
}
+ free(pathbufptr);
}
- free(pathbufptr);
}
return path;
}
*/
PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
{
- int act;
- switch (ap->type) {
+ int act;
+ switch( ap->type ){
case SHIFT: act = ap->x.stp->statenum; break;
case SHIFTREDUCE: {
- /* Since a SHIFT is inherient after a prior REDUCE, convert any
- ** SHIFTREDUCE action with a nonterminal on the LHS into a simple
- ** REDUCE action: */
- if (ap->sp->index >= lemp->nterminal) {
- act = lemp->minReduce + ap->x.rp->iRule;
- } else {
- act = lemp->minShiftReduce + ap->x.rp->iRule;
- }
- break;
+ /* Since a SHIFT is inherient after a prior REDUCE, convert any
+ ** SHIFTREDUCE action with a nonterminal on the LHS into a simple
+ ** REDUCE action: */
+ if( ap->sp->index>=lemp->nterminal ){
+ act = lemp->minReduce + ap->x.rp->iRule;
+ }else{
+ act = lemp->minShiftReduce + ap->x.rp->iRule;
+ }
+ break;
}
case REDUCE: act = lemp->minReduce + ap->x.rp->iRule; break;
case ERROR: act = lemp->errAction; break;
case ACCEPT: act = lemp->accAction; break;
default: act = -1; break;
- }
- return act;
+ }
+ return act;
}
#define LINESIZE 1000
char buf[1000];
FILE *in;
char *tpltname;
- int tpltname_allocd = LEMON_FALSE;
char *cp;
+ /* We always require the -T option, avoid memleak in the other code path. */
+ assert(user_templatename);
+
/* first, see if user specified a template filename on the command line. */
if (user_templatename != 0) {
if( access(user_templatename,004)==-1 ){
tpltname = templatename;
}else{
tpltname = pathsearch(lemp->argv0,templatename,0);
- tpltname_allocd = LEMON_TRUE;
}
if( tpltname==0 ){
fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
templatename);
lemp->errorcnt++;
- if (tpltname_allocd)
- free(tpltname);
return 0;
}
in = fopen(tpltname,"rb");
if( in==0 ){
fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
lemp->errorcnt++;
- if (tpltname_allocd)
- free(tpltname);
return 0;
}
-
- if (tpltname_allocd)
- free(tpltname);
return in;
}
** The following routine emits code for the destructor for the
** symbol sp
*/
-PRIVATE void emit_destructor_code(
+void emit_destructor_code(
FILE *out,
struct symbol *sp,
struct lemon *lemp,
/*
** Return TRUE (non-zero) if the given symbol has a destructor.
*/
-PRIVATE int has_destructor(struct symbol *sp, struct lemon *lemp)
+int has_destructor(struct symbol *sp, struct lemon *lemp)
{
int ret;
if( sp->type==TERMINAL ){
n = lemonStrlen(zText);
}
if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
- alloced = (int)(n + sizeof(zInt)*2 + used + 200);
+ alloced = n + sizeof(zInt)*2 + used + 200;
z = (char *) realloc(z, alloced);
- MemoryCheck( z );
}
if( z==0 ) return empty;
while( n-- > 0 ){
append_str(0,0,0,0);
- #ifndef __clang_analyzer__
/* This const cast is wrong but harmless, if we're careful. */
for(cp=(char *)rp->code; *cp; cp++){
if( cp==zSkip ){
}
append_str(cp, 1, 0, 0);
} /* End loop */
- #endif
/* Main code generation completed */
cp = append_str(0,0,0,0);
** union, also set the ".dtnum" field of every terminal and nonterminal
** symbol.
*/
-PRIVATE void print_stack_union(
+void print_stack_union(
FILE *out, /* The output stream */
struct lemon *lemp, /* The main info structure for this parser */
int *plineno, /* Pointer to the line number */
int mhflag /* True if generating makeheaders output */
){
- int lineno = *plineno; /* The line number of the output */
+ int lineno; /* The line number of the output */
char **types; /* A hash table of datatypes */
int arraysize; /* Size of the "types" array */
int maxdtlength; /* Maximum length of any ".datatype" field. */
if( len>maxdtlength ) maxdtlength = len;
}
stddt = (char*)malloc( maxdtlength*2 + 1 );
- if (stddt == 0) {
- fprintf(stderr, "Out of memory.\n");
- exit(1);
+ if( stddt==0 ){
+ fprintf(stderr,"Out of memory.\n");
+ exit(1);
}
/* Build a hash table of datatypes. The ".dtnum" field of each symbol
if( types[hash]==0 ){
sp->dtnum = hash + 1;
types[hash] = (char*)malloc( lemonStrlen(stddt)+1 );
- if (types[hash] == 0) {
- fprintf(stderr, "Out of memory.\n");
- exit(1);
+ if( types[hash]==0 ){
+ fprintf(stderr,"Out of memory.\n");
+ exit(1);
}
lemon_strcpy(types[hash],stddt);
}
/* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
name = lemp->name ? lemp->name : "Parse";
+ lineno = *plineno;
if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
fprintf(out,"#define %sTOKENTYPE %s\n",name,
lemp->tokentype?lemp->tokentype:"void*"); lineno++;
fprintf(out," %s yy%d;\n",types[i],i+1); lineno++;
free(types[i]);
}
- if( lemp->errsym->useCnt ){
+ if( lemp->errsym && lemp->errsym->useCnt ){
fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++;
}
free(stddt);
** Compare to axset structures for sorting purposes
*/
static int axset_compare(const void *a, const void *b){
- const struct axset *p1 = (const struct axset*)a;
- const struct axset *p2 = (const struct axset*)b;
+ struct axset *p1 = (struct axset*)a;
+ struct axset *p2 = (struct axset*)b;
int c;
c = p2->nAction - p1->nAction;
if( c==0 ){
/* Generate the defines */
fprintf(out,"#define YYCODETYPE %s\n",
- minimum_size_type(0, lemp->nsymbol+1, &szCodeType)); lineno++;
- fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
+ minimum_size_type(0, lemp->nsymbol, &szCodeType)); lineno++;
+ fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol); lineno++;
fprintf(out,"#define YYACTIONTYPE %s\n",
- minimum_size_type(0, lemp->maxAction, &szActionType)); lineno++;
+ minimum_size_type(0,lemp->maxAction,&szActionType)); lineno++;
if( lemp->wildcard ){
fprintf(out,"#define YYWILDCARD %d\n",
lemp->wildcard->index); lineno++;
while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++;
fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++;
- fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
+ fprintf(out,"#define %sARG_PARAM ,%s\n",name,&lemp->arg[i]); lineno++;
+ fprintf(out,"#define %sARG_FETCH %s=yypParser->%s;\n",
name,lemp->arg,&lemp->arg[i]); lineno++;
- fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
+ fprintf(out,"#define %sARG_STORE yypParser->%s=%s;\n",
name,&lemp->arg[i],&lemp->arg[i]); lineno++;
}else{
- fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
- fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
+ fprintf(out,"#define %sARG_SDECL\n",name); lineno++;
+ fprintf(out,"#define %sARG_PDECL\n",name); lineno++;
+ fprintf(out,"#define %sARG_PARAM\n",name); lineno++;
fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
fprintf(out,"#define %sARG_STORE\n",name); lineno++;
}
+ if( lemp->ctx && lemp->ctx[0] ){
+ i = lemonStrlen(lemp->ctx);
+ while( i>=1 && ISSPACE(lemp->ctx[i-1]) ) i--;
+ while( i>=1 && (ISALNUM(lemp->ctx[i-1]) || lemp->ctx[i-1]=='_') ) i--;
+ fprintf(out,"#define %sCTX_SDECL %s;\n",name,lemp->ctx); lineno++;
+ fprintf(out,"#define %sCTX_PDECL ,%s\n",name,lemp->ctx); lineno++;
+ fprintf(out,"#define %sCTX_PARAM ,%s\n",name,&lemp->ctx[i]); lineno++;
+ fprintf(out,"#define %sCTX_FETCH %s=yypParser->%s;\n",
+ name,lemp->ctx,&lemp->ctx[i]); lineno++;
+ fprintf(out,"#define %sCTX_STORE yypParser->%s=%s;\n",
+ name,&lemp->ctx[i],&lemp->ctx[i]); lineno++;
+ }else{
+ fprintf(out,"#define %sCTX_SDECL\n",name); lineno++;
+ fprintf(out,"#define %sCTX_PDECL\n",name); lineno++;
+ fprintf(out,"#define %sCTX_PARAM\n",name); lineno++;
+ fprintf(out,"#define %sCTX_FETCH\n",name); lineno++;
+ fprintf(out,"#define %sCTX_STORE\n",name); lineno++;
+ }
if( mhflag ){
fprintf(out,"#endif\n"); lineno++;
}
- if( lemp->errsym->useCnt ){
+ if( lemp->errsym && lemp->errsym->useCnt ){
fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++;
fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++;
}
** we need to know how many states can be eliminated.
*/
ax = (struct axset *) calloc(lemp->nxstate*2, sizeof(ax[0]));
- if (ax == 0) {
- fprintf(stderr, "malloc failed\n");
- exit(1);
+ if( ax==0 ){
+ fprintf(stderr,"malloc failed\n");
+ exit(1);
}
for(i=0; i<lemp->nxstate; i++){
stp = lemp->sorted[i];
for(i=0; i<lemp->nxstate; i++){
for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
if( ap->type==REDUCE || ap->type==SHIFTREDUCE ){
- ap->x.rp->doesReduce = i ? LEMON_TRUE : LEMON_FALSE ;
+ ap->x.rp->doesReduce = 1;
}
}
}
/* Finish rendering the constants now that the action table has
** been computed */
- fprintf(out, "#define YYNSTATE %d\n", lemp->nxstate); lineno++;
- fprintf(out, "#define YYNRULE %d\n", lemp->nrule); lineno++;
- fprintf(out, "#define YYNTOKEN %d\n", lemp->nterminal); lineno++;
- fprintf(out, "#define YY_MAX_SHIFT %d\n", lemp->nxstate - 1); lineno++;
+ fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++;
+ fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++;
+ fprintf(out,"#define YYNTOKEN %d\n",lemp->nterminal); lineno++;
+ fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++;
i = lemp->minShiftReduce;
- fprintf(out, "#define YY_MIN_SHIFTREDUCE %d\n", i); lineno++;
+ fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",i); lineno++;
i += lemp->nrule;
- fprintf(out, "#define YY_MAX_SHIFTREDUCE %d\n", i - 1); lineno++;
- fprintf(out, "#define YY_ERROR_ACTION %d\n", lemp->errAction); lineno++;
- fprintf(out, "#define YY_ACCEPT_ACTION %d\n", lemp->accAction); lineno++;
- fprintf(out, "#define YY_NO_ACTION %d\n", lemp->noAction); lineno++;
- fprintf(out, "#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++;
+ fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++;
+ fprintf(out,"#define YY_ERROR_ACTION %d\n", lemp->errAction); lineno++;
+ fprintf(out,"#define YY_ACCEPT_ACTION %d\n", lemp->accAction); lineno++;
+ fprintf(out,"#define YY_NO_ACTION %d\n", lemp->noAction); lineno++;
+ fprintf(out,"#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++;
i = lemp->minReduce + lemp->nrule;
- fprintf(out, "#define YY_MAX_REDUCE %d\n", i - 1); lineno++;
- tplt_xfer(lemp->name, in, out, &lineno);
+ fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
+ tplt_xfer(lemp->name,in,out,&lineno);
/* Now output the action table and its associates:
**
lemp->tablesize += n*szActionType;
fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++;
fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
- for (i = j = 0; i<n; i++) {
- int action = acttab_yyaction(pActtab, i);
- if (action<0) action = lemp->noAction;
- if (j == 0) fprintf(out, " /* %5d */ ", i);
- fprintf(out, " %4d,", action);
- if (j == 9 || i == n - 1) {
- fprintf(out, "\n"); lineno++;
- j = 0;
- } else {
- j++;
- }
+ for(i=j=0; i<n; i++){
+ int action = acttab_yyaction(pActtab, i);
+ if( action<0 ) action = lemp->noAction;
+ if( j==0 ) fprintf(out," /* %5d */ ", i);
+ fprintf(out, " %4d,", action);
+ if( j==9 || i==n-1 ){
+ fprintf(out, "\n"); lineno++;
+ j = 0;
+ }else{
+ j++;
+ }
}
fprintf(out, "};\n"); lineno++;
fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
n = lemp->nxstate;
lemp->tablesize += n*szActionType;
- for (i = j = 0; i<n; i++) {
- stp = lemp->sorted[i];
- if (j == 0) fprintf(out, " /* %5d */ ", i);
- if (stp->iDfltReduce<0) {
- fprintf(out, " %4d,", lemp->errAction);
- } else {
- fprintf(out, " %4d,", stp->iDfltReduce + lemp->minReduce);
- }
- if (j == 9 || i == n - 1) {
- fprintf(out, "\n"); lineno++;
- j = 0;
- } else {
- j++;
- }
+ for(i=j=0; i<n; i++){
+ stp = lemp->sorted[i];
+ if( j==0 ) fprintf(out," /* %5d */ ", i);
+ if( stp->iDfltReduce<0 ){
+ fprintf(out, " %4d,", lemp->errAction);
+ }else{
+ fprintf(out, " %4d,", stp->iDfltReduce + lemp->minReduce);
+ }
+ if( j==9 || i==n-1 ){
+ fprintf(out, "\n"); lineno++;
+ j = 0;
+ }else{
+ j++;
+ }
}
fprintf(out, "};\n"); lineno++;
tplt_xfer(lemp->name,in,out,&lineno);
/* Generate a table containing the symbolic name of every symbol
*/
- for (i = 0; i<lemp->nsymbol; i++) {
- lemon_sprintf(line, "\"%s\",", lemp->symbols[i]->name);
- fprintf(out, " /* %4d */ \"%s\",\n", i, lemp->symbols[i]->name); lineno++;
+ for(i=0; i<lemp->nsymbol; i++){
+ lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name);
+ fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++;
}
tplt_xfer(lemp->name,in,out,&lineno);
if( sp==0 || sp->type==TERMINAL ||
sp->index<=0 || sp->destructor!=0 ) continue;
if( once ){
- fprintf(out, " /* Default NON-TERMINAL Destructor */\n"); lineno++;
+ fprintf(out, " /* Default NON-TERMINAL Destructor */\n");lineno++;
once = 0;
}
fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++;
** Note: This code depends on the fact that rules are number
** sequentually beginning with 0.
*/
- for (i = 0, rp = lemp->rule; rp; rp = rp->next, i++) {
- fprintf(out, " { %4d, %4d }, /* (%d) ", rp->lhs->index, -rp->nrhs, i);
- rule_print(out, rp);
- fprintf(out, " */\n"); lineno++;
+ for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
+ fprintf(out," { %4d, %4d }, /* (%d) ",rp->lhs->index,-rp->nrhs,i);
+ rule_print(out, rp);
+ fprintf(out," */\n"); lineno++;
}
tplt_xfer(lemp->name,in,out,&lineno);
** token actions.
*/
static int stateResortCompare(const void *a, const void *b){
- const struct state *pA = *(const struct state *const *)a;
- const struct state *pB = *(const struct state *const *)b;
+ const struct state *pA = *(const struct state**)a;
+ const struct state *pB = *(const struct state**)b;
int n;
n = pB->nNtAct - pA->nNtAct;
char *SetNew(void){
char *s;
s = (char*)calloc( size, 1);
- MemoryCheck( s );
+ if( s==0 ){
+ extern void memory_error();
+ memory_error();
+ }
return s;
}
array.ht[h] = newnp;
}
free(x1a->tbl);
- *x1a = array;
+ memcpy(x1a, &array, sizeof(array)); /* *x1a = array; */
}
-#ifndef __clang_analyzer__
/* Insert the new data */
h = ph & (x1a->size-1);
np = &(x1a->tbl[x1a->count++]);
np->next = x1a->ht[h];
x1a->ht[h] = np;
np->from = &(x1a->ht[h]);
-#endif
return 1;
}
*/
int Symbolcmpp(const void *_a, const void *_b)
{
- const struct symbol *a = *(const struct symbol *const *) _a;
- const struct symbol *b = *(const struct symbol *const *) _b;
+ const struct symbol *a = *(const struct symbol **) _a;
+ const struct symbol *b = *(const struct symbol **) _b;
int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1;
int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1;
return i1==i2 ? a->index - b->index : i1 - i2;
array.ht[h] = newnp;
}
free(x2a->tbl);
- *x2a = array;
+ memcpy(x2a, &array, sizeof(array)); /* *x2a = array; */
}
-#ifndef __clang_analyzer__
/* Insert the new data */
h = ph & (x2a->size-1);
np = &(x2a->tbl[x2a->count++]);
np->next = x2a->ht[h];
x2a->ht[h] = np;
np->from = &(x2a->ht[h]);
-#endif
return 1;
}
}
/* Return the size of the array */
-int Symbol_count(void)
+int Symbol_count()
{
return x2a ? x2a->count : 0;
}
/* Return an array of pointers to all data in the table.
** The array is obtained from malloc. Return NULL if memory allocation
** problems, or if the array is empty. */
-struct symbol **Symbol_arrayof(void)
+struct symbol **Symbol_arrayof()
{
struct symbol **array;
int i,arrSize;
/* Compare two configurations */
int Configcmp(const char *_a,const char *_b)
{
- const struct config *a = (const struct config *) _a;
- const struct config *b = (const struct config *) _b;
+ const struct config *a = (struct config *) _a;
+ const struct config *b = (struct config *) _b;
int x;
x = a->rp->index - b->rp->index;
if( x==0 ) x = a->dot - b->dot;
}
/* Allocate a new state structure */
-struct state *State_new(void)
+struct state *State_new()
{
struct state *newstate;
newstate = (struct state *)calloc(1, sizeof(struct state) );
array.ht[h] = newnp;
}
free(x3a->tbl);
- *x3a = array;
+ memcpy(x3a, &array, sizeof(array)); /* *x3a = array; */
}
-#ifndef __clang_analyzer__
/* Insert the new data */
h = ph & (x3a->size-1);
np = &(x3a->tbl[x3a->count++]);
np->next = x3a->ht[h];
x3a->ht[h] = np;
np->from = &(x3a->ht[h]);
-#endif
return 1;
}
array.ht[h] = newnp;
}
free(x4a->tbl);
- *x4a = array;
+ memcpy(x4a, &array, sizeof(array)); /* *x4a = array; */
}
-#ifndef __clang_analyzer__
/* Insert the new data */
h = ph & (x4a->size-1);
np = &(x4a->tbl[x4a->count++]);
np->next = x4a->ht[h];
x4a->ht[h] = np;
np->from = &(x4a->ht[h]);
-#endif
return 1;
}