Created
June 12, 2011 21:38
-
-
Save flavius/1022015 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
assert( | |
apx->type==SH_RESOLVED || | |
apx->type==RD_RESOLVED || | |
apx->type==SSCONFLICT || | |
apx->type==SRCONFLICT || | |
apx->type==RRCONFLICT || | |
apy->type==SH_RESOLVED || | |
apy->type==RD_RESOLVED || | |
apy->type==SSCONFLICT || | |
apy->type==SRCONFLICT || | |
apy->type==RRCONFLICT | |
); | |
/* The REDUCE/SHIFT case cannot happen because SHIFTs come before | |
** REDUCEs on the list. If we reach this point it must be because | |
** the parser conflict had already been resolved. */ | |
} | |
return errcnt; | |
} | |
/********************* From the file "configlist.c" *************************/ | |
/* | |
** Routines to processing a configuration list and building a state | |
** in the LEMON parser generator. | |
*/ | |
static struct config *freelist = 0; /* List of free configurations */ | |
static struct config *current = 0; /* Top of list of configurations */ | |
static struct config **currentend = 0; /* Last on list of configs */ | |
static struct config *basis = 0; /* Top of list of basis configs */ | |
static struct config **basisend = 0; /* End of list of basis configs */ | |
/* Return a pointer to a new configuration */ | |
PRIVATE struct config *newconfig(){ | |
struct config *newcfg; | |
if( freelist==0 ){ | |
int i; | |
int amt = 3; | |
freelist = (struct config *)calloc( amt, sizeof(struct config) ); | |
if( freelist==0 ){ | |
fprintf(stderr,"Unable to allocate memory for a new configuration."); | |
exit(1); | |
} | |
for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1]; | |
freelist[amt-1].next = 0; | |
} | |
newcfg = freelist; | |
freelist = freelist->next; | |
return newcfg; | |
} | |
/* The configuration "old" is no longer used */ | |
PRIVATE void deleteconfig(struct config *old) | |
{ | |
old->next = freelist; | |
freelist = old; | |
} | |
/* Initialized the configuration list builder */ | |
void Configlist_init(){ | |
current = 0; | |
currentend = ¤t; | |
basis = 0; | |
basisend = &basis; | |
Configtable_init(); | |
return; | |
} | |
/* Initialized the configuration list builder */ | |
void Configlist_reset(){ | |
current = 0; | |
currentend = ¤t; | |
basis = 0; | |
basisend = &basis; | |
Configtable_clear(0); | |
return; | |
} | |
/* Add another configuration to the configuration list */ | |
struct config *Configlist_add( | |
struct rule *rp, /* The rule */ | |
int dot /* Index into the RHS of the rule where the dot goes */ | |
){ | |
struct config *cfp, model; | |
assert( currentend!=0 ); | |
model.rp = rp; | |
model.dot = dot; | |
cfp = Configtable_find(&model); | |
if( cfp==0 ){ | |
cfp = newconfig(); | |
cfp->rp = rp; | |
cfp->dot = dot; | |
cfp->fws = SetNew(); | |
cfp->stp = 0; | |
cfp->fplp = cfp->bplp = 0; | |
cfp->next = 0; | |
cfp->bp = 0; | |
*currentend = cfp; | |
currentend = &cfp->next; | |
Configtable_insert(cfp); | |
} | |
return cfp; | |
} | |
/* Add a basis configuration to the configuration list */ | |
struct config *Configlist_addbasis(struct rule *rp, int dot) | |
{ | |
struct config *cfp, model; | |
assert( basisend!=0 ); | |
assert( currentend!=0 ); | |
model.rp = rp; | |
model.dot = dot; | |
cfp = Configtable_find(&model); | |
if( cfp==0 ){ | |
cfp = newconfig(); | |
cfp->rp = rp; | |
cfp->dot = dot; | |
cfp->fws = SetNew(); | |
cfp->stp = 0; | |
cfp->fplp = cfp->bplp = 0; | |
cfp->next = 0; | |
cfp->bp = 0; | |
*currentend = cfp; | |
currentend = &cfp->next; | |
*basisend = cfp; | |
basisend = &cfp->bp; | |
Configtable_insert(cfp); | |
} | |
return cfp; | |
} | |
/* Compute the closure of the configuration list */ | |
void Configlist_closure(struct lemon *lemp) | |
{ | |
struct config *cfp, *newcfp; | |
struct rule *rp, *newrp; | |
struct symbol *sp, *xsp; | |
int i, dot; | |
assert( currentend!=0 ); | |
for(cfp=current; cfp; cfp=cfp->next){ | |
rp = cfp->rp; | |
dot = cfp->dot; | |
if( dot>=rp->nrhs ) continue; | |
sp = rp->rhs[dot]; | |
if( sp->type==NONTERMINAL ){ | |
if( sp->rule==0 && sp!=lemp->errsym ){ | |
ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.", | |
sp->name); | |
lemp->errorcnt++; | |
} | |
for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){ | |
newcfp = Configlist_add(newrp,0); | |
for(i=dot+1; i<rp->nrhs; i++){ | |
xsp = rp->rhs[i]; | |
if( xsp->type==TERMINAL ){ | |
SetAdd(newcfp->fws,xsp->index); | |
break; | |
}else if( xsp->type==MULTITERMINAL ){ | |
int k; | |
for(k=0; k<xsp->nsubsym; k++){ | |
SetAdd(newcfp->fws, xsp->subsym[k]->index); | |
} | |
break; | |
}else{ | |
SetUnion(newcfp->fws,xsp->firstset); | |
if( xsp->lambda==LEMON_FALSE ) break; | |
} | |
} | |
if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); | |
} | |
} | |
} | |
return; | |
} | |
/* Sort the configuration list */ | |
void Configlist_sort(){ | |
current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp); | |
currentend = 0; | |
return; | |
} | |
/* Sort the basis configuration list */ | |
void Configlist_sortbasis(){ | |
basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp); | |
basisend = 0; | |
return; | |
} | |
/* Return a pointer to the head of the configuration list and | |
** reset the list */ | |
struct config *Configlist_return(){ | |
struct config *old; | |
old = current; | |
current = 0; | |
currentend = 0; | |
return old; | |
} | |
/* Return a pointer to the head of the configuration list and | |
** reset the list */ | |
struct config *Configlist_basis(){ | |
struct config *old; | |
old = basis; | |
basis = 0; | |
basisend = 0; | |
return old; | |
} | |
/* Free all elements of the given configuration list */ | |
void Configlist_eat(struct config *cfp) | |
{ | |
struct config *nextcfp; | |
for(; cfp; cfp=nextcfp){ | |
nextcfp = cfp->next; | |
assert( cfp->fplp==0 ); | |
assert( cfp->bplp==0 ); | |
if( cfp->fws ) SetFree(cfp->fws); | |
deleteconfig(cfp); | |
} | |
return; | |
} | |
/***************** From the file "error.c" *********************************/ | |
/* | |
** Code for printing error message. | |
*/ | |
void ErrorMsg(const char *filename, int lineno, const char *format, ...){ | |
va_list ap; | |
fprintf(stderr, "%s:%d: ", filename, lineno); | |
va_start(ap, format); | |
vfprintf(stderr,format,ap); | |
va_end(ap); | |
fprintf(stderr, "\n"); | |
} | |
/**************** From the file "main.c" ************************************/ | |
/* | |
** Main program file for the LEMON parser generator. | |
*/ | |
/* Report an out-of-memory condition and abort. This function | |
** is used mostly by the "MemoryCheck" macro in struct.h | |
*/ | |
void memory_error(){ | |
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){ | |
char **paz; | |
nDefine++; | |
azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine); | |
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); | |
} | |
strcpy(*paz, z); | |
for(z=*paz; *z && *z!='='; z++){} | |
*z = 0; | |
} | |
static char *user_templatename = NULL; | |
static void handle_T_option(char *z){ | |
user_templatename = (char *) malloc( lemonStrlen(z)+1 ); | |
if( user_templatename==0 ){ | |
memory_error(); | |
} | |
strcpy(user_templatename, z); | |
} | |
/* The main program. Parse the command line and do it... */ | |
int main(int argc, char **argv) | |
{ | |
static int version = 0; | |
static int rpflag = 0; | |
static int basisflag = 0; | |
static int compress = 0; | |
static int quiet = 0; | |
static int statistics = 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, "T", (char*)handle_T_option, "Specify a template file."}, | |
{OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, | |
{OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."}, | |
{OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."}, | |
{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_FLAG,0,0,0} | |
}; | |
int i; | |
int exitcode; | |
struct lemon lem; | |
atexit(LemonAtExit); | |
OptInit(argv,options,stderr); | |
if( version ){ | |
printf("Lemon version 1.0\n"); | |
exit(0); | |
} | |
(there are some spaces in there in bar, use copy/paste if you want to test) | |
The end result is supposed to be: | |
assert( | |
apx->type==SH_RESOLVED || | |
apx->type==RD_RESOLVED || | |
apx->type==SSCONFLICT || | |
apx->type==SRCONFLICT || | |
apx->type==RRCONFLICT || | |
apy->type==SH_RESOLVED || | |
apy->type==RD_RESOLVED || | |
apy->type==SSCONFLICT || | |
apy->type==SRCONFLICT || | |
apy->type==RRCONFLICT | |
); | |
/* The REDUCE/SHIFT case cannot happen because SHIFTs come before | |
** REDUCEs on the list. If we reach this point it must be because | |
** the parser conflict had already been resolved. */ | |
} | |
return errcnt; | |
} | |
/********************* From the file "configlist.c" *************************/ | |
/* | |
** Routines to processing a configuration list and building a state | |
** in the LEMON parser generator. | |
*/ | |
static struct config *freelist = 0; /* List of free configurations */ | |
static struct config *current = 0; /* Top of list of configurations */ | |
static struct config **currentend = 0; /* Last on list of configs */ | |
static struct config *basis = 0; /* Top of list of basis configs */ | |
static struct config **basisend = 0; /* End of list of basis configs */ | |
/* Return a pointer to a new configuration */ | |
PRIVATE struct config *newconfig(){ | |
struct config *newcfg; | |
if( freelist==0 ){ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
assert( | |
apx->type==SH_RESOLVED || | |
apx->type==RD_RESOLVED || | |
apx->type==SSCONFLICT || | |
apx->type==SRCONFLICT || | |
apx->type==RRCONFLICT || | |
apy->type==SH_RESOLVED || | |
apy->type==RD_RESOLVED || | |
apy->type==SSCONFLICT || | |
apy->type==SRCONFLICT || | |
apy->type==RRCONFLICT | |
); | |
/* The REDUCE/SHIFT case cannot happen because SHIFTs come before | |
** REDUCEs on the list. If we reach this point it must be because | |
** the parser conflict had already been resolved. */ | |
} | |
return errcnt; | |
} | |
/********************* From the file "configlist.c" *************************/ | |
/* | |
** Routines to processing a configuration list and building a state | |
** in the LEMON parser generator. | |
*/ | |
static struct config *freelist = 0; /* List of free configurations */ | |
static struct config *current = 0; /* Top of list of configurations */ | |
static struct config **currentend = 0; /* Last on list of configs */ | |
static struct config *basis = 0; /* Top of list of basis configs */ | |
static struct config **basisend = 0; /* End of list of basis configs */ | |
/* Return a pointer to a new configuration */ | |
PRIVATE struct config *newconfig(){ | |
struct config *newcfg; | |
if( freelist==0 ){ | |
int i; | |
int amt = 3; | |
freelist = (struct config *)calloc( amt, sizeof(struct config) ); | |
if( freelist==0 ){ | |
fprintf(stderr,"Unable to allocate memory for a new configuration."); | |
exit(1); | |
} | |
for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1]; | |
freelist[amt-1].next = 0; | |
} | |
newcfg = freelist; | |
freelist = freelist->next; | |
return newcfg; | |
} | |
/* The configuration "old" is no longer used */ | |
PRIVATE void deleteconfig(struct config *old) | |
{ | |
old->next = freelist; | |
freelist = old; | |
} | |
/* Initialized the configuration list builder */ | |
void Configlist_init(){ | |
current = 0; | |
currentend = ¤t; | |
basis = 0; | |
basisend = &basis; | |
Configtable_init(); | |
return; | |
} | |
/* Initialized the configuration list builder */ | |
void Configlist_reset(){ | |
current = 0; | |
currentend = ¤t; | |
basis = 0; | |
basisend = &basis; | |
Configtable_clear(0); | |
return; | |
} | |
/* Add another configuration to the configuration list */ | |
struct config *Configlist_add( | |
struct rule *rp, /* The rule */ | |
int dot /* Index into the RHS of the rule where the dot goes */ | |
){ | |
struct config *cfp, model; | |
assert( currentend!=0 ); | |
model.rp = rp; | |
model.dot = dot; | |
cfp = Configtable_find(&model); | |
if( cfp==0 ){ | |
cfp = newconfig(); | |
cfp->rp = rp; | |
cfp->dot = dot; | |
cfp->fws = SetNew(); | |
cfp->stp = 0; | |
cfp->fplp = cfp->bplp = 0; | |
cfp->next = 0; | |
cfp->bp = 0; | |
*currentend = cfp; | |
currentend = &cfp->next; | |
Configtable_insert(cfp); | |
} | |
return cfp; | |
} | |
/* Add a basis configuration to the configuration list */ | |
struct config *Configlist_addbasis(struct rule *rp, int dot) | |
{ | |
struct config *cfp, model; | |
assert( basisend!=0 ); | |
assert( currentend!=0 ); | |
model.rp = rp; | |
model.dot = dot; | |
cfp = Configtable_find(&model); | |
if( cfp==0 ){ | |
cfp = newconfig(); | |
cfp->rp = rp; | |
cfp->dot = dot; | |
cfp->fws = SetNew(); | |
cfp->stp = 0; | |
cfp->fplp = cfp->bplp = 0; | |
cfp->next = 0; | |
cfp->bp = 0; | |
*currentend = cfp; | |
currentend = &cfp->next; | |
*basisend = cfp; | |
basisend = &cfp->bp; | |
Configtable_insert(cfp); | |
} | |
return cfp; | |
} | |
/* Compute the closure of the configuration list */ | |
void Configlist_closure(struct lemon *lemp) | |
{ | |
struct config *cfp, *newcfp; | |
struct rule *rp, *newrp; | |
struct symbol *sp, *xsp; | |
int i, dot; | |
assert( currentend!=0 ); | |
for(cfp=current; cfp; cfp=cfp->next){ | |
rp = cfp->rp; | |
dot = cfp->dot; | |
if( dot>=rp->nrhs ) continue; | |
sp = rp->rhs[dot]; | |
if( sp->type==NONTERMINAL ){ | |
if( sp->rule==0 && sp!=lemp->errsym ){ | |
ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.", | |
sp->name); | |
lemp->errorcnt++; | |
} | |
for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){ | |
newcfp = Configlist_add(newrp,0); | |
for(i=dot+1; i<rp->nrhs; i++){ | |
xsp = rp->rhs[i]; | |
if( xsp->type==TERMINAL ){ | |
SetAdd(newcfp->fws,xsp->index); | |
break; | |
}else if( xsp->type==MULTITERMINAL ){ | |
int k; | |
for(k=0; k<xsp->nsubsym; k++){ | |
SetAdd(newcfp->fws, xsp->subsym[k]->index); | |
} | |
break; | |
}else{ | |
SetUnion(newcfp->fws,xsp->firstset); | |
if( xsp->lambda==LEMON_FALSE ) break; | |
} | |
} | |
if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); | |
} | |
} | |
} | |
return; | |
} | |
/* Sort the configuration list */ | |
void Configlist_sort(){ | |
current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp); | |
currentend = 0; | |
return; | |
} | |
/* Sort the basis configuration list */ | |
void Configlist_sortbasis(){ | |
basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp); | |
basisend = 0; | |
return; | |
} | |
/* Return a pointer to the head of the configuration list and | |
** reset the list */ | |
struct config *Configlist_return(){ | |
struct config *old; | |
old = current; | |
current = 0; | |
currentend = 0; | |
return old; | |
} | |
/* Return a pointer to the head of the configuration list and | |
** reset the list */ | |
struct config *Configlist_basis(){ | |
struct config *old; | |
old = basis; | |
basis = 0; | |
basisend = 0; | |
return old; | |
} | |
/* Free all elements of the given configuration list */ | |
void Configlist_eat(struct config *cfp) | |
{ | |
struct config *nextcfp; | |
for(; cfp; cfp=nextcfp){ | |
nextcfp = cfp->next; | |
assert( cfp->fplp==0 ); | |
assert( cfp->bplp==0 ); | |
if( cfp->fws ) SetFree(cfp->fws); | |
deleteconfig(cfp); | |
} | |
return; | |
} | |
/***************** From the file "error.c" *********************************/ | |
/* | |
** Code for printing error message. | |
*/ | |
void ErrorMsg(const char *filename, int lineno, const char *format, ...){ | |
va_list ap; | |
fprintf(stderr, "%s:%d: ", filename, lineno); | |
va_start(ap, format); | |
vfprintf(stderr,format,ap); | |
va_end(ap); | |
fprintf(stderr, "\n"); | |
} | |
/**************** From the file "main.c" ************************************/ | |
/* | |
** Main program file for the LEMON parser generator. | |
*/ | |
/* Report an out-of-memory condition and abort. This function | |
** is used mostly by the "MemoryCheck" macro in struct.h | |
*/ | |
void memory_error(){ | |
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){ | |
char **paz; | |
nDefine++; | |
azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine); | |
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); | |
} | |
strcpy(*paz, z); | |
for(z=*paz; *z && *z!='='; z++){} | |
*z = 0; | |
} | |
static char *user_templatename = NULL; | |
static void handle_T_option(char *z){ | |
user_templatename = (char *) malloc( lemonStrlen(z)+1 ); | |
if( user_templatename==0 ){ | |
memory_error(); | |
} | |
strcpy(user_templatename, z); | |
} | |
/* file name to save the generated minor numbers to; defaults to filename */ | |
static char *minors_name = NULL; | |
static void handle_t_option(char *z) { | |
fprintf(stderr, "minors are saved to %s\n",minors_name); | |
minors_name = z; | |
} | |
/* The main program. Parse the command line and do it... */ | |
int main(int argc, char **argv) | |
{ | |
static int version = 0; | |
static int rpflag = 0; | |
static int basisflag = 0; | |
static int compress = 0; | |
static int quiet = 0; | |
static int statistics = 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, "T", (char*)handle_T_option, "Specify a template file."}, | |
{OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, | |
{OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."}, | |
{OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."}, | |
{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_FSTR, "t", (char*)&handle_t_option, "Specify the header filename to put the token defines in."}, | |
{OPT_FLAG, "x", (char*)&version, "Print the version number."}, | |
{OPT_FLAG,0,0,0} | |
}; | |
int i; | |
int exitcode; | |
struct lemon lem; | |
atexit(LemonAtExit); | |
OptInit(argv,options,stderr); | |
if( version ){ | |
printf("Lemon version 1.0\n"); | |
exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment