| Index: third_party/sqlite/src/tool/lemon.c
|
| diff --git a/third_party/sqlite/src/tool/lemon.c b/third_party/sqlite/src/tool/lemon.c
|
| index 8336e9a1ba2b249e12a320de13cf3078cba8ee1c..898022e28c1589b5c99bac7a990422dce6e089e4 100644
|
| --- a/third_party/sqlite/src/tool/lemon.c
|
| +++ b/third_party/sqlite/src/tool/lemon.c
|
| @@ -20,7 +20,13 @@
|
| #endif
|
|
|
| #ifdef __WIN32__
|
| -extern int access();
|
| +#ifdef __cplusplus
|
| +extern "C" {
|
| +#endif
|
| +extern int access(const char *path, int mode);
|
| +#ifdef __cplusplus
|
| +}
|
| +#endif
|
| #else
|
| #include <unistd.h>
|
| #endif
|
| @@ -34,6 +40,24 @@ extern int access();
|
| #define MAXRHS 1000
|
| #endif
|
|
|
| +static int showPrecedenceConflict = 0;
|
| +static const char **made_files = NULL;
|
| +static int made_files_count = 0;
|
| +static int successful_exit = 0;
|
| +static void LemonAtExit(void)
|
| +{
|
| + /* if we failed, delete (most) files we made, to unconfuse build tools. */
|
| + int i;
|
| + for (i = 0; i < made_files_count; i++) {
|
| + if (!successful_exit) {
|
| + remove(made_files[i]);
|
| + }
|
| + }
|
| + free(made_files);
|
| + made_files_count = 0;
|
| + made_files = NULL;
|
| +}
|
| +
|
| static char *msort(char*,char**,int(*)(const char*,const char*));
|
|
|
| /*
|
| @@ -43,6 +67,11 @@ static char *msort(char*,char**,int(*)(const char*,const char*));
|
| */
|
| #define lemonStrlen(X) ((int)strlen(X))
|
|
|
| +/* a few forward declarations... */
|
| +struct rule;
|
| +struct lemon;
|
| +struct action;
|
| +
|
| static struct action *Action_new(void);
|
| static struct action *Action_sort(struct action *);
|
|
|
| @@ -55,59 +84,60 @@ void FindFollowSets();
|
| void FindActions();
|
|
|
| /********* From the file "configlist.h" *********************************/
|
| -void Configlist_init(/* void */);
|
| -struct config *Configlist_add(/* struct rule *, int */);
|
| -struct config *Configlist_addbasis(/* struct rule *, int */);
|
| -void Configlist_closure(/* void */);
|
| -void Configlist_sort(/* void */);
|
| -void Configlist_sortbasis(/* void */);
|
| -struct config *Configlist_return(/* void */);
|
| -struct config *Configlist_basis(/* void */);
|
| -void Configlist_eat(/* struct config * */);
|
| -void Configlist_reset(/* void */);
|
| +void Configlist_init(void);
|
| +struct config *Configlist_add(struct rule *, int);
|
| +struct config *Configlist_addbasis(struct rule *, int);
|
| +void Configlist_closure(struct lemon *);
|
| +void Configlist_sort(void);
|
| +void Configlist_sortbasis(void);
|
| +struct config *Configlist_return(void);
|
| +struct config *Configlist_basis(void);
|
| +void Configlist_eat(struct config *);
|
| +void Configlist_reset(void);
|
|
|
| /********* From the file "error.h" ***************************************/
|
| 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};
|
| struct s_options {
|
| - enum { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR,
|
| - OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type;
|
| - char *label;
|
| + enum option_type type;
|
| + const char *label;
|
| char *arg;
|
| - char *message;
|
| + const char *message;
|
| };
|
| -int OptInit(/* char**,struct s_options*,FILE* */);
|
| -int OptNArgs(/* void */);
|
| -char *OptArg(/* int */);
|
| -void OptErr(/* int */);
|
| -void OptPrint(/* void */);
|
| +int OptInit(char**,struct s_options*,FILE*);
|
| +int OptNArgs(void);
|
| +char *OptArg(int);
|
| +void OptErr(int);
|
| +void OptPrint(void);
|
|
|
| /******** From the file "parse.h" *****************************************/
|
| -void Parse(/* struct lemon *lemp */);
|
| +void Parse(struct lemon *lemp);
|
|
|
| /********* From the file "plink.h" ***************************************/
|
| -struct plink *Plink_new(/* void */);
|
| -void Plink_add(/* struct plink **, struct config * */);
|
| -void Plink_copy(/* struct plink **, struct plink * */);
|
| -void Plink_delete(/* struct plink * */);
|
| +struct plink *Plink_new(void);
|
| +void Plink_add(struct plink **, struct config *);
|
| +void Plink_copy(struct plink **, struct plink *);
|
| +void Plink_delete(struct plink *);
|
|
|
| /********** From the file "report.h" *************************************/
|
| -void Reprint(/* struct lemon * */);
|
| -void ReportOutput(/* struct lemon * */);
|
| -void ReportTable(/* struct lemon * */);
|
| -void ReportHeader(/* struct lemon * */);
|
| -void CompressTables(/* struct lemon * */);
|
| -void ResortStates(/* struct lemon * */);
|
| +void Reprint(struct lemon *);
|
| +void ReportOutput(struct lemon *);
|
| +void ReportTable(struct lemon *, int);
|
| +void ReportHeader(struct lemon *);
|
| +void CompressTables(struct lemon *);
|
| +void ResortStates(struct lemon *);
|
|
|
| /********** From the file "set.h" ****************************************/
|
| -void SetSize(/* int N */); /* All sets will be of size N */
|
| -char *SetNew(/* void */); /* A new set for element 0..N */
|
| -void SetFree(/* char* */); /* Deallocate a set */
|
| -
|
| -int SetAdd(/* char*,int */); /* Add element to a set */
|
| -int SetUnion(/* char *A,char *B */); /* A <- A U B, thru element N */
|
| +void SetSize(int); /* All sets will be of size N */
|
| +char *SetNew(void); /* A new set for element 0..N */
|
| +void SetFree(char*); /* Deallocate a set */
|
|
|
| +char *SetNew(void); /* A new set for element 0..N */
|
| +int SetAdd(char*,int); /* Add element to a set */
|
| +int SetUnion(char *,char *); /* A <- A U B, thru element N */
|
| #define SetFind(X,Y) (X[Y]) /* True if Y is in set X */
|
|
|
| /********** From the file "struct.h" *************************************/
|
| @@ -119,23 +149,25 @@ typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean;
|
|
|
| /* Symbols (terminals and nonterminals) of the grammar are stored
|
| ** in the following: */
|
| +enum symbol_type {
|
| + TERMINAL,
|
| + NONTERMINAL,
|
| + MULTITERMINAL
|
| +};
|
| +enum e_assoc {
|
| + LEFT,
|
| + RIGHT,
|
| + NONE,
|
| + UNK
|
| +};
|
| struct symbol {
|
| - char *name; /* Name of the symbol */
|
| + const char *name; /* Name of the symbol */
|
| int index; /* Index number for this symbol */
|
| - enum {
|
| - TERMINAL,
|
| - NONTERMINAL,
|
| - MULTITERMINAL
|
| - } type; /* Symbols are all either TERMINALS or NTs */
|
| + enum symbol_type type; /* Symbols are all either TERMINALS or NTs */
|
| struct rule *rule; /* Linked list of rules of this (if an NT) */
|
| struct symbol *fallback; /* fallback token in case this token doesn't parse */
|
| int prec; /* Precedence if defined (-1 otherwise) */
|
| - enum e_assoc {
|
| - LEFT,
|
| - RIGHT,
|
| - NONE,
|
| - UNK
|
| - } assoc; /* Associativity if precedence is defined */
|
| + enum e_assoc assoc; /* Associativity if precedence is defined */
|
| char *firstset; /* First-set for all rules of this symbol */
|
| Boolean lambda; /* True if NT and can generate an empty string */
|
| int useCnt; /* Number of times used */
|
| @@ -156,14 +188,14 @@ struct symbol {
|
| ** structure. */
|
| struct rule {
|
| struct symbol *lhs; /* Left-hand side of the rule */
|
| - char *lhsalias; /* Alias for the LHS (NULL if none) */
|
| + const char *lhsalias; /* Alias for the LHS (NULL if none) */
|
| int lhsStart; /* True if left-hand side is the start symbol */
|
| int ruleline; /* Line number for the rule */
|
| int nrhs; /* Number of RHS symbols */
|
| struct symbol **rhs; /* The RHS symbols */
|
| - char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
|
| + const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */
|
| int line; /* Line number at which code begins */
|
| - char *code; /* The code executed when this rule is reduced */
|
| + const char *code; /* The code executed when this rule is reduced */
|
| struct symbol *precsym; /* Precedence symbol for this rule */
|
| int index; /* An index number for this rule */
|
| Boolean canReduce; /* True if this rule is ever reduced */
|
| @@ -176,6 +208,10 @@ struct rule {
|
| ** Configurations also contain a follow-set which is a list of terminal
|
| ** symbols which are allowed to immediately follow the end of the rule.
|
| ** Every configuration is recorded as an instance of the following: */
|
| +enum cfgstatus {
|
| + COMPLETE,
|
| + INCOMPLETE
|
| +};
|
| struct config {
|
| struct rule *rp; /* The rule upon which the configuration is based */
|
| int dot; /* The parse point */
|
| @@ -183,29 +219,28 @@ struct config {
|
| struct plink *fplp; /* Follow-set forward propagation links */
|
| struct plink *bplp; /* Follow-set backwards propagation links */
|
| struct state *stp; /* Pointer to state which contains this */
|
| - enum {
|
| - COMPLETE, /* The status is used during followset and */
|
| - INCOMPLETE /* shift computations */
|
| - } status;
|
| + enum cfgstatus status; /* used during followset and shift computations */
|
| struct config *next; /* Next configuration in the state */
|
| struct config *bp; /* The next basis configuration */
|
| };
|
|
|
| +enum e_action {
|
| + SHIFT,
|
| + ACCEPT,
|
| + REDUCE,
|
| + ERROR,
|
| + SSCONFLICT, /* A shift/shift conflict */
|
| + SRCONFLICT, /* Was a reduce, but part of a conflict */
|
| + RRCONFLICT, /* Was a reduce, but part of a conflict */
|
| + SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
|
| + RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
|
| + NOT_USED /* Deleted by compression */
|
| +};
|
| +
|
| /* Every shift or reduce operation is stored as one of the following */
|
| struct action {
|
| struct symbol *sp; /* The look-ahead symbol */
|
| - enum e_action {
|
| - SHIFT,
|
| - ACCEPT,
|
| - REDUCE,
|
| - ERROR,
|
| - SSCONFLICT, /* A shift/shift conflict */
|
| - SRCONFLICT, /* Was a reduce, but part of a conflict */
|
| - RRCONFLICT, /* Was a reduce, but part of a conflict */
|
| - SH_RESOLVED, /* Was a shift. Precedence resolved conflict */
|
| - RD_RESOLVED, /* Was reduce. Precedence resolved conflict */
|
| - NOT_USED /* Deleted by compression */
|
| - } type;
|
| + enum e_action type;
|
| union {
|
| struct state *stp; /* The new state, if a shift */
|
| struct rule *rp; /* The rule, if a reduce */
|
| @@ -292,41 +327,41 @@ struct lemon {
|
| /*
|
| ** Code for processing tables in the LEMON parser generator.
|
| */
|
| -
|
| /* Routines for handling a strings */
|
|
|
| -char *Strsafe();
|
| +const char *Strsafe(const char *);
|
|
|
| -void Strsafe_init(/* void */);
|
| -int Strsafe_insert(/* char * */);
|
| -char *Strsafe_find(/* char * */);
|
| +void Strsafe_init(void);
|
| +int Strsafe_insert(const char *);
|
| +const char *Strsafe_find(const char *);
|
|
|
| /* Routines for handling symbols of the grammar */
|
|
|
| -struct symbol *Symbol_new();
|
| -int Symbolcmpp(/* struct symbol **, struct symbol ** */);
|
| -void Symbol_init(/* void */);
|
| -int Symbol_insert(/* struct symbol *, char * */);
|
| -struct symbol *Symbol_find(/* char * */);
|
| -struct symbol *Symbol_Nth(/* int */);
|
| -int Symbol_count(/* */);
|
| -struct symbol **Symbol_arrayof(/* */);
|
| +struct symbol *Symbol_new(const char *);
|
| +int Symbolcmpp(const void *, const void *);
|
| +void Symbol_init(void);
|
| +int Symbol_insert(struct symbol *, const char *);
|
| +struct symbol *Symbol_find(const char *);
|
| +struct symbol *Symbol_Nth(int);
|
| +int Symbol_count(void);
|
| +struct symbol **Symbol_arrayof(void);
|
|
|
| /* Routines to manage the state table */
|
|
|
| -int Configcmp(/* struct config *, struct config * */);
|
| -struct state *State_new();
|
| -void State_init(/* void */);
|
| -int State_insert(/* struct state *, struct config * */);
|
| -struct state *State_find(/* struct config * */);
|
| +int Configcmp(const char *, const char *);
|
| +struct state *State_new(void);
|
| +void State_init(void);
|
| +int State_insert(struct state *, struct config *);
|
| +struct state *State_find(struct config *);
|
| struct state **State_arrayof(/* */);
|
|
|
| /* Routines used for efficiency in Configlist_add */
|
|
|
| -void Configtable_init(/* void */);
|
| -int Configtable_insert(/* struct config * */);
|
| -struct config *Configtable_find(/* struct config * */);
|
| -void Configtable_clear(/* int(*)(struct config *) */);
|
| +void Configtable_init(void);
|
| +int Configtable_insert(struct config *);
|
| +struct config *Configtable_find(struct config *);
|
| +void Configtable_clear(int(*)(struct config *));
|
| +
|
| /****************** From the file "action.c" *******************************/
|
| /*
|
| ** Routines processing parser actions in the LEMON parser generator.
|
| @@ -335,7 +370,7 @@ void Configtable_clear(/* int(*)(struct config *) */);
|
| /* Allocate a new parser action */
|
| static struct action *Action_new(void){
|
| static struct action *freelist = 0;
|
| - struct action *new;
|
| + struct action *newaction;
|
|
|
| if( freelist==0 ){
|
| int i;
|
| @@ -348,9 +383,9 @@ static struct action *Action_new(void){
|
| for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
|
| freelist[amt-1].next = 0;
|
| }
|
| - new = freelist;
|
| + newaction = freelist;
|
| freelist = freelist->next;
|
| - return new;
|
| + return newaction;
|
| }
|
|
|
| /* Compare two actions for sorting purposes. Return negative, zero, or
|
| @@ -369,6 +404,9 @@ static int actioncmp(
|
| if( rc==0 && ap1->type==REDUCE ){
|
| rc = ap1->x.rp->index - ap2->x.rp->index;
|
| }
|
| + if( rc==0 ){
|
| + rc = (int) (ap2 - ap1);
|
| + }
|
| return rc;
|
| }
|
|
|
| @@ -381,22 +419,22 @@ static struct action *Action_sort(
|
| return ap;
|
| }
|
|
|
| -void Action_add(app,type,sp,arg)
|
| -struct action **app;
|
| -enum e_action type;
|
| -struct symbol *sp;
|
| -char *arg;
|
| -{
|
| - struct action *new;
|
| - new = Action_new();
|
| - new->next = *app;
|
| - *app = new;
|
| - new->type = type;
|
| - new->sp = sp;
|
| +void Action_add(
|
| + struct action **app,
|
| + enum e_action type,
|
| + struct symbol *sp,
|
| + char *arg
|
| +){
|
| + struct action *newaction;
|
| + newaction = Action_new();
|
| + newaction->next = *app;
|
| + *app = newaction;
|
| + newaction->type = type;
|
| + newaction->sp = sp;
|
| if( type==SHIFT ){
|
| - new->x.stp = (struct state *)arg;
|
| + newaction->x.stp = (struct state *)arg;
|
| }else{
|
| - new->x.rp = (struct rule *)arg;
|
| + newaction->x.rp = (struct rule *)arg;
|
| }
|
| }
|
| /********************** New code to implement the "acttab" module ***********/
|
| @@ -406,16 +444,34 @@ char *arg;
|
|
|
| /*
|
| ** The state of the yy_action table under construction is an instance of
|
| -** the following structure
|
| +** the following structure.
|
| +**
|
| +** The yy_action table maps the pair (state_number, lookahead) into an
|
| +** action_number. The table is an array of integers pairs. The state_number
|
| +** determines an initial offset into the yy_action array. The lookahead
|
| +** value is then added to this initial offset to get an index X into the
|
| +** yy_action array. If the aAction[X].lookahead equals the value of the
|
| +** of the lookahead input, then the value of the action_number output is
|
| +** aAction[X].action. If the lookaheads do not match then the
|
| +** default action for the state_number is returned.
|
| +**
|
| +** All actions associated with a single state_number are first entered
|
| +** into aLookahead[] using multiple calls to acttab_action(). Then the
|
| +** actions for that single state_number are placed into the aAction[]
|
| +** array with a single call to acttab_insert(). The acttab_insert() call
|
| +** also resets the aLookahead[] array in preparation for the next
|
| +** state number.
|
| */
|
| +struct lookahead_action {
|
| + int lookahead; /* Value of the lookahead token */
|
| + int action; /* Action to take on the given lookahead */
|
| +};
|
| typedef struct acttab acttab;
|
| struct acttab {
|
| int nAction; /* Number of used slots in aAction[] */
|
| int nActionAlloc; /* Slots allocated for aAction[] */
|
| - struct {
|
| - int lookahead; /* Value of the lookahead token */
|
| - int action; /* Action to take on the given lookahead */
|
| - } *aAction, /* The yy_action[] table under construction */
|
| + struct lookahead_action
|
| + *aAction, /* The yy_action[] table under construction */
|
| *aLookahead; /* A single new transaction set */
|
| int mnLookahead; /* Minimum aLookahead[].lookahead */
|
| int mnAction; /* Action associated with mnLookahead */
|
| @@ -442,7 +498,7 @@ void acttab_free(acttab *p){
|
|
|
| /* Allocate a new acttab structure */
|
| acttab *acttab_alloc(void){
|
| - acttab *p = calloc( 1, sizeof(*p) );
|
| + acttab *p = (acttab *) calloc( 1, sizeof(*p) );
|
| if( p==0 ){
|
| fprintf(stderr,"Unable to allocate memory for a new acttab.");
|
| exit(1);
|
| @@ -451,12 +507,15 @@ acttab *acttab_alloc(void){
|
| return p;
|
| }
|
|
|
| -/* Add a new action to the current transaction set
|
| +/* Add a new action to the current transaction set.
|
| +**
|
| +** This routine is called once for each lookahead for a particular
|
| +** state.
|
| */
|
| void acttab_action(acttab *p, int lookahead, int action){
|
| if( p->nLookahead>=p->nLookaheadAlloc ){
|
| p->nLookaheadAlloc += 25;
|
| - p->aLookahead = realloc( p->aLookahead,
|
| + p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead,
|
| sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
|
| if( p->aLookahead==0 ){
|
| fprintf(stderr,"malloc failed\n");
|
| @@ -498,7 +557,7 @@ int acttab_insert(acttab *p){
|
| if( p->nAction + n >= p->nActionAlloc ){
|
| int oldAlloc = p->nActionAlloc;
|
| p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
|
| - p->aAction = realloc( p->aAction,
|
| + p->aAction = (struct lookahead_action *) realloc( p->aAction,
|
| sizeof(p->aAction[0])*p->nActionAlloc);
|
| if( p->aAction==0 ){
|
| fprintf(stderr,"malloc failed\n");
|
| @@ -510,28 +569,16 @@ int acttab_insert(acttab *p){
|
| }
|
| }
|
|
|
| - /* Scan the existing action table looking for an offset where we can
|
| - ** insert the current transaction set. Fall out of the loop when that
|
| - ** offset is found. In the worst case, we fall out of the loop when
|
| - ** i reaches p->nAction, which means we append the new transaction set.
|
| + /* Scan the existing action table looking for an offset that is a
|
| + ** duplicate of the current transaction set. Fall out of the loop
|
| + ** if and when the duplicate is found.
|
| **
|
| ** i is the index in p->aAction[] where p->mnLookahead is inserted.
|
| */
|
| - for(i=0; i<p->nAction+p->mnLookahead; i++){
|
| - if( p->aAction[i].lookahead<0 ){
|
| - for(j=0; j<p->nLookahead; j++){
|
| - k = p->aLookahead[j].lookahead - p->mnLookahead + i;
|
| - if( k<0 ) break;
|
| - if( p->aAction[k].lookahead>=0 ) break;
|
| - }
|
| - if( j<p->nLookahead ) continue;
|
| - for(j=0; j<p->nAction; j++){
|
| - if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
|
| - }
|
| - if( j==p->nAction ){
|
| - break; /* Fits in empty slots */
|
| - }
|
| - }else if( p->aAction[i].lookahead==p->mnLookahead ){
|
| + for(i=p->nAction-1; i>=0; i--){
|
| + if( p->aAction[i].lookahead==p->mnLookahead ){
|
| + /* All lookaheads and actions in the aLookahead[] transaction
|
| + ** must match against the candidate aAction[i] entry. */
|
| if( p->aAction[i].action!=p->mnAction ) continue;
|
| for(j=0; j<p->nLookahead; j++){
|
| k = p->aLookahead[j].lookahead - p->mnLookahead + i;
|
| @@ -540,13 +587,43 @@ int acttab_insert(acttab *p){
|
| if( p->aLookahead[j].action!=p->aAction[k].action ) break;
|
| }
|
| if( j<p->nLookahead ) continue;
|
| +
|
| + /* No possible lookahead value that is not in the aLookahead[]
|
| + ** transaction is allowed to match aAction[i] */
|
| n = 0;
|
| for(j=0; j<p->nAction; j++){
|
| if( p->aAction[j].lookahead<0 ) continue;
|
| if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
|
| }
|
| if( n==p->nLookahead ){
|
| - break; /* Same as a prior transaction set */
|
| + break; /* An exact match is found at offset i */
|
| + }
|
| + }
|
| + }
|
| +
|
| + /* If no existing offsets exactly match the current transaction, find an
|
| + ** an empty offset in the aAction[] table in which we can add the
|
| + ** aLookahead[] transaction.
|
| + */
|
| + if( i<0 ){
|
| + /* 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. */
|
| + for(i=0; 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;
|
| + if( k<0 ) break;
|
| + if( p->aAction[k].lookahead>=0 ) break;
|
| + }
|
| + if( j<p->nLookahead ) continue;
|
| + for(j=0; j<p->nAction; j++){
|
| + if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
|
| + }
|
| + if( j==p->nAction ){
|
| + break; /* Fits in empty slots */
|
| + }
|
| }
|
| }
|
| }
|
| @@ -578,8 +655,7 @@ int acttab_insert(acttab *p){
|
| ** are not RHS symbols with a defined precedence, the precedence
|
| ** symbol field is left blank.
|
| */
|
| -void FindRulePrecedences(xp)
|
| -struct lemon *xp;
|
| +void FindRulePrecedences(struct lemon *xp)
|
| {
|
| struct rule *rp;
|
| for(rp=xp->rule; rp; rp=rp->next){
|
| @@ -608,8 +684,7 @@ struct lemon *xp;
|
| ** The first set is the set of all terminal symbols which can begin
|
| ** a string generated by that nonterminal.
|
| */
|
| -void FindFirstSets(lemp)
|
| -struct lemon *lemp;
|
| +void FindFirstSets(struct lemon *lemp)
|
| {
|
| int i, j;
|
| struct rule *rp;
|
| @@ -670,9 +745,8 @@ struct lemon *lemp;
|
| ** are added to between some states so that the LR(1) follow sets
|
| ** can be computed later.
|
| */
|
| -PRIVATE struct state *getstate(/* struct lemon * */); /* forward reference */
|
| -void FindStates(lemp)
|
| -struct lemon *lemp;
|
| +PRIVATE struct state *getstate(struct lemon *); /* forward reference */
|
| +void FindStates(struct lemon *lemp)
|
| {
|
| struct symbol *sp;
|
| struct rule *rp;
|
| @@ -730,9 +804,8 @@ does not work properly.",sp->name);
|
| /* Return a pointer to a state which is described by the configuration
|
| ** list which has been built from calls to Configlist_add.
|
| */
|
| -PRIVATE void buildshifts(/* struct lemon *, struct state * */); /* Forwd ref */
|
| -PRIVATE struct state *getstate(lemp)
|
| -struct lemon *lemp;
|
| +PRIVATE void buildshifts(struct lemon *, struct state *); /* Forwd ref */
|
| +PRIVATE struct state *getstate(struct lemon *lemp)
|
| {
|
| struct config *cfp, *bp;
|
| struct state *stp;
|
| @@ -776,9 +849,7 @@ struct lemon *lemp;
|
| /*
|
| ** Return true if two symbols are the same.
|
| */
|
| -int same_symbol(a,b)
|
| -struct symbol *a;
|
| -struct symbol *b;
|
| +int same_symbol(struct symbol *a, struct symbol *b)
|
| {
|
| int i;
|
| if( a==b ) return 1;
|
| @@ -794,13 +865,11 @@ struct symbol *b;
|
| /* Construct all successor states to the given state. A "successor"
|
| ** state is any state which can be reached by a shift action.
|
| */
|
| -PRIVATE void buildshifts(lemp,stp)
|
| -struct lemon *lemp;
|
| -struct state *stp; /* The state from which successors are computed */
|
| +PRIVATE void buildshifts(struct lemon *lemp, struct state *stp)
|
| {
|
| struct config *cfp; /* For looping thru the config closure of "stp" */
|
| struct config *bcfp; /* For the inner loop on config closure of "stp" */
|
| - struct config *new; /* */
|
| + struct config *newcfg; /* */
|
| struct symbol *sp; /* Symbol following the dot in configuration "cfp" */
|
| struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */
|
| struct state *newstp; /* A pointer to a successor state */
|
| @@ -825,8 +894,8 @@ struct state *stp; /* The state from which successors are computed */
|
| bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */
|
| if( !same_symbol(bsp,sp) ) continue; /* Must be same as for "cfp" */
|
| bcfp->status = COMPLETE; /* Mark this config as used */
|
| - new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
|
| - Plink_add(&new->bplp,bcfp);
|
| + newcfg = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
|
| + Plink_add(&newcfg->bplp,bcfp);
|
| }
|
|
|
| /* Get a pointer to the state described by the basis configuration set
|
| @@ -849,8 +918,7 @@ struct state *stp; /* The state from which successors are computed */
|
| /*
|
| ** Construct the propagation links
|
| */
|
| -void FindLinks(lemp)
|
| -struct lemon *lemp;
|
| +void FindLinks(struct lemon *lemp)
|
| {
|
| int i;
|
| struct config *cfp, *other;
|
| @@ -885,8 +953,7 @@ struct lemon *lemp;
|
| ** A followset is the set of all symbols which can come immediately
|
| ** after a configuration.
|
| */
|
| -void FindFollowSets(lemp)
|
| -struct lemon *lemp;
|
| +void FindFollowSets(struct lemon *lemp)
|
| {
|
| int i;
|
| struct config *cfp;
|
| @@ -918,12 +985,11 @@ struct lemon *lemp;
|
| }while( progress );
|
| }
|
|
|
| -static int resolve_conflict();
|
| +static int resolve_conflict(struct action *,struct action *, struct symbol *);
|
|
|
| /* Compute the reduce actions, and resolve conflicts.
|
| */
|
| -void FindActions(lemp)
|
| -struct lemon *lemp;
|
| +void FindActions(struct lemon *lemp)
|
| {
|
| int i,j;
|
| struct config *cfp;
|
| @@ -1006,11 +1072,11 @@ struct lemon *lemp;
|
| ** If either action is a SHIFT, then it must be apx. This
|
| ** function won't work if apx->type==REDUCE and apy->type==SHIFT.
|
| */
|
| -static int resolve_conflict(apx,apy,errsym)
|
| -struct action *apx;
|
| -struct action *apy;
|
| -struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
|
| -{
|
| +static int resolve_conflict(
|
| + struct action *apx,
|
| + struct action *apy,
|
| + struct symbol *errsym /* The error symbol (if defined. NULL otherwise) */
|
| +){
|
| struct symbol *spx, *spy;
|
| int errcnt = 0;
|
| assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */
|
| @@ -1025,7 +1091,7 @@ struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */
|
| /* Not enough precedence information. */
|
| apy->type = SRCONFLICT;
|
| errcnt++;
|
| - }else if( spx->prec>spy->prec ){ /* Lower precedence wins */
|
| + }else if( spx->prec>spy->prec ){ /* higher precedence wins */
|
| apy->type = RD_RESOLVED;
|
| }else if( spx->prec<spy->prec ){
|
| apx->type = SH_RESOLVED;
|
| @@ -1083,7 +1149,7 @@ static struct config **basisend = 0; /* End of list of basis configs */
|
|
|
| /* Return a pointer to a new configuration */
|
| PRIVATE struct config *newconfig(){
|
| - struct config *new;
|
| + struct config *newcfg;
|
| if( freelist==0 ){
|
| int i;
|
| int amt = 3;
|
| @@ -1095,14 +1161,13 @@ PRIVATE struct config *newconfig(){
|
| for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
|
| freelist[amt-1].next = 0;
|
| }
|
| - new = freelist;
|
| + newcfg = freelist;
|
| freelist = freelist->next;
|
| - return new;
|
| + return newcfg;
|
| }
|
|
|
| /* The configuration "old" is no longer used */
|
| -PRIVATE void deleteconfig(old)
|
| -struct config *old;
|
| +PRIVATE void deleteconfig(struct config *old)
|
| {
|
| old->next = freelist;
|
| freelist = old;
|
| @@ -1129,10 +1194,10 @@ void Configlist_reset(){
|
| }
|
|
|
| /* Add another configuration to the configuration list */
|
| -struct config *Configlist_add(rp,dot)
|
| -struct rule *rp; /* The rule */
|
| -int dot; /* Index into the RHS of the rule where the dot goes */
|
| -{
|
| +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 );
|
| @@ -1156,9 +1221,7 @@ int dot; /* Index into the RHS of the rule where the dot goes */
|
| }
|
|
|
| /* Add a basis configuration to the configuration list */
|
| -struct config *Configlist_addbasis(rp,dot)
|
| -struct rule *rp;
|
| -int dot;
|
| +struct config *Configlist_addbasis(struct rule *rp, int dot)
|
| {
|
| struct config *cfp, model;
|
|
|
| @@ -1186,8 +1249,7 @@ int dot;
|
| }
|
|
|
| /* Compute the closure of the configuration list */
|
| -void Configlist_closure(lemp)
|
| -struct lemon *lemp;
|
| +void Configlist_closure(struct lemon *lemp)
|
| {
|
| struct config *cfp, *newcfp;
|
| struct rule *rp, *newrp;
|
| @@ -1266,8 +1328,7 @@ struct config *Configlist_basis(){
|
| }
|
|
|
| /* Free all elements of the given configuration list */
|
| -void Configlist_eat(cfp)
|
| -struct config *cfp;
|
| +void Configlist_eat(struct config *cfp)
|
| {
|
| struct config *nextcfp;
|
| for(; cfp; cfp=nextcfp){
|
| @@ -1284,72 +1345,13 @@ struct config *cfp;
|
| ** Code for printing error message.
|
| */
|
|
|
| -/* Find a good place to break "msg" so that its length is at least "min"
|
| -** but no more than "max". Make the point as close to max as possible.
|
| -*/
|
| -static int findbreak(msg,min,max)
|
| -char *msg;
|
| -int min;
|
| -int max;
|
| -{
|
| - int i,spot;
|
| - char c;
|
| - for(i=spot=min; i<=max; i++){
|
| - c = msg[i];
|
| - if( c=='\t' ) msg[i] = ' ';
|
| - if( c=='\n' ){ msg[i] = ' '; spot = i; break; }
|
| - if( c==0 ){ spot = i; break; }
|
| - if( c=='-' && i<max-1 ) spot = i+1;
|
| - if( c==' ' ) spot = i;
|
| - }
|
| - return spot;
|
| -}
|
| -
|
| -/*
|
| -** The error message is split across multiple lines if necessary. The
|
| -** splits occur at a space, if there is a space available near the end
|
| -** of the line.
|
| -*/
|
| -#define ERRMSGSIZE 10000 /* Hope this is big enough. No way to error check */
|
| -#define LINEWIDTH 79 /* Max width of any output line */
|
| -#define PREFIXLIMIT 30 /* Max width of the prefix on each line */
|
| void ErrorMsg(const char *filename, int lineno, const char *format, ...){
|
| - char errmsg[ERRMSGSIZE];
|
| - char prefix[PREFIXLIMIT+10];
|
| - int errmsgsize;
|
| - int prefixsize;
|
| - int availablewidth;
|
| va_list ap;
|
| - int end, restart, base;
|
| -
|
| + fprintf(stderr, "%s:%d: ", filename, lineno);
|
| va_start(ap, format);
|
| - /* Prepare a prefix to be prepended to every output line */
|
| - if( lineno>0 ){
|
| - sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno);
|
| - }else{
|
| - sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename);
|
| - }
|
| - prefixsize = lemonStrlen(prefix);
|
| - availablewidth = LINEWIDTH - prefixsize;
|
| -
|
| - /* Generate the error message */
|
| - vsprintf(errmsg,format,ap);
|
| + vfprintf(stderr,format,ap);
|
| va_end(ap);
|
| - errmsgsize = lemonStrlen(errmsg);
|
| - /* Remove trailing '\n's from the error message. */
|
| - while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){
|
| - errmsg[--errmsgsize] = 0;
|
| - }
|
| -
|
| - /* Print the error message */
|
| - base = 0;
|
| - while( errmsg[base]!=0 ){
|
| - end = restart = findbreak(&errmsg[base],0,availablewidth);
|
| - restart += base;
|
| - while( errmsg[restart]==' ' ) restart++;
|
| - fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]);
|
| - base = restart;
|
| - }
|
| + fprintf(stderr, "\n");
|
| }
|
| /**************** From the file "main.c" ************************************/
|
| /*
|
| @@ -1373,13 +1375,13 @@ static char **azDefine = 0; /* Name of the -D macros */
|
| static void handle_D_option(char *z){
|
| char **paz;
|
| nDefine++;
|
| - azDefine = realloc(azDefine, sizeof(azDefine[0])*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 = malloc( lemonStrlen(z)+1 );
|
| + *paz = (char *) malloc( lemonStrlen(z)+1 );
|
| if( *paz==0 ){
|
| fprintf(stderr,"out of memory\n");
|
| exit(1);
|
| @@ -1389,11 +1391,17 @@ static void handle_D_option(char *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(argc,argv)
|
| -int argc;
|
| -char **argv;
|
| +int main(int argc, char **argv)
|
| {
|
| static int version = 0;
|
| static int rpflag = 0;
|
| @@ -1403,22 +1411,30 @@ char **argv;
|
| 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");
|
| @@ -1456,8 +1472,7 @@ char **argv;
|
| Symbol_new("{default}");
|
| lem.symbols = Symbol_arrayof();
|
| for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
|
| - qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
|
| - (int(*)())Symbolcmpp);
|
| + qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*), Symbolcmpp);
|
| for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
|
| for(i=1; isupper(lem.symbols[i]->name[0]); i++);
|
| lem.nterminal = i;
|
| @@ -1495,8 +1510,9 @@ char **argv;
|
| if( compress==0 ) CompressTables(&lem);
|
|
|
| /* Reorder and renumber the states so that states with fewer choices
|
| - ** occur at the end. */
|
| - ResortStates(&lem);
|
| + ** occur at the end. This is an optimization that helps make the
|
| + ** generated parser tables smaller. */
|
| + if( noResort==0 ) ResortStates(&lem);
|
|
|
| /* Generate a report of the parser generated. (the "y.output" file) */
|
| if( !quiet ) ReportOutput(&lem);
|
| @@ -1515,11 +1531,15 @@ char **argv;
|
| printf(" %d states, %d parser table entries, %d conflicts\n",
|
| lem.nstate, lem.tablesize, lem.nconflict);
|
| }
|
| - if( lem.nconflict ){
|
| + if( lem.nconflict > 0 ){
|
| fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
|
| }
|
| - exit(lem.errorcnt + lem.nconflict);
|
| - return (lem.errorcnt + lem.nconflict);
|
| +
|
| + /* return 0 on success, 1 on failure. */
|
| + exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0;
|
| + successful_exit = (exitcode == 0);
|
| + exit(exitcode);
|
| + return (exitcode);
|
| }
|
| /******************** From the file "msort.c" *******************************/
|
| /*
|
| @@ -1578,7 +1598,7 @@ static char *merge(
|
| }else if( b==0 ){
|
| head = a;
|
| }else{
|
| - if( (*cmp)(a,b)<0 ){
|
| + if( (*cmp)(a,b)<=0 ){
|
| ptr = a;
|
| a = NEXT(a);
|
| }else{
|
| @@ -1587,7 +1607,7 @@ static char *merge(
|
| }
|
| head = ptr;
|
| while( a && b ){
|
| - if( (*cmp)(a,b)<0 ){
|
| + if( (*cmp)(a,b)<=0 ){
|
| NEXT(ptr) = a;
|
| ptr = a;
|
| a = NEXT(a);
|
| @@ -1639,7 +1659,7 @@ static char *msort(
|
| set[i] = ep;
|
| }
|
| ep = 0;
|
| - for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset);
|
| + for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(set[i],ep,cmp,offset);
|
| return ep;
|
| }
|
| /************************ From the file "option.c" **************************/
|
| @@ -1653,10 +1673,7 @@ static FILE *errstream;
|
| ** Print the command line with a carrot pointing to the k-th character
|
| ** of the n-th field.
|
| */
|
| -static void errline(n,k,err)
|
| -int n;
|
| -int k;
|
| -FILE *err;
|
| +static void errline(int n, int k, FILE *err)
|
| {
|
| int spcnt, i;
|
| if( argv[0] ) fprintf(err,"%s",argv[0]);
|
| @@ -1678,8 +1695,7 @@ FILE *err;
|
| ** Return the index of the N-th non-switch argument. Return -1
|
| ** if N is out of range.
|
| */
|
| -static int argindex(n)
|
| -int n;
|
| +static int argindex(int n)
|
| {
|
| int i;
|
| int dashdash = 0;
|
| @@ -1700,9 +1716,7 @@ static char emsg[] = "Command line syntax error: ";
|
| /*
|
| ** Process a flag command line argument.
|
| */
|
| -static int handleflags(i,err)
|
| -int i;
|
| -FILE *err;
|
| +static int handleflags(int i, FILE *err)
|
| {
|
| int v;
|
| int errcnt = 0;
|
| @@ -1720,9 +1734,9 @@ FILE *err;
|
| }else if( op[j].type==OPT_FLAG ){
|
| *((int*)op[j].arg) = v;
|
| }else if( op[j].type==OPT_FFLAG ){
|
| - (*(void(*)())(op[j].arg))(v);
|
| + (*(void(*)(int))(op[j].arg))(v);
|
| }else if( op[j].type==OPT_FSTR ){
|
| - (*(void(*)())(op[j].arg))(&argv[i][2]);
|
| + (*(void(*)(char *))(op[j].arg))(&argv[i][2]);
|
| }else{
|
| if( err ){
|
| fprintf(err,"%smissing argument on switch.\n",emsg);
|
| @@ -1736,9 +1750,7 @@ FILE *err;
|
| /*
|
| ** Process a command line switch which has an argument.
|
| */
|
| -static int handleswitch(i,err)
|
| -int i;
|
| -FILE *err;
|
| +static int handleswitch(int i, FILE *err)
|
| {
|
| int lv = 0;
|
| double dv = 0.0;
|
| @@ -1805,29 +1817,26 @@ FILE *err;
|
| *(double*)(op[j].arg) = dv;
|
| break;
|
| case OPT_FDBL:
|
| - (*(void(*)())(op[j].arg))(dv);
|
| + (*(void(*)(double))(op[j].arg))(dv);
|
| break;
|
| case OPT_INT:
|
| *(int*)(op[j].arg) = lv;
|
| break;
|
| case OPT_FINT:
|
| - (*(void(*)())(op[j].arg))((int)lv);
|
| + (*(void(*)(int))(op[j].arg))((int)lv);
|
| break;
|
| case OPT_STR:
|
| *(char**)(op[j].arg) = sv;
|
| break;
|
| case OPT_FSTR:
|
| - (*(void(*)())(op[j].arg))(sv);
|
| + (*(void(*)(char *))(op[j].arg))(sv);
|
| break;
|
| }
|
| }
|
| return errcnt;
|
| }
|
|
|
| -int OptInit(a,o,err)
|
| -char **a;
|
| -struct s_options *o;
|
| -FILE *err;
|
| +int OptInit(char **a, struct s_options *o, FILE *err)
|
| {
|
| int errcnt = 0;
|
| argv = a;
|
| @@ -1864,16 +1873,14 @@ int OptNArgs(){
|
| return cnt;
|
| }
|
|
|
| -char *OptArg(n)
|
| -int n;
|
| +char *OptArg(int n)
|
| {
|
| int i;
|
| i = argindex(n);
|
| return i>=0 ? argv[i] : 0;
|
| }
|
|
|
| -void OptErr(n)
|
| -int n;
|
| +void OptErr(int n)
|
| {
|
| int i;
|
| i = argindex(n);
|
| @@ -1935,42 +1942,43 @@ void OptPrint(){
|
| */
|
|
|
| /* The state of the parser */
|
| +enum e_state {
|
| + INITIALIZE,
|
| + WAITING_FOR_DECL_OR_RULE,
|
| + WAITING_FOR_DECL_KEYWORD,
|
| + WAITING_FOR_DECL_ARG,
|
| + WAITING_FOR_PRECEDENCE_SYMBOL,
|
| + WAITING_FOR_ARROW,
|
| + IN_RHS,
|
| + LHS_ALIAS_1,
|
| + LHS_ALIAS_2,
|
| + LHS_ALIAS_3,
|
| + RHS_ALIAS_1,
|
| + RHS_ALIAS_2,
|
| + PRECEDENCE_MARK_1,
|
| + PRECEDENCE_MARK_2,
|
| + RESYNC_AFTER_RULE_ERROR,
|
| + RESYNC_AFTER_DECL_ERROR,
|
| + WAITING_FOR_DESTRUCTOR_SYMBOL,
|
| + WAITING_FOR_DATATYPE_SYMBOL,
|
| + WAITING_FOR_FALLBACK_ID,
|
| + WAITING_FOR_WILDCARD_ID
|
| +};
|
| struct pstate {
|
| char *filename; /* Name of the input file */
|
| int tokenlineno; /* Linenumber at which current token starts */
|
| int errorcnt; /* Number of errors so far */
|
| char *tokenstart; /* Text of current token */
|
| struct lemon *gp; /* Global state vector */
|
| - enum e_state {
|
| - INITIALIZE,
|
| - WAITING_FOR_DECL_OR_RULE,
|
| - WAITING_FOR_DECL_KEYWORD,
|
| - WAITING_FOR_DECL_ARG,
|
| - WAITING_FOR_PRECEDENCE_SYMBOL,
|
| - WAITING_FOR_ARROW,
|
| - IN_RHS,
|
| - LHS_ALIAS_1,
|
| - LHS_ALIAS_2,
|
| - LHS_ALIAS_3,
|
| - RHS_ALIAS_1,
|
| - RHS_ALIAS_2,
|
| - PRECEDENCE_MARK_1,
|
| - PRECEDENCE_MARK_2,
|
| - RESYNC_AFTER_RULE_ERROR,
|
| - RESYNC_AFTER_DECL_ERROR,
|
| - WAITING_FOR_DESTRUCTOR_SYMBOL,
|
| - WAITING_FOR_DATATYPE_SYMBOL,
|
| - WAITING_FOR_FALLBACK_ID,
|
| - WAITING_FOR_WILDCARD_ID
|
| - } state; /* The state of the parser */
|
| + enum e_state state; /* The state of the parser */
|
| struct symbol *fallback; /* The fallback token */
|
| struct symbol *lhs; /* Left-hand side of current rule */
|
| - char *lhsalias; /* Alias for the LHS */
|
| + const char *lhsalias; /* Alias for the LHS */
|
| int nrhs; /* Number of right-hand side symbols seen */
|
| struct symbol *rhs[MAXRHS]; /* RHS symbols */
|
| - char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
|
| + const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */
|
| struct rule *prevrule; /* Previous rule parsed */
|
| - char *declkeyword; /* Keyword of a declaration */
|
| + const char *declkeyword; /* Keyword of a declaration */
|
| char **declargslot; /* Where the declaration argument should be put */
|
| int insertLineMacro; /* Add #line before declaration insert */
|
| int *decllinenoslot; /* Where to write declaration line number */
|
| @@ -1981,10 +1989,9 @@ struct pstate {
|
| };
|
|
|
| /* Parse a single token */
|
| -static void parseonetoken(psp)
|
| -struct pstate *psp;
|
| +static void parseonetoken(struct pstate *psp)
|
| {
|
| - char *x;
|
| + const char *x;
|
| x = Strsafe(psp->tokenstart); /* Save the token permanently */
|
| #if 0
|
| printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
|
| @@ -2116,7 +2123,7 @@ to follow the previous rule.");
|
| int i;
|
| rp->ruleline = psp->tokenlineno;
|
| rp->rhs = (struct symbol**)&rp[1];
|
| - rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]);
|
| + rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]);
|
| for(i=0; i<psp->nrhs; i++){
|
| rp->rhs[i] = psp->rhs[i];
|
| rp->rhsalias[i] = psp->alias[i];
|
| @@ -2155,17 +2162,18 @@ to follow the previous rule.");
|
| struct symbol *msp = psp->rhs[psp->nrhs-1];
|
| if( msp->type!=MULTITERMINAL ){
|
| struct symbol *origsp = msp;
|
| - msp = calloc(1,sizeof(*msp));
|
| + msp = (struct symbol *) calloc(1,sizeof(*msp));
|
| memset(msp, 0, sizeof(*msp));
|
| msp->type = MULTITERMINAL;
|
| msp->nsubsym = 1;
|
| - msp->subsym = calloc(1,sizeof(struct symbol*));
|
| + msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*));
|
| msp->subsym[0] = origsp;
|
| msp->name = origsp->name;
|
| psp->rhs[psp->nrhs-1] = msp;
|
| }
|
| msp->nsubsym++;
|
| - msp->subsym = realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym);
|
| + msp->subsym = (struct symbol **) realloc(msp->subsym,
|
| + sizeof(struct symbol*)*msp->nsubsym);
|
| msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
|
| if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| @@ -2284,7 +2292,7 @@ to follow the previous rule.");
|
| case WAITING_FOR_DESTRUCTOR_SYMBOL:
|
| if( !isalpha(x[0]) ){
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| - "Symbol name missing after %destructor keyword");
|
| + "Symbol name missing after %%destructor keyword");
|
| psp->errorcnt++;
|
| psp->state = RESYNC_AFTER_DECL_ERROR;
|
| }else{
|
| @@ -2298,14 +2306,24 @@ to follow the previous rule.");
|
| case WAITING_FOR_DATATYPE_SYMBOL:
|
| if( !isalpha(x[0]) ){
|
| ErrorMsg(psp->filename,psp->tokenlineno,
|
| - "Symbol name missing after %destructor keyword");
|
| + "Symbol name missing after %%type keyword");
|
| psp->errorcnt++;
|
| psp->state = RESYNC_AFTER_DECL_ERROR;
|
| }else{
|
| - struct symbol *sp = Symbol_new(x);
|
| - psp->declargslot = &sp->datatype;
|
| - psp->insertLineMacro = 0;
|
| - psp->state = WAITING_FOR_DECL_ARG;
|
| + struct symbol *sp = Symbol_find(x);
|
| + if((sp) && (sp->datatype)){
|
| + ErrorMsg(psp->filename,psp->tokenlineno,
|
| + "Symbol %%type \"%s\" already defined", x);
|
| + psp->errorcnt++;
|
| + psp->state = RESYNC_AFTER_DECL_ERROR;
|
| + }else{
|
| + if (!sp){
|
| + sp = Symbol_new(x);
|
| + }
|
| + psp->declargslot = &sp->datatype;
|
| + psp->insertLineMacro = 0;
|
| + psp->state = WAITING_FOR_DECL_ARG;
|
| + }
|
| }
|
| break;
|
| case WAITING_FOR_PRECEDENCE_SYMBOL:
|
| @@ -2330,7 +2348,8 @@ to follow the previous rule.");
|
| break;
|
| case WAITING_FOR_DECL_ARG:
|
| if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){
|
| - char *zOld, *zNew, *zBuf, *z;
|
| + const char *zOld, *zNew;
|
| + char *zBuf, *z;
|
| int nOld, n, nLine, nNew, nBack;
|
| int addLineMacro;
|
| char zLine[50];
|
| @@ -2354,8 +2373,8 @@ to follow the previous rule.");
|
| nLine = lemonStrlen(zLine);
|
| n += nLine + lemonStrlen(psp->filename) + nBack;
|
| }
|
| - *psp->declargslot = zBuf = realloc(*psp->declargslot, n);
|
| - zBuf += nOld;
|
| + *psp->declargslot = (char *) realloc(*psp->declargslot, n);
|
| + zBuf = *psp->declargslot + nOld;
|
| if( addLineMacro ){
|
| if( nOld && zBuf[-1]!='\n' ){
|
| *(zBuf++) = '\n';
|
| @@ -2491,8 +2510,7 @@ static void preprocess_input(char *z){
|
| ** token is passed to the function "parseonetoken" which builds all
|
| ** the appropriate data structures in the global state vector "gp".
|
| */
|
| -void Parse(gp)
|
| -struct lemon *gp;
|
| +void Parse(struct lemon *gp)
|
| {
|
| struct pstate ps;
|
| FILE *fp;
|
| @@ -2646,7 +2664,7 @@ static struct plink *plink_freelist = 0;
|
|
|
| /* Allocate a new plink */
|
| struct plink *Plink_new(){
|
| - struct plink *new;
|
| + struct plink *newlink;
|
|
|
| if( plink_freelist==0 ){
|
| int i;
|
| @@ -2660,27 +2678,23 @@ struct plink *Plink_new(){
|
| for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
|
| plink_freelist[amt-1].next = 0;
|
| }
|
| - new = plink_freelist;
|
| + newlink = plink_freelist;
|
| plink_freelist = plink_freelist->next;
|
| - return new;
|
| + return newlink;
|
| }
|
|
|
| /* Add a plink to a plink list */
|
| -void Plink_add(plpp,cfp)
|
| -struct plink **plpp;
|
| -struct config *cfp;
|
| +void Plink_add(struct plink **plpp, struct config *cfp)
|
| {
|
| - struct plink *new;
|
| - new = Plink_new();
|
| - new->next = *plpp;
|
| - *plpp = new;
|
| - new->cfp = cfp;
|
| + struct plink *newlink;
|
| + newlink = Plink_new();
|
| + newlink->next = *plpp;
|
| + *plpp = newlink;
|
| + newlink->cfp = cfp;
|
| }
|
|
|
| /* Transfer every plink on the list "from" to the list "to" */
|
| -void Plink_copy(to,from)
|
| -struct plink **to;
|
| -struct plink *from;
|
| +void Plink_copy(struct plink **to, struct plink *from)
|
| {
|
| struct plink *nextpl;
|
| while( from ){
|
| @@ -2692,8 +2706,7 @@ struct plink *from;
|
| }
|
|
|
| /* Delete every plink on the list */
|
| -void Plink_delete(plp)
|
| -struct plink *plp;
|
| +void Plink_delete(struct plink *plp)
|
| {
|
| struct plink *nextpl;
|
|
|
| @@ -2713,14 +2726,12 @@ struct plink *plp;
|
| ** name comes from malloc() and must be freed by the calling
|
| ** function.
|
| */
|
| -PRIVATE char *file_makename(lemp,suffix)
|
| -struct lemon *lemp;
|
| -char *suffix;
|
| +PRIVATE char *file_makename(struct lemon *lemp, const char *suffix)
|
| {
|
| char *name;
|
| char *cp;
|
|
|
| - name = malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 );
|
| + name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 );
|
| if( name==0 ){
|
| fprintf(stderr,"Can't allocate space for a filename.\n");
|
| exit(1);
|
| @@ -2735,11 +2746,11 @@ char *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 */
|
| -PRIVATE FILE *file_open(lemp,suffix,mode)
|
| -struct lemon *lemp;
|
| -char *suffix;
|
| -char *mode;
|
| -{
|
| +PRIVATE FILE *file_open(
|
| + struct lemon *lemp,
|
| + const char *suffix,
|
| + const char *mode
|
| +){
|
| FILE *fp;
|
|
|
| if( lemp->outname ) free(lemp->outname);
|
| @@ -2750,13 +2761,29 @@ char *mode;
|
| lemp->errorcnt++;
|
| return 0;
|
| }
|
| +
|
| + /* Add files we create to a list, so we can delete them if we fail. This
|
| + ** is to keep makefiles from getting confused. We don't include .out files,
|
| + ** though: this is debug information, and you don't want it deleted if there
|
| + ** was an error you need to track down.
|
| + */
|
| + if(( *mode=='w' ) && (strcmp(suffix, ".out") != 0)){
|
| + const char **ptr = (const char **)
|
| + realloc(made_files, sizeof (const char **) * (made_files_count + 1));
|
| + const char *fname = Strsafe(lemp->outname);
|
| + if ((ptr == NULL) || (fname == NULL)) {
|
| + free(ptr);
|
| + memory_error();
|
| + }
|
| + made_files = ptr;
|
| + made_files[made_files_count++] = fname;
|
| + }
|
| return fp;
|
| }
|
|
|
| /* Duplicate the input file without comments and without actions
|
| ** on rules */
|
| -void Reprint(lemp)
|
| -struct lemon *lemp;
|
| +void Reprint(struct lemon *lemp)
|
| {
|
| struct rule *rp;
|
| struct symbol *sp;
|
| @@ -2801,9 +2828,7 @@ struct lemon *lemp;
|
| }
|
| }
|
|
|
| -void ConfigPrint(fp,cfp)
|
| -FILE *fp;
|
| -struct config *cfp;
|
| +void ConfigPrint(FILE *fp, struct config *cfp)
|
| {
|
| struct rule *rp;
|
| struct symbol *sp;
|
| @@ -2883,11 +2908,25 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
|
| indent,ap->sp->name,ap->x.rp->index);
|
| break;
|
| case SSCONFLICT:
|
| - fprintf(fp,"%*s shift %d ** Parsing conflict **",
|
| + fprintf(fp,"%*s shift %-3d ** Parsing conflict **",
|
| indent,ap->sp->name,ap->x.stp->statenum);
|
| break;
|
| case SH_RESOLVED:
|
| + if( showPrecedenceConflict ){
|
| + fprintf(fp,"%*s shift %-3d -- dropped by precedence",
|
| + indent,ap->sp->name,ap->x.stp->statenum);
|
| + }else{
|
| + result = 0;
|
| + }
|
| + break;
|
| case RD_RESOLVED:
|
| + if( showPrecedenceConflict ){
|
| + fprintf(fp,"%*s reduce %-3d -- dropped by precedence",
|
| + indent,ap->sp->name,ap->x.rp->index);
|
| + }else{
|
| + result = 0;
|
| + }
|
| + break;
|
| case NOT_USED:
|
| result = 0;
|
| break;
|
| @@ -2896,8 +2935,7 @@ int PrintAction(struct action *ap, FILE *fp, int indent){
|
| }
|
|
|
| /* Generate the "y.output" log file */
|
| -void ReportOutput(lemp)
|
| -struct lemon *lemp;
|
| +void ReportOutput(struct lemon *lemp)
|
| {
|
| int i;
|
| struct state *stp;
|
| @@ -2963,12 +3001,11 @@ struct lemon *lemp;
|
|
|
| /* Search for the file "name" which is in the same directory as
|
| ** the exacutable */
|
| -PRIVATE char *pathsearch(argv0,name,modemask)
|
| -char *argv0;
|
| -char *name;
|
| -int modemask;
|
| +PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
|
| {
|
| - char *pathlist;
|
| + const char *pathlist;
|
| + char *pathbufptr;
|
| + char *pathbuf;
|
| char *path,*cp;
|
| char c;
|
|
|
| @@ -2984,22 +3021,25 @@ int modemask;
|
| if( path ) sprintf(path,"%s/%s",argv0,name);
|
| *cp = c;
|
| }else{
|
| - extern char *getenv();
|
| pathlist = getenv("PATH");
|
| if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
|
| + pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 );
|
| path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 );
|
| - if( path!=0 ){
|
| - while( *pathlist ){
|
| - cp = strchr(pathlist,':');
|
| - if( cp==0 ) cp = &pathlist[lemonStrlen(pathlist)];
|
| + if( (pathbuf != 0) && (path!=0) ){
|
| + pathbufptr = pathbuf;
|
| + strcpy(pathbuf, pathlist);
|
| + while( *pathbuf ){
|
| + cp = strchr(pathbuf,':');
|
| + if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)];
|
| c = *cp;
|
| *cp = 0;
|
| - sprintf(path,"%s/%s",pathlist,name);
|
| + sprintf(path,"%s/%s",pathbuf,name);
|
| *cp = c;
|
| - if( c==0 ) pathlist = "";
|
| - else pathlist = &cp[1];
|
| + if( c==0 ) pathbuf[0] = 0;
|
| + else pathbuf = &cp[1];
|
| if( access(path,modemask)==0 ) break;
|
| }
|
| + free(pathbufptr);
|
| }
|
| }
|
| return path;
|
| @@ -3009,9 +3049,7 @@ int modemask;
|
| ** which is to be put in the action table of the generated machine.
|
| ** Return negative if no action should be generated.
|
| */
|
| -PRIVATE int compute_action(lemp,ap)
|
| -struct lemon *lemp;
|
| -struct action *ap;
|
| +PRIVATE int compute_action(struct lemon *lemp, struct action *ap)
|
| {
|
| int act;
|
| switch( ap->type ){
|
| @@ -3034,11 +3072,7 @@ struct action *ap;
|
| ** if name!=0, then any word that begin with "Parse" is changed to
|
| ** begin with *name instead.
|
| */
|
| -PRIVATE void tplt_xfer(name,in,out,lineno)
|
| -char *name;
|
| -FILE *in;
|
| -FILE *out;
|
| -int *lineno;
|
| +PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
|
| {
|
| int i, iStart;
|
| char line[LINESIZE];
|
| @@ -3063,8 +3097,7 @@ int *lineno;
|
|
|
| /* The next function finds the template file and opens it, returning
|
| ** a pointer to the opened file. */
|
| -PRIVATE FILE *tplt_open(lemp)
|
| -struct lemon *lemp;
|
| +PRIVATE FILE *tplt_open(struct lemon *lemp)
|
| {
|
| static char templatename[] = "lempar.c";
|
| char buf[1000];
|
| @@ -3072,6 +3105,23 @@ struct lemon *lemp;
|
| char *tpltname;
|
| char *cp;
|
|
|
| + /* first, see if user specified a template filename on the command line. */
|
| + if (user_templatename != 0) {
|
| + if( access(user_templatename,004)==-1 ){
|
| + fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
|
| + user_templatename);
|
| + lemp->errorcnt++;
|
| + return 0;
|
| + }
|
| + in = fopen(user_templatename,"rb");
|
| + if( in==0 ){
|
| + fprintf(stderr,"Can't open the template file \"%s\".\n",user_templatename);
|
| + lemp->errorcnt++;
|
| + return 0;
|
| + }
|
| + return in;
|
| + }
|
| +
|
| cp = strrchr(lemp->filename,'.');
|
| if( cp ){
|
| sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
|
| @@ -3101,10 +3151,7 @@ struct lemon *lemp;
|
| }
|
|
|
| /* Print a #line directive line to the output file. */
|
| -PRIVATE void tplt_linedir(out,lineno,filename)
|
| -FILE *out;
|
| -int lineno;
|
| -char *filename;
|
| +PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename)
|
| {
|
| fprintf(out,"#line %d \"",lineno);
|
| while( *filename ){
|
| @@ -3116,11 +3163,7 @@ char *filename;
|
| }
|
|
|
| /* Print a string to the file and keep the linenumber up to date */
|
| -PRIVATE void tplt_print(out,lemp,str,lineno)
|
| -FILE *out;
|
| -struct lemon *lemp;
|
| -char *str;
|
| -int *lineno;
|
| +PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, int *lineno)
|
| {
|
| if( str==0 ) return;
|
| while( *str ){
|
| @@ -3142,12 +3185,12 @@ int *lineno;
|
| ** The following routine emits code for the destructor for the
|
| ** symbol sp
|
| */
|
| -void emit_destructor_code(out,sp,lemp,lineno)
|
| -FILE *out;
|
| -struct symbol *sp;
|
| -struct lemon *lemp;
|
| -int *lineno;
|
| -{
|
| +void emit_destructor_code(
|
| + FILE *out,
|
| + struct symbol *sp,
|
| + struct lemon *lemp,
|
| + int *lineno
|
| +){
|
| char *cp = 0;
|
|
|
| if( sp->type==TERMINAL ){
|
| @@ -3185,9 +3228,7 @@ int *lineno;
|
| /*
|
| ** Return TRUE (non-zero) if the given symbol has a destructor.
|
| */
|
| -int has_destructor(sp, lemp)
|
| -struct symbol *sp;
|
| -struct lemon *lemp;
|
| +int has_destructor(struct symbol *sp, struct lemon *lemp)
|
| {
|
| int ret;
|
| if( sp->type==TERMINAL ){
|
| @@ -3210,13 +3251,13 @@ struct lemon *lemp;
|
| **
|
| ** If n==-1, then the previous character is overwritten.
|
| */
|
| -PRIVATE char *append_str(char *zText, int n, int p1, int p2){
|
| +PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
|
| + static char empty[1] = { 0 };
|
| static char *z = 0;
|
| static int alloced = 0;
|
| static int used = 0;
|
| int c;
|
| char zInt[40];
|
| -
|
| if( zText==0 ){
|
| used = 0;
|
| return z;
|
| @@ -3228,11 +3269,11 @@ PRIVATE char *append_str(char *zText, int n, int p1, int p2){
|
| }
|
| n = lemonStrlen(zText);
|
| }
|
| - if( n+sizeof(zInt)*2+used >= alloced ){
|
| + if( (int) (n+sizeof(zInt)*2+used) >= alloced ){
|
| alloced = n + sizeof(zInt)*2 + used + 200;
|
| - z = realloc(z, alloced);
|
| + z = (char *) realloc(z, alloced);
|
| }
|
| - if( z==0 ) return "";
|
| + if( z==0 ) return empty;
|
| while( n-- > 0 ){
|
| c = *(zText++);
|
| if( c=='%' && n>0 && zText[0]=='d' ){
|
| @@ -3265,12 +3306,15 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
|
| lhsused = 0;
|
|
|
| if( rp->code==0 ){
|
| - rp->code = "\n";
|
| + static char newlinestr[2] = { '\n', '\0' };
|
| + rp->code = newlinestr;
|
| rp->line = rp->ruleline;
|
| }
|
|
|
| append_str(0,0,0,0);
|
| - for(cp=rp->code; *cp; cp++){
|
| +
|
| + /* This const cast is wrong but harmless, if we're careful. */
|
| + for(cp=(char *)rp->code; *cp; cp++){
|
| if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
|
| char saved;
|
| for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
|
| @@ -3343,13 +3387,13 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
|
| ** Generate code which executes when the rule "rp" is reduced. Write
|
| ** the code to "out". Make sure lineno stays up-to-date.
|
| */
|
| -PRIVATE void emit_code(out,rp,lemp,lineno)
|
| -FILE *out;
|
| -struct rule *rp;
|
| -struct lemon *lemp;
|
| -int *lineno;
|
| -{
|
| - char *cp;
|
| +PRIVATE void emit_code(
|
| + FILE *out,
|
| + struct rule *rp,
|
| + struct lemon *lemp,
|
| + int *lineno
|
| +){
|
| + const char *cp;
|
|
|
| /* Generate code to do the reduce action */
|
| if( rp->code ){
|
| @@ -3372,12 +3416,12 @@ int *lineno;
|
| ** union, also set the ".dtnum" field of every terminal and nonterminal
|
| ** symbol.
|
| */
|
| -void print_stack_union(out,lemp,plineno,mhflag)
|
| -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 */
|
| -{
|
| +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 */
|
| char **types; /* A hash table of datatypes */
|
| int arraysize; /* Size of the "types" array */
|
| @@ -3385,7 +3429,7 @@ int mhflag; /* True if generating makeheaders output */
|
| char *stddt; /* Standardized name for a datatype */
|
| int i,j; /* Loop counters */
|
| int hash; /* For hashing the name of a type */
|
| - char *name; /* Name of the parser */
|
| + const char *name; /* Name of the parser */
|
|
|
| /* Allocate and initialize types[] and allocate stddt[] */
|
| arraysize = lemp->nsymbol * 2;
|
| @@ -3516,6 +3560,7 @@ struct axset {
|
| struct state *stp; /* A pointer to a state */
|
| int isTkn; /* True to use tokens. False for non-terminals */
|
| int nAction; /* Number of actions */
|
| + int iOrder; /* Original order of action sets */
|
| };
|
|
|
| /*
|
| @@ -3524,7 +3569,13 @@ struct axset {
|
| static int axset_compare(const void *a, const void *b){
|
| struct axset *p1 = (struct axset*)a;
|
| struct axset *p2 = (struct axset*)b;
|
| - return p2->nAction - p1->nAction;
|
| + int c;
|
| + c = p2->nAction - p1->nAction;
|
| + if( c==0 ){
|
| + c = p2->iOrder - p1->iOrder;
|
| + }
|
| + assert( c!=0 || p1==p2 );
|
| + return c;
|
| }
|
|
|
| /*
|
| @@ -3547,10 +3598,10 @@ static void writeRuleText(FILE *out, struct rule *rp){
|
|
|
|
|
| /* Generate C source code for the parser */
|
| -void ReportTable(lemp, mhflag)
|
| -struct lemon *lemp;
|
| -int mhflag; /* Output in makeheaders format if true */
|
| -{
|
| +void ReportTable(
|
| + struct lemon *lemp,
|
| + int mhflag /* Output in makeheaders format if true */
|
| +){
|
| FILE *out, *in;
|
| char line[LINESIZE];
|
| int lineno;
|
| @@ -3559,7 +3610,7 @@ int mhflag; /* Output in makeheaders format if true */
|
| struct rule *rp;
|
| struct acttab *pActtab;
|
| int i, j, n;
|
| - char *name;
|
| + const char *name;
|
| int mnTknOfst, mxTknOfst;
|
| int mnNtOfst, mxNtOfst;
|
| struct axset *ax;
|
| @@ -3585,7 +3636,7 @@ int mhflag; /* Output in makeheaders format if true */
|
|
|
| /* Generate #defines for all tokens */
|
| if( mhflag ){
|
| - char *prefix;
|
| + const char *prefix;
|
| fprintf(out,"#if INTERFACE\n"); lineno++;
|
| if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
|
| else prefix = "";
|
| @@ -3663,7 +3714,7 @@ int mhflag; /* Output in makeheaders format if true */
|
| */
|
|
|
| /* Compute the actions on all states and count them up */
|
| - ax = calloc(lemp->nstate*2, sizeof(ax[0]));
|
| + ax = (struct axset *) calloc(lemp->nstate*2, sizeof(ax[0]));
|
| if( ax==0 ){
|
| fprintf(stderr,"malloc failed\n");
|
| exit(1);
|
| @@ -3684,6 +3735,7 @@ int mhflag; /* Output in makeheaders format if true */
|
| ** action table to a minimum, the heuristic of placing the largest action
|
| ** sets first is used.
|
| */
|
| + for(i=0; i<lemp->nstate*2; i++) ax[i].iOrder = i;
|
| qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare);
|
| pActtab = acttab_alloc();
|
| for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){
|
| @@ -3716,8 +3768,9 @@ int mhflag; /* Output in makeheaders format if true */
|
| free(ax);
|
|
|
| /* Output the yy_action table */
|
| - fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
|
| n = acttab_size(pActtab);
|
| + 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->nstate + lemp->nrule + 2;
|
| @@ -3752,7 +3805,9 @@ int mhflag; /* Output in makeheaders format if true */
|
| fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
|
| n = lemp->nstate;
|
| while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
|
| - fprintf(out, "#define YY_SHIFT_MAX %d\n", n-1); lineno++;
|
| + fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++;
|
| + fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++;
|
| + fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++;
|
| fprintf(out, "static const %s yy_shift_ofst[] = {\n",
|
| minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
|
| for(i=j=0; i<n; i++){
|
| @@ -3775,7 +3830,9 @@ int mhflag; /* Output in makeheaders format if true */
|
| fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
|
| n = lemp->nstate;
|
| while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
|
| - fprintf(out, "#define YY_REDUCE_MAX %d\n", n-1); lineno++;
|
| + fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++;
|
| + fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++;
|
| + fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++;
|
| fprintf(out, "static const %s yy_reduce_ofst[] = {\n",
|
| minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
|
| for(i=j=0; i<n; i++){
|
| @@ -3985,11 +4042,10 @@ int mhflag; /* Output in makeheaders format if true */
|
| }
|
|
|
| /* Generate a header file for the parser */
|
| -void ReportHeader(lemp)
|
| -struct lemon *lemp;
|
| +void ReportHeader(struct lemon *lemp)
|
| {
|
| FILE *out, *in;
|
| - char *prefix;
|
| + const char *prefix;
|
| char line[LINESIZE];
|
| char pattern[LINESIZE];
|
| int i;
|
| @@ -4025,8 +4081,7 @@ struct lemon *lemp;
|
| ** it the default. Except, there is no default if the wildcard token
|
| ** is a possible look-ahead.
|
| */
|
| -void CompressTables(lemp)
|
| -struct lemon *lemp;
|
| +void CompressTables(struct lemon *lemp)
|
| {
|
| struct state *stp;
|
| struct action *ap, *ap2;
|
| @@ -4097,7 +4152,11 @@ static int stateResortCompare(const void *a, const void *b){
|
| n = pB->nNtAct - pA->nNtAct;
|
| if( n==0 ){
|
| n = pB->nTknAct - pA->nTknAct;
|
| + if( n==0 ){
|
| + n = pB->statenum - pA->statenum;
|
| + }
|
| }
|
| + assert( n!=0 );
|
| return n;
|
| }
|
|
|
| @@ -4106,8 +4165,7 @@ static int stateResortCompare(const void *a, const void *b){
|
| ** Renumber and resort states so that states with fewer choices
|
| ** occur at the end. Except, keep state 0 as the first state.
|
| */
|
| -void ResortStates(lemp)
|
| -struct lemon *lemp;
|
| +void ResortStates(struct lemon *lemp)
|
| {
|
| int i;
|
| struct state *stp;
|
| @@ -4147,8 +4205,7 @@ struct lemon *lemp;
|
| static int size = 0;
|
|
|
| /* Set the set size */
|
| -void SetSize(n)
|
| -int n;
|
| +void SetSize(int n)
|
| {
|
| size = n+1;
|
| }
|
| @@ -4165,17 +4222,14 @@ char *SetNew(){
|
| }
|
|
|
| /* Deallocate a set */
|
| -void SetFree(s)
|
| -char *s;
|
| +void SetFree(char *s)
|
| {
|
| free(s);
|
| }
|
|
|
| /* Add a new element to the set. Return TRUE if the element was added
|
| ** and FALSE if it was already there. */
|
| -int SetAdd(s,e)
|
| -char *s;
|
| -int e;
|
| +int SetAdd(char *s, int e)
|
| {
|
| int rv;
|
| assert( e>=0 && e<size );
|
| @@ -4185,9 +4239,7 @@ int e;
|
| }
|
|
|
| /* Add every element of s2 to s1. Return TRUE if s1 changes. */
|
| -int SetUnion(s1,s2)
|
| -char *s1;
|
| -char *s2;
|
| +int SetUnion(char *s1, char *s2)
|
| {
|
| int i, progress;
|
| progress = 0;
|
| @@ -4213,8 +4265,7 @@ char *s2;
|
| ** Code for processing tables in the LEMON parser generator.
|
| */
|
|
|
| -PRIVATE int strhash(x)
|
| -char *x;
|
| +PRIVATE int strhash(const char *x)
|
| {
|
| int h = 0;
|
| while( *x) h = h*13 + *(x++);
|
| @@ -4225,15 +4276,16 @@ char *x;
|
| ** keep strings in a table so that the same string is not in more
|
| ** than one place.
|
| */
|
| -char *Strsafe(y)
|
| -char *y;
|
| +const char *Strsafe(const char *y)
|
| {
|
| - char *z;
|
| + const char *z;
|
| + char *cpy;
|
|
|
| if( y==0 ) return 0;
|
| z = Strsafe_find(y);
|
| - if( z==0 && (z=malloc( lemonStrlen(y)+1 ))!=0 ){
|
| - strcpy(z,y);
|
| + if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){
|
| + strcpy(cpy,y);
|
| + z = cpy;
|
| Strsafe_insert(z);
|
| }
|
| MemoryCheck(z);
|
| @@ -4256,7 +4308,7 @@ struct s_x1 {
|
| ** in an associative array of type "x1".
|
| */
|
| typedef struct s_x1node {
|
| - char *data; /* The data */
|
| + const char *data; /* The data */
|
| struct s_x1node *next; /* Next entry with the same hash */
|
| struct s_x1node **from; /* Previous link */
|
| } x1node;
|
| @@ -4285,8 +4337,7 @@ void Strsafe_init(){
|
| }
|
| /* Insert a new record into the array. Return TRUE if successful.
|
| ** Prior data with the same key is NOT overwritten */
|
| -int Strsafe_insert(data)
|
| -char *data;
|
| +int Strsafe_insert(const char *data)
|
| {
|
| x1node *np;
|
| int h;
|
| @@ -4342,8 +4393,7 @@ char *data;
|
|
|
| /* Return a pointer to data assigned to the given key. Return NULL
|
| ** if no such key. */
|
| -char *Strsafe_find(key)
|
| -char *key;
|
| +const char *Strsafe_find(const char *key)
|
| {
|
| int h;
|
| x1node *np;
|
| @@ -4361,8 +4411,7 @@ char *key;
|
| /* Return a pointer to the (terminal or nonterminal) symbol "x".
|
| ** Create a new symbol if this is the first time "x" has been seen.
|
| */
|
| -struct symbol *Symbol_new(x)
|
| -char *x;
|
| +struct symbol *Symbol_new(const char *x)
|
| {
|
| struct symbol *sp;
|
|
|
| @@ -4398,9 +4447,13 @@ char *x;
|
| ** order (the order they appeared in the grammar file) gives the
|
| ** smallest parser tables in SQLite.
|
| */
|
| -int Symbolcmpp(struct symbol **a, struct symbol **b){
|
| +int Symbolcmpp(const void *_a, const void *_b)
|
| +{
|
| + const struct symbol **a = (const struct symbol **) _a;
|
| + const struct symbol **b = (const struct symbol **) _b;
|
| int i1 = (**a).index + 10000000*((**a).name[0]>'Z');
|
| int i2 = (**b).index + 10000000*((**b).name[0]>'Z');
|
| + assert( i1!=i2 || strcmp((**a).name,(**b).name)==0 );
|
| return i1-i2;
|
| }
|
|
|
| @@ -4420,8 +4473,8 @@ struct s_x2 {
|
| ** in an associative array of type "x2".
|
| */
|
| typedef struct s_x2node {
|
| - struct symbol *data; /* The data */
|
| - char *key; /* The key */
|
| + struct symbol *data; /* The data */
|
| + const char *key; /* The key */
|
| struct s_x2node *next; /* Next entry with the same hash */
|
| struct s_x2node **from; /* Previous link */
|
| } x2node;
|
| @@ -4450,9 +4503,7 @@ void Symbol_init(){
|
| }
|
| /* Insert a new record into the array. Return TRUE if successful.
|
| ** Prior data with the same key is NOT overwritten */
|
| -int Symbol_insert(data,key)
|
| -struct symbol *data;
|
| -char *key;
|
| +int Symbol_insert(struct symbol *data, const char *key)
|
| {
|
| x2node *np;
|
| int h;
|
| @@ -4510,8 +4561,7 @@ char *key;
|
|
|
| /* Return a pointer to data assigned to the given key. Return NULL
|
| ** if no such key. */
|
| -struct symbol *Symbol_find(key)
|
| -char *key;
|
| +struct symbol *Symbol_find(const char *key)
|
| {
|
| int h;
|
| x2node *np;
|
| @@ -4527,8 +4577,7 @@ char *key;
|
| }
|
|
|
| /* Return the n-th data. Return NULL if n is out of range. */
|
| -struct symbol *Symbol_Nth(n)
|
| -int n;
|
| +struct symbol *Symbol_Nth(int n)
|
| {
|
| struct symbol *data;
|
| if( x2a && n>0 && n<=x2a->count ){
|
| @@ -4562,10 +4611,10 @@ struct symbol **Symbol_arrayof()
|
| }
|
|
|
| /* Compare two configurations */
|
| -int Configcmp(a,b)
|
| -struct config *a;
|
| -struct config *b;
|
| +int Configcmp(const char *_a,const char *_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;
|
| @@ -4573,9 +4622,7 @@ struct config *b;
|
| }
|
|
|
| /* Compare two states */
|
| -PRIVATE int statecmp(a,b)
|
| -struct config *a;
|
| -struct config *b;
|
| +PRIVATE int statecmp(struct config *a, struct config *b)
|
| {
|
| int rc;
|
| for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){
|
| @@ -4590,8 +4637,7 @@ struct config *b;
|
| }
|
|
|
| /* Hash a state */
|
| -PRIVATE int statehash(a)
|
| -struct config *a;
|
| +PRIVATE int statehash(struct config *a)
|
| {
|
| int h=0;
|
| while( a ){
|
| @@ -4604,10 +4650,10 @@ struct config *a;
|
| /* Allocate a new state structure */
|
| struct state *State_new()
|
| {
|
| - struct state *new;
|
| - new = (struct state *)calloc(1, sizeof(struct state) );
|
| - MemoryCheck(new);
|
| - return new;
|
| + struct state *newstate;
|
| + newstate = (struct state *)calloc(1, sizeof(struct state) );
|
| + MemoryCheck(newstate);
|
| + return newstate;
|
| }
|
|
|
| /* There is one instance of the following structure for each
|
| @@ -4656,9 +4702,7 @@ void State_init(){
|
| }
|
| /* Insert a new record into the array. Return TRUE if successful.
|
| ** Prior data with the same key is NOT overwritten */
|
| -int State_insert(data,key)
|
| -struct state *data;
|
| -struct config *key;
|
| +int State_insert(struct state *data, struct config *key)
|
| {
|
| x3node *np;
|
| int h;
|
| @@ -4716,8 +4760,7 @@ struct config *key;
|
|
|
| /* Return a pointer to data assigned to the given key. Return NULL
|
| ** if no such key. */
|
| -struct state *State_find(key)
|
| -struct config *key;
|
| +struct state *State_find(struct config *key)
|
| {
|
| int h;
|
| x3node *np;
|
| @@ -4749,8 +4792,7 @@ struct state **State_arrayof()
|
| }
|
|
|
| /* Hash a configuration */
|
| -PRIVATE int confighash(a)
|
| -struct config *a;
|
| +PRIVATE int confighash(struct config *a)
|
| {
|
| int h=0;
|
| h = h*571 + a->rp->index*37 + a->dot;
|
| @@ -4802,8 +4844,7 @@ void Configtable_init(){
|
| }
|
| /* Insert a new record into the array. Return TRUE if successful.
|
| ** Prior data with the same key is NOT overwritten */
|
| -int Configtable_insert(data)
|
| -struct config *data;
|
| +int Configtable_insert(struct config *data)
|
| {
|
| x4node *np;
|
| int h;
|
| @@ -4814,7 +4855,7 @@ struct config *data;
|
| h = ph & (x4a->size-1);
|
| np = x4a->ht[h];
|
| while( np ){
|
| - if( Configcmp(np->data,data)==0 ){
|
| + if( Configcmp((const char *) np->data,(const char *) data)==0 ){
|
| /* An existing entry with the same key is found. */
|
| /* Fail because overwrite is not allows. */
|
| return 0;
|
| @@ -4859,8 +4900,7 @@ struct config *data;
|
|
|
| /* Return a pointer to data assigned to the given key. Return NULL
|
| ** if no such key. */
|
| -struct config *Configtable_find(key)
|
| -struct config *key;
|
| +struct config *Configtable_find(struct config *key)
|
| {
|
| int h;
|
| x4node *np;
|
| @@ -4869,7 +4909,7 @@ struct config *key;
|
| h = confighash(key) & (x4a->size-1);
|
| np = x4a->ht[h];
|
| while( np ){
|
| - if( Configcmp(np->data,key)==0 ) break;
|
| + if( Configcmp((const char *) np->data,(const char *) key)==0 ) break;
|
| np = np->next;
|
| }
|
| return np ? np->data : 0;
|
| @@ -4877,8 +4917,7 @@ struct config *key;
|
|
|
| /* Remove all data from the table. Pass each data to the function "f"
|
| ** as it is removed. ("f" may be null to avoid this step.) */
|
| -void Configtable_clear(f)
|
| -int(*f)(/* struct config * */);
|
| +void Configtable_clear(int(*f)(struct config *))
|
| {
|
| int i;
|
| if( x4a==0 || x4a->count==0 ) return;
|
|
|