#pragma ident "%Z%%M% %I% %E% SMI"
/*
** This file contains all sources (including headers) to the LEMON
** LALR(1) parser generator. The sources have been combined into a
** single file to make it easy to include LEMON in the source tree
** and Makefile of another program.
**
** The author of this program disclaims copyright.
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#ifndef __WIN32__
# define __WIN32__
# endif
#endif
/* #define PRIVATE static */
#define PRIVATE
#ifdef TEST
#else
#endif
char *msort();
extern void *malloc();
/******** From the file "action.h" *************************************/
struct action *Action_new();
struct action *Action_sort();
/********* From the file "assert.h" ************************************/
void myassert();
#ifndef NDEBUG
#else
# define assert(X)
#endif
/********** From the file "build.h" ************************************/
void FindRulePrecedences();
void FindFirstSets();
void FindStates();
void FindLinks();
void FindFollowSets();
void FindActions();
/********* From the file "configlist.h" *********************************/
void Configlist_init(/* void */);
void Configlist_closure(/* void */);
void Configlist_sort(/* void */);
void Configlist_sortbasis(/* void */);
void Configlist_eat(/* struct config * */);
void Configlist_reset(/* void */);
/********* From the file "error.h" ***************************************/
void ErrorMsg(const char *, int,const char *, ...);
/****** From the file "option.h" ******************************************/
struct s_options {
char *label;
char *arg;
char *message;
};
int OptInit(/* char**,struct s_options*,FILE* */);
int OptNArgs(/* void */);
char *OptArg(/* int */);
void OptErr(/* int */);
void OptPrint(/* void */);
/******** From the file "parse.h" *****************************************/
void Parse(/* struct lemon *lemp */);
/********* From the file "plink.h" ***************************************/
void Plink_add(/* struct plink **, struct config * */);
void Plink_copy(/* struct plink **, struct plink * */);
void Plink_delete(/* struct plink * */);
/********** From the file "report.h" *************************************/
void Reprint(/* struct lemon * */);
void ReportOutput(/* struct lemon * */);
void ReportTable(/* struct lemon * */);
void ReportHeader(/* struct lemon * */);
void CompressTables(/* struct lemon * */);
/********** From the file "set.h" ****************************************/
/********** From the file "struct.h" *************************************/
/*
** Principal data structures for the LEMON parser generator.
*/
/* Symbols (terminals and nonterminals) of the grammar are stored
** in the following: */
struct symbol {
enum {
enum e_assoc {
LEFT,
NONE,
** popped from the stack during error processing */
** object. Only used if type==NONTERMINAL */
** stack is a union. The .yy%d element of this
** union is the correct data type for this object */
};
/* Each production rule in the grammar is stored in the following
** structure. */
struct rule {
};
/* A configuration is a production rule of the grammar together with
** a mark (dot) showing how much of that rule has been processed so far.
** Configurations also contain a follow-set which is a list of terminal
** symbols which are allowed to immediately follow the end of the rule.
** Every configuration is recorded as an instance of the following: */
struct config {
enum {
} status;
};
/* Every shift or reduce operation is stored as one of the following */
struct action {
enum e_action {
} type;
union {
} x;
};
/* Each state of the generated parser's finite state machine
** is encoded as an instance of the following structure. */
struct state {
};
/* A followset propagation link indicates that the contents of one
** configuration followset should be propagated to another whenever
** the first changes. */
struct plink {
};
/* The state vector for the entire parser generator is recorded as
** follows. (LEMON uses no global variables and makes little use of
** static variables. Fields in the following structure can be thought
** of as begin global variables in the program.) */
struct lemon {
char *include; /* Code to put at the start of the C file */
};
#define MemoryCheck(X) if((X)==0){ \
extern void memory_error(); \
memory_error(); \
}
/**************** From the file "table.h" *********************************/
/*
** All code in this file has been automatically generated
** from a specification in the file
** "table.q"
** by the associative array code building program "aagen".
** Do not edit this file! Instead, edit the specification
** file, then rerun aagen.
*/
/*
** Code for processing tables in the LEMON parser generator.
*/
/* Routines for handling a strings */
char *Strsafe();
void Strsafe_init(/* void */);
int Strsafe_insert(/* char * */);
char *Strsafe_find(/* char * */);
/* Routines for handling symbols of the grammar */
struct symbol *Symbol_new();
int Symbolcmpp(/* struct symbol **, struct symbol ** */);
void Symbol_init(/* void */);
int Symbol_insert(/* struct symbol *, char * */);
int Symbol_count(/* */);
/* Routines to manage the state table */
int Configcmp(/* struct config *, struct config * */);
void State_init(/* void */);
int State_insert(/* struct state *, struct config * */);
/* Routines used for efficiency in Configlist_add */
void Configtable_init(/* void */);
int Configtable_insert(/* struct config * */);
void Configtable_clear(/* int(*)(struct config *) */);
/****************** From the file "action.c" *******************************/
/*
** Routines processing parser actions in the LEMON parser generator.
*/
/* Allocate a new parser action */
if( freelist==0 ){
int i;
if( freelist==0 ){
exit(1);
}
}
return new;
}
/* Compare two actions */
{
int rc;
if( rc==0 ){
}
return rc;
}
/* Sort parser actions */
{
return ap;
}
char *arg;
{
new = Action_new();
}else{
}
}
/********************** New code to implement the "acttab" module ***********/
/*
** This module implements routines use to construct the yy_action[] table.
*/
/*
** The state of the yy_action table under construction is an instance of
** the following structure
*/
struct acttab {
struct {
};
/* Return the number of entries in the yy_action table */
/* The value for the N-th entry in yy_action */
/* The value for the N-th entry in yy_lookahead */
/* Free all memory associated with the given acttab */
free( p->aLookahead );
free( p );
}
/* Allocate a new acttab structure */
if( p==0 ){
exit(1);
}
memset(p, 0, sizeof(*p));
return p;
}
/* Add a new action to the current transaction set
*/
if( p->nLookahead>=p->nLookaheadAlloc ){
p->nLookaheadAlloc += 25;
sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
if( p->aLookahead==0 ){
exit(1);
}
}
if( p->nLookahead==0 ){
p->mxLookahead = lookahead;
p->mnLookahead = lookahead;
}else{
if( p->mnLookahead>lookahead ){
p->mnLookahead = lookahead;
}
}
p->nLookahead++;
}
/*
** Add the transaction set built up with prior calls to acttab_action()
** into the current action table. Then reset the transaction set back
** to an empty set in preparation for a new round of acttab_action() calls.
**
** Return the offset into the action table of the new transaction.
*/
int i, j, k, n;
assert( p->nLookahead>0 );
/* Make sure we have enough space to hold the expanded action table
** in the worst case. The worst case occurs if the transaction set
** must be appended to the current action table
*/
n = p->mxLookahead + 1;
if( p->nAction + n >= p->nActionAlloc ){
sizeof(p->aAction[0])*p->nActionAlloc);
if( p->aAction==0 ){
exit(1);
}
for(i=oldAlloc; i<p->nActionAlloc; i++){
}
}
/* Scan the existing action table looking for an offset where we can
** insert the current transaction set. Fall out of the loop when that
** offset is found. In the worst case, we fall out of the loop when
** i reaches p->nAction, which means we append the new transaction set.
**
** i is the index in p->aAction[] where p->mnLookahead is inserted.
*/
for(i=0; i<p->nAction+p->mnLookahead; i++){
for(j=0; j<p->nLookahead; j++){
if( k<0 ) break;
}
if( j<p->nLookahead ) continue;
for(j=0; j<p->nAction; j++){
}
if( j==p->nAction ){
break; /* Fits in empty slots */
}
for(j=0; j<p->nLookahead; j++){
if( k<0 || k>=p->nAction ) break;
}
if( j<p->nLookahead ) continue;
n = 0;
for(j=0; j<p->nAction; j++){
}
if( n==p->nLookahead ){
break; /* Same as a prior transaction set */
}
}
}
/* Insert transaction set at index i. */
for(j=0; j<p->nLookahead; j++){
p->aAction[k] = p->aLookahead[j];
}
p->nLookahead = 0;
/* Return the offset that is added to the lookahead in order to get the
** index into yy_action of the action */
return i - p->mnLookahead;
}
/********************** From the file "assert.c" ****************************/
/*
** A more efficient way of handling assertions.
*/
char *file;
int line;
{
exit(1);
}
/********************** From the file "build.c" *****************************/
/*
** Routines to construction the finite state machine for the LEMON
** parser generator.
*/
/* Find a precedence symbol of every rule in the grammar.
**
** Those rules which have a precedence symbol coded in the input
** grammar using the "[symbol]" construct will already have the
** rp->precsym field filled. Other rules take as their precedence
** symbol the first RHS symbol with a defined precedence. If there
** are not RHS symbols with a defined precedence, the precedence
** symbol field is left blank.
*/
{
int i;
break;
}
}
}
}
return;
}
/* Find all nonterminals which will generate the empty string.
** Then go back and compute the first sets of every nonterminal.
** The first set is the set of all terminal symbols which can begin
** a string generated by that nonterminal.
*/
{
int i;
int progress;
}
}
/* First compute all lambdas */
do{
progress = 0;
}
progress = 1;
}
}
}while( progress );
/* Now compute all first sets */
do{
progress = 0;
break;
}else{
}
}
}
}while( progress );
return;
}
/* Compute all LR(0) states for the grammar. Links
** are added to between some states so that the LR(1) follow sets
** can be computed later.
*/
{
/* Find the start symbol */
if( sp==0 ){
"The specified start symbol \"%s\" is not \
in a nonterminal of the grammar. \"%s\" will be used as the start \
}
}else{
}
/* Make sure the start symbol doesn't occur on the right-hand side of
** any rule. Report an error if it does. (YACC would generate a new
** start symbol in this case.) */
int i;
"The start symbol \"%s\" occurs on the \
right-hand side of a rule. This will result in a parser which \
}
}
}
/* The basis configuration set for the first state
** is all rules which have the start symbol as their
** left-hand side */
}
/* Compute the first state. All other states will be
** computed automatically during the computation of the first one.
** The returned pointer to the first state is not used. */
return;
}
/* Return a pointer to a state which is described by the configuration
** list which has been built from calls to Configlist_add.
*/
{
/* Extract the sorted basis of the new state. The basis was constructed
** by prior calls to "Configlist_addbasis()". */
bp = Configlist_basis();
/* Get a state with the same basis */
if( stp ){
/* A state with the same basis already exists! Copy all the follow-set
** propagation links from the state under construction into the
** preexisting state, then return a pointer to the preexisting state */
struct config *x, *y;
Plink_delete(x->fplp);
}
cfp = Configlist_return();
}else{
/* This really is a new state. Construct all the details */
Configlist_sort(); /* Sort the configuration closure */
}
return stp;
}
/* Construct all successor states to the given state. A "successor"
** state is any state which can be reached by a shift action.
*/
{
/* Each configuration becomes complete after it contibutes to a successor
** state. Initially, all configurations are incomplete */
/* Loop through all configurations of the state "stp" */
Configlist_reset(); /* Reset the new config set */
/* For every configuration in the state "stp" which has the symbol "sp"
** following its dot, add the same configuration to the basis set under
** construction but with the dot shifted one symbol to the right. */
}
/* Get a pointer to the state described by the basis configuration set
** constructed in the preceding loop */
/* The state "newstp" is reached from the state "stp" by a shift action
** on the symbol "sp" */
}
}
/*
** Construct the propagation links
*/
{
int i;
/* Housekeeping detail:
** Add to every propagate link a pointer back to the state to
** which the link is attached. */
}
}
/* Convert all backlinks into forward links. Only the forward
** links are used in the follow-set computation. */
}
}
}
}
/* Compute all followsets.
**
** A followset is the set of all symbols which can come immediately
** after a configuration.
*/
{
int i;
int progress;
int change;
}
}
do{
progress = 0;
if( change ){
progress = 1;
}
}
}
}
}while( progress );
}
static int resolve_conflict();
/* Compute the reduce actions, and resolve conflicts.
*/
{
int i,j;
/* Add all of the reduce actions
** A reduce action is added for each element of the followset of
** a configuration which has its dot at the extreme right.
*/
/* Add a reduce action to the state "stp" which will reduce by the
** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
}
}
}
}
}
/* Add the accepting token */
}else{
}
/* Add to the first state (which is always the starting state of the
** finite state machine) an action to ACCEPT if the lookahead is the
** start nonterminal. */
/* Resolve conflicts */
/* The two actions "ap" and "nap" have the same lookahead.
** Figure out which one should be used */
}
}
}
/* Report an error for each rule that can never be reduced. */
}
}
}
}
/* Resolve a conflict between the two given actions. If the
** conflict can't be resolve, return non-zero.
**
** NO LONGER TRUE:
** To resolve a conflict, first look to see if either action
** is on an error rule. In that case, take the action which
** is not associated with the error rule. If neither or both
** actions are associated with an error rule, then try to
** use precedence to resolve the conflict.
**
** If either action is a SHIFT, then it must be apx. This
** function won't work if apx->type==REDUCE and apy->type==SHIFT.
*/
{
int errcnt = 0;
/* Not enough precedence information. */
errcnt++;
}else{
errcnt++;
}
errcnt++;
}
}else{
);
** REDUCEs on the list. If we reach this point it must be because
** the parser conflict had already been resolved. */
}
return errcnt;
}
/********************* From the file "configlist.c" *************************/
/*
** Routines to processing a configuration list and building a state
** in the LEMON parser generator.
*/
/* Return a pointer to a new configuration */
if( freelist==0 ){
int i;
if( freelist==0 ){
exit(1);
}
}
return new;
}
/* The configuration "old" is no longer used */
{
}
/* Initialized the configuration list builder */
void Configlist_init(){
current = 0;
currentend = ¤t;
basis = 0;
return;
}
/* Initialized the configuration list builder */
void Configlist_reset(){
current = 0;
currentend = ¤t;
basis = 0;
return;
}
/* Add another configuration to the configuration list */
int dot; /* Index into the RHS of the rule where the dot goes */
{
assert( currentend!=0 );
if( cfp==0 ){
*currentend = cfp;
}
return cfp;
}
/* Add a basis configuration to the configuration list */
int dot;
{
assert( currentend!=0 );
if( cfp==0 ){
*currentend = cfp;
}
return cfp;
}
/* Compute the closure of the configuration list */
{
int i, dot;
assert( currentend!=0 );
}
break;
}else{
}
}
}
}
}
return;
}
/* Sort the configuration list */
void Configlist_sort(){
currentend = 0;
return;
}
/* Sort the basis configuration list */
void Configlist_sortbasis(){
basisend = 0;
return;
}
/* Return a pointer to the head of the configuration list and
** reset the list */
current = 0;
currentend = 0;
return old;
}
/* Return a pointer to the head of the configuration list and
** reset the list */
basis = 0;
basisend = 0;
return old;
}
/* Free all elements of the given configuration list */
{
}
return;
}
/***************** From the file "error.c" *********************************/
/*
** Code for printing error message.
*/
/* Find a good place to break "msg" so that its length is at least "min"
** but no more than "max". Make the point as close to max as possible.
*/
char *msg;
int min;
int max;
{
int i,spot;
char c;
c = msg[i];
if( c==0 ){ spot = i; break; }
if( c==' ' ) spot = i;
}
return spot;
}
/*
** The error message is split across multiple lines if necessary. The
** splits occur at a space, if there is a space available near the end
** of the line.
*/
int errmsgsize;
int prefixsize;
int availablewidth;
/* Prepare a prefix to be prepended to every output line */
if( lineno>0 ){
}else{
}
/* Generate the error message */
/* Remove trailing '\n's from the error message. */
errmsg[--errmsgsize] = 0;
}
/* Print the error message */
base = 0;
}
}
/**************** From the file "main.c" ************************************/
/*
** Main program file for the LEMON parser generator.
*/
/* Report an out-of-memory condition and abort. This function
** is used mostly by the "MemoryCheck" macro in struct.h
*/
void memory_error(){
exit(1);
}
/* The main program. Parse the command line and do it... */
int argc;
char **argv;
{
static int version = 0;
static int rpflag = 0;
static int basisflag = 0;
static int compress = 0;
static int quiet = 0;
static int statistics = 0;
static int mhflag = 0;
{OPT_FLAG,0,0,0}
};
int i;
if( version ){
printf("Lemon version 1.0\n");
exit(0);
}
if( OptNArgs()!=1 ){
exit(1);
}
/* Initialize the machine */
Strsafe_init();
Symbol_init();
State_init();
lem.has_fallback = 0;
Symbol_new("$");
/* Parse the input file */
exit(1);
}
/* Count and index the symbols of the grammar */
Symbol_new("{default}");
(int(*)())Symbolcmpp);
/* Generate a reprint of the grammar, if requested on the command line */
if( rpflag ){
}else{
/* Initialize the size for all follow and first sets */
/* Find the precedence for every production rule (that has one) */
/* Compute the lambda-nonterminals and the first-sets for every
** nonterminal */
FindFirstSets(&lem);
/* Compute all LR(0) states. Also record follow-set propagation
** links so that the follow-set can be computed later */
FindStates(&lem);
/* Tie up loose ends on the propagation links */
/* Compute the follow set of every reducible configuration */
/* Compute the action tables */
FindActions(&lem);
/* Compress the action tables */
/* Generate a report of the parser generated. (the "y.output" file) */
/* Generate the source code for the parser */
/* Produce a header file for use by the scanner. (This step is
** omitted if the "-m" option is used because makeheaders will
** generate the file for us.) */
}
if( statistics ){
printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n",
printf(" %d states, %d parser table entries, %d conflicts\n",
}
}
}
/******************** From the file "msort.c" *******************************/
/*
** A generic merge-sort program.
**
** USAGE:
** Let "ptr" be a pointer to some structure which is at the head of
** a null-terminated list. Then to sort the list call:
**
** ptr = msort(ptr,&(ptr->next),cmpfnc);
**
** In the above, "cmpfnc" is a pointer to a function which compares
** two instances of the structure and returns an integer, as in
** strcmp. The second argument is a pointer to the pointer to the
** second element of the linked list. This address is used to compute
** the offset to the "next" field within the structure. The offset to
** the "next" field must be constant for all structures in the list.
**
** The function returns a new pointer which is the head of the list
** after sorting.
**
** ALGORITHM:
** Merge-sort.
*/
/*
** Return a pointer to the next structure in the linked list.
*/
/*
** Inputs:
** a: A sorted, null-terminated linked list. (May be null).
** b: A sorted, null-terminated linked list. (May be null).
** cmp: A pointer to the comparison function.
** offset: Offset in the structure to the "next" field.
**
** Return Value:
** A pointer to the head of a sorted list containing the elements
** of both a and b.
**
** Side effects:
** The "next" pointers for elements in the lists a and b are
** changed.
*/
char *a;
char *b;
int (*cmp)();
int offset;
{
if( a==0 ){
head = b;
}else if( b==0 ){
head = a;
}else{
if( (*cmp)(a,b)<0 ){
ptr = a;
a = NEXT(a);
}else{
ptr = b;
b = NEXT(b);
}
while( a && b ){
if( (*cmp)(a,b)<0 ){
ptr = a;
a = NEXT(a);
}else{
ptr = b;
b = NEXT(b);
}
}
}
return head;
}
/*
** Inputs:
** list: Pointer to a singly-linked list of structures.
** next: Pointer to pointer to the second element of the list.
** cmp: A comparison function.
**
** Return Value:
** A pointer to the head of a sorted list containing the elements
** orginally in list.
**
** Side effects:
** The "next" pointers for elements in list are changed.
*/
char *list;
char **next;
int (*cmp)();
{
unsigned long offset;
char *ep;
int i;
while( list ){
set[i] = 0;
}
}
ep = 0;
return ep;
}
/************************ From the file "option.c" **************************/
static char **argv;
/*
** Print the command line with a carrot pointing to the k-th character
** of the n-th field.
*/
int n;
int k;
{
int spcnt, i;
spcnt = 0;
for(i=1; i<n && argv[i]; i++){
}
spcnt += k;
if( spcnt<20 ){
}else{
}
}
/*
** Return the index of the N-th non-switch argument. Return -1
** if N is out of range.
*/
static int argindex(n)
int n;
{
int i;
int dashdash = 0;
for(i=1; argv[i]; i++){
if( n==0 ) return i;
n--;
}
}
}
return -1;
}
/*
** Process a flag command line argument.
*/
int i;
{
int v;
int errcnt = 0;
int j;
}
if( err ){
}
errcnt++;
}else{
if( err ){
}
errcnt++;
}
return errcnt;
}
/*
** Process a command line switch which has an argument.
*/
int i;
{
int lv = 0;
char *cp;
int j;
int errcnt = 0;
*cp = 0;
}
*cp = '=';
if( err ){
}
errcnt++;
}else{
cp++;
case OPT_FLAG:
case OPT_FFLAG:
if( err ){
}
errcnt++;
break;
case OPT_DBL:
case OPT_FDBL:
if( *end ){
if( err ){
}
errcnt++;
}
break;
case OPT_INT:
case OPT_FINT:
if( *end ){
if( err ){
}
errcnt++;
}
break;
case OPT_STR:
case OPT_FSTR:
break;
}
case OPT_FLAG:
case OPT_FFLAG:
break;
case OPT_DBL:
break;
case OPT_FDBL:
break;
case OPT_INT:
break;
case OPT_FINT:
break;
case OPT_STR:
break;
case OPT_FSTR:
break;
}
}
return errcnt;
}
char **a;
struct s_options *o;
{
int errcnt = 0;
argv = a;
op = o;
int i;
for(i=1; argv[i]; i++){
}
}
}
if( errcnt>0 ){
OptPrint();
exit(1);
}
return 0;
}
int OptNArgs(){
int cnt = 0;
int dashdash = 0;
int i;
for(i=1; argv[i]; i++){
}
}
return cnt;
}
char *OptArg(n)
int n;
{
int i;
i = argindex(n);
return i>=0 ? argv[i] : 0;
}
void OptErr(n)
int n;
{
int i;
i = argindex(n);
}
void OptPrint(){
int i;
max = 0;
case OPT_FLAG:
case OPT_FFLAG:
break;
case OPT_INT:
case OPT_FINT:
break;
case OPT_DBL:
case OPT_FDBL:
break;
case OPT_STR:
case OPT_FSTR:
break;
}
}
case OPT_FLAG:
case OPT_FFLAG:
break;
case OPT_INT:
case OPT_FINT:
break;
case OPT_DBL:
case OPT_FDBL:
break;
case OPT_STR:
case OPT_FSTR:
break;
}
}
}
/*********************** From the file "parse.c" ****************************/
/*
** Input file parser for the LEMON parser generator.
*/
/* The state of the parser */
struct pstate {
enum e_state {
};
/* Parse a single token */
{
char *x;
#if 0
#endif
case INITIALIZE:
psp->preccounter = 0;
/* Fall thru to next case */
case WAITING_FOR_DECL_OR_RULE:
if( x[0]=='%' ){
}else if( islower(x[0]) ){
}else if( x[0]=='{' ){
"There is not prior rule opon which to attach the code \
fragment which begins on this line.");
"Code fragment beginning on this line is not the first \
to follow the previous rule.");
}else{
}
}else if( x[0]=='[' ){
}else{
"Token \"%s\" should be either \"%%\" or a nonterminal name.",
x);
}
break;
case PRECEDENCE_MARK_1:
if( !isupper(x[0]) ){
"The precedence symbol must be a terminal.");
"There is no prior rule to assign precedence \"[%s]\".",x);
"Precedence mark on this line is not the first \
to follow the previous rule.");
}else{
}
break;
case PRECEDENCE_MARK_2:
if( x[0]!=']' ){
"Missing \"]\" on precedence mark.");
}
break;
case WAITING_FOR_ARROW:
if( x[0]==':' && x[1]==':' && x[2]=='=' ){
}else if( x[0]=='(' ){
}else{
"Expected to see a \":\" following the LHS symbol \"%s\".",
}
break;
case LHS_ALIAS_1:
if( isalpha(x[0]) ){
}else{
"\"%s\" is not a valid alias for the LHS \"%s\"\n",
}
break;
case LHS_ALIAS_2:
if( x[0]==')' ){
}else{
}
break;
case LHS_ALIAS_3:
if( x[0]==':' && x[1]==':' && x[2]=='=' ){
}else{
"Missing \"->\" following: \"%s(%s)\".",
}
break;
case IN_RHS:
if( x[0]=='.' ){
if( rp==0 ){
"Can't allocate enough memory for this rule.");
}else{
int i;
}
}else{
}
}
}else if( isalpha(x[0]) ){
"Too many symbol on RHS or rule beginning at \"%s\".",
x);
}else{
}
}else{
"Illegal character on RHS of rule: \"%s\".",x);
}
break;
case RHS_ALIAS_1:
if( isalpha(x[0]) ){
}else{
"\"%s\" is not a valid alias for the RHS symbol \"%s\"\n",
}
break;
case RHS_ALIAS_2:
if( x[0]==')' ){
}else{
}
break;
case WAITING_FOR_DECL_KEYWORD:
if( isalpha(x[0]) ){
psp->declkeyword = x;
psp->declargslot = 0;
psp->decllnslot = 0;
if( strcmp(x,"name")==0 ){
}else if( strcmp(x,"include")==0 ){
}else if( strcmp(x,"code")==0 ){
}else if( strcmp(x,"token_destructor")==0 ){
}else if( strcmp(x,"default_destructor")==0 ){
}else if( strcmp(x,"token_prefix")==0 ){
}else if( strcmp(x,"syntax_error")==0 ){
}else if( strcmp(x,"parse_accept")==0 ){
}else if( strcmp(x,"parse_failure")==0 ){
}else if( strcmp(x,"stack_overflow")==0 ){
}else if( strcmp(x,"extra_argument")==0 ){
}else if( strcmp(x,"token_type")==0 ){
}else if( strcmp(x,"default_type")==0 ){
}else if( strcmp(x,"stack_size")==0 ){
}else if( strcmp(x,"start_symbol")==0 ){
}else if( strcmp(x,"left")==0 ){
psp->preccounter++;
}else if( strcmp(x,"right")==0 ){
psp->preccounter++;
}else if( strcmp(x,"nonassoc")==0 ){
psp->preccounter++;
}else if( strcmp(x,"destructor")==0 ){
}else if( strcmp(x,"type")==0 ){
}else if( strcmp(x,"fallback")==0 ){
}else{
"Unknown declaration keyword: \"%%%s\".",x);
}
}else{
"Illegal declaration keyword: \"%s\".",x);
}
break;
if( !isalpha(x[0]) ){
"Symbol name missing after %destructor keyword");
}else{
}
break;
if( !isalpha(x[0]) ){
"Symbol name missing after %destructor keyword");
}else{
psp->decllnslot = 0;
}
break;
if( x[0]=='.' ){
}else if( isupper(x[0]) ){
sp = Symbol_new(x);
"Symbol \"%s\" has already be given a precedence.",x);
}else{
}
}else{
"Can't assign a precedence to \"%s\".",x);
}
break;
case WAITING_FOR_DECL_ARG:
if( *(psp->declargslot)!=0 ){
"The argument \"%s\" to declaration \"%%%s\" is not the first.",
}else{
}
}else{
}
break;
case WAITING_FOR_FALLBACK_ID:
if( x[0]=='.' ){
}else if( !isupper(x[0]) ){
"%%fallback argument \"%s\" should be a token", x);
}else{
"More than one fallback assigned to token %s", x);
}else{
}
}
break;
case RESYNC_AFTER_RULE_ERROR:
/* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE;
** break; */
case RESYNC_AFTER_DECL_ERROR:
break;
}
}
/* In spite of its name, this function is really a scanner. It read
** in the entire input file (all at once) then tokenizes it. Each
** token is passed to the function "parseonetoken" which builds all
** the appropriate data structures in the global state vector "gp".
*/
{
char *filebuf;
int filesize;
int lineno;
int c;
int startline = 0;
/* Begin by reading the input file */
if( fp==0 ){
return;
}
if( filebuf==0 ){
filesize+1);
return;
}
filesize);
return;
}
/* Now scan the text of the input file */
lineno = 1;
cp+=2;
continue;
}
cp+=2;
if( c=='\n' ) lineno++;
cp++;
}
if( c ) cp++;
continue;
}
if( c=='\"' ){ /* String literals */
cp++;
while( (c= *cp)!=0 && c!='\"' ){
if( c=='\n' ) lineno++;
cp++;
}
if( c==0 ){
"String starting on this line is not terminated before the end of the file.");
}else{
}
}else if( c=='{' ){ /* A block of C code */
int level;
cp++;
if( c=='\n' ) lineno++;
else if( c=='{' ) level++;
else if( c=='}' ) level--;
int prevc;
prevc = 0;
if( c=='\n' ) lineno++;
prevc = c;
cp++;
}
if( c ) lineno++;
}else if( c=='\'' || c=='\"' ){ /* String a character literals */
startchar = c;
prevc = 0;
if( c=='\n' ) lineno++;
else prevc = c;
}
}
}
if( c==0 ){
"C code starting on this line is not terminated before the end of the file.");
}else{
}
}else if( isalnum(c) ){ /* Identifiers */
cp += 3;
}else{ /* All other (one character) operators */
cp++;
}
c = *cp;
*cp = 0; /* Null terminate the token */
*cp = c; /* Restore the buffer */
}
}
/*************************** From the file "plink.c" *********************/
/*
** Routines processing configuration follow-set propagation links
** in the LEMON parser generator.
*/
/* Allocate a new plink */
if( plink_freelist==0 ){
int i;
if( plink_freelist==0 ){
"Unable to allocate memory for a new follow-set propagation link.\n");
exit(1);
}
}
return new;
}
/* Add a plink to a plink list */
{
}
/* Transfer every plink on the list "from" to the list "to" */
{
while( from ){
}
}
/* Delete every plink on the list */
{
while( plp ){
}
}
/*********************** From the file "report.c" **************************/
/*
** Procedures for generating reports and tables in the LEMON parser generator.
*/
/* Generate a filename with the given suffix. Space to hold the
** name comes from malloc() and must be freed by the calling
** function.
*/
char *suffix;
{
char *name;
char *cp;
if( name==0 ){
exit(1);
}
return name;
}
/* Open a file with a name based on the name of the input file,
** but with a different (specified) suffix, and return a pointer
** to the stream */
char *suffix;
char *mode;
{
return 0;
}
return fp;
}
/* Duplicate the input file without comments and without actions
** on rules */
{
maxlen = 10;
}
for(i=0; i<skip; i++){
printf("//");
}
printf("\n");
}
/* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */
printf(" ::=");
/* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */
}
printf(".");
/* if( rp->code ) printf("\n %s",rp->code); */
printf("\n");
}
}
{
int i;
}
}
/* #define TEST */
#ifdef TEST
/* Print a set */
char *set;
{
int i;
char *spacer;
spacer = "";
spacer = " ";
}
}
}
/* Print a plink chain */
char *tag;
{
while( plp ){
}
}
#endif
/* Print an action to the given file descriptor. Return FALSE if
** nothing was actually printed.
*/
case SHIFT:
break;
case REDUCE:
break;
case ACCEPT:
break;
case ERROR:
break;
case CONFLICT:
break;
case SH_RESOLVED:
case RD_RESOLVED:
case NOT_USED:
result = 0;
break;
}
return result;
}
/* Generate the "y.output" log file */
{
int i;
if( fp==0 ) return;
while( cfp ){
}else{
}
#ifdef TEST
#endif
}
}
}
return;
}
/* Search for the file "name" which is in the same directory as
** the exacutable */
char *argv0;
char *name;
int modemask;
{
char *pathlist;
char c;
extern int access();
#ifdef __WIN32__
#else
#endif
if( cp ){
c = *cp;
*cp = 0;
*cp = c;
}else{
extern char *getenv();
if( path!=0 ){
while( *pathlist ){
c = *cp;
*cp = 0;
*cp = c;
if( c==0 ) pathlist = "";
}
}
}
return path;
}
/* Given an action, compute the integer value for that action
** which is to be put in the action table of the generated machine.
** Return negative if no action should be generated.
*/
{
int act;
default: act = -1; break;
}
return act;
}
/* The next cluster of routines are for reading the template file
** and writing the results to the generated parser */
/* The first function transfers data from "in" to "out" until
** a line is seen which begins with "%%". The line number is
** tracked.
**
** if name!=0, then any word that begin with "Parse" is changed to
** begin with *name instead.
*/
char *name;
int *lineno;
{
int i, iStart;
(*lineno)++;
iStart = 0;
if( name ){
for(i=0; line[i]; i++){
){
i += 4;
iStart = i+1;
}
}
}
}
}
/* The next function finds the template file and opens it, returning
** a pointer to the opened file. */
{
char *tpltname;
char *cp;
if( cp ){
}else{
}
}else{
}
if( tpltname==0 ){
return 0;
}
if( in==0 ){
return 0;
}
return in;
}
/* Print a string to the file and keep the linenumber up to date */
char *str;
int strln;
int *lineno;
{
if( str==0 ) return;
while( *str ){
str++;
}
return;
}
/*
** The following routine emits code for the destructor for the
** symbol sp
*/
int *lineno;
{
char *cp = 0;
int linecnt = 0;
if( cp==0 ) return;
}else if( sp->destructor ){
if( cp==0 ) return;
}else{
assert( 0 ); /* Cannot happen */
}
cp++;
continue;
}
}
return;
}
/*
** Return TRUE (non-zero) if the given symbol has a destructor.
*/
{
int ret;
}else{
}
return ret;
}
/*
** Generate code which executes when the rule "rp" is reduced. Write
** the code to "out". Make sure lineno stays up-to-date.
*/
int *lineno;
{
int linecnt = 0;
int i;
lhsused = 0;
/* Generate code to do the reduce action */
char saved;
*xp = 0;
lhsused = 1;
}else{
used[i] = 1;
break;
}
}
}
}
} /* End loop */
} /* End if( rp->code ) */
/* Check to make sure the LHS has been used */
"Label \"%s\" for \"%s(%s)\" is never used.",
}
/* Generate destructor code for RHS symbols which are not used in the
** reduce code */
"Label %s for \"%s(%s)\" is never used.",
}else{
(*lineno)++;
}
}
}
return;
}
/*
** Print the definition of the union used for the parser's data stack.
** This union contains fields for every possible data type for tokens
** and nonterminals. In the process of computing and printing this
** union, also set the ".dtnum" field of every terminal and nonterminal
** symbol.
*/
int *plineno; /* Pointer to the line number */
int mhflag; /* True if generating makeheaders output */
{
int i,j; /* Loop counters */
/* Allocate and initialize types[] and allocate stddt[] */
maxdtlength = 0;
}
int len;
}
exit(1);
}
/* Build a hash table of datatypes. The ".dtnum" field of each symbol
** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
** used for terminal symbols. If there is no %default_type defined then
** 0 is also used as the .dtnum value for nonterminals which do not specify
** a datatype using the %type directive.
*/
char *cp;
continue;
}
continue;
}
j = 0;
stddt[j] = 0;
hash = 0;
for(j=0; stddt[j]; j++){
}
break;
}
hash++;
}
exit(1);
}
}
}
/* Print out the definition of YYTOKENTYPE and YYMINORTYPE */
for(i=0; i<arraysize; i++){
if( types[i]==0 ) continue;
}
}
/*
** Return the name of a C datatype able to represent values between
** lwr and upr, inclusive.
*/
if( lwr>=0 ){
if( upr<=255 ){
return "unsigned char";
}else if( upr<65535 ){
return "unsigned short int";
}else{
return "unsigned int";
}
return "signed char";
return "short";
}else{
return "int";
}
}
/*
** Each state contains a set of token transaction and a set of
** nonterminal transactions. Each of these sets makes an instance
** of the following structure. An array of these structures is used
** to order the creation of entries in the yy_action[] table.
*/
struct axset {
};
/*
** Compare to axset structures for sorting purposes
*/
static int axset_compare(const void *a, const void *b){
}
/* Generate C source code for the parser */
int mhflag; /* Output in makeheaders format if true */
{
int lineno;
int i, j, n;
char *name;
if( in==0 ) return;
if( out==0 ){
return;
}
lineno = 1;
/* Generate the include code, if any */
if( mhflag ){
}
/* Generate #defines for all tokens */
if( mhflag ){
char *prefix;
else prefix = "";
lineno++;
}
}
/* Generate the defines */
"Illegal stack size: [%s]. The stack size should be an integer constant.",
}
}else{
}
if( mhflag ){
}
int i;
}else{
}
if( mhflag ){
}
if( lemp->has_fallback ){
}
/* Generate the action table and its associates:
**
** yy_action[] A single table containing all actions.
** yy_lookahead[] A table containing the lookahead for each entry in
** yy_action. Used to detect hash collisions.
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
/* Compute the actions on all states and count them up */
if( ax==0 ){
exit(1);
}
}else{
}
}
}
}
/* Compute the action table. In order to try to keep the size of the
** action table to a minimum, the heuristic of placing the largest action
** sets first is used.
*/
pActtab = acttab_alloc();
int action;
if( action<0 ) continue;
}
}else{
int action;
if( action<0 ) continue;
}
}
}
/* Output the yy_action table */
n = acttab_size(pActtab);
for(i=j=0; i<n; i++){
if( j==9 || i==n-1 ){
j = 0;
}else{
j++;
}
}
/* Output the yy_lookahead table */
for(i=j=0; i<n; i++){
if( j==9 || i==n-1 ){
j = 0;
}else{
j++;
}
}
/* Output the yy_shift_ofst[] table */
for(i=j=0; i<n; i++){
int ofst;
if( j==9 || i==n-1 ){
j = 0;
}else{
j++;
}
}
/* Output the yy_reduce_ofst[] table */
for(i=j=0; i<n; i++){
int ofst;
if( j==9 || i==n-1 ){
j = 0;
}else{
j++;
}
}
/* Output the default action table */
for(i=j=0; i<n; i++){
if( j==9 || i==n-1 ){
j = 0;
}else{
j++;
}
}
/* Generate the table of fallback tokens.
*/
if( lemp->has_fallback ){
if( p->fallback==0 ){
}else{
}
lineno++;
}
}
/* Generate a table containing the symbolic name of every symbol
*/
}
/* Generate a table containing a text string that describes every
** rule in the rule set of the grammer. This information is used
** when tracing REDUCE actions.
*/
}
/* Generate code which executes every time a symbol is popped from
** the stack while processing errors or while destroying the parser.
** (In other words, generate the %destructor actions)
*/
}
}
}
}
}
if( dflt_sp!=0 ){
}
}
/* Generate code which executes whenever the parser stack overflows */
/* Generate the table of rule information
**
** Note: This code depends on the fact that rules are number
** sequentually beginning with 0.
*/
}
/* Generate code which execution during each REDUCE action */
}
/* Generate code which executes if a parse fails */
/* Generate code which executes when a syntax error occurs */
/* Generate code which executes when the parser accepts its input */
/* Append any addition code the user desires */
return;
}
/* Generate a header file for the parser */
{
char *prefix;
int i;
else prefix = "";
if( in ){
}
/* No change in the file. Don't rewrite it. */
return;
}
}
if( out ){
}
}
return;
}
/* Reduce the size of the action tables, if possible, by making use
** of defaults.
**
** In this version, we take the most frequent REDUCE action and make
** it the default. Only default a reduce if there are more than one.
*/
{
int nbest, n;
int i;
nbest = 0;
rbest = 0;
n = 1;
}
if( n>nbest ){
nbest = n;
}
}
/* Do not make a default if the number of rules to default
** is not at least 2 */
if( nbest<2 ) continue;
/* Combine matching REDUCE actions into a single default */
}
}
}
}
/***************** From the file "set.c" ************************************/
/*
** Set manipulation routines for the LEMON parser generator.
*/
static int size = 0;
/* Set the set size */
void SetSize(n)
int n;
{
size = n+1;
}
/* Allocate a new set */
char *SetNew(){
char *s;
int i;
if( s==0 ){
extern void memory_error();
memory_error();
}
for(i=0; i<size; i++) s[i] = 0;
return s;
}
/* Deallocate a set */
void SetFree(s)
char *s;
{
free(s);
}
/* Add a new element to the set. Return TRUE if the element was added
** and FALSE if it was already there. */
int SetAdd(s,e)
char *s;
int e;
{
int rv;
rv = s[e];
s[e] = 1;
return !rv;
}
/* Add every element of s2 to s1. Return TRUE if s1 changes. */
char *s1;
char *s2;
{
int i, progress;
progress = 0;
for(i=0; i<size; i++){
if( s2[i]==0 ) continue;
if( s1[i]==0 ){
progress = 1;
s1[i] = 1;
}
}
return progress;
}
/********************** From the file "table.c" ****************************/
/*
** All code in this file has been automatically generated
** from a specification in the file
** "table.q"
** by the associative array code building program "aagen".
** Do not edit this file! Instead, edit the specification
** file, then rerun aagen.
*/
/*
** Code for processing tables in the LEMON parser generator.
*/
char *x;
{
int h = 0;
while( *x) h = h*13 + *(x++);
return h;
}
/* Works like strdup, sort of. Save a string in malloced memory, but
** keep strings in a table so that the same string is not in more
** than one place.
*/
char *Strsafe(y)
char *y;
{
char *z;
z = Strsafe_find(y);
strcpy(z,y);
Strsafe_insert(z);
}
MemoryCheck(z);
return z;
}
/* There is one instance of the following structure for each
** associative array of type "x1".
*/
struct s_x1 {
/* Must be a power of 2 greater than or */
/* equal to 1 */
};
/* There is one instance of this structure for every data element
** in an associative array of type "x1".
*/
typedef struct s_x1node {
} x1node;
/* There is only one instance of the array, which is the following */
/* Allocate a new associative array */
void Strsafe_init(){
if( x1a ) return;
if( x1a ){
x1a = 0;
}else{
int i;
}
}
}
/* Insert a new record into the array. Return TRUE if successful.
** Prior data with the same key is NOT overwritten */
char *data;
{
int h;
int ph;
if( x1a==0 ) return 0;
while( np ){
/* An existing entry with the same key is found. */
/* Fail because overwrite is not allows. */
return 0;
}
}
/* Need to make the hash table bigger */
int i,size;
}
}
/* Insert the new data */
return 1;
}
/* Return a pointer to data assigned to the given key. Return NULL
** if no such key. */
char *key;
{
int h;
if( x1a==0 ) return 0;
while( np ){
}
}
/* Return a pointer to the (terminal or nonterminal) symbol "x".
** Create a new symbol if this is the first time "x" has been seen.
*/
char *x;
{
sp = Symbol_find(x);
if( sp==0 ){
sp->destructor = 0;
}
return sp;
}
/* Compare two symbols for working purposes
**
** Symbols that begin with upper case letters (terminals or tokens)
** must sort before symbols that begin with lower case letters
** (non-terminals). Other than that, the order does not matter.
**
** We find experimentally that leaving the symbols in their original
** order (the order they appeared in the grammar file) gives the
** smallest parser tables in SQLite.
*/
}
/* There is one instance of the following structure for each
** associative array of type "x2".
*/
struct s_x2 {
/* Must be a power of 2 greater than or */
/* equal to 1 */
};
/* There is one instance of this structure for every data element
** in an associative array of type "x2".
*/
typedef struct s_x2node {
} x2node;
/* There is only one instance of the array, which is the following */
/* Allocate a new associative array */
void Symbol_init(){
if( x2a ) return;
if( x2a ){
x2a = 0;
}else{
int i;
}
}
}
/* Insert a new record into the array. Return TRUE if successful.
** Prior data with the same key is NOT overwritten */
char *key;
{
int h;
int ph;
if( x2a==0 ) return 0;
while( np ){
/* An existing entry with the same key is found. */
/* Fail because overwrite is not allows. */
return 0;
}
}
/* Need to make the hash table bigger */
int i,size;
}
}
/* Insert the new data */
return 1;
}
/* Return a pointer to data assigned to the given key. Return NULL
** if no such key. */
char *key;
{
int h;
if( x2a==0 ) return 0;
while( np ){
}
}
/* Return the n-th data. Return NULL if n is out of range. */
int n;
{
}else{
data = 0;
}
return data;
}
/* Return the size of the array */
int Symbol_count()
{
}
/* Return an array of pointers to all data in the table.
** The array is obtained from malloc. Return NULL if memory allocation
** problems, or if the array is empty. */
{
int i,size;
if( x2a==0 ) return 0;
if( array ){
}
return array;
}
/* Compare two configurations */
int Configcmp(a,b)
struct config *a;
struct config *b;
{
int x;
return x;
}
/* Compare two states */
struct config *a;
struct config *b;
{
int rc;
}
if( rc==0 ){
if( a ) rc = 1;
if( b ) rc = -1;
}
return rc;
}
/* Hash a state */
struct config *a;
{
int h=0;
while( a ){
a = a->bp;
}
return h;
}
/* Allocate a new state structure */
{
return new;
}
/* There is one instance of the following structure for each
** associative array of type "x3".
*/
struct s_x3 {
/* Must be a power of 2 greater than or */
/* equal to 1 */
};
/* There is one instance of this structure for every data element
** in an associative array of type "x3".
*/
typedef struct s_x3node {
} x3node;
/* There is only one instance of the array, which is the following */
/* Allocate a new associative array */
void State_init(){
if( x3a ) return;
if( x3a ){
x3a = 0;
}else{
int i;
}
}
}
/* Insert a new record into the array. Return TRUE if successful.
** Prior data with the same key is NOT overwritten */
{
int h;
int ph;
if( x3a==0 ) return 0;
while( np ){
/* An existing entry with the same key is found. */
/* Fail because overwrite is not allows. */
return 0;
}
}
/* Need to make the hash table bigger */
int i,size;
}
}
/* Insert the new data */
return 1;
}
/* Return a pointer to data assigned to the given key. Return NULL
** if no such key. */
{
int h;
if( x3a==0 ) return 0;
while( np ){
}
}
/* Return an array of pointers to all data in the table.
** The array is obtained from malloc. Return NULL if memory allocation
** problems, or if the array is empty. */
{
int i,size;
if( x3a==0 ) return 0;
if( array ){
}
return array;
}
/* Hash a configuration */
struct config *a;
{
int h=0;
return h;
}
/* There is one instance of the following structure for each
** associative array of type "x4".
*/
struct s_x4 {
/* Must be a power of 2 greater than or */
/* equal to 1 */
};
/* There is one instance of this structure for every data element
** in an associative array of type "x4".
*/
typedef struct s_x4node {
} x4node;
/* There is only one instance of the array, which is the following */
/* Allocate a new associative array */
void Configtable_init(){
if( x4a ) return;
if( x4a ){
x4a = 0;
}else{
int i;
}
}
}
/* Insert a new record into the array. Return TRUE if successful.
** Prior data with the same key is NOT overwritten */
{
int h;
int ph;
if( x4a==0 ) return 0;
while( np ){
/* An existing entry with the same key is found. */
/* Fail because overwrite is not allows. */
return 0;
}
}
/* Need to make the hash table bigger */
int i,size;
}
}
/* Insert the new data */
return 1;
}
/* Return a pointer to data assigned to the given key. Return NULL
** if no such key. */
{
int h;
if( x4a==0 ) return 0;
while( np ){
}
}
/* Remove all data from the table. Pass each data to the function "f"
** as it is removed. ("f" may be null to avoid this step.) */
void Configtable_clear(f)
int(*f)(/* struct config * */);
{
int i;
return;
}