text:
/* Driver template for the LEMON parser generator.
** The author disclaims copyright to this source code.
*/
/* First off, code is include which follows the "include" declaration
** in the input file. */
#include <stdio.h>
%%
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
/*
** These constants (all generated automatically by the parser generator)
** specify the various kinds of tokens (terminals) that the parser
** understands.
**
** Each symbol here is a terminal symbol in the grammar.
*/
%%
/* Make sure the INTERFACE macro is defined.
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/* The next thing included is series of defines which control
** various aspects of the generated parser.
**    YYCODETYPE         is the data type used for storing terminal
**                       and nonterminal numbers.  "unsigned char" is
**                       used if there are fewer than 250 terminals
**                       and nonterminals.  "int" is used otherwise.
**    YYNOCODE           is a number of type YYCODETYPE which corresponds
**                       to no legal terminal or nonterminal number.  This
**                       number is used to fill in empty slots of the hash
**                       table.
**    YYFALLBACK         If defined, this indicates that one or more tokens
**                       have fall-back values which should be used if the
**                       original value of the token will not parse.
**    YYACTIONTYPE       is the data type used for storing terminal
**                       and nonterminal numbers.  "unsigned char" is
**                       used if there are fewer than 250 rules and
**                       states combined.  "int" is used otherwise.
**    ParseTOKENTYPE     is the data type used for minor tokens given
**                       directly to the parser from the tokenizer.
**    YYMINORTYPE        is the data type used for all minor tokens.
**                       This is typically a union of many types, one of
**                       which is ParseTOKENTYPE.  The entry in the union
**                       for base tokens is called "yy0".
**    YYSTACKDEPTH       is the maximum depth of the parser's stack.
**    ParseARG_SDECL     A static variable declaration for the %extra_argument
**    ParseARG_PDECL     A parameter declaration for the %extra_argument
**    ParseARG_STORE     Code to store %extra_argument into yypParser
**    ParseARG_FETCH     Code to extract %extra_argument from yypParser
**    YYNSTATE           the combined number of states.
**    YYNRULE            the number of rules in the grammar
**    YYERRORSYMBOL      is the code number of the error symbol.  If not
**                       defined, then do no error processing.
*/
%%
#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)

/* Next are that tables used to determine what action to take based on the
** current state and lookahead token.  These tables are used to implement
** functions that take a state number and lookahead value and return an
** action integer.
**
** Suppose the action integer is N.  Then the action is determined as
** follows
**
**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead
**                                      token onto the stack and goto state N.
**
**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE.
**
**   N == YYNSTATE+YYNRULE              A syntax error has occurred.
**
**   N == YYNSTATE+YYNRULE+1            The parser accepts its input.
**
**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused
**                                      slots in the yy_action[] table.
**
** The action table is constructed as a single large table named yy_action[].
** Given state S and lookahead X, the action is computed as
**
**      yy_action[ yy_shift_ofst[S] + X ]
**
** If the index value yy_shift_ofst[S]+X is out of range or if the value
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
** and that yy_default[S] should be used instead.
**
** The formula above is for computing the action when the lookahead is
** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
** a reduce action) then the yy_reduce_ofst[] array is used in place of
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
** YY_SHIFT_USE_DFLT.
**
** The following are the tables generated in this section:
**
**  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.
*/
%%
#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))

/* The next table maps tokens into fallback tokens.  If a construct
** like the following:
**
**      %fallback ID X Y Z.
**
** appears in the grammer, then ID becomes a fallback token for X, Y,
** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
** but it does not parse, the type of the token is changed to ID and
** the parse is retried before an error is thrown.
*/
#ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = {
%%
};
#endif /* YYFALLBACK */

/* The following structure represents a single element of the
** parser's stack.  Information stored includes:
**
**   +  The state number for the parser at this level of the stack.
**
**   +  The value of the token stored at this level of the stack.
**      (In other words, the "major" token.)
**
**   +  The semantic value stored at this level of the stack.  This is
**      the information used by the action routines in the grammar.
**      It is sometimes called the "minor" token.
*/
struct yyStackEntry {
  int stateno;       /* The state-number */
  int major;         /* The major token value.  This is the code
                     ** number for the token at this stack level */
  YYMINORTYPE minor; /* The user-supplied minor token value.  This
                     ** is the value of the token  */
};
typedef struct yyStackEntry yyStackEntry;

/* The state of the parser is completely contained in an instance of
** the following structure */
struct yyParser {
  int yyidx;                    /* Index of top element in stack */
  int yyerrcnt;                 /* Shifts left before out of the error */
  ParseARG_SDECL                /* A place to hold %extra_argument */
  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
};
typedef struct yyParser yyParser;

#ifndef NDEBUG
#include <stdio.h>
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */

#ifndef NDEBUG
/*
** Turn parser tracing on by giving a stream to which to write the trace
** and a prompt to preface each trace message.  Tracing is turned off
** by making either argument NULL
**
** Inputs:
**

**
 A FILE* to which trace output should be written.
**      If NULL, then tracing is turned off.
**
 A prefix string written at the beginning of every
**      line of trace output.  If NULL, then tracing is
**      turned off.
**

**
** Outputs:
** None.
*/
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
  yyTraceFILE = TraceFILE;
  yyTracePrompt = zTracePrompt;
  if( yyTraceFILE==0 ) yyTracePrompt = 0;
  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
}
#endif /* NDEBUG */

#ifndef NDEBUG
/* For tracing shifts, the names of all terminals and nonterminals
** are required.  The following table supplies these names */
static const char *const yyTokenName[] = {
%%
};
#endif /* NDEBUG */

#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *const yyRuleName[] = {
%%
};
#endif /* NDEBUG */

/*
** This function returns the symbolic name associated with a token
** value.
*/
const char *ParseTokenName(int tokenType){
#ifndef NDEBUG
  if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
    return yyTokenName[tokenType];
  }else{
    return "Unknown";
  }
#else
  return "";
#endif
}

/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
**
** Inputs:
** A pointer to the function used to allocate memory.
**
** Outputs:
** A pointer to a parser.  This pointer is used in subsequent calls
** to Parse and ParseFree.
*/
void *ParseAlloc(void *(*mallocProc)(size_t)){
  yyParser *pParser;
  pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
  if( pParser ){
    pParser->yyidx = -1;
  }
  return pParser;
}

/* The following function deletes the value associated with a
** symbol.  The symbol can be either a terminal or nonterminal.
** "yymajor" is the symbol code, and "yypminor" is a pointer to
** the value.
*/
static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
  switch( yymajor ){
    /* Here is inserted the actions which take place when a
    ** terminal or non-terminal is destroyed.  This can happen
    ** when the symbol is popped from the stack during a
    ** reduce or during error processing or when a parser is
    ** being destroyed before it is finished parsing.
    **
    ** Note: during a reduce, the only symbols destroyed are those
    ** which appear on the RHS of the rule, but which are not used
    ** inside the C code.
    */
%%
    default:  break;   /* If no destructor action specified: do nothing */
  }
}

/*
** Pop the parser's stack once.
**
** If there is a destructor routine associated with the token which
** is popped from the stack, then call it.
**
** Return the major token number for the symbol popped.
*/
static int yy_pop_parser_stack(yyParser *pParser){
  YYCODETYPE yymajor;
  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];

  if( pParser->yyidx<0 ) return 0;
#ifndef NDEBUG
  if( yyTraceFILE && pParser->yyidx>=0 ){
    fprintf(yyTraceFILE,"%sPopping %s\n",
      yyTracePrompt,
      yyTokenName[yytos->major]);
  }
#endif
  yymajor = yytos->major;
  yy_destructor( yymajor, &yytos->minor);
  pParser->yyidx--;
  return yymajor;
}

/*
** Deallocate and destroy a parser.  Destructors are all called for
** all stack elements before shutting the parser down.
**
** Inputs:
**

**
  A pointer to the parser.  This should be a pointer
**       obtained from ParseAlloc.
**
  A pointer to a function used to reclaim memory obtained
**       from malloc.
**

*/
void ParseFree(
  void *p,                    /* The parser to be deleted */
  void (*freeProc)(void*)     /* Function used to reclaim memory */
){
  yyParser *pParser = (yyParser*)p;
  if( pParser==0 ) return;
  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
  (*freeProc)((void*)pParser);
}

/*
** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead.  If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_shift_action(
  yyParser *pParser,        /* The parser */
  int iLookAhead            /* The look-ahead token */
){
  int i;
  int stateno = pParser->yystack[pParser->yyidx].stateno;

  if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
    return yy_default[stateno];
  }
  if( iLookAhead==YYNOCODE ){
    return YY_NO_ACTION;
  }
  i += iLookAhead;
  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK
    int iFallback;            /* Fallback token */
    if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
           && (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG
      if( yyTraceFILE ){
        fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
           yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
      }
#endif
      return yy_find_shift_action(pParser, iFallback);
    }
#endif
    return yy_default[stateno];
  }else{
    return yy_action[i];
  }
}

/*
** Find the appropriate action for a parser given the non-terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead.  If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_reduce_action(
  int stateno,              /* Current state number */
  int iLookAhead            /* The look-ahead token */
){
  int i;
  /* int stateno = pParser->yystack[pParser->yyidx].stateno; */

  if( stateno>YY_REDUCE_MAX ||
      (i = yy_reduce_ofst[stateno])==YY_REDUCE_USE_DFLT ){
    return yy_default[stateno];
  }
  if( iLookAhead==YYNOCODE ){
    return YY_NO_ACTION;
  }
  i += iLookAhead;
  if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
    return yy_default[stateno];
  }else{
    return yy_action[i];
  }
}

/*
** Perform a shift action.
*/
static void yy_shift(
  yyParser *yypParser,          /* The parser to be shifted */
  int yyNewState,               /* The new state to shift in */
  int yyMajor,                  /* The major token to shift in */
  YYMINORTYPE *yypMinor         /* Pointer ot the minor token to shift in */
){
  yyStackEntry *yytos;
  yypParser->yyidx++;
  if( yypParser->yyidx>=YYSTACKDEPTH ){
     ParseARG_FETCH;
     yypParser->yyidx--;
#ifndef NDEBUG
     if( yyTraceFILE ){
       fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
     }
#endif
     while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
     /* Here code is inserted which will execute if the parser
     ** stack every overflows */
%%
     ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
     return;
  }
  yytos = &yypParser->yystack[yypParser->yyidx];
  yytos->stateno = yyNewState;
  yytos->major = yyMajor;
  yytos->minor = *yypMinor;
#ifndef NDEBUG
  if( yyTraceFILE && yypParser->yyidx>0 ){
    int i;
    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
    for(i=1; i<=yypParser->yyidx; i++)
      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
    fprintf(yyTraceFILE,"\n");
  }
#endif
}

/* The following table contains information about every rule that
** is used during the reduce.
*/
static const struct {
  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
%%
};

static void yy_accept(yyParser*);  /* Forward Declaration */

/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
*/
static void yy_reduce(
  yyParser *yypParser,         /* The parser */
  int yyruleno                 /* Number of the rule by which to reduce */
){
  int yygoto;                     /* The next state */
  int yyact;                      /* The next action */
  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
  yyStackEntry *yymsp;            /* The top of the parser's stack */
  int yysize;                     /* Amount to pop the stack */
  ParseARG_FETCH;
  yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
  if( yyTraceFILE && yyruleno>=0
        && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
      yyRuleName[yyruleno]);
  }
#endif /* NDEBUG */

#ifndef NDEBUG
  /* Silence complaints from purify about yygotominor being uninitialized
  ** in some cases when it is copied into the stack after the following
  ** switch.  yygotominor is uninitialized when a rule reduces that does
  ** not set the value of its left-hand side nonterminal.  Leaving the
  ** value of the nonterminal uninitialized is utterly harmless as long
  ** as the value is never used.  So really the only thing this code
  ** accomplishes is to quieten purify.
  */
  memset(&yygotominor, 0, sizeof(yygotominor));
#endif

  switch( yyruleno ){
  /* Beginning here are the reduction cases.  A typical example
  ** follows:
  **   case 0:
  **  #line <lineno> <grammarfile>
  **     { ... }           // User supplied code
  **  #line <lineno> <thisfile>
  **     break;
  */
%%
  };
  yygoto = yyRuleInfo[yyruleno].lhs;
  yysize = yyRuleInfo[yyruleno].nrhs;
  yypParser->yyidx -= yysize;
  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,yygoto);
  if( yyact < YYNSTATE ){
#ifdef NDEBUG
    /* If we are not debugging and the reduce action popped at least
    ** one element off the stack, then we can push the new element back
    ** onto the stack here, and skip the stack overflow test in yy_shift().
    ** That gives a significant speed improvement. */
    if( yysize ){
      yypParser->yyidx++;
      yymsp -= yysize-1;
      yymsp->stateno = yyact;
      yymsp->major = yygoto;
      yymsp->minor = yygotominor;
    }else
#endif
    {
      yy_shift(yypParser,yyact,yygoto,&yygotominor);
    }
  }else if( yyact == YYNSTATE + YYNRULE + 1 ){
    yy_accept(yypParser);
  }
}

/*
** The following code executes when the parse fails
*/
static void yy_parse_failed(
  yyParser *yypParser           /* The parser */
){
  ParseARG_FETCH;
#ifndef NDEBUG
  if( yyTraceFILE ){
    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
  }
#endif
  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
  /* Here code is inserted which will be executed whenever the
  ** parser fails */
%%
  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}

/*
** The following code executes when a syntax error first occurs.
*/
static void yy_syntax_error(
  yyParser *yypParser,           /* The parser */
  int yymajor,                   /* The major type of the error token */
  YYMINORTYPE yyminor            /* The minor type of the error token */
){
  ParseARG_FETCH;
#define TOKEN (yyminor.yy0)
%%
  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}

/*
** The following is executed when the parser accepts
*/
static void yy_accept(
  yyParser *yypParser           /* The parser */
){
  ParseARG_FETCH;
#ifndef NDEBUG
  if( yyTraceFILE ){
    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
  }
#endif
  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
  /* Here code is inserted which will be executed whenever the
  ** parser accepts */
%%
  ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}

/* The main parser program.
** The first argument is a pointer to a structure obtained from
** "ParseAlloc" which describes the current state of the parser.
** The second argument is the major token number.  The third is
** the minor token.  The fourth optional argument is whatever the
** user wants (and specified in the grammar) and is available for
** use by the action routines.
**
** Inputs:
**

**
 A pointer to the parser (an opaque structure.)
**
 The major token number.
**
 The minor token number.
**
 An option argument of a grammar-specified type.
**

**
** Outputs:
** None.
*/
void Parse(
  void *yyp,                   /* The parser */
  int yymajor,                 /* The major token code number */
  ParseTOKENTYPE yyminor       /* The value for the token */
  ParseARG_PDECL               /* Optional %extra_argument parameter */
){
  YYMINORTYPE yyminorunion;
  int yyact;            /* The parser action. */
  int yyendofinput;     /* True if we are at the end of input */
  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
  yyParser *yypParser;  /* The parser */

  /* (re)initialize the parser, if necessary */
  yypParser = (yyParser*)yyp;
  if( yypParser->yyidx<0 ){
    /* if( yymajor==0 ) return; // not sure why this was here... */
    yypParser->yyidx = 0;
    yypParser->yyerrcnt = -1;
    yypParser->yystack[0].stateno = 0;
    yypParser->yystack[0].major = 0;
  }
  yyminorunion.yy0 = yyminor;
  yyendofinput = (yymajor==0);
  ParseARG_STORE;

#ifndef NDEBUG
  if( yyTraceFILE ){
    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
  }
#endif

  do{
    yyact = yy_find_shift_action(yypParser,yymajor);
    if( yyact<YYNSTATE ){
      yy_shift(yypParser,yyact,yymajor,&yyminorunion);
      yypParser->yyerrcnt--;
      if( yyendofinput && yypParser->yyidx>=0 ){
        yymajor = 0;
      }else{
        yymajor = YYNOCODE;
      }
    }else if( yyact < YYNSTATE + YYNRULE ){
      yy_reduce(yypParser,yyact-YYNSTATE);
    }else if( yyact == YY_ERROR_ACTION ){
      int yymx;
#ifndef NDEBUG
      if( yyTraceFILE ){
        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
      }
#endif
#ifdef YYERRORSYMBOL
      /* A syntax error has occurred.
      ** The response to an error depends upon whether or not the
      ** grammar defines an error token "ERROR".
      **
      ** This is what we do if the grammar does define ERROR:
      **
      **  * Call the %syntax_error function.
      **
      **  * Begin popping the stack until we enter a state where
      **    it is legal to shift the error symbol, then shift
      **    the error symbol.
      **
      **  * Set the error count to three.
      **
      **  * Begin accepting and shifting new tokens.  No new error
      **    processing will occur until three tokens have been
      **    shifted successfully.
      **
      */
      if( yypParser->yyerrcnt<0 ){
        yy_syntax_error(yypParser,yymajor,yyminorunion);
      }
      yymx = yypParser->yystack[yypParser->yyidx].major;
      if( yymx==YYERRORSYMBOL || yyerrorhit ){
#ifndef NDEBUG
        if( yyTraceFILE ){
          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
             yyTracePrompt,yyTokenName[yymajor]);
        }
#endif
        yy_destructor(yymajor,&yyminorunion);
        yymajor = YYNOCODE;
      }else{
         while(
          yypParser->yyidx >= 0 &&
          yymx != YYERRORSYMBOL &&
          (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
        ){
          yy_pop_parser_stack(yypParser);
        }
        if( yypParser->yyidx < 0 || yymajor==0 ){
          yy_destructor(yymajor,&yyminorunion);
          yy_parse_failed(yypParser);
          yymajor = YYNOCODE;
        }else if( yymx!=YYERRORSYMBOL ){
          YYMINORTYPE u2;
          u2.YYERRSYMDT = 0;
          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
        }
      }
      yypParser->yyerrcnt = 3;
      yyerrorhit = 1;
#else  /* YYERRORSYMBOL is not defined */
      /* This is what we do if the grammar does not define ERROR:
      **
      **  * Report an error message, and throw away the input token.
      **
      **  * If the input token is $, then fail the parse.
      **
      ** As before, subsequent error messages are suppressed until
      ** three input tokens have been successfully shifted.
      */
      if( yypParser->yyerrcnt<=0 ){
        yy_syntax_error(yypParser,yymajor,yyminorunion);
      }
      yypParser->yyerrcnt = 3;
      yy_destructor(yymajor,&yyminorunion);
      if( yyendofinput ){
        yy_parse_failed(yypParser);
      }
      yymajor = YYNOCODE;
#endif
    }else{
      yy_accept(yypParser);
      yymajor = YYNOCODE;
    }
  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
  return;
}

repo_language: C

mime_type: text/x-c


text:
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.199 2006/03/13 12:54:10 drh Exp $
*/

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
//
%token_type {Token}
%default_type {Token}

// The generated parser function takes a 4th argument as follows:
%extra_argument {Parse *pParse}

// This code runs whenever there is a syntax error
//
%syntax_error {
  if( pParse->zErrMsg==0 ){
    if( TOKEN.z[0] ){
      sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
    }else{
      sqlite3ErrorMsg(pParse, "incomplete SQL statement");
    }
  }
}
%stack_overflow {
  sqlite3ErrorMsg(pParse, "parser stack overflow");
}

// The name of the generated procedure that implements the parser
// is as follows:
%name Parser

// The following text is included near the beginning of the C source
// code file that implements the parser.
//
%include {
#include "sqliteInt.h"
#include "parse.h"

/*
** An instance of this structure holds information about the
** LIMIT clause of a SELECT statement.
*/
struct LimitVal {
  Expr *pLimit;    /* The LIMIT expression.  NULL if there is no limit */
  Expr *pOffset;   /* The OFFSET expression.  NULL if there is none */
};

/*
** An instance of this structure is used to store the LIKE,
** GLOB, NOT LIKE, and NOT GLOB operators.
*/
struct LikeOp {
  Token eOperator;  /* "like" or "glob" or "regexp" */
  int not;         /* True if the NOT keyword is present */
};

/*
** An instance of the following structure describes the event of a
** TRIGGER.  "a" is the event type, one of TK_UPDATE, TK_INSERT,
** TK_DELETE, or TK_INSTEAD.  If the event is of the form
**
**      UPDATE ON (a,b,c)
**
** Then the "b" IdList records the list "a,b,c".
*/
struct TrigEvent { int a; IdList * b; };

/*
** An instance of this structure holds the ATTACH key and the key type.
*/
struct AttachKey { int type;  Token key; };

} // end %include

// Input is a single SQL command
input ::= cmdlist.
cmdlist ::= cmdlist ecmd.
cmdlist ::= ecmd.
cmdx ::= cmd.           { }
cmdx ::= LP cmd RP.     { pParse->sflag |= SQL_FLAG_CODING;}
ecmd ::= SEMI.
ecmd ::= explain cmdx SEMI.
explain ::= .           { }
%ifndef SQLITE_OMIT_EXPLAIN
explain ::= EXPLAIN.              { pParse->sflag |= SQL_FLAG_PARSE; }
explain ::= EXPLAIN QUERY PLAN.   { pParse->sflag |= SQL_FLAG_PARSE; }
%endif

///////////////////// Begin and end transactions. ////////////////////////////
//

//cmd ::= BEGIN transtype(Y) trans_opt.  { pParse->sflag |= SQL_FLAG_TR;}
cmd ::= BEGIN trans_opt.  { pParse->sflag |= SQL_FLAG_TR;}
cmd ::= START TRANSACTION. { pParse->sflag |= SQL_FLAG_TR;}
trans_opt ::= .
trans_opt ::= WORK.
//trans_opt ::= TRANSACTION.
//trans_opt ::= TRANSACTION nm.

//%type transtype {int}
//transtype(A) ::= .             {A = TK_DEFERRED;}
//transtype(A) ::= DEFERRED(X).  {A = @X;}
//transtype(A) ::= IMMEDIATE(X). {A = @X;}
//transtype(A) ::= EXCLUSIVE(X). {A = @X;}
cmd ::= COMMIT trans_opt.      { pParse->sflag |= SQL_FLAG_TR; }
//cmd ::= END trans_opt.         { pParse->sflag |= SQL_FLAG_TR; }
cmd ::= ROLLBACK trans_opt.    { pParse->sflag |= SQL_FLAG_TR; }

///////////////////// The CREATE TABLE statement ////////////////////////////
//
cmd ::= create_table create_table_args.
create_table ::= CREATE temp TABLE ifnotexists nm dbnm. {
   pParse->sflag |= SQL_FLAG_TABLE;
}

%type ifnotexists {int}
ifnotexists(A) ::= .              {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
%type temp {int}
%ifndef SQLITE_OMIT_TEMPDB
temp(A) ::= TEMP.  {A = 1;}
%endif
temp(A) ::= .      {A = 0;}
create_table_args ::= LP columnlist conslist_opt RP table_opt. {
  //sqlite3EndTable(pParse,&X,&Y,0);
}
create_table_args ::= AS select. {
	pParse->sflag |= SQL_FLAG_TABLE;
}
columnlist ::= columnlist COMMA column.
columnlist ::= column.

// -- TODO FAKE grammer-- TO COMPLETE THIS
table_opt ::= .
table_opt ::= table_opt ID.
table_opt ::= table_opt ID EQ ID.
table_opt ::= table_opt DEFAULT CHARSET SET eq_or_null ID.
table_opt ::= table_opt DEFAULT COLLATE eq_or_null ID.

eq_or_null ::= .
eq_or_null ::= EQ.

// A "column" is a complete description of a single column in a
// CREATE TABLE statement.  This includes the column name, its
// datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES,
// NOT NULL and so forth.
//
column ::= columnid type carglist. {
  //A.z = X.z;
  //A.n = (pParse->sLastToken.z-X.z) + pParse->sLastToken.n;
}
columnid ::= nm. {
  //sqlite3AddColumn(pParse,&X);
  //A = X;
}

// An IDENTIFIER can be a generic identifier, or one of several
// keywords.  Any non-standard keyword can also be an identifier.
//
%type id {Token}
id(A) ::= ID(X).         {A = X;}

// The following directive causes tokens ABORT, AFTER, ASC, etc. to
// fallback to ID if they will not parse as their original value.
// This obviates the need for the "id" nonterminal.
//
%fallback ID
  ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT
  DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH PLAN QUERY KEY
  OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT
  TEMP TRIGGER VACUUM VIEW
%ifdef SQLITE_OMIT_COMPOUND_SELECT
  EXCEPT INTERSECT UNION
%endif
  REINDEX RENAME CTIME_KW IF
  .

// Define operator precedence early so that this is the first occurance
// of the operator tokens in the grammer.  Keeping the operators together
// causes them to be assigned integer values that are close together,
// which keeps parser tables smaller.
//
// The token values assigned to these symbols is determined by the order
// in which lemon first sees them.  It must be the case that ISNULL/NOTNULL,
// NE/EQ, GT/LE, and GE/LT are separated by only a single value.  See
// the sqlite3ExprIfFalse() routine for additional information on this
// constraint.
//
%left OR.
%left AND.
%right NOT.
%left IS LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
%left GT LE LT GE.
%right ESCAPE.
%left BITAND BITOR LSHIFT RSHIFT.
%left PLUS MINUS.
%left STAR SLASH REM.
%left CONCAT.
%right UMINUS UPLUS BITNOT.

// And "ids" is an identifer-or-string.
//
%type ids {Token}
ids(A) ::= ID|STRING(X).   {A = X;}

// The name of a column or table can be any of the following:
//
%type nm {Token}
nm(A) ::= ID(X).         {A = X;}
nm(A) ::= STRING(X).     {A = X;}
nm(A) ::= JOIN_KW(X).    {A = X;}

// A typetoken is really one or more tokens that form a type name such
// as can be found after the column name in a CREATE TABLE statement.
// Multiple tokens are concatenated to form the value of the typetoken.
//
%type typetoken {Token}
type ::= .
type ::= typetoken.                   { /*sqlite3AddColumnType(pParse,&X);*/ }
typetoken(A) ::= typename(X).   {A = X;}
typetoken(A) ::= typename(X) LP signed RP(Y). {
  A.z = X.z;
  A.n = &Y.z[Y.n] - X.z;
}
typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). {
  A.z = X.z;
  A.n = &Y.z[Y.n] - X.z;
}
%type typename {Token}
typename(A) ::= ids(X).             {A = X;}
typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(Y.z-X.z);}
%type signed {int}
signed(A) ::= plus_num(X).    { A = atoi((char*)X.z); }
signed(A) ::= minus_num(X).   { A = -atoi((char*)X.z); }

// "carglist" is a list of additional constraints that come after the
// column name and column type in a CREATE TABLE statement.
//
carglist ::= carglist carg.
carglist ::= .
carg ::= CONSTRAINT nm ccons.
carg ::= ccons.
carg ::= DEFAULT term.            { /*sqlite3AddDefaultValue(pParse,X);*/ }
carg ::= DEFAULT LP expr RP.      { /*sqlite3AddDefaultValue(pParse,X);*/ }
carg ::= DEFAULT PLUS term.       { /*sqlite3AddDefaultValue(pParse,X);*/}
carg ::= DEFAULT MINUS term.      {
  //Expr *p = sqlite3Expr(TK_UMINUS, X, 0, 0);
  //sqlite3AddDefaultValue(pParse,p);
}
carg ::= DEFAULT id.              {
  //Expr *p = sqlite3Expr(TK_STRING, 0, 0, &X);
  //sqlite3AddDefaultValue(pParse,p);
}

// In addition to the type name, we also care about the primary key and
// UNIQUE constraints.
//
ccons ::= AUTOINCR.
ccons ::= NULL onconf.
ccons ::= NOT NULL onconf.               {/*sqlite3AddNotNull(pParse, R);*/}
ccons ::= PRIMARY KEY sortorder onconf.
                                     {/*sqlite3AddPrimaryKey(pParse,0,R,I,Z);*/}
ccons ::= UNIQUE onconf.    {/*sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);*/}
ccons ::= CHECK LP expr RP.       { }
ccons ::= REFERENCES nm idxlist_opt refargs.
                                { }
ccons ::= defer_subclause.   {/*sqlite3DeferForeignKey(pParse,D);*/}
ccons ::= COLLATE id.  {/*sqlite3AddCollateType(pParse, (char*)C.z, C.n);*/}

// The optional AUTOINCREMENT keyword
%type autoinc {int}
autoinc(X) ::= .          {X = 0;}
autoinc(X) ::= AUTOINCR.  {X = 1;}

// The next group of rules parses the arguments to a REFERENCES clause
// that determine if the referential integrity checking is deferred or
// or immediate and which determine what action to take if a ref-integ
// check fails.
//
%type refargs {int}
refargs(A) ::= .                     { A = OE_Restrict * 0x010101; }
refargs(A) ::= refargs(X) refarg(Y). { A = (X & Y.mask) | Y.value; }
%type refarg {struct {int value; int mask;}}
refarg(A) ::= MATCH nm.              { A.value = 0;     A.mask = 0x000000; }
refarg(A) ::= ON DELETE refact(X).   { A.value = X;     A.mask = 0x0000ff; }
refarg(A) ::= ON UPDATE refact(X).   { A.value = X<<8;  A.mask = 0x00ff00; }
refarg(A) ::= ON INSERT refact(X).   { A.value = X<<16; A.mask = 0xff0000; }
%type refact {int}
refact(A) ::= SET NULL.              { A = OE_SetNull; }
refact(A) ::= SET DEFAULT.           { A = OE_SetDflt; }
refact(A) ::= CASCADE.               { A = OE_Cascade; }
refact(A) ::= RESTRICT.              { A = OE_Restrict; }
%type defer_subclause {int}
defer_subclause(A) ::= NOT DEFERRABLE init_deferred_pred_opt(X).  {A = X;}
defer_subclause(A) ::= DEFERRABLE init_deferred_pred_opt(X).      {A = X;}
%type init_deferred_pred_opt {int}
init_deferred_pred_opt(A) ::= .                       {A = 0;}
init_deferred_pred_opt(A) ::= INITIALLY DEFERRED.     {A = 1;}
init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE.    {A = 0;}

// For the time being, the only constraint we care about is the primary
// key and UNIQUE.  Both create indices.
//
conslist_opt ::= .
conslist_opt ::= COMMA conslist.
conslist ::= conslist COMMA tcons.
conslist ::= conslist tcons.
conslist ::= tcons.
tcons ::= CONSTRAINT nm.

// -- TODO --
// idxlist and idxlist_opt need to explicit call its destructor, or will make memleak, do not know why it don't call automatically...
tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf. { }
tcons ::= UNIQUE LP idxlist RP onconf.
                                 { }
tcons ::= CHECK LP expr RP onconf. { }
tcons ::= FOREIGN KEY LP idxlist RP
          REFERENCES nm idxlist_opt refargs defer_subclause_opt. {
 }

%type defer_subclause_opt {int}
defer_subclause_opt(A) ::= .                    {A = 0;}
defer_subclause_opt(A) ::= defer_subclause(X).  {A = X;}

// The following is a non-standard extension that allows us to declare the
// default behavior when there is a constraint conflict.
//
%type onconf {int}
%type orconf {int}
%type resolvetype {int}
onconf(A) ::= .                              {A = OE_Default;}
onconf(A) ::= ON CONFLICT resolvetype(X).    {A = X;}
//orconf(A) ::= .                              {A = OE_Default;}
//orconf(A) ::= OR resolvetype(X).             {A = X;}
resolvetype(A) ::= raisetype(X).             {A = X;}
resolvetype(A) ::= IGNORE.                   {A = OE_Ignore;}
resolvetype(A) ::= REPLACE.                  {A = OE_Replace;}

////////////////////////// The DROP TABLE /////////////////////////////////////
//
cmd ::= DROP TABLE ifexists fullname. {
  pParse->sflag |= SQL_FLAG_TABLE;
}
%type ifexists {int}
ifexists(A) ::= IF EXISTS.   {A = 1;}
ifexists(A) ::= .            {A = 0;}

///////////////////// The CREATE VIEW statement /////////////////////////////
//
%ifndef SQLITE_OMIT_VIEW
//cmd ::= CREATE(X) temp(T) VIEW nm(Y) dbnm(Z) AS select(S). {
//  sqlite3CreateView(pParse, &X, &Y, &Z, S, T);
//}
//cmd ::= DROP VIEW ifexists(E) fullname(X). {
//  sqlite3DropTable(pParse, X, 1, E);
//}
%endif // SQLITE_OMIT_VIEW

//////////////////////// The SELECT statement /////////////////////////////////
//
cmd ::= select.  {
}

%type select {Select*}
//%destructor select { }
%type oneselect {Select*}
//%destructor oneselect { }

select(A) ::= oneselect(X).                      {A = X;}
%ifndef SQLITE_OMIT_COMPOUND_SELECT
select(A) ::= select(X) multiselect_op(Y) oneselect(Z).  {
  if( Z ){
    Z->op = Y;
    Z->pPrior = X;
  }
  A = Z;
}
%type multiselect_op {int}
multiselect_op(A) ::= UNION(OP).             {A = @OP;}
multiselect_op(A) ::= UNION ALL.             {A = TK_ALL;}
multiselect_op(A) ::= EXCEPT|INTERSECT(OP).  {A = @OP;}
%endif // SQLITE_OMIT_COMPOUND_SELECT
oneselect ::= SELECT distinct selcollist from where_opt
                 groupby_opt having_opt orderby_opt limit_opt. {
  pParse->select_num++;
}

// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not.
//
%type distinct {int}
distinct(A) ::= DISTINCT.   {A = 1;}
distinct(A) ::= ALL.        {A = 0;}
distinct(A) ::= .           {A = 0;}

// selcollist is a list of expressions that are to become the return
// values of the SELECT statement.  The "*" in statements like
// "SELECT * FROM ..." is encoded as a special expression with an
// opcode of TK_ALL.
//
%type selcollist {ExprList*}
%destructor selcollist { }
%type sclp {ExprList*}
%destructor sclp { }
sclp(A) ::= selcollist(X) COMMA.             {A = X;}
sclp(A) ::= .                                {A = 0;}
selcollist ::= sclp expr as.     {
  pParse->sflag |= SQL_FLAG_EXPR;
}
selcollist ::= sclp STAR. {
  pParse->sflag |= SQL_FLAG_EXPR;
}
selcollist ::= sclp nm DOT STAR. {
  pParse->sflag |= SQL_FLAG_EXPR;
}

// An option "AS <id>" phrase that can follow one of the expressions that
// define the result set, or one of the tables in the FROM clause.
//
%type as {Token}
as(X) ::= AS nm(Y).    {X = Y;}
as(X) ::= ids(Y).      {X = Y;}
as(X) ::= .            {X.n = 0;}

%type seltablist {SrcList*}
%destructor seltablist {}
%type stl_prefix {SrcList*}
%destructor stl_prefix {}
%type from {SrcList*}
%destructor from {}

// A complete FROM clause.
//
from(A) ::= .                                 {A = sqliteMalloc(sizeof(*A));}
from(A) ::= FROM seltablist(X).               {A = X;}

// "seltablist" is a "Select Table List" - the content of the FROM clause
// in a SELECT statement.  "stl_prefix" is a prefix of this list.
//
stl_prefix(A) ::= seltablist(X) joinop(Y).    {
   A = X;
   if( A && A->nSrc>0 ) A->a[A->nSrc-1].jointype = Y;
}
stl_prefix(A) ::= .                           {A = 0;}
seltablist ::= stl_prefix nm dbnm as on_opt using_opt. {
  pParse->sflag |= SQL_FLAG_EXPR;
}
%ifndef SQLITE_OMIT_SUBQUERY
  seltablist ::= stl_prefix LP seltablist_paren RP
                    as on_opt using_opt. {
  pParse->sflag |= SQL_FLAG_EXPR;
}

  // A seltablist_paren nonterminal represents anything in a FROM that
  // is contained inside parentheses.  This can be either a subquery or
  // a grouping of table and subqueries.
  //
  %type seltablist_paren {Select*}
  %destructor seltablist_paren { }
  seltablist_paren(A) ::= select(S).      {A = S;}
  seltablist_paren ::= seltablist.  {
     pParse->select_num++;
  }
%endif // SQLITE_OMIT_SUBQUERY

%type dbnm {Token}
dbnm(A) ::= .          {A.z=0; A.n=0;}
dbnm(A) ::= DOT nm(X). {A = X;}

%type fullname {SrcList*}
%destructor fullname {}
fullname ::= nm dbnm.  {  pParse->sflag |= SQL_FLAG_LIST; }

%type joinop {int}
%type joinop2 {int}
joinop(X) ::= COMMA|JOIN.              { X = JT_INNER; }
joinop ::= JOIN_KW JOIN.         { pParse->sflag |= SQL_FLAG_JOIN; }
joinop ::= JOIN_KW nm JOIN.   { pParse->sflag |= SQL_FLAG_JOIN; }
joinop ::= JOIN_KW nm nm JOIN.
                                       { pParse->sflag |= SQL_FLAG_JOIN; }

%type on_opt {Expr*}
%destructor on_opt { }
on_opt(N) ::= ON expr(E).   {N = E;}
on_opt(N) ::= .             {N = 0;}

%type using_opt {IdList*}
%destructor using_opt { }
using_opt(U) ::= USING LP inscollist(L) RP.  {U = L;}
using_opt(U) ::= .                        {U = 0;}

%type orderby_opt {ExprList*}
%destructor orderby_opt { }
%type sortlist {ExprList*}
%destructor sortlist { }
%type sortitem {Expr*}
%destructor sortitem { }

orderby_opt(A) ::= .                          {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
sortlist ::= sortlist COMMA sortitem collate sortorder. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
sortlist ::= sortitem collate sortorder. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
sortitem(A) ::= expr(X).   {A = X;}

%type sortorder {int}
%type collate {Token}

sortorder(A) ::= ASC.           {A = SQLITE_SO_ASC;}
sortorder(A) ::= DESC.          {A = SQLITE_SO_DESC;}
sortorder(A) ::= .              {A = SQLITE_SO_ASC;}
collate(C) ::= .                {C.z = 0; C.n = 0;}
collate(C) ::= COLLATE id(X).   {C = X;}

%type groupby_opt {ExprList*}
%destructor groupby_opt { }
groupby_opt(A) ::= .                      {A = 0;}
groupby_opt(A) ::= GROUP BY exprlist(X).  {A = X;}

%type having_opt {Expr*}
%destructor having_opt {}
having_opt(A) ::= .                {A = 0;}
having_opt(A) ::= HAVING expr(X).  {A = X;}

%type limit_opt {struct LimitVal}
%destructor limit_opt {
}
limit_opt(A) ::= .                     {A.pLimit = 0; A.pOffset = 0;}
limit_opt(A) ::= LIMIT expr(X).        {A.pLimit = X; A.pOffset = 0;}
limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y).
                                       {A.pLimit = X; A.pOffset = Y;}
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
                                       {A.pOffset = X; A.pLimit = Y;}

/////////////////////////// The DELETE statement /////////////////////////////
//
cmd ::= DELETE FROM fullname where_opt limit_opt. {pParse->sflag |= SQL_FLAG_DELETE;}

%type where_opt {Expr*}
%destructor where_opt { }

where_opt(A) ::= .                    {A = 0;}
where_opt(A) ::= WHERE expr(X).       {A = X;}

////////////////////////// The UPDATE command ////////////////////////////////
//
//cmd ::= UPDATE orconf(R) fullname(X) SET setlist(Y) where_opt(Z).
cmd ::= UPDATE fullname SET setlist where_opt limit_opt.
    {pParse->sflag |= SQL_FLAG_UPDATE;}

%type setlist {ExprList*}
%destructor setlist { }

setlist ::= setlist COMMA nm EQ expr.
    {pParse->sflag |= SQL_FLAG_EXPR;}
setlist ::= nm EQ expr.   {pParse->sflag |= SQL_FLAG_EXPR;}

////////////////////////// The INSERT command /////////////////////////////////
//
/* cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) */
/*         VALUES LP itemlist(Y) RP. */
/*             {sqlite3Insert(pParse, X, Y, 0, F, R);} */
cmd ::= insert_cmd INTO fullname inscollist_opt
        VALUES valueslist.
            {pParse->sflag |= SQL_FLAG_INSERT;}

cmd ::= insert_cmd INTO fullname inscollist_opt
        SET setlist.
            {pParse->sflag |= SQL_FLAG_INSERT;}

cmd ::= insert_cmd fullname inscollist_opt
        SET setlist.
            {pParse->sflag |= SQL_FLAG_INSERT;}

cmd ::= insert_cmd INTO fullname inscollist_opt select.
            {pParse->sflag |= SQL_FLAG_INSERT;}

%type insert_cmd {int}
//insert_cmd(A) ::= INSERT orconf(R).   {A = R;}
insert_cmd(A) ::= INSERT. { A = OE_Default; }
insert_cmd(A) ::= REPLACE.            {A = OE_Replace;}

%type valueslist {ValuesList*}
%destructor valueslist { }

valueslist ::= valueslist COMMA LP itemlist RP.   { pParse->sflag |= SQL_FLAG_EXPR; }
valueslist ::= LP itemlist RP.                       { pParse->sflag |= SQL_FLAG_EXPR; }
valueslist(VL) ::= LP RP.                                   { VL = 0; }

%type itemlist {ExprList*}
%destructor itemlist { }

itemlist ::= itemlist COMMA expr.  {pParse->sflag |= SQL_FLAG_EXPR;}
itemlist ::= expr.                    {pParse->sflag |= SQL_FLAG_EXPR;}

%type inscollist_opt {IdList*}
%destructor inscollist_opt {}
%type inscollist {IdList*}
%destructor inscollist {}

inscollist_opt(A) ::= .                       {A = 0;}
inscollist_opt(A) ::= LP RP.                  {A = 0;}
inscollist_opt(A) ::= LP inscollist(X) RP.    {A = X;}
inscollist ::= inscollist COMMA nm.  { pParse->sflag |= SQL_FLAG_LIST;}
inscollist ::= nm.                      { pParse->sflag |= SQL_FLAG_LIST;}

/////////////////////////// Expression Processing /////////////////////////////
//

%type expr {Expr*}
%destructor expr {}
%type term {Expr*}
%destructor term {}

expr(A) ::= term(X).             {A = X;}
expr ::= LP expr RP. {pParse->sflag |= SQL_FLAG_EXPR;}
term ::= NULL.             {pParse->sflag |= SQL_FLAG_EXPR;}
expr ::= ID.               {pParse->sflag |= SQL_FLAG_EXPR;}
expr ::= JOIN_KW.          {pParse->sflag |= SQL_FLAG_EXPR;}
expr ::= nm DOT nm. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= nm DOT nm DOT nm. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
term ::= INTEGER|FLOAT|BLOB.      {pParse->sflag |= SQL_FLAG_EXPR;}
term ::= STRING.       {pParse->sflag |= SQL_FLAG_EXPR;}
expr ::= REGISTER.     {pParse->sflag |= SQL_FLAG_EXPR;}
expr ::= VARIABLE.     {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= VARIABLE1.     {
	pParse->sflag |= SQL_FLAG_EXPR;
}
%ifndef SQLITE_OMIT_CAST
expr ::= CAST LP expr AS typetoken RP. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
%endif // SQLITE_OMIT_CAST
expr ::= ID LP distinct exprlist RP. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= ID LP STAR RP. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
term ::= CTIME_KW. {
  /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
  ** treated as functions that return constants */
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= expr AND expr.            {pParse->sflag |= SQL_FLAG_OPT;}
expr ::= expr OR expr.             {pParse->sflag |= SQL_FLAG_OPT;}
expr ::= expr LT|GT|GE|LE expr.    {pParse->sflag |= SQL_FLAG_OPT;}
expr ::= expr EQ expr.          {pParse->sflag |= SQL_FLAG_EXPR;}
expr ::= expr NE expr.          {pParse->sflag |= SQL_FLAG_OPT;}
expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr.
                                                {pParse->sflag |= SQL_FLAG_OPT;}
expr ::= expr PLUS|MINUS expr.     {pParse->sflag |= SQL_FLAG_OPT;}
expr ::= expr STAR|SLASH|REM expr. {pParse->sflag |= SQL_FLAG_OPT;}
expr ::= expr CONCAT expr.         {pParse->sflag |= SQL_FLAG_OPT;}
%type likeop {struct LikeOp}
likeop(A) ::= LIKE_KW(X).     {A.eOperator = X; A.not = 0;}
likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.not = 1;}
%type escape {Expr*}
%destructor escape {}
escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;}
escape(X) ::= .               [ESCAPE] {X = 0;}
expr ::= expr likeop expr escape.  [LIKE_KW]  {
	pParse->sflag |= SQL_FLAG_EXPR;
}

expr ::= expr ISNULL|NOTNULL. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= expr IS NULL. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= expr NOT NULL. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= expr IS NOT NULL. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= NOT|BITNOT expr. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= MINUS expr. [UMINUS] {
	pParse->sflag |= SQL_FLAG_EXPR;
}
expr ::= PLUS expr. [UPLUS] {
	pParse->sflag |= SQL_FLAG_EXPR;
}
%type between_op {int}
between_op(A) ::= BETWEEN.     {A = 0;}
between_op(A) ::= NOT BETWEEN. {A = 1;}

%type between_elem {Expr*}
%destructor between_elem {}

between_elem ::= INTEGER|STRING. {pParse->sflag |= SQL_FLAG_EXPR;}

//expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
expr ::= expr between_op between_elem AND between_elem. [BETWEEN] {
	pParse->sflag |= SQL_FLAG_EXPR;
}
%ifndef SQLITE_OMIT_SUBQUERY
  %type in_op {int}
  in_op(A) ::= IN.      {A = 0;}
  in_op(A) ::= NOT IN.  {A = 1;}
  expr ::= expr in_op LP exprlist RP. [IN] {
	  pParse->sflag |= SQL_FLAG_EXPR;
  }
  expr ::= LP select RP. {
	  pParse->sflag |= SQL_FLAG_EXPR;
  }
  expr ::= expr in_op LP select RP.  [IN] {
	  pParse->sflag |= SQL_FLAG_EXPR;
  }
  expr ::= expr in_op nm dbnm. [IN] {
	  pParse->sflag |= SQL_FLAG_EXPR;
  }
  expr ::= EXISTS LP select RP. {
	  pParse->sflag |= SQL_FLAG_EXPR;
  }
%endif // SQLITE_OMIT_SUBQUERY

/* CASE expressions */
expr ::= CASE case_operand case_exprlist case_else END. {
  pParse->sflag |= SQL_FLAG_EXPR;
}
%type case_exprlist {ExprList*}
%destructor case_exprlist { }
case_exprlist ::= case_exprlist WHEN expr THEN expr. {
  pParse->sflag |= SQL_FLAG_EXPR;
}
case_exprlist ::= WHEN expr THEN expr. {
  pParse->sflag |= SQL_FLAG_EXPR;
}
%type case_else {Expr*}
%destructor case_else {}
case_else(A) ::=  ELSE expr(X).         {A = X;}
case_else(A) ::=  .                     {A = 0;}
%type case_operand {Expr*}
%destructor case_operand {}
case_operand(A) ::= expr(X).            {A = X;}
case_operand(A) ::= .                   {A = 0;}

%type exprlist {ExprList*}
%destructor exprlist { }
%type expritem {Expr*}
%destructor expritem { }

exprlist ::= exprlist COMMA expritem.
                                        {pParse->sflag |= SQL_FLAG_EXPR;}
exprlist ::= expritem.            {pParse->sflag |= SQL_FLAG_EXPR;}
expritem(A) ::= expr(X).                {A = X;}
expritem(A) ::= .                       {A = 0;}

///////////////////////////// The CREATE INDEX command ///////////////////////
//
//cmd ::= CREATE(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D)
//        ON nm(Y) LP idxlist(Z) RP(E). {
//  sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,0), Z, U,
//                      &S, &E, SQLITE_SO_ASC, NE);
//}

//%type uniqueflag {int}
//uniqueflag(A) ::= UNIQUE.  {A = OE_Abort;}
//uniqueflag(A) ::= .        {A = OE_None;}

%type idxlist {ExprList*}
%destructor idxlist { }
%type idxlist_opt {ExprList*}
%destructor idxlist_opt {}
%type idxitem {Token}

idxlist_opt(A) ::= .                         {A = 0;}
idxlist_opt(A) ::= LP idxlist(X) RP.         {A = X;}
idxlist ::= idxlist COMMA idxitem collate sortorder.  {
	pParse->sflag |= SQL_FLAG_EXPR;
}
idxlist ::= idxitem collate sortorder. {
	pParse->sflag |= SQL_FLAG_EXPR;
}
idxitem(A) ::= nm(X).              {A = X;}

///////////////////////////// The DROP INDEX command /////////////////////////
//
//cmd ::= DROP INDEX ifexists(E) fullname(X).   {sqlite3DropIndex(pParse, X, E);}

///////////////////////////// The VACUUM command /////////////////////////////
//
//cmd ::= VACUUM.                {sqlite3Vacuum(pParse);}
//cmd ::= VACUUM nm.             {sqlite3Vacuum(pParse);}

///////////////////////////// The PRAGMA command /////////////////////////////
//
%ifndef SQLITE_OMIT_PRAGMA
//cmd ::= PRAGMA nm(X) dbnm(Z) EQ nm(Y).  {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
//cmd ::= PRAGMA nm(X) dbnm(Z) EQ ON(Y).  {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
//cmd ::= PRAGMA nm(X) dbnm(Z) EQ plus_num(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
//cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). {
//  sqlite3Pragma(pParse,&X,&Z,&Y,1);
//}
//cmd ::= PRAGMA nm(X) dbnm(Z) LP nm(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
//cmd ::= PRAGMA nm(X) dbnm(Z).             {sqlite3Pragma(pParse,&X,&Z,0,0);}
%endif // SQLITE_OMIT_PRAGMA
plus_num(A) ::= plus_opt number(X).   {A = X;}
minus_num(A) ::= MINUS number(X).     {A = X;}
number(A) ::= INTEGER|FLOAT(X).       {A = X;}
plus_opt ::= PLUS.
plus_opt ::= .

//////////////////////////// The CREATE TRIGGER command /////////////////////

%ifndef SQLITE_OMIT_TRIGGER

/* cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). { */
/*   Token all; */
/*   all.z = A.z; */
/*   all.n = (Z.z - A.z) + Z.n; */
/*   sqlite3FinishTrigger(pParse, S, &all); */
/* } */

/* trigger_decl(A) ::= temp(T) TRIGGER nm(B) dbnm(Z) trigger_time(C) */
/*                     trigger_event(D) */
/*                     ON fullname(E) foreach_clase(F) when_clause(G). { */
/*   sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, F, G, T); */
/*   A = (Z.n==0?B:Z); */
/* } */

/* %type trigger_time  {int} */
/* trigger_time(A) ::= BEFORE.      { A = TK_BEFORE; } */
/* trigger_time(A) ::= AFTER.       { A = TK_AFTER;  } */
/* trigger_time(A) ::= INSTEAD OF.  { A = TK_INSTEAD;} */
/* trigger_time(A) ::= .            { A = TK_BEFORE; } */

/* %type trigger_event {struct TrigEvent} */
/* %destructor trigger_event {sqlite3IdListDelete($$.b);} */
/* trigger_event(A) ::= DELETE|INSERT(OP).       {A.a = @OP; A.b = 0;} */
/* trigger_event(A) ::= UPDATE(OP).              {A.a = @OP; A.b = 0;} */
/* trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X;} */

/* %type foreach_clause {int} */
/* foreach_clause(A) ::= .                   { A = TK_ROW; } */
/* foreach_clause(A) ::= FOR EACH ROW.       { A = TK_ROW; } */
/* foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; } */

/* %type when_clause {Expr*} */
/* %destructor when_clause {sqlite3ExprDelete($$);} */
/* when_clause(A) ::= .             { A = 0; } */
/* when_clause(A) ::= WHEN expr(X). { A = X; } */

/* %type trigger_cmd_list {TriggerStep*} */
/* %destructor trigger_cmd_list {sqlite3DeleteTriggerStep($$);} */
/* trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. { */
/*   if( Y ){ */
/*     Y->pLast->pNext = X; */
/*   }else{ */
/*     Y = X; */
/*   } */
/*   Y->pLast = X; */
/*   A = Y; */
/* } */
/* trigger_cmd_list(A) ::= . { A = 0; } */

/* %type trigger_cmd {TriggerStep*} */
/* %destructor trigger_cmd {sqlite3DeleteTriggerStep($$);} */
/* // UPDATE */
/* trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z). */
/*                { A = sqlite3TriggerUpdateStep(&X, Y, Z, R); } */

/* // INSERT */
/* trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) */
/*                    VALUES LP itemlist(Y) RP. */
/*                {A = sqlite3TriggerInsertStep(&X, F, Y, 0, R);} */

/* trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) select(S). */
/*                {A = sqlite3TriggerInsertStep(&X, F, 0, S, R);} */

/* // DELETE */
/* trigger_cmd(A) ::= DELETE FROM nm(X) where_opt(Y). */
/*                {A = sqlite3TriggerDeleteStep(&X, Y);} */

/* // SELECT */
/* trigger_cmd(A) ::= select(X).  {A = sqlite3TriggerSelectStep(X); } */

/* // The special RAISE expression that may occur in trigger programs */
/* expr(A) ::= RAISE(X) LP IGNORE RP(Y).  { */
/*   A = sqlite3Expr(TK_RAISE, 0, 0, 0); */
/*   if( A ){ */
/*     A->iColumn = OE_Ignore; */
/*     sqlite3ExprSpan(A, &X, &Y); */
/*   } */
/* } */
/* expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y).  { */
/*   A = sqlite3Expr(TK_RAISE, 0, 0, &Z); */
/*   if( A ) { */
/*     A->iColumn = T; */
/*     sqlite3ExprSpan(A, &X, &Y); */
/*   } */
/* } */
%endif // !SQLITE_OMIT_TRIGGER

%type raisetype {int}
raisetype(A) ::= ROLLBACK.  {A = OE_Rollback;}
raisetype(A) ::= ABORT.     {A = OE_Abort;}
raisetype(A) ::= FAIL.      {A = OE_Fail;}

////////////////////////  DROP TRIGGER statement //////////////////////////////
%ifndef SQLITE_OMIT_TRIGGER
/* cmd ::= DROP TRIGGER fullname(X). { */
/*   sqlite3DropTrigger(pParse,X); */
/* } */
%endif // !SQLITE_OMIT_TRIGGER

//////////////////////// ATTACH DATABASE file AS name /////////////////////////
//cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). {
//  sqlite3Attach(pParse, F, D, K);
//}
//%type key_opt {Expr *}
//%destructor key_opt {sqlite3ExprDelete($$);}
//key_opt(A) ::= .                     { A = 0; }
//key_opt(A) ::= KEY expr(X).          { A = X; }

//database_kw_opt ::= DATABASE.
//database_kw_opt ::= .

//////////////////////// DETACH DATABASE name /////////////////////////////////
//cmd ::= DETACH database_kw_opt expr(D). {
//  sqlite3Detach(pParse, D);
//}

////////////////////////// REINDEX collation //////////////////////////////////
%ifndef SQLITE_OMIT_REINDEX
//cmd ::= REINDEX.                {sqlite3Reindex(pParse, 0, 0);}
//cmd ::= REINDEX nm(X) dbnm(Y).  {sqlite3Reindex(pParse, &X, &Y);}
%endif

/////////////////////////////////// ANALYZE ///////////////////////////////////
%ifndef SQLITE_OMIT_ANALYZE
//cmd ::= ANALYZE.                {sqlite3Analyze(pParse, 0, 0);}
//cmd ::= ANALYZE nm(X) dbnm(Y).  {sqlite3Analyze(pParse, &X, &Y);}
%endif

//////////////////////// ALTER TABLE table ... ////////////////////////////////
%ifndef SQLITE_OMIT_ALTERTABLE
/* cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { */
/*   sqlite3AlterRenameTable(pParse,X,&Z); */
/* } */
/* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). { */
/*   sqlite3AlterFinishAddColumn(pParse, &Y); */
/* } */
/* add_column_fullname ::= fullname(X). { */
/*   sqlite3AlterBeginAddColumn(pParse, X); */
/* } */
/* kwcolumn_opt ::= . */
/* kwcolumn_opt ::= COLUMNKW. */
%endif

//////////////////////// the SET statement ////////////////////////////////
cmd ::= SET variable_assignment_list. {
	  pParse->sflag |= SQL_FLAG_STMT;
}

cmd ::= SET NAMES ids.  {
	  pParse->sflag |= SQL_FLAG_STMT;
}

cmd ::= SET CHARACTER SET ids. {
	  pParse->sflag |= SQL_FLAG_STMT;
}

%type variable_assignment_list {ExprList*}
%destructor variable_assignment_list { }
variable_assignment_list ::= variable_assignment_list COMMA scope_qualifier user_var_name EQ expr. {
	  pParse->sflag |= SQL_FLAG_EXPR;
}

variable_assignment_list ::= scope_qualifier user_var_name EQ expr. {
	  pParse->sflag |= SQL_FLAG_EXPR;
}

// @@global or @@session or @@local
scope_qualifier ::= GLOBAL.
scope_qualifier ::= LOCAL.
scope_qualifier ::= SESSION.
scope_qualifier ::= VARIABLE1 DOT. { pParse->sflag |= SQL_FLAG_SCOPE; }
scope_qualifier ::= .

%type user_var_name {Token}
user_var_name(A) ::= ids(V). { A = V; }
user_var_name(A) ::= VARIABLE(V). { A = V; }

/////////////////// the SHOW statement /////////////////////////
cmd ::= show_databes.
cmd ::= show_tables.
cmd ::= show_table_status.
cmd ::= show_variables.
cmd ::= show_collation.

show_databes ::= SHOW DATABASES|SCHEMAS show_statement_pattern. {
		pParse->sflag |= SQL_FLAG_SHOW;
}

show_tables ::= SHOW full_keyword TABLES from_db show_statement_pattern. {
		pParse->sflag |= SQL_FLAG_SHOW;
}

show_table_status ::= SHOW TABLE STATUS from_db show_statement_pattern. {
		pParse->sflag |= SQL_FLAG_SHOW;
}

show_variables ::= SHOW scope_qualifier VARIABLES show_statement_pattern. {
		pParse->sflag |= SQL_FLAG_SHOW;
}

show_collation ::= SHOW COLLATION show_statement_pattern. {
		pParse->sflag |= SQL_FLAG_SHOW;
}

full_keyword ::= JOIN_KW.
full_keyword ::= .

show_statement_pattern ::= LIKE_KW STRING|ID.
show_statement_pattern ::= where_opt. {
}

from_db ::= .
from_db ::= FROM|IN nm.


text:
CC0 1.0 Universal

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").

Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.

For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.

Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;

ii. moral rights retained by the original author(s) and/or performer(s);

iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;

iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;

v. rights protecting the extraction, dissemination, use and reuse of data in a Work;

vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and

vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.

Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.

Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.

Limitations and Disclaimers.

a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.

b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.

c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.

d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.

For more information, please see http://creativecommons.org/publicdomain/zero/1.0

repo_name: filiplajszczak/awesome-zen-of-python

mime_type: text/plain


text:
# Awesome Zen of Python [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)

This is a collection of awesome resources related to
[the Zen of Python (PEP 20)](https://www.python.org/dev/peps/pep-0020/)
aka [The Python Way](https://mail.python.org/pipermail/python-list/1999-June/001951.html)
by [Tim Peters](https://en.wikipedia.org/wiki/Tim_Peters_(software_engineer))

    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    Flat is better than nested.
    Sparse is better than dense.
    Readability counts.
    Special cases aren't special enough to break the rules.
    Although practicality beats purity.
    Errors should never pass silently.
    Unless explicitly silenced.
    In the face of ambiguity, refuse the temptation to guess.
    There should be one-- and preferably only one:obvious way to do it.
    Although that way may not be obvious at first unless you're Dutch.
    Now is better than never.
    Although never is often better than *right* now.
    If the implementation is hard to explain, it's a bad idea.
    If the implementation is easy to explain, it may be a good idea.
    Namespaces are one honking great idea: let's do more of those!

### Articles
* [Chaitanya Baweja: Contemplating the Zen of Python](https://medium.com/better-programming/contemplating-the-zen-of-python-186722b833e5)
* [Radomir Dopieralski: Zen of Python Considered Harmful](http://sheep.art.pl/Zen%20of%20Python%20Considered%20Harmful)
* [Aamir Farooq, Vadim Zaytsev: There Is More Than One Way to Zen Your Python](https://dl.acm.org/doi/10.1145/3486608.3486909)
* [Jonathan M. Hammond: A Brief Analysis of “The Zen of Python”](https://medium.com/@Pythonidaer/a-brief-analysis-of-the-zen-of-python-2bfd3b76edbf)
* [Abdur-Rahmaan Janhangeer: The Zen Of Python Is A Joke And Here Is Why](https://dev.to/abdurrahmaanj/the-zen-of-python-is-a-joke-and-here-is-why-you-should-not-take-it-too-seriously-508d)
* [Abdur-Rahmaan Janhangeer: The Zen of Python: As Related by Masters](https://dev.to/abdurrahmaanj/the-zen-of-python-as-related-by-masters-1p9i)
* [Dima Kotik: Application Security and the Zen of Python](https://www.securityjourney.com/post/application-security-and-the-zen-of-python)
* [Łukasz Langa: Zen of Python, Again](https://lukasz.langa.pl/b6888f38-2e14-4595-a4fe-187fd0557a55/)
* [Adrienne Lowe: The Zen of Python Teams: COVID-19 edition](https://leadingwithspoons.com/2020/07/15/the-zen-of-python-teams-covid-19-edition/) [(see also the talk)](https://www.youtube.com/watch?v=WZ8FEB4J8-c)
* [Reinout van Rees: “Complex” and “complicated”](https://reinout.vanrees.org/weblog/2015/12/21/complex-complicated.html)
* [Al Sweigart: The Zen of Python, Explained](https://inventwithpython.com/blog/2018/08/17/the-zen-of-python-explained/)
* [Moshe Zadka: Meditations on the Zen of Python [that's summary, individual articles below]](https://orbifold.xyz/zen-of-python.html)
  * [Why your Python code needs to be beautiful and explicit](https://opensource.com/article/19/12/zen-python-beauty-clarity)
  * [Prioritizing simplicity in your Python code](https://opensource.com/article/19/12/zen-python-simplicity-complexity)
  * [Why your Python code should be flat and sparse](https://opensource.com/article/19/12/zen-python-flat-sparse)
  * [Making trade-offs when writing Python code](https://opensource.com/article/19/12/zen-python-trade-offs)
  * [How the Zen of Python handles errors](https://opensource.com/article/19/12/zen-python-errors)
  * [The importance of consistency in your Python code](https://opensource.com/article/19/12/zen-python-consistency)
  * [The Zen of Python: Why timing is everything](https://opensource.com/article/19/12/zen-python-timeliness)
  * [How to tell if implementing your Python code is a good idea](https://opensource.com/article/19/12/zen-python-implementation)
  * [Namespaces are the shamash candle of the Zen of Python](https://opensource.com/article/19/12/zen-python-namespaces)

### Talks
* [Raymond Hettinger: Beyond PEP 8 -- Best practices for beautiful intelligible code](https://www.youtube.com/watch?v=wf-BqAjZb8M)
* [Łukasz Langa: Life Is Better Painted Black](https://www.youtube.com/watch?v=esZLCuWs_2Y)
* [Adrienne Lowe: The Zen of Python for Teams](https://www.youtube.com/watch?v=WZ8FEB4J8-c) [(see also the article)](https://leadingwithspoons.com/2020/07/15/the-zen-of-python-teams-covid-19-edition/)
* [Justin Mayer: Zen of Python Dependency Management](https://www.youtube.com/watch?v=asL0dbN6pAY)
* [Christopher Neugebauer: Practicality Beats Purity: The Zen of Python’s Escape Hatch?](https://youtu.be/XU9_3AlCy84)
* [Rudolf Olah: Python as a philosophy](https://www.youtube.com/watch?v=zkjYOKLvZko)
* [Kenneth Reitz: Python For Humans](https://www.youtube.com/watch?v=Y97D8j6CAog)

### Tools
* [Black - The uncompromising Python code formatter](https://github.com/psf/black)
* [Obey your Zen with wemake-python-styleguide](https://github.com/wemake-services/wemake-python-styleguide)

### Other
* [Fundamental philosophies Django’s developers have used in creating the framework](https://docs.djangoproject.com/en/dev/misc/design-philosophies/)
* [Yannis Rizos: Is the 14th line of The Zen of Python a reference to Dijkstra? (stackoverflow answer)](https://softwareengineering.stackexchange.com/a/148794)
* [Bug #3364: I'm afraid you missed the joke](https://bugs.python.org/issue3364)

###### And now for something completely different
* [import that](https://github.com/pydanny/that)
* [PEP 8 song, written and performed by Leon Sandøy, A.K.A. lemonsaurus; music and melody from Mad World by Roland Orzabal](https://www.youtube.com/watch?v=hgI0p1zf31k)
* [Zen of git](https://tdhopper.com/blog/zen-of-git/)
* [Zen of Python song, lyrics by Tim Peters 1999, music and arrangement by Barry Warsaw 2020](https://www.youtube.com/watch?v=i6G6dmVJy74)


text:
<?xml version="1.0"?>

<!DOCTYPE rdf:RDF [
    <!ENTITY owl "http://www.w3.org/2002/07/owl#" >
    <!ENTITY obo "http://purl.obolibrary.org/obo/" >
    <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
    <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
    <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
    <!ENTITY oboInOwl "http://www.geneontology.org/formats/oboInOwl#" >
]>

<rdf:RDF xmlns="http://purl.obolibrary.org/obo/x-bfo.owl#"
     xml:base="http://purl.obolibrary.org/obo/x-bfo.owl"
     xmlns:obo="http://purl.obolibrary.org/obo/"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:oboInOwl="http://www.geneontology.org/formats/oboInOwl#">
    <owl:Ontology rdf:about="http://purl.obolibrary.org/obo/upheno/metazoa.owl">
        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/upheno/vertebrate.owl"/>

        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/uberon/bridge/cl-bridge-to-wbbt.owl"/>
        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/uberon/bridge/uberon-bridge-to-wbbt.owl"/>
        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/uberon/bridge/cl-bridge-to-fbbt.owl"/>
        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/uberon/bridge/uberon-bridge-to-fbbt.owl"/>

        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/upheno/imports/fbbt_phenotype.owl"/>
        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/dpo.owl"/>
        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/wbphenotype.owl"/>

        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/upheno/upheno_root_alignments.owl"/>
    </owl:Ontology>
</rdf:RDF>

<!-- Generated by the OWL API (version 3.4.2) http://owlapi.sourceforge.net -->

repo_name: obophenotype/upheno

repo_language: Makefile


text:
Prefix(:=<http://purl.obolibrary.org/obo/upheno.owl/>)
Prefix(dc:=<http://purl.org/dc/elements/1.1/>)
Prefix(owl:=<http://www.w3.org/2002/07/owl#>)
Prefix(rdf:=<http://www.w3.org/1999/02/22-rdf-syntax-ns#>)
Prefix(xml:=<http://www.w3.org/XML/1998/namespace>)
Prefix(xsd:=<http://www.w3.org/2001/XMLSchema#>)
Prefix(rdfs:=<http://www.w3.org/2000/01/rdf-schema#>)

Ontology(<http://purl.obolibrary.org/obo/upheno/upheno_root_alignments.owl>

SubClassOf(<http://purl.obolibrary.org/obo/HP_0000118> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/MP_0000001> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/WBPhenotype_0000886> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/XPO_00000000> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/PLANP_00000000> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/ZP_00000000> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/FBcv_0001347> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/DDPHENO_0010000> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/MGPO_0001001> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
SubClassOf(<http://purl.obolibrary.org/obo/PHIPO_0000505> <http://purl.obolibrary.org/obo/UPHENO_0001001>)
)


text:
<?xml version="1.0"?>
<rdf:RDF xmlns="http://purl.obolibrary.org/obo/x-bfo.owl#"
     xml:base="http://purl.obolibrary.org/obo/x-bfo.owl"
     xmlns:obo="http://purl.obolibrary.org/obo/"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:oboInOwl="http://www.geneontology.org/formats/oboInOwl#">
    <owl:Ontology rdf:about="http://purl.obolibrary.org/obo/upheno/mp-hp.owl">
        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/mp.owl"/>
        <owl:imports rdf:resource="http://purl.obolibrary.org/obo/hp.owl"/>
    </owl:Ontology>
</rdf:RDF>

<!-- Generated by the OWL API (version 0.5.1-SNAPSHOT) http://owlapi.sourceforge.net -->


text:
pipeline {
	agent any

	// In additional to manual runs, trigger somewhere at midnight to
	// give us the max time in a day to get things right without
	// disrupting people.

	//triggers {
		// Nightly, between 8pm-12:59pm PDT.
	//	cron('H H(20-23) 1-31 * *')
	//}

	environment {

		///
		/// Automatic run variables.
		// Acquire dates and day to beginning of run.

		START_DATE = sh (
			script: 'date +%Y-%m-%d',
			returnStdout: true
		).trim()

		START_DAY = sh (
			script: 'date +%A',
			returnStdout: true
		).trim()

		///
		/// Internal run variables.
		///

		// What is the file "namespace" of the ontology--used for
		// finding artifacts.
		ONTOLOGY_FILE_HINT = 'upheno'
		// Ontology repo information.
		TARGET_ONTOLOGY_BRANCH = 'master'
		TARGET_ONTOLOGY_URL = 'https://github.com/obophenotype/upheno.git'
		// The people to call when things go bad or go well. It is a
		// comma-space "separated" string.
		TARGET_ADMIN_EMAILS = 'nicolas.matentzoglu@gmail.com'
		TARGET_SUCCESS_EMAILS = 'nicolas.matentzoglu@gmail.com'
		// This variable should typically be 'TRUE', which will cause
		// some additional basic checks to be made. There are some
		// very exotic cases where these check may need to be skipped
		// for a run, in that case this variable is set to 'FALSE'.
		WE_ARE_BEING_SAFE_P = 'TRUE'
		// Control make to get through our loads faster if
		// possible.
		MAKECMD = 'make'
		// Control the ROBOT environment.
		ROBOT_JAVA_ARGS = '-Xmx120G'
	}
	options{
		//timestamps()
		buildDiscarder(logRotator(numToKeepStr: '14'))
	}
	stages {
	// Very first: check branch sanity and pause for a minute to
	// give a chance to cancel; clean the workspace before use.

		stage('Ready and clean') {
			steps {
			// Give us a minute to cancel if we want.
			//sleep time: 1, unit: 'MINUTES'
			cleanWs deleteDirs: true, disableDeferredWipeout: true
			}
		}

		stage('Initialize') {
			steps {
				// Upgrading docker image
				sh 'docker pull obolibrary/odkfull:latest'
				// Start preparing environment.
				sh 'env > env.txt'
				sh 'echo $BRANCH_NAME > branch.txt'
				sh 'echo "$BRANCH_NAME"'
				sh 'cat env.txt'
				sh 'cat branch.txt'
				sh 'echo $START_DAY > dow.txt'
				sh 'echo "$START_DAY"'
				archiveArtifacts artifacts: "env.txt"
			}
		}

		stage('Produce ontology') {
			agent {
				docker {
					image 'obolibrary/odkfull:latest'
					// Reset Jenkins Docker agent default to original
					// root.
					//args '-u root:root -v /foo:/work -e ROBOT_JAVA_ARGS=-Xmx120G'
					args '-u root:root'
					alwaysPull true
				}
			}
			steps {
				// Create a relative working directory and setup our
				// data environment.
				sh 'env > env.txt'
				sh 'cat env.txt'
				sh 'pwd'
				sh 'ls -AlF'
				sh 'ls -AlF /'
				dir('.') {
					git branch: TARGET_ONTOLOGY_BRANCH,
						url: TARGET_ONTOLOGY_URL

					// Default namespace.
					// sh 'OBO=http://purl.obolibrary.org/obo'
						retry(2){
							sh 'pwd'
							sh 'ls'
							sh 'env > env.txt'
							sh 'cat env.txt'
							sh 'make all_mappings -B'
							sh 'make mp-hp-view.owl -B'
					}

					// Move the products to somewhere "safe".
					archiveArtifacts artifacts: "*.owl",
					onlyIfSuccessful: true
					archiveArtifacts artifacts: "mappings/*.tsv",
					onlyIfSuccessful: true

					// Now that the files are safely away onto skyhook for
					// debugging, test for the core dump.
					script {
						if( WE_ARE_BEING_SAFE_P == 'TRUE' ){
							def found_core_dump_p = fileExists 'target/core_dump.owl'
							if( found_core_dump_p ){
								error 'ROBOT core dump detected--bailing out.'
							}
						}
					}
				}
			}
		}

		// stage('Archive') {
		//     when { anyOf { branch 'release'; branch 'snapshot'; branch 'master' } }
		//     steps {
		// 	// Stanza to push to real file server.
		//     }
		// }
	}

	post {
		// Let's let our people know if things go well.
		success {
			script {
			echo "There has been a successful run of the ${env.BRANCH_NAME} pipeline."
			}
		}

		// Let's let our internal people know if things change.
		changed {
			echo "There has been a change in the ${env.BRANCH_NAME} pipeline."
		}
	// Let's let our internal people know if things go badly.
		failure {
			echo "There has been a failure in the ${env.BRANCH_NAME} pipeline."
			//mail bcc: '', body: "There has been a pipeline failure in ${env.BRANCH_NAME}. Please see: ${env.JOB_DISPLAY_URL}", cc: '', from: '', replyTo: '', subject: "Pipeline FAIL for ${env.ONTOLOGY_FILE_HINT} on ${env.BRANCH_NAME}", to: "${TARGET_ADMIN_EMAILS}"
		}
	}
}


text:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalog prefer="public" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/" uri="imports/upheno-preimporter.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/go.owl" uri="mirror/go.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/hsapdv.owl" uri="imports/hsapdv_import.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/hp-mp/mp_hp-align-equiv.owl" uri="hp-mp/mp_hp-align-equiv.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/nbo.owl" uri="mirror/nbo.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/temporary/5140a674-088d-4b48-83e3-761a078507e3" uri="imports/ro_extra.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/uberon.owl" uri="mirror/uberon.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/uberon/ext.owl" uri="mirror/uberon-ext.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/fbbt_import.owl" uri="imports/fbbt_import.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/fbbt_phenotype.owl" uri="imports/fbbt_phenotype.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/go_import.owl" uri="imports/go_import.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/go_phenotype.owl" uri="imports/go_phenotype.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/imports/wbbt_import.owl" uri="imports/wbbt_import.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/mpath_phenotype.owl" uri="imports/mpath_phenotype.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/nbo_import.owl" uri="imports/nbo_import.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/nbo_phenotype.owl" uri="imports/nbo_phenotype.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/ro_import.owl" uri="imports/ro_import.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/so_import.owl" uri="imports/so_import.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/uberon_import.owl" uri="imports/uberon_import.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/imports/wbbt_phenotype.owl" uri="imports/wbbt_phenotype.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="http://purl.obolibrary.org/obo/upheno/wbphenotype/wbphenotype-equivalence-axioms.owl" uri="wbphenotype/wbphenotype-equivalence-axioms.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="duplicate:http://purl.obolibrary.org/obo/x-bfo.owl" uri="mammal.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="duplicate:http://purl.obolibrary.org/obo/x-bfo.owl" uri="metazoa.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="duplicate:http://purl.obolibrary.org/obo/x-bfo.owl" uri="vertebrate.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="shadowed:http://purl.obolibrary.org/obo/x-bfo.owl" uri="dpo/dpo-bridge.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="shadowed:http://purl.obolibrary.org/obo/x-bfo.owl" uri="imports/extra.owl"/>
        <uri id="Automatically generated entry, Timestamp=1455054043267" name="shadowed:http://purl.obolibrary.org/obo/x-bfo.owl" uri="imports/grouping_phenotypes.owl"/>
</catalog>


text:
#!/bin/sh
# Wrapper script for docker.
#
# This is used primarily for wrapping the GNU Make workflow.
# Instead of typing "make TARGET", type "./run.sh make TARGET".
# This will run the make workflow within a docker container.
#
# The assumption is that you are working in the src/ontology folder;
# we therefore map the whole repo (../..) to a docker volume.
#
# See README-editors.md for more details.
docker run -v $PWD/:/work -w /work/ -e ROBOT_JAVA_ARGS='-Xmx8G' --rm -ti obolibrary/odkfull "$@"