~ubuntu-branches/debian/sid/tk-html3/sid

« back to all changes in this revision

Viewing changes to tools/lemon.c

  • Committer: Package Import Robot
  • Author(s): Ole Streicher
  • Date: 2012-03-02 18:45:00 UTC
  • Revision ID: package-import@ubuntu.com-20120302184500-np17d7d6gd1jedj0
Tags: upstream-3.0~fossil20110109
ImportĀ upstreamĀ versionĀ 3.0~fossil20110109

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** This file contains all sources (including headers) to the LEMON
 
3
** LALR(1) parser generator.  The sources have been combined into a
 
4
** single file to make it easy to include LEMON in the source tree
 
5
** and Makefile of another program.
 
6
**
 
7
** The author of this program disclaims copyright.
 
8
*/
 
9
#include <stdio.h>
 
10
#include <stdarg.h>
 
11
#include <string.h>
 
12
#include <ctype.h>
 
13
#include <stdlib.h>
 
14
 
 
15
#ifndef __WIN32__
 
16
#   if defined(_WIN32) || defined(WIN32)
 
17
#       define __WIN32__
 
18
#   endif
 
19
#endif
 
20
 
 
21
/* #define PRIVATE static */
 
22
#define PRIVATE
 
23
 
 
24
#ifdef TEST
 
25
#define MAXRHS 5       /* Set low to exercise exception code */
 
26
#else
 
27
#define MAXRHS 1000
 
28
#endif
 
29
 
 
30
char *msort();
 
31
extern void *malloc();
 
32
 
 
33
/******** From the file "action.h" *************************************/
 
34
struct action *Action_new();
 
35
struct action *Action_sort();
 
36
 
 
37
/********* From the file "assert.h" ************************************/
 
38
void myassert();
 
39
#ifndef NDEBUG
 
40
#  define assert(X) if(!(X))myassert(__FILE__,__LINE__)
 
41
#else
 
42
#  define assert(X)
 
43
#endif
 
44
 
 
45
/********** From the file "build.h" ************************************/
 
46
void FindRulePrecedences();
 
47
void FindFirstSets();
 
48
void FindStates();
 
49
void FindLinks();
 
50
void FindFollowSets();
 
51
void FindActions();
 
52
 
 
53
/********* From the file "configlist.h" *********************************/
 
54
void Configlist_init(/* void */);
 
55
struct config *Configlist_add(/* struct rule *, int */);
 
56
struct config *Configlist_addbasis(/* struct rule *, int */);
 
57
void Configlist_closure(/* void */);
 
58
void Configlist_sort(/* void */);
 
59
void Configlist_sortbasis(/* void */);
 
60
struct config *Configlist_return(/* void */);
 
61
struct config *Configlist_basis(/* void */);
 
62
void Configlist_eat(/* struct config * */);
 
63
void Configlist_reset(/* void */);
 
64
 
 
65
/********* From the file "error.h" ***************************************/
 
66
void ErrorMsg(const char *, int,const char *, ...);
 
67
 
 
68
/****** From the file "option.h" ******************************************/
 
69
struct s_options {
 
70
  enum { OPT_FLAG=1,  OPT_INT,  OPT_DBL,  OPT_STR,
 
71
         OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR} type;
 
72
  char *label;
 
73
  char *arg;
 
74
  char *message;
 
75
};
 
76
int    OptInit(/* char**,struct s_options*,FILE* */);
 
77
int    OptNArgs(/* void */);
 
78
char  *OptArg(/* int */);
 
79
void   OptErr(/* int */);
 
80
void   OptPrint(/* void */);
 
81
 
 
82
/******** From the file "parse.h" *****************************************/
 
83
void Parse(/* struct lemon *lemp */);
 
84
 
 
85
/********* From the file "plink.h" ***************************************/
 
86
struct plink *Plink_new(/* void */);
 
87
void Plink_add(/* struct plink **, struct config * */);
 
88
void Plink_copy(/* struct plink **, struct plink * */);
 
89
void Plink_delete(/* struct plink * */);
 
90
 
 
91
/********** From the file "report.h" *************************************/
 
92
void Reprint(/* struct lemon * */);
 
93
void ReportOutput(/* struct lemon * */);
 
94
void ReportTable(/* struct lemon * */);
 
95
void ReportHeader(/* struct lemon * */);
 
96
void CompressTables(/* struct lemon * */);
 
97
void ResortStates(/* struct lemon * */);
 
98
 
 
99
/********** From the file "set.h" ****************************************/
 
100
void  SetSize(/* int N */);             /* All sets will be of size N */
 
101
char *SetNew(/* void */);               /* A new set for element 0..N */
 
102
void  SetFree(/* char* */);             /* Deallocate a set */
 
103
 
 
104
int SetAdd(/* char*,int */);            /* Add element to a set */
 
105
int SetUnion(/* char *A,char *B */);    /* A <- A U B, thru element N */
 
106
 
 
107
#define SetFind(X,Y) (X[Y])       /* True if Y is in set X */
 
108
 
 
109
/********** From the file "struct.h" *************************************/
 
110
/*
 
111
** Principal data structures for the LEMON parser generator.
 
112
*/
 
113
 
 
114
typedef enum {B_FALSE=0, B_TRUE} Boolean;
 
115
 
 
116
/* Symbols (terminals and nonterminals) of the grammar are stored
 
117
** in the following: */
 
118
struct symbol {
 
119
  char *name;              /* Name of the symbol */
 
120
  int index;               /* Index number for this symbol */
 
121
  enum {
 
122
    TERMINAL,
 
123
    NONTERMINAL,
 
124
    MULTITERMINAL
 
125
  } type;                  /* Symbols are all either TERMINALS or NTs */
 
126
  struct rule *rule;       /* Linked list of rules of this (if an NT) */
 
127
  struct symbol *fallback; /* fallback token in case this token doesn't parse */
 
128
  int prec;                /* Precedence if defined (-1 otherwise) */
 
129
  enum e_assoc {
 
130
    LEFT,
 
131
    RIGHT,
 
132
    NONE,
 
133
    UNK
 
134
  } assoc;                 /* Associativity if predecence is defined */
 
135
  char *firstset;          /* First-set for all rules of this symbol */
 
136
  Boolean lambda;          /* True if NT and can generate an empty string */
 
137
  char *destructor;        /* Code which executes whenever this symbol is
 
138
                           ** popped from the stack during error processing */
 
139
  int destructorln;        /* Line number of destructor code */
 
140
  char *datatype;          /* The data type of information held by this
 
141
                           ** object. Only used if type==NONTERMINAL */
 
142
  int dtnum;               /* The data type number.  In the parser, the value
 
143
                           ** stack is a union.  The .yy%d element of this
 
144
                           ** union is the correct data type for this object */
 
145
  /* The following fields are used by MULTITERMINALs only */
 
146
  int nsubsym;             /* Number of constituent symbols in the MULTI */
 
147
  struct symbol **subsym;  /* Array of constituent symbols */
 
148
};
 
149
 
 
150
/* Each production rule in the grammar is stored in the following
 
151
** structure.  */
 
152
struct rule {
 
153
  struct symbol *lhs;      /* Left-hand side of the rule */
 
154
  char *lhsalias;          /* Alias for the LHS (NULL if none) */
 
155
  int ruleline;            /* Line number for the rule */
 
156
  int nrhs;                /* Number of RHS symbols */
 
157
  struct symbol **rhs;     /* The RHS symbols */
 
158
  char **rhsalias;         /* An alias for each RHS symbol (NULL if none) */
 
159
  int line;                /* Line number at which code begins */
 
160
  char *code;              /* The code executed when this rule is reduced */
 
161
  struct symbol *precsym;  /* Precedence symbol for this rule */
 
162
  int index;               /* An index number for this rule */
 
163
  Boolean canReduce;       /* True if this rule is ever reduced */
 
164
  struct rule *nextlhs;    /* Next rule with the same LHS */
 
165
  struct rule *next;       /* Next rule in the global list */
 
166
};
 
167
 
 
168
/* A configuration is a production rule of the grammar together with
 
169
** a mark (dot) showing how much of that rule has been processed so far.
 
170
** Configurations also contain a follow-set which is a list of terminal
 
171
** symbols which are allowed to immediately follow the end of the rule.
 
172
** Every configuration is recorded as an instance of the following: */
 
173
struct config {
 
174
  struct rule *rp;         /* The rule upon which the configuration is based */
 
175
  int dot;                 /* The parse point */
 
176
  char *fws;               /* Follow-set for this configuration only */
 
177
  struct plink *fplp;      /* Follow-set forward propagation links */
 
178
  struct plink *bplp;      /* Follow-set backwards propagation links */
 
179
  struct state *stp;       /* Pointer to state which contains this */
 
180
  enum {
 
181
    COMPLETE,              /* The status is used during followset and */
 
182
    INCOMPLETE             /*    shift computations */
 
183
  } status;
 
184
  struct config *next;     /* Next configuration in the state */
 
185
  struct config *bp;       /* The next basis configuration */
 
186
};
 
187
 
 
188
/* Every shift or reduce operation is stored as one of the following */
 
189
struct action {
 
190
  struct symbol *sp;       /* The look-ahead symbol */
 
191
  enum e_action {
 
192
    SHIFT,
 
193
    ACCEPT,
 
194
    REDUCE,
 
195
    ERROR,
 
196
    CONFLICT,                /* Was a reduce, but part of a conflict */
 
197
    SH_RESOLVED,             /* Was a shift.  Precedence resolved conflict */
 
198
    RD_RESOLVED,             /* Was reduce.  Precedence resolved conflict */
 
199
    NOT_USED                 /* Deleted by compression */
 
200
  } type;
 
201
  union {
 
202
    struct state *stp;     /* The new state, if a shift */
 
203
    struct rule *rp;       /* The rule, if a reduce */
 
204
  } x;
 
205
  struct action *next;     /* Next action for this state */
 
206
  struct action *collide;  /* Next action with the same hash */
 
207
};
 
208
 
 
209
/* Each state of the generated parser's finite state machine
 
210
** is encoded as an instance of the following structure. */
 
211
struct state {
 
212
  struct config *bp;       /* The basis configurations for this state */
 
213
  struct config *cfp;      /* All configurations in this set */
 
214
  int statenum;            /* Sequencial number for this state */
 
215
  struct action *ap;       /* Array of actions for this state */
 
216
  int nTknAct, nNtAct;     /* Number of actions on terminals and nonterminals */
 
217
  int iTknOfst, iNtOfst;   /* yy_action[] offset for terminals and nonterms */
 
218
  int iDflt;               /* Default action */
 
219
};
 
220
#define NO_OFFSET (-2147483647)
 
221
 
 
222
/* A followset propagation link indicates that the contents of one
 
223
** configuration followset should be propagated to another whenever
 
224
** the first changes. */
 
225
struct plink {
 
226
  struct config *cfp;      /* The configuration to which linked */
 
227
  struct plink *next;      /* The next propagate link */
 
228
};
 
229
 
 
230
/* The state vector for the entire parser generator is recorded as
 
231
** follows.  (LEMON uses no global variables and makes little use of
 
232
** static variables.  Fields in the following structure can be thought
 
233
** of as begin global variables in the program.) */
 
234
struct lemon {
 
235
  struct state **sorted;   /* Table of states sorted by state number */
 
236
  struct rule *rule;       /* List of all rules */
 
237
  int nstate;              /* Number of states */
 
238
  int nrule;               /* Number of rules */
 
239
  int nsymbol;             /* Number of terminal and nonterminal symbols */
 
240
  int nterminal;           /* Number of terminal symbols */
 
241
  struct symbol **symbols; /* Sorted array of pointers to symbols */
 
242
  int errorcnt;            /* Number of errors */
 
243
  struct symbol *errsym;   /* The error symbol */
 
244
  char *name;              /* Name of the generated parser */
 
245
  char *arg;               /* Declaration of the 3th argument to parser */
 
246
  char *tokentype;         /* Type of terminal symbols in the parser stack */
 
247
  char *vartype;           /* The default type of non-terminal symbols */
 
248
  char *start;             /* Name of the start symbol for the grammar */
 
249
  char *stacksize;         /* Size of the parser stack */
 
250
  char *include;           /* Code to put at the start of the C file */
 
251
  int  includeln;          /* Line number for start of include code */
 
252
  char *error;             /* Code to execute when an error is seen */
 
253
  int  errorln;            /* Line number for start of error code */
 
254
  char *overflow;          /* Code to execute on a stack overflow */
 
255
  int  overflowln;         /* Line number for start of overflow code */
 
256
  char *failure;           /* Code to execute on parser failure */
 
257
  int  failureln;          /* Line number for start of failure code */
 
258
  char *accept;            /* Code to execute when the parser excepts */
 
259
  int  acceptln;           /* Line number for the start of accept code */
 
260
  char *extracode;         /* Code appended to the generated file */
 
261
  int  extracodeln;        /* Line number for the start of the extra code */
 
262
  char *tokendest;         /* Code to execute to destroy token data */
 
263
  int  tokendestln;        /* Line number for token destroyer code */
 
264
  char *vardest;           /* Code for the default non-terminal destructor */
 
265
  int  vardestln;          /* Line number for default non-term destructor code*/
 
266
  char *filename;          /* Name of the input file */
 
267
  char *outname;           /* Name of the current output file */
 
268
  char *tokenprefix;       /* A prefix added to token names in the .h file */
 
269
  int nconflict;           /* Number of parsing conflicts */
 
270
  int tablesize;           /* Size of the parse tables */
 
271
  int basisflag;           /* Print only basis configurations */
 
272
  int has_fallback;        /* True if any %fallback is seen in the grammer */
 
273
  char *argv0;             /* Name of the program */
 
274
};
 
275
 
 
276
#define MemoryCheck(X) if((X)==0){ \
 
277
  extern void memory_error(); \
 
278
  memory_error(); \
 
279
}
 
280
 
 
281
/**************** From the file "table.h" *********************************/
 
282
/*
 
283
** All code in this file has been automatically generated
 
284
** from a specification in the file
 
285
**              "table.q"
 
286
** by the associative array code building program "aagen".
 
287
** Do not edit this file!  Instead, edit the specification
 
288
** file, then rerun aagen.
 
289
*/
 
290
/*
 
291
** Code for processing tables in the LEMON parser generator.
 
292
*/
 
293
 
 
294
/* Routines for handling a strings */
 
295
 
 
296
char *Strsafe();
 
297
 
 
298
void Strsafe_init(/* void */);
 
299
int Strsafe_insert(/* char * */);
 
300
char *Strsafe_find(/* char * */);
 
301
 
 
302
/* Routines for handling symbols of the grammar */
 
303
 
 
304
struct symbol *Symbol_new();
 
305
int Symbolcmpp(/* struct symbol **, struct symbol ** */);
 
306
void Symbol_init(/* void */);
 
307
int Symbol_insert(/* struct symbol *, char * */);
 
308
struct symbol *Symbol_find(/* char * */);
 
309
struct symbol *Symbol_Nth(/* int */);
 
310
int Symbol_count(/*  */);
 
311
struct symbol **Symbol_arrayof(/*  */);
 
312
 
 
313
/* Routines to manage the state table */
 
314
 
 
315
int Configcmp(/* struct config *, struct config * */);
 
316
struct state *State_new();
 
317
void State_init(/* void */);
 
318
int State_insert(/* struct state *, struct config * */);
 
319
struct state *State_find(/* struct config * */);
 
320
struct state **State_arrayof(/*  */);
 
321
 
 
322
/* Routines used for efficiency in Configlist_add */
 
323
 
 
324
void Configtable_init(/* void */);
 
325
int Configtable_insert(/* struct config * */);
 
326
struct config *Configtable_find(/* struct config * */);
 
327
void Configtable_clear(/* int(*)(struct config *) */);
 
328
/****************** From the file "action.c" *******************************/
 
329
/*
 
330
** Routines processing parser actions in the LEMON parser generator.
 
331
*/
 
332
 
 
333
/* Allocate a new parser action */
 
334
struct action *Action_new(){
 
335
  static struct action *freelist = 0;
 
336
  struct action *new;
 
337
 
 
338
  if( freelist==0 ){
 
339
    int i;
 
340
    int amt = 100;
 
341
    freelist = (struct action *)malloc( sizeof(struct action)*amt );
 
342
    if( freelist==0 ){
 
343
      fprintf(stderr,"Unable to allocate memory for a new parser action.");
 
344
      exit(1);
 
345
    }
 
346
    for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
 
347
    freelist[amt-1].next = 0;
 
348
  }
 
349
  new = freelist;
 
350
  freelist = freelist->next;
 
351
  return new;
 
352
}
 
353
 
 
354
/* Compare two actions */
 
355
static int actioncmp(ap1,ap2)
 
356
struct action *ap1;
 
357
struct action *ap2;
 
358
{
 
359
  int rc;
 
360
  rc = ap1->sp->index - ap2->sp->index;
 
361
  if( rc==0 ) rc = (int)ap1->type - (int)ap2->type;
 
362
  if( rc==0 ){
 
363
    assert( ap1->type==REDUCE || ap1->type==RD_RESOLVED || ap1->type==CONFLICT);
 
364
    assert( ap2->type==REDUCE || ap2->type==RD_RESOLVED || ap2->type==CONFLICT);
 
365
    rc = ap1->x.rp->index - ap2->x.rp->index;
 
366
  }
 
367
  return rc;
 
368
}
 
369
 
 
370
/* Sort parser actions */
 
371
struct action *Action_sort(ap)
 
372
struct action *ap;
 
373
{
 
374
  ap = (struct action *)msort((char *)ap,(char **)&ap->next,actioncmp);
 
375
  return ap;
 
376
}
 
377
 
 
378
void Action_add(app,type,sp,arg)
 
379
struct action **app;
 
380
enum e_action type;
 
381
struct symbol *sp;
 
382
char *arg;
 
383
{
 
384
  struct action *new;
 
385
  new = Action_new();
 
386
  new->next = *app;
 
387
  *app = new;
 
388
  new->type = type;
 
389
  new->sp = sp;
 
390
  if( type==SHIFT ){
 
391
    new->x.stp = (struct state *)arg;
 
392
  }else{
 
393
    new->x.rp = (struct rule *)arg;
 
394
  }
 
395
}
 
396
/********************** New code to implement the "acttab" module ***********/
 
397
/*
 
398
** This module implements routines use to construct the yy_action[] table.
 
399
*/
 
400
 
 
401
/*
 
402
** The state of the yy_action table under construction is an instance of
 
403
** the following structure
 
404
*/
 
405
typedef struct acttab acttab;
 
406
struct acttab {
 
407
  int nAction;                 /* Number of used slots in aAction[] */
 
408
  int nActionAlloc;            /* Slots allocated for aAction[] */
 
409
  struct {
 
410
    int lookahead;             /* Value of the lookahead token */
 
411
    int action;                /* Action to take on the given lookahead */
 
412
  } *aAction,                  /* The yy_action[] table under construction */
 
413
    *aLookahead;               /* A single new transaction set */
 
414
  int mnLookahead;             /* Minimum aLookahead[].lookahead */
 
415
  int mnAction;                /* Action associated with mnLookahead */
 
416
  int mxLookahead;             /* Maximum aLookahead[].lookahead */
 
417
  int nLookahead;              /* Used slots in aLookahead[] */
 
418
  int nLookaheadAlloc;         /* Slots allocated in aLookahead[] */
 
419
};
 
420
 
 
421
/* Return the number of entries in the yy_action table */
 
422
#define acttab_size(X) ((X)->nAction)
 
423
 
 
424
/* The value for the N-th entry in yy_action */
 
425
#define acttab_yyaction(X,N)  ((X)->aAction[N].action)
 
426
 
 
427
/* The value for the N-th entry in yy_lookahead */
 
428
#define acttab_yylookahead(X,N)  ((X)->aAction[N].lookahead)
 
429
 
 
430
/* Free all memory associated with the given acttab */
 
431
void acttab_free(acttab *p){
 
432
  free( p->aAction );
 
433
  free( p->aLookahead );
 
434
  free( p );
 
435
}
 
436
 
 
437
/* Allocate a new acttab structure */
 
438
acttab *acttab_alloc(void){
 
439
  acttab *p = malloc( sizeof(*p) );
 
440
  if( p==0 ){
 
441
    fprintf(stderr,"Unable to allocate memory for a new acttab.");
 
442
    exit(1);
 
443
  }
 
444
  memset(p, 0, sizeof(*p));
 
445
  return p;
 
446
}
 
447
 
 
448
/* Add a new action to the current transaction set
 
449
*/
 
450
void acttab_action(acttab *p, int lookahead, int action){
 
451
  if( p->nLookahead>=p->nLookaheadAlloc ){
 
452
    p->nLookaheadAlloc += 25;
 
453
    p->aLookahead = realloc( p->aLookahead,
 
454
                             sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
 
455
    if( p->aLookahead==0 ){
 
456
      fprintf(stderr,"malloc failed\n");
 
457
      exit(1);
 
458
    }
 
459
  }
 
460
  if( p->nLookahead==0 ){
 
461
    p->mxLookahead = lookahead;
 
462
    p->mnLookahead = lookahead;
 
463
    p->mnAction = action;
 
464
  }else{
 
465
    if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
 
466
    if( p->mnLookahead>lookahead ){
 
467
      p->mnLookahead = lookahead;
 
468
      p->mnAction = action;
 
469
    }
 
470
  }
 
471
  p->aLookahead[p->nLookahead].lookahead = lookahead;
 
472
  p->aLookahead[p->nLookahead].action = action;
 
473
  p->nLookahead++;
 
474
}
 
475
 
 
476
/*
 
477
** Add the transaction set built up with prior calls to acttab_action()
 
478
** into the current action table.  Then reset the transaction set back
 
479
** to an empty set in preparation for a new round of acttab_action() calls.
 
480
**
 
481
** Return the offset into the action table of the new transaction.
 
482
*/
 
483
int acttab_insert(acttab *p){
 
484
  int i, j, k, n;
 
485
  assert( p->nLookahead>0 );
 
486
 
 
487
  /* Make sure we have enough space to hold the expanded action table
 
488
  ** in the worst case.  The worst case occurs if the transaction set
 
489
  ** must be appended to the current action table
 
490
  */
 
491
  n = p->mxLookahead + 1;
 
492
  if( p->nAction + n >= p->nActionAlloc ){
 
493
    int oldAlloc = p->nActionAlloc;
 
494
    p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
 
495
    p->aAction = realloc( p->aAction,
 
496
                          sizeof(p->aAction[0])*p->nActionAlloc);
 
497
    if( p->aAction==0 ){
 
498
      fprintf(stderr,"malloc failed\n");
 
499
      exit(1);
 
500
    }
 
501
    for(i=oldAlloc; i<p->nActionAlloc; i++){
 
502
      p->aAction[i].lookahead = -1;
 
503
      p->aAction[i].action = -1;
 
504
    }
 
505
  }
 
506
 
 
507
  /* Scan the existing action table looking for an offset where we can
 
508
  ** insert the current transaction set.  Fall out of the loop when that
 
509
  ** offset is found.  In the worst case, we fall out of the loop when
 
510
  ** i reaches p->nAction, which means we append the new transaction set.
 
511
  **
 
512
  ** i is the index in p->aAction[] where p->mnLookahead is inserted.
 
513
  */
 
514
  for(i=0; i<p->nAction+p->mnLookahead; i++){
 
515
    if( p->aAction[i].lookahead<0 ){
 
516
      for(j=0; j<p->nLookahead; j++){
 
517
        k = p->aLookahead[j].lookahead - p->mnLookahead + i;
 
518
        if( k<0 ) break;
 
519
        if( p->aAction[k].lookahead>=0 ) break;
 
520
      }
 
521
      if( j<p->nLookahead ) continue;
 
522
      for(j=0; j<p->nAction; j++){
 
523
        if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break;
 
524
      }
 
525
      if( j==p->nAction ){
 
526
        break;  /* Fits in empty slots */
 
527
      }
 
528
    }else if( p->aAction[i].lookahead==p->mnLookahead ){
 
529
      if( p->aAction[i].action!=p->mnAction ) continue;
 
530
      for(j=0; j<p->nLookahead; j++){
 
531
        k = p->aLookahead[j].lookahead - p->mnLookahead + i;
 
532
        if( k<0 || k>=p->nAction ) break;
 
533
        if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
 
534
        if( p->aLookahead[j].action!=p->aAction[k].action ) break;
 
535
      }
 
536
      if( j<p->nLookahead ) continue;
 
537
      n = 0;
 
538
      for(j=0; j<p->nAction; j++){
 
539
        if( p->aAction[j].lookahead<0 ) continue;
 
540
        if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++;
 
541
      }
 
542
      if( n==p->nLookahead ){
 
543
        break;  /* Same as a prior transaction set */
 
544
      }
 
545
    }
 
546
  }
 
547
  /* Insert transaction set at index i. */
 
548
  for(j=0; j<p->nLookahead; j++){
 
549
    k = p->aLookahead[j].lookahead - p->mnLookahead + i;
 
550
    p->aAction[k] = p->aLookahead[j];
 
551
    if( k>=p->nAction ) p->nAction = k+1;
 
552
  }
 
553
  p->nLookahead = 0;
 
554
 
 
555
  /* Return the offset that is added to the lookahead in order to get the
 
556
  ** index into yy_action of the action */
 
557
  return i - p->mnLookahead;
 
558
}
 
559
 
 
560
/********************** From the file "assert.c" ****************************/
 
561
/*
 
562
** A more efficient way of handling assertions.
 
563
*/
 
564
void myassert(file,line)
 
565
char *file;
 
566
int line;
 
567
{
 
568
  fprintf(stderr,"Assertion failed on line %d of file \"%s\"\n",line,file);
 
569
  exit(1);
 
570
}
 
571
/********************** From the file "build.c" *****************************/
 
572
/*
 
573
** Routines to construction the finite state machine for the LEMON
 
574
** parser generator.
 
575
*/
 
576
 
 
577
/* Find a precedence symbol of every rule in the grammar.
 
578
** 
 
579
** Those rules which have a precedence symbol coded in the input
 
580
** grammar using the "[symbol]" construct will already have the
 
581
** rp->precsym field filled.  Other rules take as their precedence
 
582
** symbol the first RHS symbol with a defined precedence.  If there
 
583
** are not RHS symbols with a defined precedence, the precedence
 
584
** symbol field is left blank.
 
585
*/
 
586
void FindRulePrecedences(xp)
 
587
struct lemon *xp;
 
588
{
 
589
  struct rule *rp;
 
590
  for(rp=xp->rule; rp; rp=rp->next){
 
591
    if( rp->precsym==0 ){
 
592
      int i, j;
 
593
      for(i=0; i<rp->nrhs && rp->precsym==0; i++){
 
594
        struct symbol *sp = rp->rhs[i];
 
595
        if( sp->type==MULTITERMINAL ){
 
596
          for(j=0; j<sp->nsubsym; j++){
 
597
            if( sp->subsym[j]->prec>=0 ){
 
598
              rp->precsym = sp->subsym[j];
 
599
              break;
 
600
            }
 
601
          }
 
602
        }else if( sp->prec>=0 ){
 
603
          rp->precsym = rp->rhs[i];
 
604
        }
 
605
      }
 
606
    }
 
607
  }
 
608
  return;
 
609
}
 
610
 
 
611
/* Find all nonterminals which will generate the empty string.
 
612
** Then go back and compute the first sets of every nonterminal.
 
613
** The first set is the set of all terminal symbols which can begin
 
614
** a string generated by that nonterminal.
 
615
*/
 
616
void FindFirstSets(lemp)
 
617
struct lemon *lemp;
 
618
{
 
619
  int i, j;
 
620
  struct rule *rp;
 
621
  int progress;
 
622
 
 
623
  for(i=0; i<lemp->nsymbol; i++){
 
624
    lemp->symbols[i]->lambda = B_FALSE;
 
625
  }
 
626
  for(i=lemp->nterminal; i<lemp->nsymbol; i++){
 
627
    lemp->symbols[i]->firstset = SetNew();
 
628
  }
 
629
 
 
630
  /* First compute all lambdas */
 
631
  do{
 
632
    progress = 0;
 
633
    for(rp=lemp->rule; rp; rp=rp->next){
 
634
      if( rp->lhs->lambda ) continue;
 
635
      for(i=0; i<rp->nrhs; i++){
 
636
         struct symbol *sp = rp->rhs[i];
 
637
         if( sp->type!=TERMINAL || sp->lambda==B_FALSE ) break;
 
638
      }
 
639
      if( i==rp->nrhs ){
 
640
        rp->lhs->lambda = B_TRUE;
 
641
        progress = 1;
 
642
      }
 
643
    }
 
644
  }while( progress );
 
645
 
 
646
  /* Now compute all first sets */
 
647
  do{
 
648
    struct symbol *s1, *s2;
 
649
    progress = 0;
 
650
    for(rp=lemp->rule; rp; rp=rp->next){
 
651
      s1 = rp->lhs;
 
652
      for(i=0; i<rp->nrhs; i++){
 
653
        s2 = rp->rhs[i];
 
654
        if( s2->type==TERMINAL ){
 
655
          progress += SetAdd(s1->firstset,s2->index);
 
656
          break;
 
657
        }else if( s2->type==MULTITERMINAL ){
 
658
          for(j=0; j<s2->nsubsym; j++){
 
659
            progress += SetAdd(s1->firstset,s2->subsym[j]->index);
 
660
          }
 
661
          break;
 
662
        }else if( s1==s2 ){
 
663
          if( s1->lambda==B_FALSE ) break;
 
664
        }else{
 
665
          progress += SetUnion(s1->firstset,s2->firstset);
 
666
          if( s2->lambda==B_FALSE ) break;
 
667
        }
 
668
      }
 
669
    }
 
670
  }while( progress );
 
671
  return;
 
672
}
 
673
 
 
674
/* Compute all LR(0) states for the grammar.  Links
 
675
** are added to between some states so that the LR(1) follow sets
 
676
** can be computed later.
 
677
*/
 
678
PRIVATE struct state *getstate(/* struct lemon * */);  /* forward reference */
 
679
void FindStates(lemp)
 
680
struct lemon *lemp;
 
681
{
 
682
  struct symbol *sp;
 
683
  struct rule *rp;
 
684
 
 
685
  Configlist_init();
 
686
 
 
687
  /* Find the start symbol */
 
688
  if( lemp->start ){
 
689
    sp = Symbol_find(lemp->start);
 
690
    if( sp==0 ){
 
691
      ErrorMsg(lemp->filename,0,
 
692
"The specified start symbol \"%s\" is not \
 
693
in a nonterminal of the grammar.  \"%s\" will be used as the start \
 
694
symbol instead.",lemp->start,lemp->rule->lhs->name);
 
695
      lemp->errorcnt++;
 
696
      sp = lemp->rule->lhs;
 
697
    }
 
698
  }else{
 
699
    sp = lemp->rule->lhs;
 
700
  }
 
701
 
 
702
  /* Make sure the start symbol doesn't occur on the right-hand side of
 
703
  ** any rule.  Report an error if it does.  (YACC would generate a new
 
704
  ** start symbol in this case.) */
 
705
  for(rp=lemp->rule; rp; rp=rp->next){
 
706
    int i;
 
707
    for(i=0; i<rp->nrhs; i++){
 
708
      if( rp->rhs[i]==sp ){   /* FIX ME:  Deal with multiterminals */
 
709
        ErrorMsg(lemp->filename,0,
 
710
"The start symbol \"%s\" occurs on the \
 
711
right-hand side of a rule. This will result in a parser which \
 
712
does not work properly.",sp->name);
 
713
        lemp->errorcnt++;
 
714
      }
 
715
    }
 
716
  }
 
717
 
 
718
  /* The basis configuration set for the first state
 
719
  ** is all rules which have the start symbol as their
 
720
  ** left-hand side */
 
721
  for(rp=sp->rule; rp; rp=rp->nextlhs){
 
722
    struct config *newcfp;
 
723
    newcfp = Configlist_addbasis(rp,0);
 
724
    SetAdd(newcfp->fws,0);
 
725
  }
 
726
 
 
727
  /* Compute the first state.  All other states will be
 
728
  ** computed automatically during the computation of the first one.
 
729
  ** The returned pointer to the first state is not used. */
 
730
  (void)getstate(lemp);
 
731
  return;
 
732
}
 
733
 
 
734
/* Return a pointer to a state which is described by the configuration
 
735
** list which has been built from calls to Configlist_add.
 
736
*/
 
737
PRIVATE void buildshifts(/* struct lemon *, struct state * */); /* Forwd ref */
 
738
PRIVATE struct state *getstate(lemp)
 
739
struct lemon *lemp;
 
740
{
 
741
  struct config *cfp, *bp;
 
742
  struct state *stp;
 
743
 
 
744
  /* Extract the sorted basis of the new state.  The basis was constructed
 
745
  ** by prior calls to "Configlist_addbasis()". */
 
746
  Configlist_sortbasis();
 
747
  bp = Configlist_basis();
 
748
 
 
749
  /* Get a state with the same basis */
 
750
  stp = State_find(bp);
 
751
  if( stp ){
 
752
    /* A state with the same basis already exists!  Copy all the follow-set
 
753
    ** propagation links from the state under construction into the
 
754
    ** preexisting state, then return a pointer to the preexisting state */
 
755
    struct config *x, *y;
 
756
    for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){
 
757
      Plink_copy(&y->bplp,x->bplp);
 
758
      Plink_delete(x->fplp);
 
759
      x->fplp = x->bplp = 0;
 
760
    }
 
761
    cfp = Configlist_return();
 
762
    Configlist_eat(cfp);
 
763
  }else{
 
764
    /* This really is a new state.  Construct all the details */
 
765
    Configlist_closure(lemp);    /* Compute the configuration closure */
 
766
    Configlist_sort();           /* Sort the configuration closure */
 
767
    cfp = Configlist_return();   /* Get a pointer to the config list */
 
768
    stp = State_new();           /* A new state structure */
 
769
    MemoryCheck(stp);
 
770
    stp->bp = bp;                /* Remember the configuration basis */
 
771
    stp->cfp = cfp;              /* Remember the configuration closure */
 
772
    stp->statenum = lemp->nstate++; /* Every state gets a sequence number */
 
773
    stp->ap = 0;                 /* No actions, yet. */
 
774
    State_insert(stp,stp->bp);   /* Add to the state table */
 
775
    buildshifts(lemp,stp);       /* Recursively compute successor states */
 
776
  }
 
777
  return stp;
 
778
}
 
779
 
 
780
/*
 
781
** Return true if two symbols are the same.
 
782
*/
 
783
int same_symbol(a,b)
 
784
struct symbol *a;
 
785
struct symbol *b;
 
786
{
 
787
  int i;
 
788
  if( a==b ) return 1;
 
789
  if( a->type!=MULTITERMINAL ) return 0;
 
790
  if( b->type!=MULTITERMINAL ) return 0;
 
791
  if( a->nsubsym!=b->nsubsym ) return 0;
 
792
  for(i=0; i<a->nsubsym; i++){
 
793
    if( a->subsym[i]!=b->subsym[i] ) return 0;
 
794
  }
 
795
  return 1;
 
796
}
 
797
 
 
798
/* Construct all successor states to the given state.  A "successor"
 
799
** state is any state which can be reached by a shift action.
 
800
*/
 
801
PRIVATE void buildshifts(lemp,stp)
 
802
struct lemon *lemp;
 
803
struct state *stp;     /* The state from which successors are computed */
 
804
{
 
805
  struct config *cfp;  /* For looping thru the config closure of "stp" */
 
806
  struct config *bcfp; /* For the inner loop on config closure of "stp" */
 
807
  struct config *new;  /* */
 
808
  struct symbol *sp;   /* Symbol following the dot in configuration "cfp" */
 
809
  struct symbol *bsp;  /* Symbol following the dot in configuration "bcfp" */
 
810
  struct state *newstp; /* A pointer to a successor state */
 
811
 
 
812
  /* Each configuration becomes complete after it contibutes to a successor
 
813
  ** state.  Initially, all configurations are incomplete */
 
814
  for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE;
 
815
 
 
816
  /* Loop through all configurations of the state "stp" */
 
817
  for(cfp=stp->cfp; cfp; cfp=cfp->next){
 
818
    if( cfp->status==COMPLETE ) continue;    /* Already used by inner loop */
 
819
    if( cfp->dot>=cfp->rp->nrhs ) continue;  /* Can't shift this config */
 
820
    Configlist_reset();                      /* Reset the new config set */
 
821
    sp = cfp->rp->rhs[cfp->dot];             /* Symbol after the dot */
 
822
 
 
823
    /* For every configuration in the state "stp" which has the symbol "sp"
 
824
    ** following its dot, add the same configuration to the basis set under
 
825
    ** construction but with the dot shifted one symbol to the right. */
 
826
    for(bcfp=cfp; bcfp; bcfp=bcfp->next){
 
827
      if( bcfp->status==COMPLETE ) continue;    /* Already used */
 
828
      if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */
 
829
      bsp = bcfp->rp->rhs[bcfp->dot];           /* Get symbol after dot */
 
830
      if( !same_symbol(bsp,sp) ) continue;      /* Must be same as for "cfp" */
 
831
      bcfp->status = COMPLETE;                  /* Mark this config as used */
 
832
      new = Configlist_addbasis(bcfp->rp,bcfp->dot+1);
 
833
      Plink_add(&new->bplp,bcfp);
 
834
    }
 
835
 
 
836
    /* Get a pointer to the state described by the basis configuration set
 
837
    ** constructed in the preceding loop */
 
838
    newstp = getstate(lemp);
 
839
 
 
840
    /* The state "newstp" is reached from the state "stp" by a shift action
 
841
    ** on the symbol "sp" */
 
842
    if( sp->type==MULTITERMINAL ){
 
843
      int i;
 
844
      for(i=0; i<sp->nsubsym; i++){
 
845
        Action_add(&stp->ap,SHIFT,sp->subsym[i],(char*)newstp);
 
846
      }
 
847
    }else{
 
848
      Action_add(&stp->ap,SHIFT,sp,(char *)newstp);
 
849
    }
 
850
  }
 
851
}
 
852
 
 
853
/*
 
854
** Construct the propagation links
 
855
*/
 
856
void FindLinks(lemp)
 
857
struct lemon *lemp;
 
858
{
 
859
  int i;
 
860
  struct config *cfp, *other;
 
861
  struct state *stp;
 
862
  struct plink *plp;
 
863
 
 
864
  /* Housekeeping detail:
 
865
  ** Add to every propagate link a pointer back to the state to
 
866
  ** which the link is attached. */
 
867
  for(i=0; i<lemp->nstate; i++){
 
868
    stp = lemp->sorted[i];
 
869
    for(cfp=stp->cfp; cfp; cfp=cfp->next){
 
870
      cfp->stp = stp;
 
871
    }
 
872
  }
 
873
 
 
874
  /* Convert all backlinks into forward links.  Only the forward
 
875
  ** links are used in the follow-set computation. */
 
876
  for(i=0; i<lemp->nstate; i++){
 
877
    stp = lemp->sorted[i];
 
878
    for(cfp=stp->cfp; cfp; cfp=cfp->next){
 
879
      for(plp=cfp->bplp; plp; plp=plp->next){
 
880
        other = plp->cfp;
 
881
        Plink_add(&other->fplp,cfp);
 
882
      }
 
883
    }
 
884
  }
 
885
}
 
886
 
 
887
/* Compute all followsets.
 
888
**
 
889
** A followset is the set of all symbols which can come immediately
 
890
** after a configuration.
 
891
*/
 
892
void FindFollowSets(lemp)
 
893
struct lemon *lemp;
 
894
{
 
895
  int i;
 
896
  struct config *cfp;
 
897
  struct plink *plp;
 
898
  int progress;
 
899
  int change;
 
900
 
 
901
  for(i=0; i<lemp->nstate; i++){
 
902
    for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
 
903
      cfp->status = INCOMPLETE;
 
904
    }
 
905
  }
 
906
  
 
907
  do{
 
908
    progress = 0;
 
909
    for(i=0; i<lemp->nstate; i++){
 
910
      for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){
 
911
        if( cfp->status==COMPLETE ) continue;
 
912
        for(plp=cfp->fplp; plp; plp=plp->next){
 
913
          change = SetUnion(plp->cfp->fws,cfp->fws);
 
914
          if( change ){
 
915
            plp->cfp->status = INCOMPLETE;
 
916
            progress = 1;
 
917
          }
 
918
        }
 
919
        cfp->status = COMPLETE;
 
920
      }
 
921
    }
 
922
  }while( progress );
 
923
}
 
924
 
 
925
static int resolve_conflict();
 
926
 
 
927
/* Compute the reduce actions, and resolve conflicts.
 
928
*/
 
929
void FindActions(lemp)
 
930
struct lemon *lemp;
 
931
{
 
932
  int i,j;
 
933
  struct config *cfp;
 
934
  struct state *stp;
 
935
  struct symbol *sp;
 
936
  struct rule *rp;
 
937
 
 
938
  /* Add all of the reduce actions 
 
939
  ** A reduce action is added for each element of the followset of
 
940
  ** a configuration which has its dot at the extreme right.
 
941
  */
 
942
  for(i=0; i<lemp->nstate; i++){   /* Loop over all states */
 
943
    stp = lemp->sorted[i];
 
944
    for(cfp=stp->cfp; cfp; cfp=cfp->next){  /* Loop over all configurations */
 
945
      if( cfp->rp->nrhs==cfp->dot ){        /* Is dot at extreme right? */
 
946
        for(j=0; j<lemp->nterminal; j++){
 
947
          if( SetFind(cfp->fws,j) ){
 
948
            /* Add a reduce action to the state "stp" which will reduce by the
 
949
            ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
 
950
            Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
 
951
          }
 
952
        }
 
953
      }
 
954
    }
 
955
  }
 
956
 
 
957
  /* Add the accepting token */
 
958
  if( lemp->start ){
 
959
    sp = Symbol_find(lemp->start);
 
960
    if( sp==0 ) sp = lemp->rule->lhs;
 
961
  }else{
 
962
    sp = lemp->rule->lhs;
 
963
  }
 
964
  /* Add to the first state (which is always the starting state of the
 
965
  ** finite state machine) an action to ACCEPT if the lookahead is the
 
966
  ** start nonterminal.  */
 
967
  Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0);
 
968
 
 
969
  /* Resolve conflicts */
 
970
  for(i=0; i<lemp->nstate; i++){
 
971
    struct action *ap, *nap;
 
972
    struct state *stp;
 
973
    stp = lemp->sorted[i];
 
974
    assert( stp->ap );
 
975
    stp->ap = Action_sort(stp->ap);
 
976
    for(ap=stp->ap; ap && ap->next; ap=ap->next){
 
977
      for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){
 
978
         /* The two actions "ap" and "nap" have the same lookahead.
 
979
         ** Figure out which one should be used */
 
980
         lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym);
 
981
      }
 
982
    }
 
983
  }
 
984
 
 
985
  /* Report an error for each rule that can never be reduced. */
 
986
  for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = B_FALSE;
 
987
  for(i=0; i<lemp->nstate; i++){
 
988
    struct action *ap;
 
989
    for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){
 
990
      if( ap->type==REDUCE ) ap->x.rp->canReduce = B_TRUE;
 
991
    }
 
992
  }
 
993
  for(rp=lemp->rule; rp; rp=rp->next){
 
994
    if( rp->canReduce ) continue;
 
995
    ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n");
 
996
    lemp->errorcnt++;
 
997
  }
 
998
}
 
999
 
 
1000
/* Resolve a conflict between the two given actions.  If the
 
1001
** conflict can't be resolve, return non-zero.
 
1002
**
 
1003
** NO LONGER TRUE:
 
1004
**   To resolve a conflict, first look to see if either action
 
1005
**   is on an error rule.  In that case, take the action which
 
1006
**   is not associated with the error rule.  If neither or both
 
1007
**   actions are associated with an error rule, then try to
 
1008
**   use precedence to resolve the conflict.
 
1009
**
 
1010
** If either action is a SHIFT, then it must be apx.  This
 
1011
** function won't work if apx->type==REDUCE and apy->type==SHIFT.
 
1012
*/
 
1013
static int resolve_conflict(apx,apy,errsym)
 
1014
struct action *apx;
 
1015
struct action *apy;
 
1016
struct symbol *errsym;   /* The error symbol (if defined.  NULL otherwise) */
 
1017
{
 
1018
  struct symbol *spx, *spy;
 
1019
  int errcnt = 0;
 
1020
  assert( apx->sp==apy->sp );  /* Otherwise there would be no conflict */
 
1021
  if( apx->type==SHIFT && apy->type==REDUCE ){
 
1022
    spx = apx->sp;
 
1023
    spy = apy->x.rp->precsym;
 
1024
    if( spy==0 || spx->prec<0 || spy->prec<0 ){
 
1025
      /* Not enough precedence information. */
 
1026
      apy->type = CONFLICT;
 
1027
      errcnt++;
 
1028
    }else if( spx->prec>spy->prec ){    /* Lower precedence wins */
 
1029
      apy->type = RD_RESOLVED;
 
1030
    }else if( spx->prec<spy->prec ){
 
1031
      apx->type = SH_RESOLVED;
 
1032
    }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */
 
1033
      apy->type = RD_RESOLVED;                             /* associativity */
 
1034
    }else if( spx->prec==spy->prec && spx->assoc==LEFT ){  /* to break tie */
 
1035
      apx->type = SH_RESOLVED;
 
1036
    }else{
 
1037
      assert( spx->prec==spy->prec && spx->assoc==NONE );
 
1038
      apy->type = CONFLICT;
 
1039
      errcnt++;
 
1040
    }
 
1041
  }else if( apx->type==REDUCE && apy->type==REDUCE ){
 
1042
    spx = apx->x.rp->precsym;
 
1043
    spy = apy->x.rp->precsym;
 
1044
    if( spx==0 || spy==0 || spx->prec<0 ||
 
1045
    spy->prec<0 || spx->prec==spy->prec ){
 
1046
      apy->type = CONFLICT;
 
1047
      errcnt++;
 
1048
    }else if( spx->prec>spy->prec ){
 
1049
      apy->type = RD_RESOLVED;
 
1050
    }else if( spx->prec<spy->prec ){
 
1051
      apx->type = RD_RESOLVED;
 
1052
    }
 
1053
  }else{
 
1054
    assert( 
 
1055
      apx->type==SH_RESOLVED ||
 
1056
      apx->type==RD_RESOLVED ||
 
1057
      apx->type==CONFLICT ||
 
1058
      apy->type==SH_RESOLVED ||
 
1059
      apy->type==RD_RESOLVED ||
 
1060
      apy->type==CONFLICT
 
1061
    );
 
1062
    /* The REDUCE/SHIFT case cannot happen because SHIFTs come before
 
1063
    ** REDUCEs on the list.  If we reach this point it must be because
 
1064
    ** the parser conflict had already been resolved. */
 
1065
  }
 
1066
  return errcnt;
 
1067
}
 
1068
/********************* From the file "configlist.c" *************************/
 
1069
/*
 
1070
** Routines to processing a configuration list and building a state
 
1071
** in the LEMON parser generator.
 
1072
*/
 
1073
 
 
1074
static struct config *freelist = 0;      /* List of free configurations */
 
1075
static struct config *current = 0;       /* Top of list of configurations */
 
1076
static struct config **currentend = 0;   /* Last on list of configs */
 
1077
static struct config *basis = 0;         /* Top of list of basis configs */
 
1078
static struct config **basisend = 0;     /* End of list of basis configs */
 
1079
 
 
1080
/* Return a pointer to a new configuration */
 
1081
PRIVATE struct config *newconfig(){
 
1082
  struct config *new;
 
1083
  if( freelist==0 ){
 
1084
    int i;
 
1085
    int amt = 3;
 
1086
    freelist = (struct config *)malloc( sizeof(struct config)*amt );
 
1087
    if( freelist==0 ){
 
1088
      fprintf(stderr,"Unable to allocate memory for a new configuration.");
 
1089
      exit(1);
 
1090
    }
 
1091
    for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1];
 
1092
    freelist[amt-1].next = 0;
 
1093
  }
 
1094
  new = freelist;
 
1095
  freelist = freelist->next;
 
1096
  return new;
 
1097
}
 
1098
 
 
1099
/* The configuration "old" is no longer used */
 
1100
PRIVATE void deleteconfig(old)
 
1101
struct config *old;
 
1102
{
 
1103
  old->next = freelist;
 
1104
  freelist = old;
 
1105
}
 
1106
 
 
1107
/* Initialized the configuration list builder */
 
1108
void Configlist_init(){
 
1109
  current = 0;
 
1110
  currentend = &current;
 
1111
  basis = 0;
 
1112
  basisend = &basis;
 
1113
  Configtable_init();
 
1114
  return;
 
1115
}
 
1116
 
 
1117
/* Initialized the configuration list builder */
 
1118
void Configlist_reset(){
 
1119
  current = 0;
 
1120
  currentend = &current;
 
1121
  basis = 0;
 
1122
  basisend = &basis;
 
1123
  Configtable_clear(0);
 
1124
  return;
 
1125
}
 
1126
 
 
1127
/* Add another configuration to the configuration list */
 
1128
struct config *Configlist_add(rp,dot)
 
1129
struct rule *rp;    /* The rule */
 
1130
int dot;            /* Index into the RHS of the rule where the dot goes */
 
1131
{
 
1132
  struct config *cfp, model;
 
1133
 
 
1134
  assert( currentend!=0 );
 
1135
  model.rp = rp;
 
1136
  model.dot = dot;
 
1137
  cfp = Configtable_find(&model);
 
1138
  if( cfp==0 ){
 
1139
    cfp = newconfig();
 
1140
    cfp->rp = rp;
 
1141
    cfp->dot = dot;
 
1142
    cfp->fws = SetNew();
 
1143
    cfp->stp = 0;
 
1144
    cfp->fplp = cfp->bplp = 0;
 
1145
    cfp->next = 0;
 
1146
    cfp->bp = 0;
 
1147
    *currentend = cfp;
 
1148
    currentend = &cfp->next;
 
1149
    Configtable_insert(cfp);
 
1150
  }
 
1151
  return cfp;
 
1152
}
 
1153
 
 
1154
/* Add a basis configuration to the configuration list */
 
1155
struct config *Configlist_addbasis(rp,dot)
 
1156
struct rule *rp;
 
1157
int dot;
 
1158
{
 
1159
  struct config *cfp, model;
 
1160
 
 
1161
  assert( basisend!=0 );
 
1162
  assert( currentend!=0 );
 
1163
  model.rp = rp;
 
1164
  model.dot = dot;
 
1165
  cfp = Configtable_find(&model);
 
1166
  if( cfp==0 ){
 
1167
    cfp = newconfig();
 
1168
    cfp->rp = rp;
 
1169
    cfp->dot = dot;
 
1170
    cfp->fws = SetNew();
 
1171
    cfp->stp = 0;
 
1172
    cfp->fplp = cfp->bplp = 0;
 
1173
    cfp->next = 0;
 
1174
    cfp->bp = 0;
 
1175
    *currentend = cfp;
 
1176
    currentend = &cfp->next;
 
1177
    *basisend = cfp;
 
1178
    basisend = &cfp->bp;
 
1179
    Configtable_insert(cfp);
 
1180
  }
 
1181
  return cfp;
 
1182
}
 
1183
 
 
1184
/* Compute the closure of the configuration list */
 
1185
void Configlist_closure(lemp)
 
1186
struct lemon *lemp;
 
1187
{
 
1188
  struct config *cfp, *newcfp;
 
1189
  struct rule *rp, *newrp;
 
1190
  struct symbol *sp, *xsp;
 
1191
  int i, dot;
 
1192
 
 
1193
  assert( currentend!=0 );
 
1194
  for(cfp=current; cfp; cfp=cfp->next){
 
1195
    rp = cfp->rp;
 
1196
    dot = cfp->dot;
 
1197
    if( dot>=rp->nrhs ) continue;
 
1198
    sp = rp->rhs[dot];
 
1199
    if( sp->type==NONTERMINAL ){
 
1200
      if( sp->rule==0 && sp!=lemp->errsym ){
 
1201
        ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.",
 
1202
          sp->name);
 
1203
        lemp->errorcnt++;
 
1204
      }
 
1205
      for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){
 
1206
        newcfp = Configlist_add(newrp,0);
 
1207
        for(i=dot+1; i<rp->nrhs; i++){
 
1208
          xsp = rp->rhs[i];
 
1209
          if( xsp->type==TERMINAL ){
 
1210
            SetAdd(newcfp->fws,xsp->index);
 
1211
            break;
 
1212
          }else if( xsp->type==MULTITERMINAL ){
 
1213
            int k;
 
1214
            for(k=0; k<xsp->nsubsym; k++){
 
1215
              SetAdd(newcfp->fws, xsp->subsym[k]->index);
 
1216
            }
 
1217
            break;
 
1218
          }else{
 
1219
            SetUnion(newcfp->fws,xsp->firstset);
 
1220
            if( xsp->lambda==B_FALSE ) break;
 
1221
          }
 
1222
        }
 
1223
        if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
 
1224
      }
 
1225
    }
 
1226
  }
 
1227
  return;
 
1228
}
 
1229
 
 
1230
/* Sort the configuration list */
 
1231
void Configlist_sort(){
 
1232
  current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp);
 
1233
  currentend = 0;
 
1234
  return;
 
1235
}
 
1236
 
 
1237
/* Sort the basis configuration list */
 
1238
void Configlist_sortbasis(){
 
1239
  basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp);
 
1240
  basisend = 0;
 
1241
  return;
 
1242
}
 
1243
 
 
1244
/* Return a pointer to the head of the configuration list and
 
1245
** reset the list */
 
1246
struct config *Configlist_return(){
 
1247
  struct config *old;
 
1248
  old = current;
 
1249
  current = 0;
 
1250
  currentend = 0;
 
1251
  return old;
 
1252
}
 
1253
 
 
1254
/* Return a pointer to the head of the configuration list and
 
1255
** reset the list */
 
1256
struct config *Configlist_basis(){
 
1257
  struct config *old;
 
1258
  old = basis;
 
1259
  basis = 0;
 
1260
  basisend = 0;
 
1261
  return old;
 
1262
}
 
1263
 
 
1264
/* Free all elements of the given configuration list */
 
1265
void Configlist_eat(cfp)
 
1266
struct config *cfp;
 
1267
{
 
1268
  struct config *nextcfp;
 
1269
  for(; cfp; cfp=nextcfp){
 
1270
    nextcfp = cfp->next;
 
1271
    assert( cfp->fplp==0 );
 
1272
    assert( cfp->bplp==0 );
 
1273
    if( cfp->fws ) SetFree(cfp->fws);
 
1274
    deleteconfig(cfp);
 
1275
  }
 
1276
  return;
 
1277
}
 
1278
/***************** From the file "error.c" *********************************/
 
1279
/*
 
1280
** Code for printing error message.
 
1281
*/
 
1282
 
 
1283
/* Find a good place to break "msg" so that its length is at least "min"
 
1284
** but no more than "max".  Make the point as close to max as possible.
 
1285
*/
 
1286
static int findbreak(msg,min,max)
 
1287
char *msg;
 
1288
int min;
 
1289
int max;
 
1290
{
 
1291
  int i,spot;
 
1292
  char c;
 
1293
  for(i=spot=min; i<=max; i++){
 
1294
    c = msg[i];
 
1295
    if( c=='\t' ) msg[i] = ' ';
 
1296
    if( c=='\n' ){ msg[i] = ' '; spot = i; break; }
 
1297
    if( c==0 ){ spot = i; break; }
 
1298
    if( c=='-' && i<max-1 ) spot = i+1;
 
1299
    if( c==' ' ) spot = i;
 
1300
  }
 
1301
  return spot;
 
1302
}
 
1303
 
 
1304
/*
 
1305
** The error message is split across multiple lines if necessary.  The
 
1306
** splits occur at a space, if there is a space available near the end
 
1307
** of the line.
 
1308
*/
 
1309
#define ERRMSGSIZE  10000 /* Hope this is big enough.  No way to error check */
 
1310
#define LINEWIDTH      79 /* Max width of any output line */
 
1311
#define PREFIXLIMIT    30 /* Max width of the prefix on each line */
 
1312
void ErrorMsg(const char *filename, int lineno, const char *format, ...){
 
1313
  char errmsg[ERRMSGSIZE];
 
1314
  char prefix[PREFIXLIMIT+10];
 
1315
  int errmsgsize;
 
1316
  int prefixsize;
 
1317
  int availablewidth;
 
1318
  va_list ap;
 
1319
  int end, restart, base;
 
1320
 
 
1321
  va_start(ap, format);
 
1322
  /* Prepare a prefix to be prepended to every output line */
 
1323
  if( lineno>0 ){
 
1324
    sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno);
 
1325
  }else{
 
1326
    sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename);
 
1327
  }
 
1328
  prefixsize = strlen(prefix);
 
1329
  availablewidth = LINEWIDTH - prefixsize;
 
1330
 
 
1331
  /* Generate the error message */
 
1332
  vsprintf(errmsg,format,ap);
 
1333
  va_end(ap);
 
1334
  errmsgsize = strlen(errmsg);
 
1335
  /* Remove trailing '\n's from the error message. */
 
1336
  while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){
 
1337
     errmsg[--errmsgsize] = 0;
 
1338
  }
 
1339
 
 
1340
  /* Print the error message */
 
1341
  base = 0;
 
1342
  while( errmsg[base]!=0 ){
 
1343
    end = restart = findbreak(&errmsg[base],0,availablewidth);
 
1344
    restart += base;
 
1345
    while( errmsg[restart]==' ' ) restart++;
 
1346
    fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]);
 
1347
    base = restart;
 
1348
  }
 
1349
}
 
1350
/**************** From the file "main.c" ************************************/
 
1351
/*
 
1352
** Main program file for the LEMON parser generator.
 
1353
*/
 
1354
 
 
1355
/* Report an out-of-memory condition and abort.  This function
 
1356
** is used mostly by the "MemoryCheck" macro in struct.h
 
1357
*/
 
1358
void memory_error(){
 
1359
  fprintf(stderr,"Out of memory.  Aborting...\n");
 
1360
  exit(1);
 
1361
}
 
1362
 
 
1363
static int nDefine = 0;      /* Number of -D options on the command line */
 
1364
static char **azDefine = 0;  /* Name of the -D macros */
 
1365
 
 
1366
/* This routine is called with the argument to each -D command-line option.
 
1367
** Add the macro defined to the azDefine array.
 
1368
*/
 
1369
static void handle_D_option(char *z){
 
1370
  char **paz;
 
1371
  nDefine++;
 
1372
  azDefine = realloc(azDefine, sizeof(azDefine[0])*nDefine);
 
1373
  if( azDefine==0 ){
 
1374
    fprintf(stderr,"out of memory\n");
 
1375
    exit(1);
 
1376
  }
 
1377
  paz = &azDefine[nDefine-1];
 
1378
  *paz = malloc( strlen(z)+1 );
 
1379
  if( *paz==0 ){
 
1380
    fprintf(stderr,"out of memory\n");
 
1381
    exit(1);
 
1382
  }
 
1383
  strcpy(*paz, z);
 
1384
  for(z=*paz; *z && *z!='='; z++){}
 
1385
  *z = 0;
 
1386
}
 
1387
 
 
1388
 
 
1389
/* The main program.  Parse the command line and do it... */
 
1390
int main(argc,argv)
 
1391
int argc;
 
1392
char **argv;
 
1393
{
 
1394
  static int version = 0;
 
1395
  static int rpflag = 0;
 
1396
  static int basisflag = 0;
 
1397
  static int compress = 0;
 
1398
  static int quiet = 0;
 
1399
  static int statistics = 0;
 
1400
  static int mhflag = 0;
 
1401
  static struct s_options options[] = {
 
1402
    {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."},
 
1403
    {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."},
 
1404
    {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."},
 
1405
    {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."},
 
1406
    {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"},
 
1407
    {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."},
 
1408
    {OPT_FLAG, "s", (char*)&statistics,
 
1409
                                   "Print parser stats to standard output."},
 
1410
    {OPT_FLAG, "x", (char*)&version, "Print the version number."},
 
1411
    {OPT_FLAG,0,0,0}
 
1412
  };
 
1413
  int i;
 
1414
  struct lemon lem;
 
1415
 
 
1416
  OptInit(argv,options,stderr);
 
1417
  if( version ){
 
1418
     printf("Lemon version 1.0\n");
 
1419
     exit(0); 
 
1420
  }
 
1421
  if( OptNArgs()!=1 ){
 
1422
    fprintf(stderr,"Exactly one filename argument is required.\n");
 
1423
    exit(1);
 
1424
  }
 
1425
  lem.errorcnt = 0;
 
1426
 
 
1427
  /* Initialize the machine */
 
1428
  Strsafe_init();
 
1429
  Symbol_init();
 
1430
  State_init();
 
1431
  lem.argv0 = argv[0];
 
1432
  lem.filename = OptArg(0);
 
1433
  lem.basisflag = basisflag;
 
1434
  lem.has_fallback = 0;
 
1435
  lem.nconflict = 0;
 
1436
  lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
 
1437
  lem.vartype = 0;
 
1438
  lem.stacksize = 0;
 
1439
  lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
 
1440
     lem.tokenprefix = lem.outname = lem.extracode = 0;
 
1441
  lem.vardest = 0;
 
1442
  lem.tablesize = 0;
 
1443
  Symbol_new("$");
 
1444
  lem.errsym = Symbol_new("error");
 
1445
 
 
1446
  /* Parse the input file */
 
1447
  Parse(&lem);
 
1448
  if( lem.errorcnt ) exit(lem.errorcnt);
 
1449
  if( lem.rule==0 ){
 
1450
    fprintf(stderr,"Empty grammar.\n");
 
1451
    exit(1);
 
1452
  }
 
1453
 
 
1454
  /* Count and index the symbols of the grammar */
 
1455
  lem.nsymbol = Symbol_count();
 
1456
  Symbol_new("{default}");
 
1457
  lem.symbols = Symbol_arrayof();
 
1458
  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
 
1459
  qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
 
1460
        (int(*)())Symbolcmpp);
 
1461
  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
 
1462
  for(i=1; isupper(lem.symbols[i]->name[0]); i++);
 
1463
  lem.nterminal = i;
 
1464
 
 
1465
  /* Generate a reprint of the grammar, if requested on the command line */
 
1466
  if( rpflag ){
 
1467
    Reprint(&lem);
 
1468
  }else{
 
1469
    /* Initialize the size for all follow and first sets */
 
1470
    SetSize(lem.nterminal);
 
1471
 
 
1472
    /* Find the precedence for every production rule (that has one) */
 
1473
    FindRulePrecedences(&lem);
 
1474
 
 
1475
    /* Compute the lambda-nonterminals and the first-sets for every
 
1476
    ** nonterminal */
 
1477
    FindFirstSets(&lem);
 
1478
 
 
1479
    /* Compute all LR(0) states.  Also record follow-set propagation
 
1480
    ** links so that the follow-set can be computed later */
 
1481
    lem.nstate = 0;
 
1482
    FindStates(&lem);
 
1483
    lem.sorted = State_arrayof();
 
1484
 
 
1485
    /* Tie up loose ends on the propagation links */
 
1486
    FindLinks(&lem);
 
1487
 
 
1488
    /* Compute the follow set of every reducible configuration */
 
1489
    FindFollowSets(&lem);
 
1490
 
 
1491
    /* Compute the action tables */
 
1492
    FindActions(&lem);
 
1493
 
 
1494
    /* Compress the action tables */
 
1495
    if( compress==0 ) CompressTables(&lem);
 
1496
 
 
1497
    /* Reorder and renumber the states so that states with fewer choices
 
1498
    ** occur at the end. */
 
1499
    ResortStates(&lem);
 
1500
 
 
1501
    /* Generate a report of the parser generated.  (the "y.output" file) */
 
1502
    if( !quiet ) ReportOutput(&lem);
 
1503
 
 
1504
    /* Generate the source code for the parser */
 
1505
    ReportTable(&lem, mhflag);
 
1506
 
 
1507
    /* Produce a header file for use by the scanner.  (This step is
 
1508
    ** omitted if the "-m" option is used because makeheaders will
 
1509
    ** generate the file for us.) */
 
1510
    if( !mhflag ) ReportHeader(&lem);
 
1511
  }
 
1512
  if( statistics ){
 
1513
    printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
 
1514
      lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule);
 
1515
    printf("                   %d states, %d parser table entries, %d conflicts\n",
 
1516
      lem.nstate, lem.tablesize, lem.nconflict);
 
1517
  }
 
1518
  if( lem.nconflict ){
 
1519
    fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict);
 
1520
  }
 
1521
  exit(lem.errorcnt + lem.nconflict);
 
1522
  return (lem.errorcnt + lem.nconflict);
 
1523
}
 
1524
/******************** From the file "msort.c" *******************************/
 
1525
/*
 
1526
** A generic merge-sort program.
 
1527
**
 
1528
** USAGE:
 
1529
** Let "ptr" be a pointer to some structure which is at the head of
 
1530
** a null-terminated list.  Then to sort the list call:
 
1531
**
 
1532
**     ptr = msort(ptr,&(ptr->next),cmpfnc);
 
1533
**
 
1534
** In the above, "cmpfnc" is a pointer to a function which compares
 
1535
** two instances of the structure and returns an integer, as in
 
1536
** strcmp.  The second argument is a pointer to the pointer to the
 
1537
** second element of the linked list.  This address is used to compute
 
1538
** the offset to the "next" field within the structure.  The offset to
 
1539
** the "next" field must be constant for all structures in the list.
 
1540
**
 
1541
** The function returns a new pointer which is the head of the list
 
1542
** after sorting.
 
1543
**
 
1544
** ALGORITHM:
 
1545
** Merge-sort.
 
1546
*/
 
1547
 
 
1548
/*
 
1549
** Return a pointer to the next structure in the linked list.
 
1550
*/
 
1551
#define NEXT(A) (*(char**)(((unsigned long)A)+offset))
 
1552
 
 
1553
/*
 
1554
** Inputs:
 
1555
**   a:       A sorted, null-terminated linked list.  (May be null).
 
1556
**   b:       A sorted, null-terminated linked list.  (May be null).
 
1557
**   cmp:     A pointer to the comparison function.
 
1558
**   offset:  Offset in the structure to the "next" field.
 
1559
**
 
1560
** Return Value:
 
1561
**   A pointer to the head of a sorted list containing the elements
 
1562
**   of both a and b.
 
1563
**
 
1564
** Side effects:
 
1565
**   The "next" pointers for elements in the lists a and b are
 
1566
**   changed.
 
1567
*/
 
1568
static char *merge(a,b,cmp,offset)
 
1569
char *a;
 
1570
char *b;
 
1571
int (*cmp)();
 
1572
int offset;
 
1573
{
 
1574
  char *ptr, *head;
 
1575
 
 
1576
  if( a==0 ){
 
1577
    head = b;
 
1578
  }else if( b==0 ){
 
1579
    head = a;
 
1580
  }else{
 
1581
    if( (*cmp)(a,b)<0 ){
 
1582
      ptr = a;
 
1583
      a = NEXT(a);
 
1584
    }else{
 
1585
      ptr = b;
 
1586
      b = NEXT(b);
 
1587
    }
 
1588
    head = ptr;
 
1589
    while( a && b ){
 
1590
      if( (*cmp)(a,b)<0 ){
 
1591
        NEXT(ptr) = a;
 
1592
        ptr = a;
 
1593
        a = NEXT(a);
 
1594
      }else{
 
1595
        NEXT(ptr) = b;
 
1596
        ptr = b;
 
1597
        b = NEXT(b);
 
1598
      }
 
1599
    }
 
1600
    if( a ) NEXT(ptr) = a;
 
1601
    else    NEXT(ptr) = b;
 
1602
  }
 
1603
  return head;
 
1604
}
 
1605
 
 
1606
/*
 
1607
** Inputs:
 
1608
**   list:      Pointer to a singly-linked list of structures.
 
1609
**   next:      Pointer to pointer to the second element of the list.
 
1610
**   cmp:       A comparison function.
 
1611
**
 
1612
** Return Value:
 
1613
**   A pointer to the head of a sorted list containing the elements
 
1614
**   orginally in list.
 
1615
**
 
1616
** Side effects:
 
1617
**   The "next" pointers for elements in list are changed.
 
1618
*/
 
1619
#define LISTSIZE 30
 
1620
char *msort(list,next,cmp)
 
1621
char *list;
 
1622
char **next;
 
1623
int (*cmp)();
 
1624
{
 
1625
  unsigned long offset;
 
1626
  char *ep;
 
1627
  char *set[LISTSIZE];
 
1628
  int i;
 
1629
  offset = (unsigned long)next - (unsigned long)list;
 
1630
  for(i=0; i<LISTSIZE; i++) set[i] = 0;
 
1631
  while( list ){
 
1632
    ep = list;
 
1633
    list = NEXT(list);
 
1634
    NEXT(ep) = 0;
 
1635
    for(i=0; i<LISTSIZE-1 && set[i]!=0; i++){
 
1636
      ep = merge(ep,set[i],cmp,offset);
 
1637
      set[i] = 0;
 
1638
    }
 
1639
    set[i] = ep;
 
1640
  }
 
1641
  ep = 0;
 
1642
  for(i=0; i<LISTSIZE; i++) if( set[i] ) ep = merge(ep,set[i],cmp,offset);
 
1643
  return ep;
 
1644
}
 
1645
/************************ From the file "option.c" **************************/
 
1646
static char **argv;
 
1647
static struct s_options *op;
 
1648
static FILE *errstream;
 
1649
 
 
1650
#define ISOPT(X) ((X)[0]=='-'||(X)[0]=='+'||strchr((X),'=')!=0)
 
1651
 
 
1652
/*
 
1653
** Print the command line with a carrot pointing to the k-th character
 
1654
** of the n-th field.
 
1655
*/
 
1656
static void errline(n,k,err)
 
1657
int n;
 
1658
int k;
 
1659
FILE *err;
 
1660
{
 
1661
  int spcnt, i;
 
1662
  if( argv[0] ) fprintf(err,"%s",argv[0]);
 
1663
  spcnt = strlen(argv[0]) + 1;
 
1664
  for(i=1; i<n && argv[i]; i++){
 
1665
    fprintf(err," %s",argv[i]);
 
1666
    spcnt += strlen(argv[i])+1;
 
1667
  }
 
1668
  spcnt += k;
 
1669
  for(; argv[i]; i++) fprintf(err," %s",argv[i]);
 
1670
  if( spcnt<20 ){
 
1671
    fprintf(err,"\n%*s^-- here\n",spcnt,"");
 
1672
  }else{
 
1673
    fprintf(err,"\n%*shere --^\n",spcnt-7,"");
 
1674
  }
 
1675
}
 
1676
 
 
1677
/*
 
1678
** Return the index of the N-th non-switch argument.  Return -1
 
1679
** if N is out of range.
 
1680
*/
 
1681
static int argindex(n)
 
1682
int n;
 
1683
{
 
1684
  int i;
 
1685
  int dashdash = 0;
 
1686
  if( argv!=0 && *argv!=0 ){
 
1687
    for(i=1; argv[i]; i++){
 
1688
      if( dashdash || !ISOPT(argv[i]) ){
 
1689
        if( n==0 ) return i;
 
1690
        n--;
 
1691
      }
 
1692
      if( strcmp(argv[i],"--")==0 ) dashdash = 1;
 
1693
    }
 
1694
  }
 
1695
  return -1;
 
1696
}
 
1697
 
 
1698
static char emsg[] = "Command line syntax error: ";
 
1699
 
 
1700
/*
 
1701
** Process a flag command line argument.
 
1702
*/
 
1703
static int handleflags(i,err)
 
1704
int i;
 
1705
FILE *err;
 
1706
{
 
1707
  int v;
 
1708
  int errcnt = 0;
 
1709
  int j;
 
1710
  for(j=0; op[j].label; j++){
 
1711
    if( strncmp(&argv[i][1],op[j].label,strlen(op[j].label))==0 ) break;
 
1712
  }
 
1713
  v = argv[i][0]=='-' ? 1 : 0;
 
1714
  if( op[j].label==0 ){
 
1715
    if( err ){
 
1716
      fprintf(err,"%sundefined option.\n",emsg);
 
1717
      errline(i,1,err);
 
1718
    }
 
1719
    errcnt++;
 
1720
  }else if( op[j].type==OPT_FLAG ){
 
1721
    *((int*)op[j].arg) = v;
 
1722
  }else if( op[j].type==OPT_FFLAG ){
 
1723
    (*(void(*)())(op[j].arg))(v);
 
1724
  }else if( op[j].type==OPT_FSTR ){
 
1725
    (*(void(*)())(op[j].arg))(&argv[i][2]);
 
1726
  }else{
 
1727
    if( err ){
 
1728
      fprintf(err,"%smissing argument on switch.\n",emsg);
 
1729
      errline(i,1,err);
 
1730
    }
 
1731
    errcnt++;
 
1732
  }
 
1733
  return errcnt;
 
1734
}
 
1735
 
 
1736
/*
 
1737
** Process a command line switch which has an argument.
 
1738
*/
 
1739
static int handleswitch(i,err)
 
1740
int i;
 
1741
FILE *err;
 
1742
{
 
1743
  int lv = 0;
 
1744
  double dv = 0.0;
 
1745
  char *sv = 0, *end;
 
1746
  char *cp;
 
1747
  int j;
 
1748
  int errcnt = 0;
 
1749
  cp = strchr(argv[i],'=');
 
1750
  assert( cp!=0 );
 
1751
  *cp = 0;
 
1752
  for(j=0; op[j].label; j++){
 
1753
    if( strcmp(argv[i],op[j].label)==0 ) break;
 
1754
  }
 
1755
  *cp = '=';
 
1756
  if( op[j].label==0 ){
 
1757
    if( err ){
 
1758
      fprintf(err,"%sundefined option.\n",emsg);
 
1759
      errline(i,0,err);
 
1760
    }
 
1761
    errcnt++;
 
1762
  }else{
 
1763
    cp++;
 
1764
    switch( op[j].type ){
 
1765
      case OPT_FLAG:
 
1766
      case OPT_FFLAG:
 
1767
        if( err ){
 
1768
          fprintf(err,"%soption requires an argument.\n",emsg);
 
1769
          errline(i,0,err);
 
1770
        }
 
1771
        errcnt++;
 
1772
        break;
 
1773
      case OPT_DBL:
 
1774
      case OPT_FDBL:
 
1775
        dv = strtod(cp,&end);
 
1776
        if( *end ){
 
1777
          if( err ){
 
1778
            fprintf(err,"%sillegal character in floating-point argument.\n",emsg);
 
1779
            errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
 
1780
          }
 
1781
          errcnt++;
 
1782
        }
 
1783
        break;
 
1784
      case OPT_INT:
 
1785
      case OPT_FINT:
 
1786
        lv = strtol(cp,&end,0);
 
1787
        if( *end ){
 
1788
          if( err ){
 
1789
            fprintf(err,"%sillegal character in integer argument.\n",emsg);
 
1790
            errline(i,((unsigned long)end)-(unsigned long)argv[i],err);
 
1791
          }
 
1792
          errcnt++;
 
1793
        }
 
1794
        break;
 
1795
      case OPT_STR:
 
1796
      case OPT_FSTR:
 
1797
        sv = cp;
 
1798
        break;
 
1799
    }
 
1800
    switch( op[j].type ){
 
1801
      case OPT_FLAG:
 
1802
      case OPT_FFLAG:
 
1803
        break;
 
1804
      case OPT_DBL:
 
1805
        *(double*)(op[j].arg) = dv;
 
1806
        break;
 
1807
      case OPT_FDBL:
 
1808
        (*(void(*)())(op[j].arg))(dv);
 
1809
        break;
 
1810
      case OPT_INT:
 
1811
        *(int*)(op[j].arg) = lv;
 
1812
        break;
 
1813
      case OPT_FINT:
 
1814
        (*(void(*)())(op[j].arg))((int)lv);
 
1815
        break;
 
1816
      case OPT_STR:
 
1817
        *(char**)(op[j].arg) = sv;
 
1818
        break;
 
1819
      case OPT_FSTR:
 
1820
        (*(void(*)())(op[j].arg))(sv);
 
1821
        break;
 
1822
    }
 
1823
  }
 
1824
  return errcnt;
 
1825
}
 
1826
 
 
1827
int OptInit(a,o,err)
 
1828
char **a;
 
1829
struct s_options *o;
 
1830
FILE *err;
 
1831
{
 
1832
  int errcnt = 0;
 
1833
  argv = a;
 
1834
  op = o;
 
1835
  errstream = err;
 
1836
  if( argv && *argv && op ){
 
1837
    int i;
 
1838
    for(i=1; argv[i]; i++){
 
1839
      if( argv[i][0]=='+' || argv[i][0]=='-' ){
 
1840
        errcnt += handleflags(i,err);
 
1841
      }else if( strchr(argv[i],'=') ){
 
1842
        errcnt += handleswitch(i,err);
 
1843
      }
 
1844
    }
 
1845
  }
 
1846
  if( errcnt>0 ){
 
1847
    fprintf(err,"Valid command line options for \"%s\" are:\n",*a);
 
1848
    OptPrint();
 
1849
    exit(1);
 
1850
  }
 
1851
  return 0;
 
1852
}
 
1853
 
 
1854
int OptNArgs(){
 
1855
  int cnt = 0;
 
1856
  int dashdash = 0;
 
1857
  int i;
 
1858
  if( argv!=0 && argv[0]!=0 ){
 
1859
    for(i=1; argv[i]; i++){
 
1860
      if( dashdash || !ISOPT(argv[i]) ) cnt++;
 
1861
      if( strcmp(argv[i],"--")==0 ) dashdash = 1;
 
1862
    }
 
1863
  }
 
1864
  return cnt;
 
1865
}
 
1866
 
 
1867
char *OptArg(n)
 
1868
int n;
 
1869
{
 
1870
  int i;
 
1871
  i = argindex(n);
 
1872
  return i>=0 ? argv[i] : 0;
 
1873
}
 
1874
 
 
1875
void OptErr(n)
 
1876
int n;
 
1877
{
 
1878
  int i;
 
1879
  i = argindex(n);
 
1880
  if( i>=0 ) errline(i,0,errstream);
 
1881
}
 
1882
 
 
1883
void OptPrint(){
 
1884
  int i;
 
1885
  int max, len;
 
1886
  max = 0;
 
1887
  for(i=0; op[i].label; i++){
 
1888
    len = strlen(op[i].label) + 1;
 
1889
    switch( op[i].type ){
 
1890
      case OPT_FLAG:
 
1891
      case OPT_FFLAG:
 
1892
        break;
 
1893
      case OPT_INT:
 
1894
      case OPT_FINT:
 
1895
        len += 9;       /* length of "<integer>" */
 
1896
        break;
 
1897
      case OPT_DBL:
 
1898
      case OPT_FDBL:
 
1899
        len += 6;       /* length of "<real>" */
 
1900
        break;
 
1901
      case OPT_STR:
 
1902
      case OPT_FSTR:
 
1903
        len += 8;       /* length of "<string>" */
 
1904
        break;
 
1905
    }
 
1906
    if( len>max ) max = len;
 
1907
  }
 
1908
  for(i=0; op[i].label; i++){
 
1909
    switch( op[i].type ){
 
1910
      case OPT_FLAG:
 
1911
      case OPT_FFLAG:
 
1912
        fprintf(errstream,"  -%-*s  %s\n",max,op[i].label,op[i].message);
 
1913
        break;
 
1914
      case OPT_INT:
 
1915
      case OPT_FINT:
 
1916
        fprintf(errstream,"  %s=<integer>%*s  %s\n",op[i].label,
 
1917
          (int)(max-strlen(op[i].label)-9),"",op[i].message);
 
1918
        break;
 
1919
      case OPT_DBL:
 
1920
      case OPT_FDBL:
 
1921
        fprintf(errstream,"  %s=<real>%*s  %s\n",op[i].label,
 
1922
          (int)(max-strlen(op[i].label)-6),"",op[i].message);
 
1923
        break;
 
1924
      case OPT_STR:
 
1925
      case OPT_FSTR:
 
1926
        fprintf(errstream,"  %s=<string>%*s  %s\n",op[i].label,
 
1927
          (int)(max-strlen(op[i].label)-8),"",op[i].message);
 
1928
        break;
 
1929
    }
 
1930
  }
 
1931
}
 
1932
/*********************** From the file "parse.c" ****************************/
 
1933
/*
 
1934
** Input file parser for the LEMON parser generator.
 
1935
*/
 
1936
 
 
1937
/* The state of the parser */
 
1938
struct pstate {
 
1939
  char *filename;       /* Name of the input file */
 
1940
  int tokenlineno;      /* Linenumber at which current token starts */
 
1941
  int errorcnt;         /* Number of errors so far */
 
1942
  char *tokenstart;     /* Text of current token */
 
1943
  struct lemon *gp;     /* Global state vector */
 
1944
  enum e_state {
 
1945
    INITIALIZE,
 
1946
    WAITING_FOR_DECL_OR_RULE,
 
1947
    WAITING_FOR_DECL_KEYWORD,
 
1948
    WAITING_FOR_DECL_ARG,
 
1949
    WAITING_FOR_PRECEDENCE_SYMBOL,
 
1950
    WAITING_FOR_ARROW,
 
1951
    IN_RHS,
 
1952
    LHS_ALIAS_1,
 
1953
    LHS_ALIAS_2,
 
1954
    LHS_ALIAS_3,
 
1955
    RHS_ALIAS_1,
 
1956
    RHS_ALIAS_2,
 
1957
    PRECEDENCE_MARK_1,
 
1958
    PRECEDENCE_MARK_2,
 
1959
    RESYNC_AFTER_RULE_ERROR,
 
1960
    RESYNC_AFTER_DECL_ERROR,
 
1961
    WAITING_FOR_DESTRUCTOR_SYMBOL,
 
1962
    WAITING_FOR_DATATYPE_SYMBOL,
 
1963
    WAITING_FOR_FALLBACK_ID
 
1964
  } state;                   /* The state of the parser */
 
1965
  struct symbol *fallback;   /* The fallback token */
 
1966
  struct symbol *lhs;        /* Left-hand side of current rule */
 
1967
  char *lhsalias;            /* Alias for the LHS */
 
1968
  int nrhs;                  /* Number of right-hand side symbols seen */
 
1969
  struct symbol *rhs[MAXRHS];  /* RHS symbols */
 
1970
  char *alias[MAXRHS];       /* Aliases for each RHS symbol (or NULL) */
 
1971
  struct rule *prevrule;     /* Previous rule parsed */
 
1972
  char *declkeyword;         /* Keyword of a declaration */
 
1973
  char **declargslot;        /* Where the declaration argument should be put */
 
1974
  int *decllnslot;           /* Where the declaration linenumber is put */
 
1975
  enum e_assoc declassoc;    /* Assign this association to decl arguments */
 
1976
  int preccounter;           /* Assign this precedence to decl arguments */
 
1977
  struct rule *firstrule;    /* Pointer to first rule in the grammar */
 
1978
  struct rule *lastrule;     /* Pointer to the most recently parsed rule */
 
1979
};
 
1980
 
 
1981
/* Parse a single token */
 
1982
static void parseonetoken(psp)
 
1983
struct pstate *psp;
 
1984
{
 
1985
  char *x;
 
1986
  x = Strsafe(psp->tokenstart);     /* Save the token permanently */
 
1987
#if 0
 
1988
  printf("%s:%d: Token=[%s] state=%d\n",psp->filename,psp->tokenlineno,
 
1989
    x,psp->state);
 
1990
#endif
 
1991
  switch( psp->state ){
 
1992
    case INITIALIZE:
 
1993
      psp->prevrule = 0;
 
1994
      psp->preccounter = 0;
 
1995
      psp->firstrule = psp->lastrule = 0;
 
1996
      psp->gp->nrule = 0;
 
1997
      /* Fall thru to next case */
 
1998
    case WAITING_FOR_DECL_OR_RULE:
 
1999
      if( x[0]=='%' ){
 
2000
        psp->state = WAITING_FOR_DECL_KEYWORD;
 
2001
      }else if( islower(x[0]) ){
 
2002
        psp->lhs = Symbol_new(x);
 
2003
        psp->nrhs = 0;
 
2004
        psp->lhsalias = 0;
 
2005
        psp->state = WAITING_FOR_ARROW;
 
2006
      }else if( x[0]=='{' ){
 
2007
        if( psp->prevrule==0 ){
 
2008
          ErrorMsg(psp->filename,psp->tokenlineno,
 
2009
"There is not prior rule opon which to attach the code \
 
2010
fragment which begins on this line.");
 
2011
          psp->errorcnt++;
 
2012
        }else if( psp->prevrule->code!=0 ){
 
2013
          ErrorMsg(psp->filename,psp->tokenlineno,
 
2014
"Code fragment beginning on this line is not the first \
 
2015
to follow the previous rule.");
 
2016
          psp->errorcnt++;
 
2017
        }else{
 
2018
          psp->prevrule->line = psp->tokenlineno;
 
2019
          psp->prevrule->code = &x[1];
 
2020
        }
 
2021
      }else if( x[0]=='[' ){
 
2022
        psp->state = PRECEDENCE_MARK_1;
 
2023
      }else{
 
2024
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2025
          "Token \"%s\" should be either \"%%\" or a nonterminal name.",
 
2026
          x);
 
2027
        psp->errorcnt++;
 
2028
      }
 
2029
      break;
 
2030
    case PRECEDENCE_MARK_1:
 
2031
      if( !isupper(x[0]) ){
 
2032
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2033
          "The precedence symbol must be a terminal.");
 
2034
        psp->errorcnt++;
 
2035
      }else if( psp->prevrule==0 ){
 
2036
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2037
          "There is no prior rule to assign precedence \"[%s]\".",x);
 
2038
        psp->errorcnt++;
 
2039
      }else if( psp->prevrule->precsym!=0 ){
 
2040
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2041
"Precedence mark on this line is not the first \
 
2042
to follow the previous rule.");
 
2043
        psp->errorcnt++;
 
2044
      }else{
 
2045
        psp->prevrule->precsym = Symbol_new(x);
 
2046
      }
 
2047
      psp->state = PRECEDENCE_MARK_2;
 
2048
      break;
 
2049
    case PRECEDENCE_MARK_2:
 
2050
      if( x[0]!=']' ){
 
2051
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2052
          "Missing \"]\" on precedence mark.");
 
2053
        psp->errorcnt++;
 
2054
      }
 
2055
      psp->state = WAITING_FOR_DECL_OR_RULE;
 
2056
      break;
 
2057
    case WAITING_FOR_ARROW:
 
2058
      if( x[0]==':' && x[1]==':' && x[2]=='=' ){
 
2059
        psp->state = IN_RHS;
 
2060
      }else if( x[0]=='(' ){
 
2061
        psp->state = LHS_ALIAS_1;
 
2062
      }else{
 
2063
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2064
          "Expected to see a \":\" following the LHS symbol \"%s\".",
 
2065
          psp->lhs->name);
 
2066
        psp->errorcnt++;
 
2067
        psp->state = RESYNC_AFTER_RULE_ERROR;
 
2068
      }
 
2069
      break;
 
2070
    case LHS_ALIAS_1:
 
2071
      if( isalpha(x[0]) ){
 
2072
        psp->lhsalias = x;
 
2073
        psp->state = LHS_ALIAS_2;
 
2074
      }else{
 
2075
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2076
          "\"%s\" is not a valid alias for the LHS \"%s\"\n",
 
2077
          x,psp->lhs->name);
 
2078
        psp->errorcnt++;
 
2079
        psp->state = RESYNC_AFTER_RULE_ERROR;
 
2080
      }
 
2081
      break;
 
2082
    case LHS_ALIAS_2:
 
2083
      if( x[0]==')' ){
 
2084
        psp->state = LHS_ALIAS_3;
 
2085
      }else{
 
2086
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2087
          "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
 
2088
        psp->errorcnt++;
 
2089
        psp->state = RESYNC_AFTER_RULE_ERROR;
 
2090
      }
 
2091
      break;
 
2092
    case LHS_ALIAS_3:
 
2093
      if( x[0]==':' && x[1]==':' && x[2]=='=' ){
 
2094
        psp->state = IN_RHS;
 
2095
      }else{
 
2096
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2097
          "Missing \"->\" following: \"%s(%s)\".",
 
2098
           psp->lhs->name,psp->lhsalias);
 
2099
        psp->errorcnt++;
 
2100
        psp->state = RESYNC_AFTER_RULE_ERROR;
 
2101
      }
 
2102
      break;
 
2103
    case IN_RHS:
 
2104
      if( x[0]=='.' ){
 
2105
        struct rule *rp;
 
2106
        rp = (struct rule *)malloc( sizeof(struct rule) + 
 
2107
             sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
 
2108
        if( rp==0 ){
 
2109
          ErrorMsg(psp->filename,psp->tokenlineno,
 
2110
            "Can't allocate enough memory for this rule.");
 
2111
          psp->errorcnt++;
 
2112
          psp->prevrule = 0;
 
2113
        }else{
 
2114
          int i;
 
2115
          rp->ruleline = psp->tokenlineno;
 
2116
          rp->rhs = (struct symbol**)&rp[1];
 
2117
          rp->rhsalias = (char**)&(rp->rhs[psp->nrhs]);
 
2118
          for(i=0; i<psp->nrhs; i++){
 
2119
            rp->rhs[i] = psp->rhs[i];
 
2120
            rp->rhsalias[i] = psp->alias[i];
 
2121
          }
 
2122
          rp->lhs = psp->lhs;
 
2123
          rp->lhsalias = psp->lhsalias;
 
2124
          rp->nrhs = psp->nrhs;
 
2125
          rp->code = 0;
 
2126
          rp->precsym = 0;
 
2127
          rp->index = psp->gp->nrule++;
 
2128
          rp->nextlhs = rp->lhs->rule;
 
2129
          rp->lhs->rule = rp;
 
2130
          rp->next = 0;
 
2131
          if( psp->firstrule==0 ){
 
2132
            psp->firstrule = psp->lastrule = rp;
 
2133
          }else{
 
2134
            psp->lastrule->next = rp;
 
2135
            psp->lastrule = rp;
 
2136
          }
 
2137
          psp->prevrule = rp;
 
2138
        }
 
2139
        psp->state = WAITING_FOR_DECL_OR_RULE;
 
2140
      }else if( isalpha(x[0]) ){
 
2141
        if( psp->nrhs>=MAXRHS ){
 
2142
          ErrorMsg(psp->filename,psp->tokenlineno,
 
2143
            "Too many symbols on RHS or rule beginning at \"%s\".",
 
2144
            x);
 
2145
          psp->errorcnt++;
 
2146
          psp->state = RESYNC_AFTER_RULE_ERROR;
 
2147
        }else{
 
2148
          psp->rhs[psp->nrhs] = Symbol_new(x);
 
2149
          psp->alias[psp->nrhs] = 0;
 
2150
          psp->nrhs++;
 
2151
        }
 
2152
      }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
 
2153
        struct symbol *msp = psp->rhs[psp->nrhs-1];
 
2154
        if( msp->type!=MULTITERMINAL ){
 
2155
          struct symbol *origsp = msp;
 
2156
          msp = malloc(sizeof(*msp));
 
2157
          memset(msp, 0, sizeof(*msp));
 
2158
          msp->type = MULTITERMINAL;
 
2159
          msp->nsubsym = 1;
 
2160
          msp->subsym = malloc(sizeof(struct symbol*));
 
2161
          msp->subsym[0] = origsp;
 
2162
          msp->name = origsp->name;
 
2163
          psp->rhs[psp->nrhs-1] = msp;
 
2164
        }
 
2165
        msp->nsubsym++;
 
2166
        msp->subsym = realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym);
 
2167
        msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]);
 
2168
        if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){
 
2169
          ErrorMsg(psp->filename,psp->tokenlineno,
 
2170
            "Cannot form a compound containing a non-terminal");
 
2171
          psp->errorcnt++;
 
2172
        }
 
2173
      }else if( x[0]=='(' && psp->nrhs>0 ){
 
2174
        psp->state = RHS_ALIAS_1;
 
2175
      }else{
 
2176
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2177
          "Illegal character on RHS of rule: \"%s\".",x);
 
2178
        psp->errorcnt++;
 
2179
        psp->state = RESYNC_AFTER_RULE_ERROR;
 
2180
      }
 
2181
      break;
 
2182
    case RHS_ALIAS_1:
 
2183
      if( isalpha(x[0]) ){
 
2184
        psp->alias[psp->nrhs-1] = x;
 
2185
        psp->state = RHS_ALIAS_2;
 
2186
      }else{
 
2187
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2188
          "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
 
2189
          x,psp->rhs[psp->nrhs-1]->name);
 
2190
        psp->errorcnt++;
 
2191
        psp->state = RESYNC_AFTER_RULE_ERROR;
 
2192
      }
 
2193
      break;
 
2194
    case RHS_ALIAS_2:
 
2195
      if( x[0]==')' ){
 
2196
        psp->state = IN_RHS;
 
2197
      }else{
 
2198
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2199
          "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias);
 
2200
        psp->errorcnt++;
 
2201
        psp->state = RESYNC_AFTER_RULE_ERROR;
 
2202
      }
 
2203
      break;
 
2204
    case WAITING_FOR_DECL_KEYWORD:
 
2205
      if( isalpha(x[0]) ){
 
2206
        psp->declkeyword = x;
 
2207
        psp->declargslot = 0;
 
2208
        psp->decllnslot = 0;
 
2209
        psp->state = WAITING_FOR_DECL_ARG;
 
2210
        if( strcmp(x,"name")==0 ){
 
2211
          psp->declargslot = &(psp->gp->name);
 
2212
        }else if( strcmp(x,"include")==0 ){
 
2213
          psp->declargslot = &(psp->gp->include);
 
2214
          psp->decllnslot = &psp->gp->includeln;
 
2215
        }else if( strcmp(x,"code")==0 ){
 
2216
          psp->declargslot = &(psp->gp->extracode);
 
2217
          psp->decllnslot = &psp->gp->extracodeln;
 
2218
        }else if( strcmp(x,"token_destructor")==0 ){
 
2219
          psp->declargslot = &psp->gp->tokendest;
 
2220
          psp->decllnslot = &psp->gp->tokendestln;
 
2221
        }else if( strcmp(x,"default_destructor")==0 ){
 
2222
          psp->declargslot = &psp->gp->vardest;
 
2223
          psp->decllnslot = &psp->gp->vardestln;
 
2224
        }else if( strcmp(x,"token_prefix")==0 ){
 
2225
          psp->declargslot = &psp->gp->tokenprefix;
 
2226
        }else if( strcmp(x,"syntax_error")==0 ){
 
2227
          psp->declargslot = &(psp->gp->error);
 
2228
          psp->decllnslot = &psp->gp->errorln;
 
2229
        }else if( strcmp(x,"parse_accept")==0 ){
 
2230
          psp->declargslot = &(psp->gp->accept);
 
2231
          psp->decllnslot = &psp->gp->acceptln;
 
2232
        }else if( strcmp(x,"parse_failure")==0 ){
 
2233
          psp->declargslot = &(psp->gp->failure);
 
2234
          psp->decllnslot = &psp->gp->failureln;
 
2235
        }else if( strcmp(x,"stack_overflow")==0 ){
 
2236
          psp->declargslot = &(psp->gp->overflow);
 
2237
          psp->decllnslot = &psp->gp->overflowln;
 
2238
        }else if( strcmp(x,"extra_argument")==0 ){
 
2239
          psp->declargslot = &(psp->gp->arg);
 
2240
        }else if( strcmp(x,"token_type")==0 ){
 
2241
          psp->declargslot = &(psp->gp->tokentype);
 
2242
        }else if( strcmp(x,"default_type")==0 ){
 
2243
          psp->declargslot = &(psp->gp->vartype);
 
2244
        }else if( strcmp(x,"stack_size")==0 ){
 
2245
          psp->declargslot = &(psp->gp->stacksize);
 
2246
        }else if( strcmp(x,"start_symbol")==0 ){
 
2247
          psp->declargslot = &(psp->gp->start);
 
2248
        }else if( strcmp(x,"left")==0 ){
 
2249
          psp->preccounter++;
 
2250
          psp->declassoc = LEFT;
 
2251
          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
 
2252
        }else if( strcmp(x,"right")==0 ){
 
2253
          psp->preccounter++;
 
2254
          psp->declassoc = RIGHT;
 
2255
          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
 
2256
        }else if( strcmp(x,"nonassoc")==0 ){
 
2257
          psp->preccounter++;
 
2258
          psp->declassoc = NONE;
 
2259
          psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
 
2260
        }else if( strcmp(x,"destructor")==0 ){
 
2261
          psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
 
2262
        }else if( strcmp(x,"type")==0 ){
 
2263
          psp->state = WAITING_FOR_DATATYPE_SYMBOL;
 
2264
        }else if( strcmp(x,"fallback")==0 ){
 
2265
          psp->fallback = 0;
 
2266
          psp->state = WAITING_FOR_FALLBACK_ID;
 
2267
        }else{
 
2268
          ErrorMsg(psp->filename,psp->tokenlineno,
 
2269
            "Unknown declaration keyword: \"%%%s\".",x);
 
2270
          psp->errorcnt++;
 
2271
          psp->state = RESYNC_AFTER_DECL_ERROR;
 
2272
        }
 
2273
      }else{
 
2274
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2275
          "Illegal declaration keyword: \"%s\".",x);
 
2276
        psp->errorcnt++;
 
2277
        psp->state = RESYNC_AFTER_DECL_ERROR;
 
2278
      }
 
2279
      break;
 
2280
    case WAITING_FOR_DESTRUCTOR_SYMBOL:
 
2281
      if( !isalpha(x[0]) ){
 
2282
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2283
          "Symbol name missing after %destructor keyword");
 
2284
        psp->errorcnt++;
 
2285
        psp->state = RESYNC_AFTER_DECL_ERROR;
 
2286
      }else{
 
2287
        struct symbol *sp = Symbol_new(x);
 
2288
        psp->declargslot = &sp->destructor;
 
2289
        psp->decllnslot = &sp->destructorln;
 
2290
        psp->state = WAITING_FOR_DECL_ARG;
 
2291
      }
 
2292
      break;
 
2293
    case WAITING_FOR_DATATYPE_SYMBOL:
 
2294
      if( !isalpha(x[0]) ){
 
2295
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2296
          "Symbol name missing after %destructor keyword");
 
2297
        psp->errorcnt++;
 
2298
        psp->state = RESYNC_AFTER_DECL_ERROR;
 
2299
      }else{
 
2300
        struct symbol *sp = Symbol_new(x);
 
2301
        psp->declargslot = &sp->datatype;
 
2302
        psp->decllnslot = 0;
 
2303
        psp->state = WAITING_FOR_DECL_ARG;
 
2304
      }
 
2305
      break;
 
2306
    case WAITING_FOR_PRECEDENCE_SYMBOL:
 
2307
      if( x[0]=='.' ){
 
2308
        psp->state = WAITING_FOR_DECL_OR_RULE;
 
2309
      }else if( isupper(x[0]) ){
 
2310
        struct symbol *sp;
 
2311
        sp = Symbol_new(x);
 
2312
        if( sp->prec>=0 ){
 
2313
          ErrorMsg(psp->filename,psp->tokenlineno,
 
2314
            "Symbol \"%s\" has already be given a precedence.",x);
 
2315
          psp->errorcnt++;
 
2316
        }else{
 
2317
          sp->prec = psp->preccounter;
 
2318
          sp->assoc = psp->declassoc;
 
2319
        }
 
2320
      }else{
 
2321
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2322
          "Can't assign a precedence to \"%s\".",x);
 
2323
        psp->errorcnt++;
 
2324
      }
 
2325
      break;
 
2326
    case WAITING_FOR_DECL_ARG:
 
2327
      if( (x[0]=='{' || x[0]=='\"' || isalnum(x[0])) ){
 
2328
        if( *(psp->declargslot)!=0 ){
 
2329
          ErrorMsg(psp->filename,psp->tokenlineno,
 
2330
            "The argument \"%s\" to declaration \"%%%s\" is not the first.",
 
2331
            x[0]=='\"' ? &x[1] : x,psp->declkeyword);
 
2332
          psp->errorcnt++;
 
2333
          psp->state = RESYNC_AFTER_DECL_ERROR;
 
2334
        }else{
 
2335
          *(psp->declargslot) = (x[0]=='\"' || x[0]=='{') ? &x[1] : x;
 
2336
          if( psp->decllnslot ) *psp->decllnslot = psp->tokenlineno;
 
2337
          psp->state = WAITING_FOR_DECL_OR_RULE;
 
2338
        }
 
2339
      }else{
 
2340
        ErrorMsg(psp->filename,psp->tokenlineno,
 
2341
          "Illegal argument to %%%s: %s",psp->declkeyword,x);
 
2342
        psp->errorcnt++;
 
2343
        psp->state = RESYNC_AFTER_DECL_ERROR;
 
2344
      }
 
2345
      break;
 
2346
    case WAITING_FOR_FALLBACK_ID:
 
2347
      if( x[0]=='.' ){
 
2348
        psp->state = WAITING_FOR_DECL_OR_RULE;
 
2349
      }else if( !isupper(x[0]) ){
 
2350
        ErrorMsg(psp->filename, psp->tokenlineno,
 
2351
          "%%fallback argument \"%s\" should be a token", x);
 
2352
        psp->errorcnt++;
 
2353
      }else{
 
2354
        struct symbol *sp = Symbol_new(x);
 
2355
        if( psp->fallback==0 ){
 
2356
          psp->fallback = sp;
 
2357
        }else if( sp->fallback ){
 
2358
          ErrorMsg(psp->filename, psp->tokenlineno,
 
2359
            "More than one fallback assigned to token %s", x);
 
2360
          psp->errorcnt++;
 
2361
        }else{
 
2362
          sp->fallback = psp->fallback;
 
2363
          psp->gp->has_fallback = 1;
 
2364
        }
 
2365
      }
 
2366
      break;
 
2367
    case RESYNC_AFTER_RULE_ERROR:
 
2368
/*      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
 
2369
**      break; */
 
2370
    case RESYNC_AFTER_DECL_ERROR:
 
2371
      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
 
2372
      if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD;
 
2373
      break;
 
2374
  }
 
2375
}
 
2376
 
 
2377
/* Run the proprocessor over the input file text.  The global variables
 
2378
** azDefine[0] through azDefine[nDefine-1] contains the names of all defined
 
2379
** macros.  This routine looks for "%ifdef" and "%ifndef" and "%endif" and
 
2380
** comments them out.  Text in between is also commented out as appropriate.
 
2381
*/
 
2382
static void preprocess_input(char *z){
 
2383
  int i, j, k, n;
 
2384
  int exclude = 0;
 
2385
  int start;
 
2386
  int lineno = 1;
 
2387
  int start_lineno;
 
2388
  for(i=0; z[i]; i++){
 
2389
    if( z[i]=='\n' ) lineno++;
 
2390
    if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue;
 
2391
    if( strncmp(&z[i],"%endif",6)==0 && isspace(z[i+6]) ){
 
2392
      if( exclude ){
 
2393
        exclude--;
 
2394
        if( exclude==0 ){
 
2395
          for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
 
2396
        }
 
2397
      }
 
2398
      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
 
2399
    }else if( (strncmp(&z[i],"%ifdef",6)==0 && isspace(z[i+6]))
 
2400
          || (strncmp(&z[i],"%ifndef",7)==0 && isspace(z[i+7])) ){
 
2401
      if( exclude ){
 
2402
        exclude++;
 
2403
      }else{
 
2404
        for(j=i+7; isspace(z[j]); j++){}
 
2405
        for(n=0; z[j+n] && !isspace(z[j+n]); n++){}
 
2406
        exclude = 1;
 
2407
        for(k=0; k<nDefine; k++){
 
2408
          if( strncmp(azDefine[k],&z[j],n)==0 && strlen(azDefine[k])==n ){
 
2409
            exclude = 0;
 
2410
            break;
 
2411
          }
 
2412
        }
 
2413
        if( z[i+3]=='n' ) exclude = !exclude;
 
2414
        if( exclude ){
 
2415
          start = i;
 
2416
          start_lineno = lineno;
 
2417
        }
 
2418
      }
 
2419
      for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
 
2420
    }
 
2421
  }
 
2422
  if( exclude ){
 
2423
    fprintf(stderr,"unterminated %%ifdef starting on line %d\n", start_lineno);
 
2424
    exit(1);
 
2425
  }
 
2426
}
 
2427
 
 
2428
/* In spite of its name, this function is really a scanner.  It read
 
2429
** in the entire input file (all at once) then tokenizes it.  Each
 
2430
** token is passed to the function "parseonetoken" which builds all
 
2431
** the appropriate data structures in the global state vector "gp".
 
2432
*/
 
2433
void Parse(gp)
 
2434
struct lemon *gp;
 
2435
{
 
2436
  struct pstate ps;
 
2437
  FILE *fp;
 
2438
  char *filebuf;
 
2439
  int filesize;
 
2440
  int lineno;
 
2441
  int c;
 
2442
  char *cp, *nextcp;
 
2443
  int startline = 0;
 
2444
 
 
2445
  ps.gp = gp;
 
2446
  ps.filename = gp->filename;
 
2447
  ps.errorcnt = 0;
 
2448
  ps.state = INITIALIZE;
 
2449
 
 
2450
  /* Begin by reading the input file */
 
2451
  fp = fopen(ps.filename,"rb");
 
2452
  if( fp==0 ){
 
2453
    ErrorMsg(ps.filename,0,"Can't open this file for reading.");
 
2454
    gp->errorcnt++;
 
2455
    return;
 
2456
  }
 
2457
  fseek(fp,0,2);
 
2458
  filesize = ftell(fp);
 
2459
  rewind(fp);
 
2460
  filebuf = (char *)malloc( filesize+1 );
 
2461
  if( filebuf==0 ){
 
2462
    ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.",
 
2463
      filesize+1);
 
2464
    gp->errorcnt++;
 
2465
    return;
 
2466
  }
 
2467
  if( fread(filebuf,1,filesize,fp)!=filesize ){
 
2468
    ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.",
 
2469
      filesize);
 
2470
    free(filebuf);
 
2471
    gp->errorcnt++;
 
2472
    return;
 
2473
  }
 
2474
  fclose(fp);
 
2475
  filebuf[filesize] = 0;
 
2476
 
 
2477
  /* Make an initial pass through the file to handle %ifdef and %ifndef */
 
2478
  preprocess_input(filebuf);
 
2479
 
 
2480
  /* Now scan the text of the input file */
 
2481
  lineno = 1;
 
2482
  for(cp=filebuf; (c= *cp)!=0; ){
 
2483
    if( c=='\n' ) lineno++;              /* Keep track of the line number */
 
2484
    if( isspace(c) ){ cp++; continue; }  /* Skip all white space */
 
2485
    if( c=='/' && cp[1]=='/' ){          /* Skip C++ style comments */
 
2486
      cp+=2;
 
2487
      while( (c= *cp)!=0 && c!='\n' ) cp++;
 
2488
      continue;
 
2489
    }
 
2490
    if( c=='/' && cp[1]=='*' ){          /* Skip C style comments */
 
2491
      cp+=2;
 
2492
      while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){
 
2493
        if( c=='\n' ) lineno++;
 
2494
        cp++;
 
2495
      }
 
2496
      if( c ) cp++;
 
2497
      continue;
 
2498
    }
 
2499
    ps.tokenstart = cp;                /* Mark the beginning of the token */
 
2500
    ps.tokenlineno = lineno;           /* Linenumber on which token begins */
 
2501
    if( c=='\"' ){                     /* String literals */
 
2502
      cp++;
 
2503
      while( (c= *cp)!=0 && c!='\"' ){
 
2504
        if( c=='\n' ) lineno++;
 
2505
        cp++;
 
2506
      }
 
2507
      if( c==0 ){
 
2508
        ErrorMsg(ps.filename,startline,
 
2509
"String starting on this line is not terminated before the end of the file.");
 
2510
        ps.errorcnt++;
 
2511
        nextcp = cp;
 
2512
      }else{
 
2513
        nextcp = cp+1;
 
2514
      }
 
2515
    }else if( c=='{' ){               /* A block of C code */
 
2516
      int level;
 
2517
      cp++;
 
2518
      for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){
 
2519
        if( c=='\n' ) lineno++;
 
2520
        else if( c=='{' ) level++;
 
2521
        else if( c=='}' ) level--;
 
2522
        else if( c=='/' && cp[1]=='*' ){  /* Skip comments */
 
2523
          int prevc;
 
2524
          cp = &cp[2];
 
2525
          prevc = 0;
 
2526
          while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){
 
2527
            if( c=='\n' ) lineno++;
 
2528
            prevc = c;
 
2529
            cp++;
 
2530
          }
 
2531
        }else if( c=='/' && cp[1]=='/' ){  /* Skip C++ style comments too */
 
2532
          cp = &cp[2];
 
2533
          while( (c= *cp)!=0 && c!='\n' ) cp++;
 
2534
          if( c ) lineno++;
 
2535
        }else if( c=='\'' || c=='\"' ){    /* String a character literals */
 
2536
          int startchar, prevc;
 
2537
          startchar = c;
 
2538
          prevc = 0;
 
2539
          for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){
 
2540
            if( c=='\n' ) lineno++;
 
2541
            if( prevc=='\\' ) prevc = 0;
 
2542
            else              prevc = c;
 
2543
          }
 
2544
        }
 
2545
      }
 
2546
      if( c==0 ){
 
2547
        ErrorMsg(ps.filename,ps.tokenlineno,
 
2548
"C code starting on this line is not terminated before the end of the file.");
 
2549
        ps.errorcnt++;
 
2550
        nextcp = cp;
 
2551
      }else{
 
2552
        nextcp = cp+1;
 
2553
      }
 
2554
    }else if( isalnum(c) ){          /* Identifiers */
 
2555
      while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
 
2556
      nextcp = cp;
 
2557
    }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */
 
2558
      cp += 3;
 
2559
      nextcp = cp;
 
2560
    }else if( (c=='/' || c=='|') && isalpha(cp[1]) ){
 
2561
      cp += 2;
 
2562
      while( (c = *cp)!=0 && (isalnum(c) || c=='_') ) cp++;
 
2563
      nextcp = cp;
 
2564
    }else{                          /* All other (one character) operators */
 
2565
      cp++;
 
2566
      nextcp = cp;
 
2567
    }
 
2568
    c = *cp;
 
2569
    *cp = 0;                        /* Null terminate the token */
 
2570
    parseonetoken(&ps);             /* Parse the token */
 
2571
    *cp = c;                        /* Restore the buffer */
 
2572
    cp = nextcp;
 
2573
  }
 
2574
  free(filebuf);                    /* Release the buffer after parsing */
 
2575
  gp->rule = ps.firstrule;
 
2576
  gp->errorcnt = ps.errorcnt;
 
2577
}
 
2578
/*************************** From the file "plink.c" *********************/
 
2579
/*
 
2580
** Routines processing configuration follow-set propagation links
 
2581
** in the LEMON parser generator.
 
2582
*/
 
2583
static struct plink *plink_freelist = 0;
 
2584
 
 
2585
/* Allocate a new plink */
 
2586
struct plink *Plink_new(){
 
2587
  struct plink *new;
 
2588
 
 
2589
  if( plink_freelist==0 ){
 
2590
    int i;
 
2591
    int amt = 100;
 
2592
    plink_freelist = (struct plink *)malloc( sizeof(struct plink)*amt );
 
2593
    if( plink_freelist==0 ){
 
2594
      fprintf(stderr,
 
2595
      "Unable to allocate memory for a new follow-set propagation link.\n");
 
2596
      exit(1);
 
2597
    }
 
2598
    for(i=0; i<amt-1; i++) plink_freelist[i].next = &plink_freelist[i+1];
 
2599
    plink_freelist[amt-1].next = 0;
 
2600
  }
 
2601
  new = plink_freelist;
 
2602
  plink_freelist = plink_freelist->next;
 
2603
  return new;
 
2604
}
 
2605
 
 
2606
/* Add a plink to a plink list */
 
2607
void Plink_add(plpp,cfp)
 
2608
struct plink **plpp;
 
2609
struct config *cfp;
 
2610
{
 
2611
  struct plink *new;
 
2612
  new = Plink_new();
 
2613
  new->next = *plpp;
 
2614
  *plpp = new;
 
2615
  new->cfp = cfp;
 
2616
}
 
2617
 
 
2618
/* Transfer every plink on the list "from" to the list "to" */
 
2619
void Plink_copy(to,from)
 
2620
struct plink **to;
 
2621
struct plink *from;
 
2622
{
 
2623
  struct plink *nextpl;
 
2624
  while( from ){
 
2625
    nextpl = from->next;
 
2626
    from->next = *to;
 
2627
    *to = from;
 
2628
    from = nextpl;
 
2629
  }
 
2630
}
 
2631
 
 
2632
/* Delete every plink on the list */
 
2633
void Plink_delete(plp)
 
2634
struct plink *plp;
 
2635
{
 
2636
  struct plink *nextpl;
 
2637
 
 
2638
  while( plp ){
 
2639
    nextpl = plp->next;
 
2640
    plp->next = plink_freelist;
 
2641
    plink_freelist = plp;
 
2642
    plp = nextpl;
 
2643
  }
 
2644
}
 
2645
/*********************** From the file "report.c" **************************/
 
2646
/*
 
2647
** Procedures for generating reports and tables in the LEMON parser generator.
 
2648
*/
 
2649
 
 
2650
/* Generate a filename with the given suffix.  Space to hold the
 
2651
** name comes from malloc() and must be freed by the calling
 
2652
** function.
 
2653
*/
 
2654
PRIVATE char *file_makename(lemp,suffix)
 
2655
struct lemon *lemp;
 
2656
char *suffix;
 
2657
{
 
2658
  char *name;
 
2659
  char *cp;
 
2660
 
 
2661
  name = malloc( strlen(lemp->filename) + strlen(suffix) + 5 );
 
2662
  if( name==0 ){
 
2663
    fprintf(stderr,"Can't allocate space for a filename.\n");
 
2664
    exit(1);
 
2665
  }
 
2666
  strcpy(name,lemp->filename);
 
2667
  cp = strrchr(name,'.');
 
2668
  if( cp ) *cp = 0;
 
2669
  strcat(name,suffix);
 
2670
  return name;
 
2671
}
 
2672
 
 
2673
/* Open a file with a name based on the name of the input file,
 
2674
** but with a different (specified) suffix, and return a pointer
 
2675
** to the stream */
 
2676
PRIVATE FILE *file_open(lemp,suffix,mode)
 
2677
struct lemon *lemp;
 
2678
char *suffix;
 
2679
char *mode;
 
2680
{
 
2681
  FILE *fp;
 
2682
 
 
2683
  if( lemp->outname ) free(lemp->outname);
 
2684
  lemp->outname = file_makename(lemp, suffix);
 
2685
  fp = fopen(lemp->outname,mode);
 
2686
  if( fp==0 && *mode=='w' ){
 
2687
    fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname);
 
2688
    lemp->errorcnt++;
 
2689
    return 0;
 
2690
  }
 
2691
  return fp;
 
2692
}
 
2693
 
 
2694
/* Duplicate the input file without comments and without actions 
 
2695
** on rules */
 
2696
void Reprint(lemp)
 
2697
struct lemon *lemp;
 
2698
{
 
2699
  struct rule *rp;
 
2700
  struct symbol *sp;
 
2701
  int i, j, maxlen, len, ncolumns, skip;
 
2702
  printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename);
 
2703
  maxlen = 10;
 
2704
  for(i=0; i<lemp->nsymbol; i++){
 
2705
    sp = lemp->symbols[i];
 
2706
    len = strlen(sp->name);
 
2707
    if( len>maxlen ) maxlen = len;
 
2708
  }
 
2709
  ncolumns = 76/(maxlen+5);
 
2710
  if( ncolumns<1 ) ncolumns = 1;
 
2711
  skip = (lemp->nsymbol + ncolumns - 1)/ncolumns;
 
2712
  for(i=0; i<skip; i++){
 
2713
    printf("//");
 
2714
    for(j=i; j<lemp->nsymbol; j+=skip){
 
2715
      sp = lemp->symbols[j];
 
2716
      assert( sp->index==j );
 
2717
      printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name);
 
2718
    }
 
2719
    printf("\n");
 
2720
  }
 
2721
  for(rp=lemp->rule; rp; rp=rp->next){
 
2722
    printf("%s",rp->lhs->name);
 
2723
    /*    if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
 
2724
    printf(" ::=");
 
2725
    for(i=0; i<rp->nrhs; i++){
 
2726
      sp = rp->rhs[i];
 
2727
      printf(" %s", sp->name);
 
2728
      if( sp->type==MULTITERMINAL ){
 
2729
        for(j=1; j<sp->nsubsym; j++){
 
2730
          printf("|%s", sp->subsym[j]->name);
 
2731
        }
 
2732
      }
 
2733
      /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
 
2734
    }
 
2735
    printf(".");
 
2736
    if( rp->precsym ) printf(" [%s]",rp->precsym->name);
 
2737
    /* if( rp->code ) printf("\n    %s",rp->code); */
 
2738
    printf("\n");
 
2739
  }
 
2740
}
 
2741
 
 
2742
void ConfigPrint(fp,cfp)
 
2743
FILE *fp;
 
2744
struct config *cfp;
 
2745
{
 
2746
  struct rule *rp;
 
2747
  struct symbol *sp;
 
2748
  int i, j;
 
2749
  rp = cfp->rp;
 
2750
  fprintf(fp,"%s ::=",rp->lhs->name);
 
2751
  for(i=0; i<=rp->nrhs; i++){
 
2752
    if( i==cfp->dot ) fprintf(fp," *");
 
2753
    if( i==rp->nrhs ) break;
 
2754
    sp = rp->rhs[i];
 
2755
    fprintf(fp," %s", sp->name);
 
2756
    if( sp->type==MULTITERMINAL ){
 
2757
      for(j=1; j<sp->nsubsym; j++){
 
2758
        fprintf(fp,"|%s",sp->subsym[j]->name);
 
2759
      }
 
2760
    }
 
2761
  }
 
2762
}
 
2763
 
 
2764
/* #define TEST */
 
2765
#if 0
 
2766
/* Print a set */
 
2767
PRIVATE void SetPrint(out,set,lemp)
 
2768
FILE *out;
 
2769
char *set;
 
2770
struct lemon *lemp;
 
2771
{
 
2772
  int i;
 
2773
  char *spacer;
 
2774
  spacer = "";
 
2775
  fprintf(out,"%12s[","");
 
2776
  for(i=0; i<lemp->nterminal; i++){
 
2777
    if( SetFind(set,i) ){
 
2778
      fprintf(out,"%s%s",spacer,lemp->symbols[i]->name);
 
2779
      spacer = " ";
 
2780
    }
 
2781
  }
 
2782
  fprintf(out,"]\n");
 
2783
}
 
2784
 
 
2785
/* Print a plink chain */
 
2786
PRIVATE void PlinkPrint(out,plp,tag)
 
2787
FILE *out;
 
2788
struct plink *plp;
 
2789
char *tag;
 
2790
{
 
2791
  while( plp ){
 
2792
    fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->statenum);
 
2793
    ConfigPrint(out,plp->cfp);
 
2794
    fprintf(out,"\n");
 
2795
    plp = plp->next;
 
2796
  }
 
2797
}
 
2798
#endif
 
2799
 
 
2800
/* Print an action to the given file descriptor.  Return FALSE if
 
2801
** nothing was actually printed.
 
2802
*/
 
2803
int PrintAction(struct action *ap, FILE *fp, int indent){
 
2804
  int result = 1;
 
2805
  switch( ap->type ){
 
2806
    case SHIFT:
 
2807
      fprintf(fp,"%*s shift  %d",indent,ap->sp->name,ap->x.stp->statenum);
 
2808
      break;
 
2809
    case REDUCE:
 
2810
      fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index);
 
2811
      break;
 
2812
    case ACCEPT:
 
2813
      fprintf(fp,"%*s accept",indent,ap->sp->name);
 
2814
      break;
 
2815
    case ERROR:
 
2816
      fprintf(fp,"%*s error",indent,ap->sp->name);
 
2817
      break;
 
2818
    case CONFLICT:
 
2819
      fprintf(fp,"%*s reduce %-3d ** Parsing conflict **",
 
2820
        indent,ap->sp->name,ap->x.rp->index);
 
2821
      break;
 
2822
    case SH_RESOLVED:
 
2823
    case RD_RESOLVED:
 
2824
    case NOT_USED:
 
2825
      result = 0;
 
2826
      break;
 
2827
  }
 
2828
  return result;
 
2829
}
 
2830
 
 
2831
/* Generate the "y.output" log file */
 
2832
void ReportOutput(lemp)
 
2833
struct lemon *lemp;
 
2834
{
 
2835
  int i;
 
2836
  struct state *stp;
 
2837
  struct config *cfp;
 
2838
  struct action *ap;
 
2839
  FILE *fp;
 
2840
 
 
2841
  fp = file_open(lemp,".out","wb");
 
2842
  if( fp==0 ) return;
 
2843
  fprintf(fp," \b");
 
2844
  for(i=0; i<lemp->nstate; i++){
 
2845
    stp = lemp->sorted[i];
 
2846
    fprintf(fp,"State %d:\n",stp->statenum);
 
2847
    if( lemp->basisflag ) cfp=stp->bp;
 
2848
    else                  cfp=stp->cfp;
 
2849
    while( cfp ){
 
2850
      char buf[20];
 
2851
      if( cfp->dot==cfp->rp->nrhs ){
 
2852
        sprintf(buf,"(%d)",cfp->rp->index);
 
2853
        fprintf(fp,"    %5s ",buf);
 
2854
      }else{
 
2855
        fprintf(fp,"          ");
 
2856
      }
 
2857
      ConfigPrint(fp,cfp);
 
2858
      fprintf(fp,"\n");
 
2859
#if 0
 
2860
      SetPrint(fp,cfp->fws,lemp);
 
2861
      PlinkPrint(fp,cfp->fplp,"To  ");
 
2862
      PlinkPrint(fp,cfp->bplp,"From");
 
2863
#endif
 
2864
      if( lemp->basisflag ) cfp=cfp->bp;
 
2865
      else                  cfp=cfp->next;
 
2866
    }
 
2867
    fprintf(fp,"\n");
 
2868
    for(ap=stp->ap; ap; ap=ap->next){
 
2869
      if( PrintAction(ap,fp,30) ) fprintf(fp,"\n");
 
2870
    }
 
2871
    fprintf(fp,"\n");
 
2872
  }
 
2873
  fclose(fp);
 
2874
  return;
 
2875
}
 
2876
 
 
2877
/* Search for the file "name" which is in the same directory as
 
2878
** the exacutable */
 
2879
PRIVATE char *pathsearch(argv0,name,modemask)
 
2880
char *argv0;
 
2881
char *name;
 
2882
int modemask;
 
2883
{
 
2884
  char *pathlist;
 
2885
  char *path,*cp;
 
2886
  char c;
 
2887
  extern int access();
 
2888
 
 
2889
#ifdef __WIN32__
 
2890
  cp = strrchr(argv0,'\\');
 
2891
#else
 
2892
  cp = strrchr(argv0,'/');
 
2893
#endif
 
2894
  if( cp ){
 
2895
    c = *cp;
 
2896
    *cp = 0;
 
2897
    path = (char *)malloc( strlen(argv0) + strlen(name) + 2 );
 
2898
    if( path ) sprintf(path,"%s/%s",argv0,name);
 
2899
    *cp = c;
 
2900
  }else{
 
2901
    extern char *getenv();
 
2902
    pathlist = getenv("PATH");
 
2903
    if( pathlist==0 ) pathlist = ".:/bin:/usr/bin";
 
2904
    path = (char *)malloc( strlen(pathlist)+strlen(name)+2 );
 
2905
    if( path!=0 ){
 
2906
      while( *pathlist ){
 
2907
        cp = strchr(pathlist,':');
 
2908
        if( cp==0 ) cp = &pathlist[strlen(pathlist)];
 
2909
        c = *cp;
 
2910
        *cp = 0;
 
2911
        sprintf(path,"%s/%s",pathlist,name);
 
2912
        *cp = c;
 
2913
        if( c==0 ) pathlist = "";
 
2914
        else pathlist = &cp[1];
 
2915
        if( access(path,modemask)==0 ) break;
 
2916
      }
 
2917
    }
 
2918
  }
 
2919
  return path;
 
2920
}
 
2921
 
 
2922
/* Given an action, compute the integer value for that action
 
2923
** which is to be put in the action table of the generated machine.
 
2924
** Return negative if no action should be generated.
 
2925
*/
 
2926
PRIVATE int compute_action(lemp,ap)
 
2927
struct lemon *lemp;
 
2928
struct action *ap;
 
2929
{
 
2930
  int act;
 
2931
  switch( ap->type ){
 
2932
    case SHIFT:  act = ap->x.stp->statenum;            break;
 
2933
    case REDUCE: act = ap->x.rp->index + lemp->nstate; break;
 
2934
    case ERROR:  act = lemp->nstate + lemp->nrule;     break;
 
2935
    case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break;
 
2936
    default:     act = -1; break;
 
2937
  }
 
2938
  return act;
 
2939
}
 
2940
 
 
2941
#define LINESIZE 1000
 
2942
/* The next cluster of routines are for reading the template file
 
2943
** and writing the results to the generated parser */
 
2944
/* The first function transfers data from "in" to "out" until
 
2945
** a line is seen which begins with "%%".  The line number is
 
2946
** tracked.
 
2947
**
 
2948
** if name!=0, then any word that begin with "Parse" is changed to
 
2949
** begin with *name instead.
 
2950
*/
 
2951
PRIVATE void tplt_xfer(name,in,out,lineno)
 
2952
char *name;
 
2953
FILE *in;
 
2954
FILE *out;
 
2955
int *lineno;
 
2956
{
 
2957
  int i, iStart;
 
2958
  char line[LINESIZE];
 
2959
  while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
 
2960
    (*lineno)++;
 
2961
    iStart = 0;
 
2962
    if( name ){
 
2963
      for(i=0; line[i]; i++){
 
2964
        if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0
 
2965
          && (i==0 || !isalpha(line[i-1]))
 
2966
        ){
 
2967
          if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]);
 
2968
          fprintf(out,"%s",name);
 
2969
          i += 4;
 
2970
          iStart = i+1;
 
2971
        }
 
2972
      }
 
2973
    }
 
2974
    fprintf(out,"%s",&line[iStart]);
 
2975
  }
 
2976
}
 
2977
 
 
2978
/* The next function finds the template file and opens it, returning
 
2979
** a pointer to the opened file. */
 
2980
PRIVATE FILE *tplt_open(lemp)
 
2981
struct lemon *lemp;
 
2982
{
 
2983
  static char templatename[] = "lempar.c";
 
2984
  char buf[1000];
 
2985
  FILE *in;
 
2986
  char *tpltname;
 
2987
  char *cp;
 
2988
 
 
2989
  cp = strrchr(lemp->filename,'.');
 
2990
  if( cp ){
 
2991
    sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
 
2992
  }else{
 
2993
    sprintf(buf,"%s.lt",lemp->filename);
 
2994
  }
 
2995
  if( access(buf,004)==0 ){
 
2996
    tpltname = buf;
 
2997
  }else if( access(templatename,004)==0 ){
 
2998
    tpltname = templatename;
 
2999
  }else{
 
3000
    tpltname = pathsearch(lemp->argv0,templatename,0);
 
3001
  }
 
3002
  if( tpltname==0 ){
 
3003
    fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
 
3004
    templatename);
 
3005
    lemp->errorcnt++;
 
3006
    return 0;
 
3007
  }
 
3008
  in = fopen(tpltname,"rb");
 
3009
  if( in==0 ){
 
3010
    fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
 
3011
    lemp->errorcnt++;
 
3012
    return 0;
 
3013
  }
 
3014
  return in;
 
3015
}
 
3016
 
 
3017
/* Print a #line directive line to the output file. */
 
3018
PRIVATE void tplt_linedir(out,lineno,filename)
 
3019
FILE *out;
 
3020
int lineno;
 
3021
char *filename;
 
3022
{
 
3023
  fprintf(out,"#line %d \"",lineno);
 
3024
  while( *filename ){
 
3025
    if( *filename == '\\' ) putc('\\',out);
 
3026
    putc(*filename,out);
 
3027
    filename++;
 
3028
  }
 
3029
  fprintf(out,"\"\n");
 
3030
}
 
3031
 
 
3032
/* Print a string to the file and keep the linenumber up to date */
 
3033
PRIVATE void tplt_print(out,lemp,str,strln,lineno)
 
3034
FILE *out;
 
3035
struct lemon *lemp;
 
3036
char *str;
 
3037
int strln;
 
3038
int *lineno;
 
3039
{
 
3040
  if( str==0 ) return;
 
3041
  tplt_linedir(out,strln,lemp->filename);
 
3042
  (*lineno)++;
 
3043
  while( *str ){
 
3044
    if( *str=='\n' ) (*lineno)++;
 
3045
    putc(*str,out);
 
3046
    str++;
 
3047
  }
 
3048
  if( str[-1]!='\n' ){
 
3049
    putc('\n',out);
 
3050
    (*lineno)++;
 
3051
  }
 
3052
  tplt_linedir(out,*lineno+2,lemp->outname); 
 
3053
  (*lineno)+=2;
 
3054
  return;
 
3055
}
 
3056
 
 
3057
/*
 
3058
** The following routine emits code for the destructor for the
 
3059
** symbol sp
 
3060
*/
 
3061
void emit_destructor_code(out,sp,lemp,lineno)
 
3062
FILE *out;
 
3063
struct symbol *sp;
 
3064
struct lemon *lemp;
 
3065
int *lineno;
 
3066
{
 
3067
 char *cp = 0;
 
3068
 
 
3069
 int linecnt = 0;
 
3070
 if( sp->type==TERMINAL ){
 
3071
   cp = lemp->tokendest;
 
3072
   if( cp==0 ) return;
 
3073
   tplt_linedir(out,lemp->tokendestln,lemp->filename);
 
3074
   fprintf(out,"{");
 
3075
 }else if( sp->destructor ){
 
3076
   cp = sp->destructor;
 
3077
   tplt_linedir(out,sp->destructorln,lemp->filename);
 
3078
   fprintf(out,"{");
 
3079
 }else if( lemp->vardest ){
 
3080
   cp = lemp->vardest;
 
3081
   if( cp==0 ) return;
 
3082
   tplt_linedir(out,lemp->vardestln,lemp->filename);
 
3083
   fprintf(out,"{");
 
3084
 }else{
 
3085
   assert( 0 );  /* Cannot happen */
 
3086
 }
 
3087
 for(; *cp; cp++){
 
3088
   if( *cp=='$' && cp[1]=='$' ){
 
3089
     fprintf(out,"(yypminor->yy%d)",sp->dtnum);
 
3090
     cp++;
 
3091
     continue;
 
3092
   }
 
3093
   if( *cp=='\n' ) linecnt++;
 
3094
   fputc(*cp,out);
 
3095
 }
 
3096
 (*lineno) += 3 + linecnt;
 
3097
 fprintf(out,"}\n");
 
3098
 tplt_linedir(out,*lineno,lemp->outname);
 
3099
 return;
 
3100
}
 
3101
 
 
3102
/*
 
3103
** Return TRUE (non-zero) if the given symbol has a destructor.
 
3104
*/
 
3105
int has_destructor(sp, lemp)
 
3106
struct symbol *sp;
 
3107
struct lemon *lemp;
 
3108
{
 
3109
  int ret;
 
3110
  if( sp->type==TERMINAL ){
 
3111
    ret = lemp->tokendest!=0;
 
3112
  }else{
 
3113
    ret = lemp->vardest!=0 || sp->destructor!=0;
 
3114
  }
 
3115
  return ret;
 
3116
}
 
3117
 
 
3118
/*
 
3119
** Append text to a dynamically allocated string.  If zText is 0 then
 
3120
** reset the string to be empty again.  Always return the complete text
 
3121
** of the string (which is overwritten with each call).
 
3122
**
 
3123
** n bytes of zText are stored.  If n==0 then all of zText up to the first
 
3124
** \000 terminator is stored.  zText can contain up to two instances of
 
3125
** %d.  The values of p1 and p2 are written into the first and second
 
3126
** %d.
 
3127
**
 
3128
** If n==-1, then the previous character is overwritten.
 
3129
*/
 
3130
PRIVATE char *append_str(char *zText, int n, int p1, int p2){
 
3131
  static char *z = 0;
 
3132
  static int alloced = 0;
 
3133
  static int used = 0;
 
3134
  int c;
 
3135
  char zInt[40];
 
3136
 
 
3137
  if( zText==0 ){
 
3138
    used = 0;
 
3139
    return z;
 
3140
  }
 
3141
  if( n<=0 ){
 
3142
    if( n<0 ){
 
3143
      used += n;
 
3144
      assert( used>=0 );
 
3145
    }
 
3146
    n = strlen(zText);
 
3147
  }
 
3148
  if( n+sizeof(zInt)*2+used >= alloced ){
 
3149
    alloced = n + sizeof(zInt)*2 + used + 200;
 
3150
    z = realloc(z,  alloced);
 
3151
  }
 
3152
  if( z==0 ) return "";
 
3153
  while( n-- > 0 ){
 
3154
    c = *(zText++);
 
3155
    if( c=='%' && zText[0]=='d' ){
 
3156
      sprintf(zInt, "%d", p1);
 
3157
      p1 = p2;
 
3158
      strcpy(&z[used], zInt);
 
3159
      used += strlen(&z[used]);
 
3160
      zText++;
 
3161
      n--;
 
3162
    }else{
 
3163
      z[used++] = c;
 
3164
    }
 
3165
  }
 
3166
  z[used] = 0;
 
3167
  return z;
 
3168
}
 
3169
 
 
3170
/*
 
3171
** zCode is a string that is the action associated with a rule.  Expand
 
3172
** the symbols in this string so that the refer to elements of the parser
 
3173
** stack.
 
3174
*/
 
3175
PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
 
3176
  char *cp, *xp;
 
3177
  int i;
 
3178
  char lhsused = 0;    /* True if the LHS element has been used */
 
3179
  char used[MAXRHS];   /* True for each RHS element which is used */
 
3180
 
 
3181
  for(i=0; i<rp->nrhs; i++) used[i] = 0;
 
3182
  lhsused = 0;
 
3183
 
 
3184
  append_str(0,0,0,0);
 
3185
  for(cp=rp->code; *cp; cp++){
 
3186
    if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){
 
3187
      char saved;
 
3188
      for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++);
 
3189
      saved = *xp;
 
3190
      *xp = 0;
 
3191
      if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
 
3192
        append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0);
 
3193
        cp = xp;
 
3194
        lhsused = 1;
 
3195
      }else{
 
3196
        for(i=0; i<rp->nrhs; i++){
 
3197
          if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){
 
3198
            if( cp!=rp->code && cp[-1]=='@' ){
 
3199
              /* If the argument is of the form @X then substituted
 
3200
              ** the token number of X, not the value of X */
 
3201
              append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0);
 
3202
            }else{
 
3203
              struct symbol *sp = rp->rhs[i];
 
3204
              int dtnum;
 
3205
              if( sp->type==MULTITERMINAL ){
 
3206
                dtnum = sp->subsym[0]->dtnum;
 
3207
              }else{
 
3208
                dtnum = sp->dtnum;
 
3209
              }
 
3210
              append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum);
 
3211
            }
 
3212
            cp = xp;
 
3213
            used[i] = 1;
 
3214
            break;
 
3215
          }
 
3216
        }
 
3217
      }
 
3218
      *xp = saved;
 
3219
    }
 
3220
    append_str(cp, 1, 0, 0);
 
3221
  } /* End loop */
 
3222
 
 
3223
  /* Check to make sure the LHS has been used */
 
3224
  if( rp->lhsalias && !lhsused ){
 
3225
    ErrorMsg(lemp->filename,rp->ruleline,
 
3226
      "Label \"%s\" for \"%s(%s)\" is never used.",
 
3227
        rp->lhsalias,rp->lhs->name,rp->lhsalias);
 
3228
    lemp->errorcnt++;
 
3229
  }
 
3230
 
 
3231
  /* Generate destructor code for RHS symbols which are not used in the
 
3232
  ** reduce code */
 
3233
  for(i=0; i<rp->nrhs; i++){
 
3234
    if( rp->rhsalias[i] && !used[i] ){
 
3235
      ErrorMsg(lemp->filename,rp->ruleline,
 
3236
        "Label %s for \"%s(%s)\" is never used.",
 
3237
        rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
 
3238
      lemp->errorcnt++;
 
3239
    }else if( rp->rhsalias[i]==0 ){
 
3240
      if( has_destructor(rp->rhs[i],lemp) ){
 
3241
        append_str("  yy_destructor(%d,&yymsp[%d].minor);\n", 0,
 
3242
           rp->rhs[i]->index,i-rp->nrhs+1);
 
3243
      }else{
 
3244
        /* No destructor defined for this term */
 
3245
      }
 
3246
    }
 
3247
  }
 
3248
  cp = append_str(0,0,0,0);
 
3249
  rp->code = Strsafe(cp);
 
3250
}
 
3251
 
 
3252
/* 
 
3253
** Generate code which executes when the rule "rp" is reduced.  Write
 
3254
** the code to "out".  Make sure lineno stays up-to-date.
 
3255
*/
 
3256
PRIVATE void emit_code(out,rp,lemp,lineno)
 
3257
FILE *out;
 
3258
struct rule *rp;
 
3259
struct lemon *lemp;
 
3260
int *lineno;
 
3261
{
 
3262
 char *cp;
 
3263
 int linecnt = 0;
 
3264
 
 
3265
 /* Generate code to do the reduce action */
 
3266
 if( rp->code ){
 
3267
   tplt_linedir(out,rp->line,lemp->filename);
 
3268
   fprintf(out,"{%s",rp->code);
 
3269
   for(cp=rp->code; *cp; cp++){
 
3270
     if( *cp=='\n' ) linecnt++;
 
3271
   } /* End loop */
 
3272
   (*lineno) += 3 + linecnt;
 
3273
   fprintf(out,"}\n");
 
3274
   tplt_linedir(out,*lineno,lemp->outname);
 
3275
 } /* End if( rp->code ) */
 
3276
 
 
3277
 return;
 
3278
}
 
3279
 
 
3280
/*
 
3281
** Print the definition of the union used for the parser's data stack.
 
3282
** This union contains fields for every possible data type for tokens
 
3283
** and nonterminals.  In the process of computing and printing this
 
3284
** union, also set the ".dtnum" field of every terminal and nonterminal
 
3285
** symbol.
 
3286
*/
 
3287
void print_stack_union(out,lemp,plineno,mhflag)
 
3288
FILE *out;                  /* The output stream */
 
3289
struct lemon *lemp;         /* The main info structure for this parser */
 
3290
int *plineno;               /* Pointer to the line number */
 
3291
int mhflag;                 /* True if generating makeheaders output */
 
3292
{
 
3293
  int lineno = *plineno;    /* The line number of the output */
 
3294
  char **types;             /* A hash table of datatypes */
 
3295
  int arraysize;            /* Size of the "types" array */
 
3296
  int maxdtlength;          /* Maximum length of any ".datatype" field. */
 
3297
  char *stddt;              /* Standardized name for a datatype */
 
3298
  int i,j;                  /* Loop counters */
 
3299
  int hash;                 /* For hashing the name of a type */
 
3300
  char *name;               /* Name of the parser */
 
3301
 
 
3302
  /* Allocate and initialize types[] and allocate stddt[] */
 
3303
  arraysize = lemp->nsymbol * 2;
 
3304
  types = (char**)malloc( arraysize * sizeof(char*) );
 
3305
  for(i=0; i<arraysize; i++) types[i] = 0;
 
3306
  maxdtlength = 0;
 
3307
  if( lemp->vartype ){
 
3308
    maxdtlength = strlen(lemp->vartype);
 
3309
  }
 
3310
  for(i=0; i<lemp->nsymbol; i++){
 
3311
    int len;
 
3312
    struct symbol *sp = lemp->symbols[i];
 
3313
    if( sp->datatype==0 ) continue;
 
3314
    len = strlen(sp->datatype);
 
3315
    if( len>maxdtlength ) maxdtlength = len;
 
3316
  }
 
3317
  stddt = (char*)malloc( maxdtlength*2 + 1 );
 
3318
  if( types==0 || stddt==0 ){
 
3319
    fprintf(stderr,"Out of memory.\n");
 
3320
    exit(1);
 
3321
  }
 
3322
 
 
3323
  /* Build a hash table of datatypes. The ".dtnum" field of each symbol
 
3324
  ** is filled in with the hash index plus 1.  A ".dtnum" value of 0 is
 
3325
  ** used for terminal symbols.  If there is no %default_type defined then
 
3326
  ** 0 is also used as the .dtnum value for nonterminals which do not specify
 
3327
  ** a datatype using the %type directive.
 
3328
  */
 
3329
  for(i=0; i<lemp->nsymbol; i++){
 
3330
    struct symbol *sp = lemp->symbols[i];
 
3331
    char *cp;
 
3332
    if( sp==lemp->errsym ){
 
3333
      sp->dtnum = arraysize+1;
 
3334
      continue;
 
3335
    }
 
3336
    if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
 
3337
      sp->dtnum = 0;
 
3338
      continue;
 
3339
    }
 
3340
    cp = sp->datatype;
 
3341
    if( cp==0 ) cp = lemp->vartype;
 
3342
    j = 0;
 
3343
    while( isspace(*cp) ) cp++;
 
3344
    while( *cp ) stddt[j++] = *cp++;
 
3345
    while( j>0 && isspace(stddt[j-1]) ) j--;
 
3346
    stddt[j] = 0;
 
3347
    hash = 0;
 
3348
    for(j=0; stddt[j]; j++){
 
3349
      hash = hash*53 + stddt[j];
 
3350
    }
 
3351
    hash = (hash & 0x7fffffff)%arraysize;
 
3352
    while( types[hash] ){
 
3353
      if( strcmp(types[hash],stddt)==0 ){
 
3354
        sp->dtnum = hash + 1;
 
3355
        break;
 
3356
      }
 
3357
      hash++;
 
3358
      if( hash>=arraysize ) hash = 0;
 
3359
    }
 
3360
    if( types[hash]==0 ){
 
3361
      sp->dtnum = hash + 1;
 
3362
      types[hash] = (char*)malloc( strlen(stddt)+1 );
 
3363
      if( types[hash]==0 ){
 
3364
        fprintf(stderr,"Out of memory.\n");
 
3365
        exit(1);
 
3366
      }
 
3367
      strcpy(types[hash],stddt);
 
3368
    }
 
3369
  }
 
3370
 
 
3371
  /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
 
3372
  name = lemp->name ? lemp->name : "Parse";
 
3373
  lineno = *plineno;
 
3374
  if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; }
 
3375
  fprintf(out,"#define %sTOKENTYPE %s\n",name,
 
3376
    lemp->tokentype?lemp->tokentype:"void*");  lineno++;
 
3377
  if( mhflag ){ fprintf(out,"#endif\n"); lineno++; }
 
3378
  fprintf(out,"typedef union {\n"); lineno++;
 
3379
  fprintf(out,"  %sTOKENTYPE yy0;\n",name); lineno++;
 
3380
  for(i=0; i<arraysize; i++){
 
3381
    if( types[i]==0 ) continue;
 
3382
    fprintf(out,"  %s yy%d;\n",types[i],i+1); lineno++;
 
3383
    free(types[i]);
 
3384
  }
 
3385
  fprintf(out,"  int yy%d;\n",lemp->errsym->dtnum); lineno++;
 
3386
  free(stddt);
 
3387
  free(types);
 
3388
  fprintf(out,"} YYMINORTYPE;\n"); lineno++;
 
3389
  *plineno = lineno;
 
3390
}
 
3391
 
 
3392
/*
 
3393
** Return the name of a C datatype able to represent values between
 
3394
** lwr and upr, inclusive.
 
3395
*/
 
3396
static const char *minimum_size_type(int lwr, int upr){
 
3397
  if( lwr>=0 ){
 
3398
    if( upr<=255 ){
 
3399
      return "unsigned char";
 
3400
    }else if( upr<65535 ){
 
3401
      return "unsigned short int";
 
3402
    }else{
 
3403
      return "unsigned int";
 
3404
    }
 
3405
  }else if( lwr>=-127 && upr<=127 ){
 
3406
    return "signed char";
 
3407
  }else if( lwr>=-32767 && upr<32767 ){
 
3408
    return "short";
 
3409
  }else{
 
3410
    return "int";
 
3411
  }
 
3412
}
 
3413
 
 
3414
/*
 
3415
** Each state contains a set of token transaction and a set of
 
3416
** nonterminal transactions.  Each of these sets makes an instance
 
3417
** of the following structure.  An array of these structures is used
 
3418
** to order the creation of entries in the yy_action[] table.
 
3419
*/
 
3420
struct axset {
 
3421
  struct state *stp;   /* A pointer to a state */
 
3422
  int isTkn;           /* True to use tokens.  False for non-terminals */
 
3423
  int nAction;         /* Number of actions */
 
3424
};
 
3425
 
 
3426
/*
 
3427
** Compare to axset structures for sorting purposes
 
3428
*/
 
3429
static int axset_compare(const void *a, const void *b){
 
3430
  struct axset *p1 = (struct axset*)a;
 
3431
  struct axset *p2 = (struct axset*)b;
 
3432
  return p2->nAction - p1->nAction;
 
3433
}
 
3434
 
 
3435
/* Generate C source code for the parser */
 
3436
void ReportTable(lemp, mhflag)
 
3437
struct lemon *lemp;
 
3438
int mhflag;     /* Output in makeheaders format if true */
 
3439
{
 
3440
  FILE *out, *in;
 
3441
  char line[LINESIZE];
 
3442
  int  lineno;
 
3443
  struct state *stp;
 
3444
  struct action *ap;
 
3445
  struct rule *rp;
 
3446
  struct acttab *pActtab;
 
3447
  int i, j, n;
 
3448
  char *name;
 
3449
  int mnTknOfst, mxTknOfst;
 
3450
  int mnNtOfst, mxNtOfst;
 
3451
  struct axset *ax;
 
3452
 
 
3453
  in = tplt_open(lemp);
 
3454
  if( in==0 ) return;
 
3455
  out = file_open(lemp,".c","wb");
 
3456
  if( out==0 ){
 
3457
    fclose(in);
 
3458
    return;
 
3459
  }
 
3460
  lineno = 1;
 
3461
  tplt_xfer(lemp->name,in,out,&lineno);
 
3462
 
 
3463
  /* Generate the include code, if any */
 
3464
  tplt_print(out,lemp,lemp->include,lemp->includeln,&lineno);
 
3465
  if( mhflag ){
 
3466
    char *name = file_makename(lemp, ".h");
 
3467
    fprintf(out,"#include \"%s\"\n", name); lineno++;
 
3468
    free(name);
 
3469
  }
 
3470
  tplt_xfer(lemp->name,in,out,&lineno);
 
3471
 
 
3472
  /* Generate #defines for all tokens */
 
3473
  if( mhflag ){
 
3474
    char *prefix;
 
3475
    fprintf(out,"#if INTERFACE\n"); lineno++;
 
3476
    if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
 
3477
    else                    prefix = "";
 
3478
    for(i=1; i<lemp->nterminal; i++){
 
3479
      fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
 
3480
      lineno++;
 
3481
    }
 
3482
    fprintf(out,"#endif\n"); lineno++;
 
3483
  }
 
3484
  tplt_xfer(lemp->name,in,out,&lineno);
 
3485
 
 
3486
  /* Generate the defines */
 
3487
  fprintf(out,"#define YYCODETYPE %s\n",
 
3488
    minimum_size_type(0, lemp->nsymbol+5)); lineno++;
 
3489
  fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1);  lineno++;
 
3490
  fprintf(out,"#define YYACTIONTYPE %s\n",
 
3491
    minimum_size_type(0, lemp->nstate+lemp->nrule+5));  lineno++;
 
3492
  print_stack_union(out,lemp,&lineno,mhflag);
 
3493
  if( lemp->stacksize ){
 
3494
    if( atoi(lemp->stacksize)<=0 ){
 
3495
      ErrorMsg(lemp->filename,0,
 
3496
"Illegal stack size: [%s].  The stack size should be an integer constant.",
 
3497
        lemp->stacksize);
 
3498
      lemp->errorcnt++;
 
3499
      lemp->stacksize = "100";
 
3500
    }
 
3501
    fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize);  lineno++;
 
3502
  }else{
 
3503
    fprintf(out,"#define YYSTACKDEPTH 100\n");  lineno++;
 
3504
  }
 
3505
  if( mhflag ){
 
3506
    fprintf(out,"#if INTERFACE\n"); lineno++;
 
3507
  }
 
3508
  name = lemp->name ? lemp->name : "Parse";
 
3509
  if( lemp->arg && lemp->arg[0] ){
 
3510
    int i;
 
3511
    i = strlen(lemp->arg);
 
3512
    while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
 
3513
    while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
 
3514
    fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg);  lineno++;
 
3515
    fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg);  lineno++;
 
3516
    fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n",
 
3517
                 name,lemp->arg,&lemp->arg[i]);  lineno++;
 
3518
    fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n",
 
3519
                 name,&lemp->arg[i],&lemp->arg[i]);  lineno++;
 
3520
  }else{
 
3521
    fprintf(out,"#define %sARG_SDECL\n",name);  lineno++;
 
3522
    fprintf(out,"#define %sARG_PDECL\n",name);  lineno++;
 
3523
    fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
 
3524
    fprintf(out,"#define %sARG_STORE\n",name); lineno++;
 
3525
  }
 
3526
  if( mhflag ){
 
3527
    fprintf(out,"#endif\n"); lineno++;
 
3528
  }
 
3529
  fprintf(out,"#define YYNSTATE %d\n",lemp->nstate);  lineno++;
 
3530
  fprintf(out,"#define YYNRULE %d\n",lemp->nrule);  lineno++;
 
3531
  fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index);  lineno++;
 
3532
  fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum);  lineno++;
 
3533
  if( lemp->has_fallback ){
 
3534
    fprintf(out,"#define YYFALLBACK 1\n");  lineno++;
 
3535
  }
 
3536
  tplt_xfer(lemp->name,in,out,&lineno);
 
3537
 
 
3538
  /* Generate the action table and its associates:
 
3539
  **
 
3540
  **  yy_action[]        A single table containing all actions.
 
3541
  **  yy_lookahead[]     A table containing the lookahead for each entry in
 
3542
  **                     yy_action.  Used to detect hash collisions.
 
3543
  **  yy_shift_ofst[]    For each state, the offset into yy_action for
 
3544
  **                     shifting terminals.
 
3545
  **  yy_reduce_ofst[]   For each state, the offset into yy_action for
 
3546
  **                     shifting non-terminals after a reduce.
 
3547
  **  yy_default[]       Default action for each state.
 
3548
  */
 
3549
 
 
3550
  /* Compute the actions on all states and count them up */
 
3551
  ax = malloc( sizeof(ax[0])*lemp->nstate*2 );
 
3552
  if( ax==0 ){
 
3553
    fprintf(stderr,"malloc failed\n");
 
3554
    exit(1);
 
3555
  }
 
3556
  for(i=0; i<lemp->nstate; i++){
 
3557
    stp = lemp->sorted[i];
 
3558
    ax[i*2].stp = stp;
 
3559
    ax[i*2].isTkn = 1;
 
3560
    ax[i*2].nAction = stp->nTknAct;
 
3561
    ax[i*2+1].stp = stp;
 
3562
    ax[i*2+1].isTkn = 0;
 
3563
    ax[i*2+1].nAction = stp->nNtAct;
 
3564
  }
 
3565
  mxTknOfst = mnTknOfst = 0;
 
3566
  mxNtOfst = mnNtOfst = 0;
 
3567
 
 
3568
  /* Compute the action table.  In order to try to keep the size of the
 
3569
  ** action table to a minimum, the heuristic of placing the largest action
 
3570
  ** sets first is used.
 
3571
  */
 
3572
  qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare);
 
3573
  pActtab = acttab_alloc();
 
3574
  for(i=0; i<lemp->nstate*2 && ax[i].nAction>0; i++){
 
3575
    stp = ax[i].stp;
 
3576
    if( ax[i].isTkn ){
 
3577
      for(ap=stp->ap; ap; ap=ap->next){
 
3578
        int action;
 
3579
        if( ap->sp->index>=lemp->nterminal ) continue;
 
3580
        action = compute_action(lemp, ap);
 
3581
        if( action<0 ) continue;
 
3582
        acttab_action(pActtab, ap->sp->index, action);
 
3583
      }
 
3584
      stp->iTknOfst = acttab_insert(pActtab);
 
3585
      if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
 
3586
      if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
 
3587
    }else{
 
3588
      for(ap=stp->ap; ap; ap=ap->next){
 
3589
        int action;
 
3590
        if( ap->sp->index<lemp->nterminal ) continue;
 
3591
        if( ap->sp->index==lemp->nsymbol ) continue;
 
3592
        action = compute_action(lemp, ap);
 
3593
        if( action<0 ) continue;
 
3594
        acttab_action(pActtab, ap->sp->index, action);
 
3595
      }
 
3596
      stp->iNtOfst = acttab_insert(pActtab);
 
3597
      if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
 
3598
      if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
 
3599
    }
 
3600
  }
 
3601
  free(ax);
 
3602
 
 
3603
  /* Output the yy_action table */
 
3604
  fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++;
 
3605
  n = acttab_size(pActtab);
 
3606
  for(i=j=0; i<n; i++){
 
3607
    int action = acttab_yyaction(pActtab, i);
 
3608
    if( action<0 ) action = lemp->nsymbol + lemp->nrule + 2;
 
3609
    if( j==0 ) fprintf(out," /* %5d */ ", i);
 
3610
    fprintf(out, " %4d,", action);
 
3611
    if( j==9 || i==n-1 ){
 
3612
      fprintf(out, "\n"); lineno++;
 
3613
      j = 0;
 
3614
    }else{
 
3615
      j++;
 
3616
    }
 
3617
  }
 
3618
  fprintf(out, "};\n"); lineno++;
 
3619
 
 
3620
  /* Output the yy_lookahead table */
 
3621
  fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++;
 
3622
  for(i=j=0; i<n; i++){
 
3623
    int la = acttab_yylookahead(pActtab, i);
 
3624
    if( la<0 ) la = lemp->nsymbol;
 
3625
    if( j==0 ) fprintf(out," /* %5d */ ", i);
 
3626
    fprintf(out, " %4d,", la);
 
3627
    if( j==9 || i==n-1 ){
 
3628
      fprintf(out, "\n"); lineno++;
 
3629
      j = 0;
 
3630
    }else{
 
3631
      j++;
 
3632
    }
 
3633
  }
 
3634
  fprintf(out, "};\n"); lineno++;
 
3635
 
 
3636
  /* Output the yy_shift_ofst[] table */
 
3637
  fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
 
3638
  n = lemp->nstate;
 
3639
  while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--;
 
3640
  fprintf(out, "#define YY_SHIFT_MAX %d\n", n-1); lineno++;
 
3641
  fprintf(out, "static const %s yy_shift_ofst[] = {\n", 
 
3642
          minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
 
3643
  for(i=j=0; i<n; i++){
 
3644
    int ofst;
 
3645
    stp = lemp->sorted[i];
 
3646
    ofst = stp->iTknOfst;
 
3647
    if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
 
3648
    if( j==0 ) fprintf(out," /* %5d */ ", i);
 
3649
    fprintf(out, " %4d,", ofst);
 
3650
    if( j==9 || i==n-1 ){
 
3651
      fprintf(out, "\n"); lineno++;
 
3652
      j = 0;
 
3653
    }else{
 
3654
      j++;
 
3655
    }
 
3656
  }
 
3657
  fprintf(out, "};\n"); lineno++;
 
3658
 
 
3659
  /* Output the yy_reduce_ofst[] table */
 
3660
  fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
 
3661
  n = lemp->nstate;
 
3662
  while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--;
 
3663
  fprintf(out, "#define YY_REDUCE_MAX %d\n", n-1); lineno++;
 
3664
  fprintf(out, "static const %s yy_reduce_ofst[] = {\n", 
 
3665
          minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
 
3666
  for(i=j=0; i<n; i++){
 
3667
    int ofst;
 
3668
    stp = lemp->sorted[i];
 
3669
    ofst = stp->iNtOfst;
 
3670
    if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
 
3671
    if( j==0 ) fprintf(out," /* %5d */ ", i);
 
3672
    fprintf(out, " %4d,", ofst);
 
3673
    if( j==9 || i==n-1 ){
 
3674
      fprintf(out, "\n"); lineno++;
 
3675
      j = 0;
 
3676
    }else{
 
3677
      j++;
 
3678
    }
 
3679
  }
 
3680
  fprintf(out, "};\n"); lineno++;
 
3681
 
 
3682
  /* Output the default action table */
 
3683
  fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++;
 
3684
  n = lemp->nstate;
 
3685
  for(i=j=0; i<n; i++){
 
3686
    stp = lemp->sorted[i];
 
3687
    if( j==0 ) fprintf(out," /* %5d */ ", i);
 
3688
    fprintf(out, " %4d,", stp->iDflt);
 
3689
    if( j==9 || i==n-1 ){
 
3690
      fprintf(out, "\n"); lineno++;
 
3691
      j = 0;
 
3692
    }else{
 
3693
      j++;
 
3694
    }
 
3695
  }
 
3696
  fprintf(out, "};\n"); lineno++;
 
3697
  tplt_xfer(lemp->name,in,out,&lineno);
 
3698
 
 
3699
  /* Generate the table of fallback tokens.
 
3700
  */
 
3701
  if( lemp->has_fallback ){
 
3702
    for(i=0; i<lemp->nterminal; i++){
 
3703
      struct symbol *p = lemp->symbols[i];
 
3704
      if( p->fallback==0 ){
 
3705
        fprintf(out, "    0,  /* %10s => nothing */\n", p->name);
 
3706
      }else{
 
3707
        fprintf(out, "  %3d,  /* %10s => %s */\n", p->fallback->index,
 
3708
          p->name, p->fallback->name);
 
3709
      }
 
3710
      lineno++;
 
3711
    }
 
3712
  }
 
3713
  tplt_xfer(lemp->name, in, out, &lineno);
 
3714
 
 
3715
  /* Generate a table containing the symbolic name of every symbol
 
3716
  */
 
3717
  for(i=0; i<lemp->nsymbol; i++){
 
3718
    sprintf(line,"\"%s\",",lemp->symbols[i]->name);
 
3719
    fprintf(out,"  %-15s",line);
 
3720
    if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; }
 
3721
  }
 
3722
  if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; }
 
3723
  tplt_xfer(lemp->name,in,out,&lineno);
 
3724
 
 
3725
  /* Generate a table containing a text string that describes every
 
3726
  ** rule in the rule set of the grammer.  This information is used
 
3727
  ** when tracing REDUCE actions.
 
3728
  */
 
3729
  for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
 
3730
    assert( rp->index==i );
 
3731
    fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name);
 
3732
    for(j=0; j<rp->nrhs; j++){
 
3733
      struct symbol *sp = rp->rhs[j];
 
3734
      fprintf(out," %s", sp->name);
 
3735
      if( sp->type==MULTITERMINAL ){
 
3736
        int k;
 
3737
        for(k=1; k<sp->nsubsym; k++){
 
3738
          fprintf(out,"|%s",sp->subsym[k]->name);
 
3739
        }
 
3740
      }
 
3741
    }
 
3742
    fprintf(out,"\",\n"); lineno++;
 
3743
  }
 
3744
  tplt_xfer(lemp->name,in,out,&lineno);
 
3745
 
 
3746
  /* Generate code which executes every time a symbol is popped from
 
3747
  ** the stack while processing errors or while destroying the parser. 
 
3748
  ** (In other words, generate the %destructor actions)
 
3749
  */
 
3750
  if( lemp->tokendest ){
 
3751
    for(i=0; i<lemp->nsymbol; i++){
 
3752
      struct symbol *sp = lemp->symbols[i];
 
3753
      if( sp==0 || sp->type!=TERMINAL ) continue;
 
3754
      fprintf(out,"    case %d:\n",sp->index); lineno++;
 
3755
    }
 
3756
    for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++);
 
3757
    if( i<lemp->nsymbol ){
 
3758
      emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
 
3759
      fprintf(out,"      break;\n"); lineno++;
 
3760
    }
 
3761
  }
 
3762
  if( lemp->vardest ){
 
3763
    struct symbol *dflt_sp = 0;
 
3764
    for(i=0; i<lemp->nsymbol; i++){
 
3765
      struct symbol *sp = lemp->symbols[i];
 
3766
      if( sp==0 || sp->type==TERMINAL ||
 
3767
          sp->index<=0 || sp->destructor!=0 ) continue;
 
3768
      fprintf(out,"    case %d:\n",sp->index); lineno++;
 
3769
      dflt_sp = sp;
 
3770
    }
 
3771
    if( dflt_sp!=0 ){
 
3772
      emit_destructor_code(out,dflt_sp,lemp,&lineno);
 
3773
      fprintf(out,"      break;\n"); lineno++;
 
3774
    }
 
3775
  }
 
3776
  for(i=0; i<lemp->nsymbol; i++){
 
3777
    struct symbol *sp = lemp->symbols[i];
 
3778
    if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue;
 
3779
    fprintf(out,"    case %d:\n",sp->index); lineno++;
 
3780
 
 
3781
    /* Combine duplicate destructors into a single case */
 
3782
    for(j=i+1; j<lemp->nsymbol; j++){
 
3783
      struct symbol *sp2 = lemp->symbols[j];
 
3784
      if( sp2 && sp2->type!=TERMINAL && sp2->destructor
 
3785
          && sp2->dtnum==sp->dtnum
 
3786
          && strcmp(sp->destructor,sp2->destructor)==0 ){
 
3787
         fprintf(out,"    case %d:\n",sp2->index); lineno++;
 
3788
         sp2->destructor = 0;
 
3789
      }
 
3790
    }
 
3791
 
 
3792
    emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
 
3793
    fprintf(out,"      break;\n"); lineno++;
 
3794
  }
 
3795
  tplt_xfer(lemp->name,in,out,&lineno);
 
3796
 
 
3797
  /* Generate code which executes whenever the parser stack overflows */
 
3798
  tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
 
3799
  tplt_xfer(lemp->name,in,out,&lineno);
 
3800
 
 
3801
  /* Generate the table of rule information 
 
3802
  **
 
3803
  ** Note: This code depends on the fact that rules are number
 
3804
  ** sequentually beginning with 0.
 
3805
  */
 
3806
  for(rp=lemp->rule; rp; rp=rp->next){
 
3807
    fprintf(out,"  { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++;
 
3808
  }
 
3809
  tplt_xfer(lemp->name,in,out,&lineno);
 
3810
 
 
3811
  /* Generate code which execution during each REDUCE action */
 
3812
  for(rp=lemp->rule; rp; rp=rp->next){
 
3813
    if( rp->code ) translate_code(lemp, rp);
 
3814
  }
 
3815
  for(rp=lemp->rule; rp; rp=rp->next){
 
3816
    struct rule *rp2;
 
3817
    if( rp->code==0 ) continue;
 
3818
    fprintf(out,"      case %d:\n",rp->index); lineno++;
 
3819
    for(rp2=rp->next; rp2; rp2=rp2->next){
 
3820
      if( rp2->code==rp->code ){
 
3821
        fprintf(out,"      case %d:\n",rp2->index); lineno++;
 
3822
        rp2->code = 0;
 
3823
      }
 
3824
    }
 
3825
    emit_code(out,rp,lemp,&lineno);
 
3826
    fprintf(out,"        break;\n"); lineno++;
 
3827
  }
 
3828
  tplt_xfer(lemp->name,in,out,&lineno);
 
3829
 
 
3830
  /* Generate code which executes if a parse fails */
 
3831
  tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno);
 
3832
  tplt_xfer(lemp->name,in,out,&lineno);
 
3833
 
 
3834
  /* Generate code which executes when a syntax error occurs */
 
3835
  tplt_print(out,lemp,lemp->error,lemp->errorln,&lineno);
 
3836
  tplt_xfer(lemp->name,in,out,&lineno);
 
3837
 
 
3838
  /* Generate code which executes when the parser accepts its input */
 
3839
  tplt_print(out,lemp,lemp->accept,lemp->acceptln,&lineno);
 
3840
  tplt_xfer(lemp->name,in,out,&lineno);
 
3841
 
 
3842
  /* Append any addition code the user desires */
 
3843
  tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno);
 
3844
 
 
3845
  fclose(in);
 
3846
  fclose(out);
 
3847
  return;
 
3848
}
 
3849
 
 
3850
/* Generate a header file for the parser */
 
3851
void ReportHeader(lemp)
 
3852
struct lemon *lemp;
 
3853
{
 
3854
  FILE *out, *in;
 
3855
  char *prefix;
 
3856
  char line[LINESIZE];
 
3857
  char pattern[LINESIZE];
 
3858
  int i;
 
3859
 
 
3860
  if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
 
3861
  else                    prefix = "";
 
3862
  in = file_open(lemp,".h","rb");
 
3863
  if( in ){
 
3864
    for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){
 
3865
      sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
 
3866
      if( strcmp(line,pattern) ) break;
 
3867
    }
 
3868
    fclose(in);
 
3869
    if( i==lemp->nterminal ){
 
3870
      /* No change in the file.  Don't rewrite it. */
 
3871
      return;
 
3872
    }
 
3873
  }
 
3874
  out = file_open(lemp,".h","wb");
 
3875
  if( out ){
 
3876
    for(i=1; i<lemp->nterminal; i++){
 
3877
      fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
 
3878
    }
 
3879
    fclose(out);  
 
3880
  }
 
3881
  return;
 
3882
}
 
3883
 
 
3884
/* Reduce the size of the action tables, if possible, by making use
 
3885
** of defaults.
 
3886
**
 
3887
** In this version, we take the most frequent REDUCE action and make
 
3888
** it the default.
 
3889
*/
 
3890
void CompressTables(lemp)
 
3891
struct lemon *lemp;
 
3892
{
 
3893
  struct state *stp;
 
3894
  struct action *ap, *ap2;
 
3895
  struct rule *rp, *rp2, *rbest;
 
3896
  int nbest, n;
 
3897
  int i;
 
3898
 
 
3899
  for(i=0; i<lemp->nstate; i++){
 
3900
    stp = lemp->sorted[i];
 
3901
    nbest = 0;
 
3902
    rbest = 0;
 
3903
 
 
3904
    for(ap=stp->ap; ap; ap=ap->next){
 
3905
      if( ap->type!=REDUCE ) continue;
 
3906
      rp = ap->x.rp;
 
3907
      if( rp==rbest ) continue;
 
3908
      n = 1;
 
3909
      for(ap2=ap->next; ap2; ap2=ap2->next){
 
3910
        if( ap2->type!=REDUCE ) continue;
 
3911
        rp2 = ap2->x.rp;
 
3912
        if( rp2==rbest ) continue;
 
3913
        if( rp2==rp ) n++;
 
3914
      }
 
3915
      if( n>nbest ){
 
3916
        nbest = n;
 
3917
        rbest = rp;
 
3918
      }
 
3919
    }
 
3920
 
 
3921
    /* Do not make a default if the number of rules to default
 
3922
    ** is not at least 1 */
 
3923
    if( nbest<1 ) continue;
 
3924
 
 
3925
 
 
3926
    /* Combine matching REDUCE actions into a single default */
 
3927
    for(ap=stp->ap; ap; ap=ap->next){
 
3928
      if( ap->type==REDUCE && ap->x.rp==rbest ) break;
 
3929
    }
 
3930
    assert( ap );
 
3931
    ap->sp = Symbol_new("{default}");
 
3932
    for(ap=ap->next; ap; ap=ap->next){
 
3933
      if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED;
 
3934
    }
 
3935
    stp->ap = Action_sort(stp->ap);
 
3936
  }
 
3937
}
 
3938
 
 
3939
 
 
3940
/*
 
3941
** Compare two states for sorting purposes.  The smaller state is the
 
3942
** one with the most non-terminal actions.  If they have the same number
 
3943
** of non-terminal actions, then the smaller is the one with the most
 
3944
** token actions.
 
3945
*/
 
3946
static int stateResortCompare(const void *a, const void *b){
 
3947
  const struct state *pA = *(const struct state**)a;
 
3948
  const struct state *pB = *(const struct state**)b;
 
3949
  int n;
 
3950
 
 
3951
  n = pB->nNtAct - pA->nNtAct;
 
3952
  if( n==0 ){
 
3953
    n = pB->nTknAct - pA->nTknAct;
 
3954
  }
 
3955
  return n;
 
3956
}
 
3957
 
 
3958
 
 
3959
/*
 
3960
** Renumber and resort states so that states with fewer choices
 
3961
** occur at the end.  Except, keep state 0 as the first state.
 
3962
*/
 
3963
void ResortStates(lemp)
 
3964
struct lemon *lemp;
 
3965
{
 
3966
  int i;
 
3967
  struct state *stp;
 
3968
  struct action *ap;
 
3969
 
 
3970
  for(i=0; i<lemp->nstate; i++){
 
3971
    stp = lemp->sorted[i];
 
3972
    stp->nTknAct = stp->nNtAct = 0;
 
3973
    stp->iDflt = lemp->nstate + lemp->nrule;
 
3974
    stp->iTknOfst = NO_OFFSET;
 
3975
    stp->iNtOfst = NO_OFFSET;
 
3976
    for(ap=stp->ap; ap; ap=ap->next){
 
3977
      if( compute_action(lemp,ap)>=0 ){
 
3978
        if( ap->sp->index<lemp->nterminal ){
 
3979
          stp->nTknAct++;
 
3980
        }else if( ap->sp->index<lemp->nsymbol ){
 
3981
          stp->nNtAct++;
 
3982
        }else{
 
3983
          stp->iDflt = compute_action(lemp, ap);
 
3984
        }
 
3985
      }
 
3986
    }
 
3987
  }
 
3988
  qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]),
 
3989
        stateResortCompare);
 
3990
  for(i=0; i<lemp->nstate; i++){
 
3991
    lemp->sorted[i]->statenum = i;
 
3992
  }
 
3993
}
 
3994
 
 
3995
 
 
3996
/***************** From the file "set.c" ************************************/
 
3997
/*
 
3998
** Set manipulation routines for the LEMON parser generator.
 
3999
*/
 
4000
 
 
4001
static int size = 0;
 
4002
 
 
4003
/* Set the set size */
 
4004
void SetSize(n)
 
4005
int n;
 
4006
{
 
4007
  size = n+1;
 
4008
}
 
4009
 
 
4010
/* Allocate a new set */
 
4011
char *SetNew(){
 
4012
  char *s;
 
4013
  int i;
 
4014
  s = (char*)malloc( size );
 
4015
  if( s==0 ){
 
4016
    extern void memory_error();
 
4017
    memory_error();
 
4018
  }
 
4019
  for(i=0; i<size; i++) s[i] = 0;
 
4020
  return s;
 
4021
}
 
4022
 
 
4023
/* Deallocate a set */
 
4024
void SetFree(s)
 
4025
char *s;
 
4026
{
 
4027
  free(s);
 
4028
}
 
4029
 
 
4030
/* Add a new element to the set.  Return TRUE if the element was added
 
4031
** and FALSE if it was already there. */
 
4032
int SetAdd(s,e)
 
4033
char *s;
 
4034
int e;
 
4035
{
 
4036
  int rv;
 
4037
  rv = s[e];
 
4038
  s[e] = 1;
 
4039
  return !rv;
 
4040
}
 
4041
 
 
4042
/* Add every element of s2 to s1.  Return TRUE if s1 changes. */
 
4043
int SetUnion(s1,s2)
 
4044
char *s1;
 
4045
char *s2;
 
4046
{
 
4047
  int i, progress;
 
4048
  progress = 0;
 
4049
  for(i=0; i<size; i++){
 
4050
    if( s2[i]==0 ) continue;
 
4051
    if( s1[i]==0 ){
 
4052
      progress = 1;
 
4053
      s1[i] = 1;
 
4054
    }
 
4055
  }
 
4056
  return progress;
 
4057
}
 
4058
/********************** From the file "table.c" ****************************/
 
4059
/*
 
4060
** All code in this file has been automatically generated
 
4061
** from a specification in the file
 
4062
**              "table.q"
 
4063
** by the associative array code building program "aagen".
 
4064
** Do not edit this file!  Instead, edit the specification
 
4065
** file, then rerun aagen.
 
4066
*/
 
4067
/*
 
4068
** Code for processing tables in the LEMON parser generator.
 
4069
*/
 
4070
 
 
4071
PRIVATE int strhash(x)
 
4072
char *x;
 
4073
{
 
4074
  int h = 0;
 
4075
  while( *x) h = h*13 + *(x++);
 
4076
  return h;
 
4077
}
 
4078
 
 
4079
/* Works like strdup, sort of.  Save a string in malloced memory, but
 
4080
** keep strings in a table so that the same string is not in more
 
4081
** than one place.
 
4082
*/
 
4083
char *Strsafe(y)
 
4084
char *y;
 
4085
{
 
4086
  char *z;
 
4087
 
 
4088
  z = Strsafe_find(y);
 
4089
  if( z==0 && (z=malloc( strlen(y)+1 ))!=0 ){
 
4090
    strcpy(z,y);
 
4091
    Strsafe_insert(z);
 
4092
  }
 
4093
  MemoryCheck(z);
 
4094
  return z;
 
4095
}
 
4096
 
 
4097
/* There is one instance of the following structure for each
 
4098
** associative array of type "x1".
 
4099
*/
 
4100
struct s_x1 {
 
4101
  int size;               /* The number of available slots. */
 
4102
                          /*   Must be a power of 2 greater than or */
 
4103
                          /*   equal to 1 */
 
4104
  int count;              /* Number of currently slots filled */
 
4105
  struct s_x1node *tbl;  /* The data stored here */
 
4106
  struct s_x1node **ht;  /* Hash table for lookups */
 
4107
};
 
4108
 
 
4109
/* There is one instance of this structure for every data element
 
4110
** in an associative array of type "x1".
 
4111
*/
 
4112
typedef struct s_x1node {
 
4113
  char *data;                  /* The data */
 
4114
  struct s_x1node *next;   /* Next entry with the same hash */
 
4115
  struct s_x1node **from;  /* Previous link */
 
4116
} x1node;
 
4117
 
 
4118
/* There is only one instance of the array, which is the following */
 
4119
static struct s_x1 *x1a;
 
4120
 
 
4121
/* Allocate a new associative array */
 
4122
void Strsafe_init(){
 
4123
  if( x1a ) return;
 
4124
  x1a = (struct s_x1*)malloc( sizeof(struct s_x1) );
 
4125
  if( x1a ){
 
4126
    x1a->size = 1024;
 
4127
    x1a->count = 0;
 
4128
    x1a->tbl = (x1node*)malloc( 
 
4129
      (sizeof(x1node) + sizeof(x1node*))*1024 );
 
4130
    if( x1a->tbl==0 ){
 
4131
      free(x1a);
 
4132
      x1a = 0;
 
4133
    }else{
 
4134
      int i;
 
4135
      x1a->ht = (x1node**)&(x1a->tbl[1024]);
 
4136
      for(i=0; i<1024; i++) x1a->ht[i] = 0;
 
4137
    }
 
4138
  }
 
4139
}
 
4140
/* Insert a new record into the array.  Return TRUE if successful.
 
4141
** Prior data with the same key is NOT overwritten */
 
4142
int Strsafe_insert(data)
 
4143
char *data;
 
4144
{
 
4145
  x1node *np;
 
4146
  int h;
 
4147
  int ph;
 
4148
 
 
4149
  if( x1a==0 ) return 0;
 
4150
  ph = strhash(data);
 
4151
  h = ph & (x1a->size-1);
 
4152
  np = x1a->ht[h];
 
4153
  while( np ){
 
4154
    if( strcmp(np->data,data)==0 ){
 
4155
      /* An existing entry with the same key is found. */
 
4156
      /* Fail because overwrite is not allows. */
 
4157
      return 0;
 
4158
    }
 
4159
    np = np->next;
 
4160
  }
 
4161
  if( x1a->count>=x1a->size ){
 
4162
    /* Need to make the hash table bigger */
 
4163
    int i,size;
 
4164
    struct s_x1 array;
 
4165
    array.size = size = x1a->size*2;
 
4166
    array.count = x1a->count;
 
4167
    array.tbl = (x1node*)malloc(
 
4168
      (sizeof(x1node) + sizeof(x1node*))*size );
 
4169
    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
 
4170
    array.ht = (x1node**)&(array.tbl[size]);
 
4171
    for(i=0; i<size; i++) array.ht[i] = 0;
 
4172
    for(i=0; i<x1a->count; i++){
 
4173
      x1node *oldnp, *newnp;
 
4174
      oldnp = &(x1a->tbl[i]);
 
4175
      h = strhash(oldnp->data) & (size-1);
 
4176
      newnp = &(array.tbl[i]);
 
4177
      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
 
4178
      newnp->next = array.ht[h];
 
4179
      newnp->data = oldnp->data;
 
4180
      newnp->from = &(array.ht[h]);
 
4181
      array.ht[h] = newnp;
 
4182
    }
 
4183
    free(x1a->tbl);
 
4184
    *x1a = array;
 
4185
  }
 
4186
  /* Insert the new data */
 
4187
  h = ph & (x1a->size-1);
 
4188
  np = &(x1a->tbl[x1a->count++]);
 
4189
  np->data = data;
 
4190
  if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next);
 
4191
  np->next = x1a->ht[h];
 
4192
  x1a->ht[h] = np;
 
4193
  np->from = &(x1a->ht[h]);
 
4194
  return 1;
 
4195
}
 
4196
 
 
4197
/* Return a pointer to data assigned to the given key.  Return NULL
 
4198
** if no such key. */
 
4199
char *Strsafe_find(key)
 
4200
char *key;
 
4201
{
 
4202
  int h;
 
4203
  x1node *np;
 
4204
 
 
4205
  if( x1a==0 ) return 0;
 
4206
  h = strhash(key) & (x1a->size-1);
 
4207
  np = x1a->ht[h];
 
4208
  while( np ){
 
4209
    if( strcmp(np->data,key)==0 ) break;
 
4210
    np = np->next;
 
4211
  }
 
4212
  return np ? np->data : 0;
 
4213
}
 
4214
 
 
4215
/* Return a pointer to the (terminal or nonterminal) symbol "x".
 
4216
** Create a new symbol if this is the first time "x" has been seen.
 
4217
*/
 
4218
struct symbol *Symbol_new(x)
 
4219
char *x;
 
4220
{
 
4221
  struct symbol *sp;
 
4222
 
 
4223
  sp = Symbol_find(x);
 
4224
  if( sp==0 ){
 
4225
    sp = (struct symbol *)malloc( sizeof(struct symbol) );
 
4226
    MemoryCheck(sp);
 
4227
    sp->name = Strsafe(x);
 
4228
    sp->type = isupper(*x) ? TERMINAL : NONTERMINAL;
 
4229
    sp->rule = 0;
 
4230
    sp->fallback = 0;
 
4231
    sp->prec = -1;
 
4232
    sp->assoc = UNK;
 
4233
    sp->firstset = 0;
 
4234
    sp->lambda = B_FALSE;
 
4235
    sp->destructor = 0;
 
4236
    sp->datatype = 0;
 
4237
    Symbol_insert(sp,sp->name);
 
4238
  }
 
4239
  return sp;
 
4240
}
 
4241
 
 
4242
/* Compare two symbols for working purposes
 
4243
**
 
4244
** Symbols that begin with upper case letters (terminals or tokens)
 
4245
** must sort before symbols that begin with lower case letters
 
4246
** (non-terminals).  Other than that, the order does not matter.
 
4247
**
 
4248
** We find experimentally that leaving the symbols in their original
 
4249
** order (the order they appeared in the grammar file) gives the
 
4250
** smallest parser tables in SQLite.
 
4251
*/
 
4252
int Symbolcmpp(struct symbol **a, struct symbol **b){
 
4253
  int i1 = (**a).index + 10000000*((**a).name[0]>'Z');
 
4254
  int i2 = (**b).index + 10000000*((**b).name[0]>'Z');
 
4255
  return i1-i2;
 
4256
}
 
4257
 
 
4258
/* There is one instance of the following structure for each
 
4259
** associative array of type "x2".
 
4260
*/
 
4261
struct s_x2 {
 
4262
  int size;               /* The number of available slots. */
 
4263
                          /*   Must be a power of 2 greater than or */
 
4264
                          /*   equal to 1 */
 
4265
  int count;              /* Number of currently slots filled */
 
4266
  struct s_x2node *tbl;  /* The data stored here */
 
4267
  struct s_x2node **ht;  /* Hash table for lookups */
 
4268
};
 
4269
 
 
4270
/* There is one instance of this structure for every data element
 
4271
** in an associative array of type "x2".
 
4272
*/
 
4273
typedef struct s_x2node {
 
4274
  struct symbol *data;                  /* The data */
 
4275
  char *key;                   /* The key */
 
4276
  struct s_x2node *next;   /* Next entry with the same hash */
 
4277
  struct s_x2node **from;  /* Previous link */
 
4278
} x2node;
 
4279
 
 
4280
/* There is only one instance of the array, which is the following */
 
4281
static struct s_x2 *x2a;
 
4282
 
 
4283
/* Allocate a new associative array */
 
4284
void Symbol_init(){
 
4285
  if( x2a ) return;
 
4286
  x2a = (struct s_x2*)malloc( sizeof(struct s_x2) );
 
4287
  if( x2a ){
 
4288
    x2a->size = 128;
 
4289
    x2a->count = 0;
 
4290
    x2a->tbl = (x2node*)malloc( 
 
4291
      (sizeof(x2node) + sizeof(x2node*))*128 );
 
4292
    if( x2a->tbl==0 ){
 
4293
      free(x2a);
 
4294
      x2a = 0;
 
4295
    }else{
 
4296
      int i;
 
4297
      x2a->ht = (x2node**)&(x2a->tbl[128]);
 
4298
      for(i=0; i<128; i++) x2a->ht[i] = 0;
 
4299
    }
 
4300
  }
 
4301
}
 
4302
/* Insert a new record into the array.  Return TRUE if successful.
 
4303
** Prior data with the same key is NOT overwritten */
 
4304
int Symbol_insert(data,key)
 
4305
struct symbol *data;
 
4306
char *key;
 
4307
{
 
4308
  x2node *np;
 
4309
  int h;
 
4310
  int ph;
 
4311
 
 
4312
  if( x2a==0 ) return 0;
 
4313
  ph = strhash(key);
 
4314
  h = ph & (x2a->size-1);
 
4315
  np = x2a->ht[h];
 
4316
  while( np ){
 
4317
    if( strcmp(np->key,key)==0 ){
 
4318
      /* An existing entry with the same key is found. */
 
4319
      /* Fail because overwrite is not allows. */
 
4320
      return 0;
 
4321
    }
 
4322
    np = np->next;
 
4323
  }
 
4324
  if( x2a->count>=x2a->size ){
 
4325
    /* Need to make the hash table bigger */
 
4326
    int i,size;
 
4327
    struct s_x2 array;
 
4328
    array.size = size = x2a->size*2;
 
4329
    array.count = x2a->count;
 
4330
    array.tbl = (x2node*)malloc(
 
4331
      (sizeof(x2node) + sizeof(x2node*))*size );
 
4332
    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
 
4333
    array.ht = (x2node**)&(array.tbl[size]);
 
4334
    for(i=0; i<size; i++) array.ht[i] = 0;
 
4335
    for(i=0; i<x2a->count; i++){
 
4336
      x2node *oldnp, *newnp;
 
4337
      oldnp = &(x2a->tbl[i]);
 
4338
      h = strhash(oldnp->key) & (size-1);
 
4339
      newnp = &(array.tbl[i]);
 
4340
      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
 
4341
      newnp->next = array.ht[h];
 
4342
      newnp->key = oldnp->key;
 
4343
      newnp->data = oldnp->data;
 
4344
      newnp->from = &(array.ht[h]);
 
4345
      array.ht[h] = newnp;
 
4346
    }
 
4347
    free(x2a->tbl);
 
4348
    *x2a = array;
 
4349
  }
 
4350
  /* Insert the new data */
 
4351
  h = ph & (x2a->size-1);
 
4352
  np = &(x2a->tbl[x2a->count++]);
 
4353
  np->key = key;
 
4354
  np->data = data;
 
4355
  if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next);
 
4356
  np->next = x2a->ht[h];
 
4357
  x2a->ht[h] = np;
 
4358
  np->from = &(x2a->ht[h]);
 
4359
  return 1;
 
4360
}
 
4361
 
 
4362
/* Return a pointer to data assigned to the given key.  Return NULL
 
4363
** if no such key. */
 
4364
struct symbol *Symbol_find(key)
 
4365
char *key;
 
4366
{
 
4367
  int h;
 
4368
  x2node *np;
 
4369
 
 
4370
  if( x2a==0 ) return 0;
 
4371
  h = strhash(key) & (x2a->size-1);
 
4372
  np = x2a->ht[h];
 
4373
  while( np ){
 
4374
    if( strcmp(np->key,key)==0 ) break;
 
4375
    np = np->next;
 
4376
  }
 
4377
  return np ? np->data : 0;
 
4378
}
 
4379
 
 
4380
/* Return the n-th data.  Return NULL if n is out of range. */
 
4381
struct symbol *Symbol_Nth(n)
 
4382
int n;
 
4383
{
 
4384
  struct symbol *data;
 
4385
  if( x2a && n>0 && n<=x2a->count ){
 
4386
    data = x2a->tbl[n-1].data;
 
4387
  }else{
 
4388
    data = 0;
 
4389
  }
 
4390
  return data;
 
4391
}
 
4392
 
 
4393
/* Return the size of the array */
 
4394
int Symbol_count()
 
4395
{
 
4396
  return x2a ? x2a->count : 0;
 
4397
}
 
4398
 
 
4399
/* Return an array of pointers to all data in the table.
 
4400
** The array is obtained from malloc.  Return NULL if memory allocation
 
4401
** problems, or if the array is empty. */
 
4402
struct symbol **Symbol_arrayof()
 
4403
{
 
4404
  struct symbol **array;
 
4405
  int i,size;
 
4406
  if( x2a==0 ) return 0;
 
4407
  size = x2a->count;
 
4408
  array = (struct symbol **)malloc( sizeof(struct symbol *)*size );
 
4409
  if( array ){
 
4410
    for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
 
4411
  }
 
4412
  return array;
 
4413
}
 
4414
 
 
4415
/* Compare two configurations */
 
4416
int Configcmp(a,b)
 
4417
struct config *a;
 
4418
struct config *b;
 
4419
{
 
4420
  int x;
 
4421
  x = a->rp->index - b->rp->index;
 
4422
  if( x==0 ) x = a->dot - b->dot;
 
4423
  return x;
 
4424
}
 
4425
 
 
4426
/* Compare two states */
 
4427
PRIVATE int statecmp(a,b)
 
4428
struct config *a;
 
4429
struct config *b;
 
4430
{
 
4431
  int rc;
 
4432
  for(rc=0; rc==0 && a && b;  a=a->bp, b=b->bp){
 
4433
    rc = a->rp->index - b->rp->index;
 
4434
    if( rc==0 ) rc = a->dot - b->dot;
 
4435
  }
 
4436
  if( rc==0 ){
 
4437
    if( a ) rc = 1;
 
4438
    if( b ) rc = -1;
 
4439
  }
 
4440
  return rc;
 
4441
}
 
4442
 
 
4443
/* Hash a state */
 
4444
PRIVATE int statehash(a)
 
4445
struct config *a;
 
4446
{
 
4447
  int h=0;
 
4448
  while( a ){
 
4449
    h = h*571 + a->rp->index*37 + a->dot;
 
4450
    a = a->bp;
 
4451
  }
 
4452
  return h;
 
4453
}
 
4454
 
 
4455
/* Allocate a new state structure */
 
4456
struct state *State_new()
 
4457
{
 
4458
  struct state *new;
 
4459
  new = (struct state *)malloc( sizeof(struct state) );
 
4460
  MemoryCheck(new);
 
4461
  return new;
 
4462
}
 
4463
 
 
4464
/* There is one instance of the following structure for each
 
4465
** associative array of type "x3".
 
4466
*/
 
4467
struct s_x3 {
 
4468
  int size;               /* The number of available slots. */
 
4469
                          /*   Must be a power of 2 greater than or */
 
4470
                          /*   equal to 1 */
 
4471
  int count;              /* Number of currently slots filled */
 
4472
  struct s_x3node *tbl;  /* The data stored here */
 
4473
  struct s_x3node **ht;  /* Hash table for lookups */
 
4474
};
 
4475
 
 
4476
/* There is one instance of this structure for every data element
 
4477
** in an associative array of type "x3".
 
4478
*/
 
4479
typedef struct s_x3node {
 
4480
  struct state *data;                  /* The data */
 
4481
  struct config *key;                   /* The key */
 
4482
  struct s_x3node *next;   /* Next entry with the same hash */
 
4483
  struct s_x3node **from;  /* Previous link */
 
4484
} x3node;
 
4485
 
 
4486
/* There is only one instance of the array, which is the following */
 
4487
static struct s_x3 *x3a;
 
4488
 
 
4489
/* Allocate a new associative array */
 
4490
void State_init(){
 
4491
  if( x3a ) return;
 
4492
  x3a = (struct s_x3*)malloc( sizeof(struct s_x3) );
 
4493
  if( x3a ){
 
4494
    x3a->size = 128;
 
4495
    x3a->count = 0;
 
4496
    x3a->tbl = (x3node*)malloc( 
 
4497
      (sizeof(x3node) + sizeof(x3node*))*128 );
 
4498
    if( x3a->tbl==0 ){
 
4499
      free(x3a);
 
4500
      x3a = 0;
 
4501
    }else{
 
4502
      int i;
 
4503
      x3a->ht = (x3node**)&(x3a->tbl[128]);
 
4504
      for(i=0; i<128; i++) x3a->ht[i] = 0;
 
4505
    }
 
4506
  }
 
4507
}
 
4508
/* Insert a new record into the array.  Return TRUE if successful.
 
4509
** Prior data with the same key is NOT overwritten */
 
4510
int State_insert(data,key)
 
4511
struct state *data;
 
4512
struct config *key;
 
4513
{
 
4514
  x3node *np;
 
4515
  int h;
 
4516
  int ph;
 
4517
 
 
4518
  if( x3a==0 ) return 0;
 
4519
  ph = statehash(key);
 
4520
  h = ph & (x3a->size-1);
 
4521
  np = x3a->ht[h];
 
4522
  while( np ){
 
4523
    if( statecmp(np->key,key)==0 ){
 
4524
      /* An existing entry with the same key is found. */
 
4525
      /* Fail because overwrite is not allows. */
 
4526
      return 0;
 
4527
    }
 
4528
    np = np->next;
 
4529
  }
 
4530
  if( x3a->count>=x3a->size ){
 
4531
    /* Need to make the hash table bigger */
 
4532
    int i,size;
 
4533
    struct s_x3 array;
 
4534
    array.size = size = x3a->size*2;
 
4535
    array.count = x3a->count;
 
4536
    array.tbl = (x3node*)malloc(
 
4537
      (sizeof(x3node) + sizeof(x3node*))*size );
 
4538
    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
 
4539
    array.ht = (x3node**)&(array.tbl[size]);
 
4540
    for(i=0; i<size; i++) array.ht[i] = 0;
 
4541
    for(i=0; i<x3a->count; i++){
 
4542
      x3node *oldnp, *newnp;
 
4543
      oldnp = &(x3a->tbl[i]);
 
4544
      h = statehash(oldnp->key) & (size-1);
 
4545
      newnp = &(array.tbl[i]);
 
4546
      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
 
4547
      newnp->next = array.ht[h];
 
4548
      newnp->key = oldnp->key;
 
4549
      newnp->data = oldnp->data;
 
4550
      newnp->from = &(array.ht[h]);
 
4551
      array.ht[h] = newnp;
 
4552
    }
 
4553
    free(x3a->tbl);
 
4554
    *x3a = array;
 
4555
  }
 
4556
  /* Insert the new data */
 
4557
  h = ph & (x3a->size-1);
 
4558
  np = &(x3a->tbl[x3a->count++]);
 
4559
  np->key = key;
 
4560
  np->data = data;
 
4561
  if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next);
 
4562
  np->next = x3a->ht[h];
 
4563
  x3a->ht[h] = np;
 
4564
  np->from = &(x3a->ht[h]);
 
4565
  return 1;
 
4566
}
 
4567
 
 
4568
/* Return a pointer to data assigned to the given key.  Return NULL
 
4569
** if no such key. */
 
4570
struct state *State_find(key)
 
4571
struct config *key;
 
4572
{
 
4573
  int h;
 
4574
  x3node *np;
 
4575
 
 
4576
  if( x3a==0 ) return 0;
 
4577
  h = statehash(key) & (x3a->size-1);
 
4578
  np = x3a->ht[h];
 
4579
  while( np ){
 
4580
    if( statecmp(np->key,key)==0 ) break;
 
4581
    np = np->next;
 
4582
  }
 
4583
  return np ? np->data : 0;
 
4584
}
 
4585
 
 
4586
/* Return an array of pointers to all data in the table.
 
4587
** The array is obtained from malloc.  Return NULL if memory allocation
 
4588
** problems, or if the array is empty. */
 
4589
struct state **State_arrayof()
 
4590
{
 
4591
  struct state **array;
 
4592
  int i,size;
 
4593
  if( x3a==0 ) return 0;
 
4594
  size = x3a->count;
 
4595
  array = (struct state **)malloc( sizeof(struct state *)*size );
 
4596
  if( array ){
 
4597
    for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
 
4598
  }
 
4599
  return array;
 
4600
}
 
4601
 
 
4602
/* Hash a configuration */
 
4603
PRIVATE int confighash(a)
 
4604
struct config *a;
 
4605
{
 
4606
  int h=0;
 
4607
  h = h*571 + a->rp->index*37 + a->dot;
 
4608
  return h;
 
4609
}
 
4610
 
 
4611
/* There is one instance of the following structure for each
 
4612
** associative array of type "x4".
 
4613
*/
 
4614
struct s_x4 {
 
4615
  int size;               /* The number of available slots. */
 
4616
                          /*   Must be a power of 2 greater than or */
 
4617
                          /*   equal to 1 */
 
4618
  int count;              /* Number of currently slots filled */
 
4619
  struct s_x4node *tbl;  /* The data stored here */
 
4620
  struct s_x4node **ht;  /* Hash table for lookups */
 
4621
};
 
4622
 
 
4623
/* There is one instance of this structure for every data element
 
4624
** in an associative array of type "x4".
 
4625
*/
 
4626
typedef struct s_x4node {
 
4627
  struct config *data;                  /* The data */
 
4628
  struct s_x4node *next;   /* Next entry with the same hash */
 
4629
  struct s_x4node **from;  /* Previous link */
 
4630
} x4node;
 
4631
 
 
4632
/* There is only one instance of the array, which is the following */
 
4633
static struct s_x4 *x4a;
 
4634
 
 
4635
/* Allocate a new associative array */
 
4636
void Configtable_init(){
 
4637
  if( x4a ) return;
 
4638
  x4a = (struct s_x4*)malloc( sizeof(struct s_x4) );
 
4639
  if( x4a ){
 
4640
    x4a->size = 64;
 
4641
    x4a->count = 0;
 
4642
    x4a->tbl = (x4node*)malloc( 
 
4643
      (sizeof(x4node) + sizeof(x4node*))*64 );
 
4644
    if( x4a->tbl==0 ){
 
4645
      free(x4a);
 
4646
      x4a = 0;
 
4647
    }else{
 
4648
      int i;
 
4649
      x4a->ht = (x4node**)&(x4a->tbl[64]);
 
4650
      for(i=0; i<64; i++) x4a->ht[i] = 0;
 
4651
    }
 
4652
  }
 
4653
}
 
4654
/* Insert a new record into the array.  Return TRUE if successful.
 
4655
** Prior data with the same key is NOT overwritten */
 
4656
int Configtable_insert(data)
 
4657
struct config *data;
 
4658
{
 
4659
  x4node *np;
 
4660
  int h;
 
4661
  int ph;
 
4662
 
 
4663
  if( x4a==0 ) return 0;
 
4664
  ph = confighash(data);
 
4665
  h = ph & (x4a->size-1);
 
4666
  np = x4a->ht[h];
 
4667
  while( np ){
 
4668
    if( Configcmp(np->data,data)==0 ){
 
4669
      /* An existing entry with the same key is found. */
 
4670
      /* Fail because overwrite is not allows. */
 
4671
      return 0;
 
4672
    }
 
4673
    np = np->next;
 
4674
  }
 
4675
  if( x4a->count>=x4a->size ){
 
4676
    /* Need to make the hash table bigger */
 
4677
    int i,size;
 
4678
    struct s_x4 array;
 
4679
    array.size = size = x4a->size*2;
 
4680
    array.count = x4a->count;
 
4681
    array.tbl = (x4node*)malloc(
 
4682
      (sizeof(x4node) + sizeof(x4node*))*size );
 
4683
    if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */
 
4684
    array.ht = (x4node**)&(array.tbl[size]);
 
4685
    for(i=0; i<size; i++) array.ht[i] = 0;
 
4686
    for(i=0; i<x4a->count; i++){
 
4687
      x4node *oldnp, *newnp;
 
4688
      oldnp = &(x4a->tbl[i]);
 
4689
      h = confighash(oldnp->data) & (size-1);
 
4690
      newnp = &(array.tbl[i]);
 
4691
      if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
 
4692
      newnp->next = array.ht[h];
 
4693
      newnp->data = oldnp->data;
 
4694
      newnp->from = &(array.ht[h]);
 
4695
      array.ht[h] = newnp;
 
4696
    }
 
4697
    free(x4a->tbl);
 
4698
    *x4a = array;
 
4699
  }
 
4700
  /* Insert the new data */
 
4701
  h = ph & (x4a->size-1);
 
4702
  np = &(x4a->tbl[x4a->count++]);
 
4703
  np->data = data;
 
4704
  if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next);
 
4705
  np->next = x4a->ht[h];
 
4706
  x4a->ht[h] = np;
 
4707
  np->from = &(x4a->ht[h]);
 
4708
  return 1;
 
4709
}
 
4710
 
 
4711
/* Return a pointer to data assigned to the given key.  Return NULL
 
4712
** if no such key. */
 
4713
struct config *Configtable_find(key)
 
4714
struct config *key;
 
4715
{
 
4716
  int h;
 
4717
  x4node *np;
 
4718
 
 
4719
  if( x4a==0 ) return 0;
 
4720
  h = confighash(key) & (x4a->size-1);
 
4721
  np = x4a->ht[h];
 
4722
  while( np ){
 
4723
    if( Configcmp(np->data,key)==0 ) break;
 
4724
    np = np->next;
 
4725
  }
 
4726
  return np ? np->data : 0;
 
4727
}
 
4728
 
 
4729
/* Remove all data from the table.  Pass each data to the function "f"
 
4730
** as it is removed.  ("f" may be null to avoid this step.) */
 
4731
void Configtable_clear(f)
 
4732
int(*f)(/* struct config * */);
 
4733
{
 
4734
  int i;
 
4735
  if( x4a==0 || x4a->count==0 ) return;
 
4736
  if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data);
 
4737
  for(i=0; i<x4a->size; i++) x4a->ht[i] = 0;
 
4738
  x4a->count = 0;
 
4739
  return;
 
4740
}