Back to index

php5  5.3.10
tokenize.c
Go to the documentation of this file.
00001 /*
00002 ** 2001 September 15
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** An tokenizer for SQL
00013 **
00014 ** This file contains C code that splits an SQL input string up into
00015 ** individual tokens and sends those tokens one-by-one over to the
00016 ** parser for analysis.
00017 **
00018 ** $Id: tokenize.c 195361 2005-09-07 15:11:33Z iliaa $
00019 */
00020 #include "sqliteInt.h"
00021 #include "os.h"
00022 #include <ctype.h>
00023 #include <stdlib.h>
00024 
00025 /*
00026 ** All the keywords of the SQL language are stored as in a hash
00027 ** table composed of instances of the following structure.
00028 */
00029 typedef struct Keyword Keyword;
00030 struct Keyword {
00031   char *zName;             /* The keyword name */
00032   u8 tokenType;            /* Token value for this keyword */
00033   u8 len;                  /* Length of this keyword */
00034   u8 iNext;                /* Index in aKeywordTable[] of next with same hash */
00035 };
00036 
00037 /*
00038 ** These are the keywords
00039 */
00040 static Keyword aKeywordTable[] = {
00041   { "ABORT",             TK_ABORT,        },
00042   { "AFTER",             TK_AFTER,        },
00043   { "ALL",               TK_ALL,          },
00044   { "AND",               TK_AND,          },
00045   { "AS",                TK_AS,           },
00046   { "ASC",               TK_ASC,          },
00047   { "ATTACH",            TK_ATTACH,       },
00048   { "BEFORE",            TK_BEFORE,       },
00049   { "BEGIN",             TK_BEGIN,        },
00050   { "BETWEEN",           TK_BETWEEN,      },
00051   { "BY",                TK_BY,           },
00052   { "CASCADE",           TK_CASCADE,      },
00053   { "CASE",              TK_CASE,         },
00054   { "CHECK",             TK_CHECK,        },
00055   { "CLUSTER",           TK_CLUSTER,      },
00056   { "COLLATE",           TK_COLLATE,      },
00057   { "COMMIT",            TK_COMMIT,       },
00058   { "CONFLICT",          TK_CONFLICT,     },
00059   { "CONSTRAINT",        TK_CONSTRAINT,   },
00060   { "COPY",              TK_COPY,         },
00061   { "CREATE",            TK_CREATE,       },
00062   { "CROSS",             TK_JOIN_KW,      },
00063   { "DATABASE",          TK_DATABASE,     },
00064   { "DEFAULT",           TK_DEFAULT,      },
00065   { "DEFERRED",          TK_DEFERRED,     },
00066   { "DEFERRABLE",        TK_DEFERRABLE,   },
00067   { "DELETE",            TK_DELETE,       },
00068   { "DELIMITERS",        TK_DELIMITERS,   },
00069   { "DESC",              TK_DESC,         },
00070   { "DETACH",            TK_DETACH,       },
00071   { "DISTINCT",          TK_DISTINCT,     },
00072   { "DROP",              TK_DROP,         },
00073   { "END",               TK_END,          },
00074   { "EACH",              TK_EACH,         },
00075   { "ELSE",              TK_ELSE,         },
00076   { "EXCEPT",            TK_EXCEPT,       },
00077   { "EXPLAIN",           TK_EXPLAIN,      },
00078   { "FAIL",              TK_FAIL,         },
00079   { "FOR",               TK_FOR,          },
00080   { "FOREIGN",           TK_FOREIGN,      },
00081   { "FROM",              TK_FROM,         },
00082   { "FULL",              TK_JOIN_KW,      },
00083   { "GLOB",              TK_GLOB,         },
00084   { "GROUP",             TK_GROUP,        },
00085   { "HAVING",            TK_HAVING,       },
00086   { "IGNORE",            TK_IGNORE,       },
00087   { "IMMEDIATE",         TK_IMMEDIATE,    },
00088   { "IN",                TK_IN,           },
00089   { "INDEX",             TK_INDEX,        },
00090   { "INITIALLY",         TK_INITIALLY,    },
00091   { "INNER",             TK_JOIN_KW,      },
00092   { "INSERT",            TK_INSERT,       },
00093   { "INSTEAD",           TK_INSTEAD,      },
00094   { "INTERSECT",         TK_INTERSECT,    },
00095   { "INTO",              TK_INTO,         },
00096   { "IS",                TK_IS,           },
00097   { "ISNULL",            TK_ISNULL,       },
00098   { "JOIN",              TK_JOIN,         },
00099   { "KEY",               TK_KEY,          },
00100   { "LEFT",              TK_JOIN_KW,      },
00101   { "LIKE",              TK_LIKE,         },
00102   { "LIMIT",             TK_LIMIT,        },
00103   { "MATCH",             TK_MATCH,        },
00104   { "NATURAL",           TK_JOIN_KW,      },
00105   { "NOT",               TK_NOT,          },
00106   { "NOTNULL",           TK_NOTNULL,      },
00107   { "NULL",              TK_NULL,         },
00108   { "OF",                TK_OF,           },
00109   { "OFFSET",            TK_OFFSET,       },
00110   { "ON",                TK_ON,           },
00111   { "OR",                TK_OR,           },
00112   { "ORDER",             TK_ORDER,        },
00113   { "OUTER",             TK_JOIN_KW,      },
00114   { "PRAGMA",            TK_PRAGMA,       },
00115   { "PRIMARY",           TK_PRIMARY,      },
00116   { "RAISE",             TK_RAISE,        },
00117   { "REFERENCES",        TK_REFERENCES,   },
00118   { "REPLACE",           TK_REPLACE,      },
00119   { "RESTRICT",          TK_RESTRICT,     },
00120   { "RIGHT",             TK_JOIN_KW,      },
00121   { "ROLLBACK",          TK_ROLLBACK,     },
00122   { "ROW",               TK_ROW,          },
00123   { "SELECT",            TK_SELECT,       },
00124   { "SET",               TK_SET,          },
00125   { "STATEMENT",         TK_STATEMENT,    },
00126   { "TABLE",             TK_TABLE,        },
00127   { "TEMP",              TK_TEMP,         },
00128   { "TEMPORARY",         TK_TEMP,         },
00129   { "THEN",              TK_THEN,         },
00130   { "TRANSACTION",       TK_TRANSACTION,  },
00131   { "TRIGGER",           TK_TRIGGER,      },
00132   { "UNION",             TK_UNION,        },
00133   { "UNIQUE",            TK_UNIQUE,       },
00134   { "UPDATE",            TK_UPDATE,       },
00135   { "USING",             TK_USING,        },
00136   { "VACUUM",            TK_VACUUM,       },
00137   { "VALUES",            TK_VALUES,       },
00138   { "VIEW",              TK_VIEW,         },
00139   { "WHEN",              TK_WHEN,         },
00140   { "WHERE",             TK_WHERE,        },
00141 };
00142 
00143 /*
00144 ** This is the hash table
00145 */
00146 #define KEY_HASH_SIZE 101
00147 static u8 aiHashTable[KEY_HASH_SIZE];
00148 
00149 
00150 /*
00151 ** This function looks up an identifier to determine if it is a
00152 ** keyword.  If it is a keyword, the token code of that keyword is 
00153 ** returned.  If the input is not a keyword, TK_ID is returned.
00154 */
00155 int sqliteKeywordCode(const char *z, int n){
00156   int h, i;
00157   Keyword *p;
00158   static char needInit = 1;
00159   if( needInit ){
00160     /* Initialize the keyword hash table */
00161     sqliteOsEnterMutex();
00162     if( needInit ){
00163       int nk;
00164       nk = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]);
00165       for(i=0; i<nk; i++){
00166         aKeywordTable[i].len = strlen(aKeywordTable[i].zName);
00167         h = sqliteHashNoCase(aKeywordTable[i].zName, aKeywordTable[i].len);
00168         h %= KEY_HASH_SIZE;
00169         aKeywordTable[i].iNext = aiHashTable[h];
00170         aiHashTable[h] = i+1;
00171       }
00172       needInit = 0;
00173     }
00174     sqliteOsLeaveMutex();
00175   }
00176   h = sqliteHashNoCase(z, n) % KEY_HASH_SIZE;
00177   for(i=aiHashTable[h]; i; i=p->iNext){
00178     p = &aKeywordTable[i-1];
00179     if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){
00180       return p->tokenType;
00181     }
00182   }
00183   return TK_ID;
00184 }
00185 
00186 
00187 /*
00188 ** If X is a character that can be used in an identifier and
00189 ** X&0x80==0 then isIdChar[X] will be 1.  If X&0x80==0x80 then
00190 ** X is always an identifier character.  (Hence all UTF-8
00191 ** characters can be part of an identifier).  isIdChar[X] will
00192 ** be 0 for every character in the lower 128 ASCII characters
00193 ** that cannot be used as part of an identifier.
00194 **
00195 ** In this implementation, an identifier can be a string of
00196 ** alphabetic characters, digits, and "_" plus any character
00197 ** with the high-order bit set.  The latter rule means that
00198 ** any sequence of UTF-8 characters or characters taken from
00199 ** an extended ISO8859 character set can form an identifier.
00200 */
00201 static const char isIdChar[] = {
00202 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
00203     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */
00204     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
00205     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
00206     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
00207     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
00208     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
00209     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 6x */
00210     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */
00211 };
00212 
00213 
00214 /*
00215 ** Return the length of the token that begins at z[0]. 
00216 ** Store the token type in *tokenType before returning.
00217 */
00218 static int sqliteGetToken(const unsigned char *z, int *tokenType){
00219   int i;
00220   switch( *z ){
00221     case ' ': case '\t': case '\n': case '\f': case '\r': {
00222       for(i=1; isspace(z[i]); i++){}
00223       *tokenType = TK_SPACE;
00224       return i;
00225     }
00226     case '-': {
00227       if( z[1]=='-' ){
00228         for(i=2; z[i] && z[i]!='\n'; i++){}
00229         *tokenType = TK_COMMENT;
00230         return i;
00231       }
00232       *tokenType = TK_MINUS;
00233       return 1;
00234     }
00235     case '(': {
00236       *tokenType = TK_LP;
00237       return 1;
00238     }
00239     case ')': {
00240       *tokenType = TK_RP;
00241       return 1;
00242     }
00243     case ';': {
00244       *tokenType = TK_SEMI;
00245       return 1;
00246     }
00247     case '+': {
00248       *tokenType = TK_PLUS;
00249       return 1;
00250     }
00251     case '*': {
00252       *tokenType = TK_STAR;
00253       return 1;
00254     }
00255     case '/': {
00256       if( z[1]!='*' || z[2]==0 ){
00257         *tokenType = TK_SLASH;
00258         return 1;
00259       }
00260       for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){}
00261       if( z[i] ) i++;
00262       *tokenType = TK_COMMENT;
00263       return i;
00264     }
00265     case '%': {
00266       *tokenType = TK_REM;
00267       return 1;
00268     }
00269     case '=': {
00270       *tokenType = TK_EQ;
00271       return 1 + (z[1]=='=');
00272     }
00273     case '<': {
00274       if( z[1]=='=' ){
00275         *tokenType = TK_LE;
00276         return 2;
00277       }else if( z[1]=='>' ){
00278         *tokenType = TK_NE;
00279         return 2;
00280       }else if( z[1]=='<' ){
00281         *tokenType = TK_LSHIFT;
00282         return 2;
00283       }else{
00284         *tokenType = TK_LT;
00285         return 1;
00286       }
00287     }
00288     case '>': {
00289       if( z[1]=='=' ){
00290         *tokenType = TK_GE;
00291         return 2;
00292       }else if( z[1]=='>' ){
00293         *tokenType = TK_RSHIFT;
00294         return 2;
00295       }else{
00296         *tokenType = TK_GT;
00297         return 1;
00298       }
00299     }
00300     case '!': {
00301       if( z[1]!='=' ){
00302         *tokenType = TK_ILLEGAL;
00303         return 2;
00304       }else{
00305         *tokenType = TK_NE;
00306         return 2;
00307       }
00308     }
00309     case '|': {
00310       if( z[1]!='|' ){
00311         *tokenType = TK_BITOR;
00312         return 1;
00313       }else{
00314         *tokenType = TK_CONCAT;
00315         return 2;
00316       }
00317     }
00318     case ',': {
00319       *tokenType = TK_COMMA;
00320       return 1;
00321     }
00322     case '&': {
00323       *tokenType = TK_BITAND;
00324       return 1;
00325     }
00326     case '~': {
00327       *tokenType = TK_BITNOT;
00328       return 1;
00329     }
00330     case '\'': case '"': {
00331       int delim = z[0];
00332       for(i=1; z[i]; i++){
00333         if( z[i]==delim ){
00334           if( z[i+1]==delim ){
00335             i++;
00336           }else{
00337             break;
00338           }
00339         }
00340       }
00341       if( z[i] ) i++;
00342       *tokenType = TK_STRING;
00343       return i;
00344     }
00345     case '.': {
00346       *tokenType = TK_DOT;
00347       return 1;
00348     }
00349     case '0': case '1': case '2': case '3': case '4':
00350     case '5': case '6': case '7': case '8': case '9': {
00351       *tokenType = TK_INTEGER;
00352       for(i=1; isdigit(z[i]); i++){}
00353       if( z[i]=='.' && isdigit(z[i+1]) ){
00354         i += 2;
00355         while( isdigit(z[i]) ){ i++; }
00356         *tokenType = TK_FLOAT;
00357       }
00358       if( (z[i]=='e' || z[i]=='E') &&
00359            ( isdigit(z[i+1]) 
00360             || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2]))
00361            )
00362       ){
00363         i += 2;
00364         while( isdigit(z[i]) ){ i++; }
00365         *tokenType = TK_FLOAT;
00366       }
00367       return i;
00368     }
00369     case '[': {
00370       for(i=1; z[i] && z[i-1]!=']'; i++){}
00371       *tokenType = TK_ID;
00372       return i;
00373     }
00374     case '?': {
00375       *tokenType = TK_VARIABLE;
00376       return 1;
00377     }
00378     default: {
00379       if( (*z&0x80)==0 && !isIdChar[*z] ){
00380         break;
00381       }
00382       for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){}
00383       *tokenType = sqliteKeywordCode((char*)z, i);
00384       return i;
00385     }
00386   }
00387   *tokenType = TK_ILLEGAL;
00388   return 1;
00389 }
00390 
00391 /*
00392 ** Run the parser on the given SQL string.  The parser structure is
00393 ** passed in.  An SQLITE_ status code is returned.  If an error occurs
00394 ** and pzErrMsg!=NULL then an error message might be written into 
00395 ** memory obtained from malloc() and *pzErrMsg made to point to that
00396 ** error message.  Or maybe not.
00397 */
00398 int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
00399   int nErr = 0;
00400   int i;
00401   void *pEngine;
00402   int tokenType;
00403   int lastTokenParsed = -1;
00404   sqlite *db = pParse->db;
00405   extern void *sqliteParserAlloc(void*(*)(int));
00406   extern void sqliteParserFree(void*, void(*)(void*));
00407   extern int sqliteParser(void*, int, Token, Parse*);
00408 
00409   db->flags &= ~SQLITE_Interrupt;
00410   pParse->rc = SQLITE_OK;
00411   i = 0;
00412   pEngine = sqliteParserAlloc((void*(*)(int))malloc);
00413   if( pEngine==0 ){
00414     sqliteSetString(pzErrMsg, "out of memory", (char*)0);
00415     return 1;
00416   }
00417   pParse->sLastToken.dyn = 0;
00418   pParse->zTail = zSql;
00419   while( sqlite_malloc_failed==0 && zSql[i]!=0 ){
00420     assert( i>=0 );
00421     pParse->sLastToken.z = &zSql[i];
00422     assert( pParse->sLastToken.dyn==0 );
00423     pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
00424     i += pParse->sLastToken.n;
00425     switch( tokenType ){
00426       case TK_SPACE:
00427       case TK_COMMENT: {
00428         if( (db->flags & SQLITE_Interrupt)!=0 ){
00429           pParse->rc = SQLITE_INTERRUPT;
00430           sqliteSetString(pzErrMsg, "interrupt", (char*)0);
00431           goto abort_parse;
00432         }
00433         break;
00434       }
00435       case TK_ILLEGAL: {
00436         sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, 
00437            pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0);
00438         nErr++;
00439         goto abort_parse;
00440       }
00441       case TK_SEMI: {
00442         pParse->zTail = &zSql[i];
00443         /* Fall thru into the default case */
00444       }
00445       default: {
00446         sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse);
00447         lastTokenParsed = tokenType;
00448         if( pParse->rc!=SQLITE_OK ){
00449           goto abort_parse;
00450         }
00451         break;
00452       }
00453     }
00454   }
00455 abort_parse:
00456   if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
00457     if( lastTokenParsed!=TK_SEMI ){
00458       sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
00459       pParse->zTail = &zSql[i];
00460     }
00461     sqliteParser(pEngine, 0, pParse->sLastToken, pParse);
00462   }
00463   sqliteParserFree(pEngine, free);
00464   if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
00465     sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc),
00466                     (char*)0);
00467   }
00468   if( pParse->zErrMsg ){
00469     if( pzErrMsg && *pzErrMsg==0 ){
00470       *pzErrMsg = pParse->zErrMsg;
00471     }else{
00472       sqliteFree(pParse->zErrMsg);
00473     }
00474     pParse->zErrMsg = 0;
00475     if( !nErr ) nErr++;
00476   }
00477   if( pParse->pVdbe && pParse->nErr>0 ){
00478     sqliteVdbeDelete(pParse->pVdbe);
00479     pParse->pVdbe = 0;
00480   }
00481   if( pParse->pNewTable ){
00482     sqliteDeleteTable(pParse->db, pParse->pNewTable);
00483     pParse->pNewTable = 0;
00484   }
00485   if( pParse->pNewTrigger ){
00486     sqliteDeleteTrigger(pParse->pNewTrigger);
00487     pParse->pNewTrigger = 0;
00488   }
00489   if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
00490     pParse->rc = SQLITE_ERROR;
00491   }
00492   return nErr;
00493 }
00494 
00495 /*
00496 ** Token types used by the sqlite_complete() routine.  See the header
00497 ** comments on that procedure for additional information.
00498 */
00499 #define tkEXPLAIN 0
00500 #define tkCREATE  1
00501 #define tkTEMP    2
00502 #define tkTRIGGER 3
00503 #define tkEND     4
00504 #define tkSEMI    5
00505 #define tkWS      6
00506 #define tkOTHER   7
00507 
00508 /*
00509 ** Return TRUE if the given SQL string ends in a semicolon.
00510 **
00511 ** Special handling is require for CREATE TRIGGER statements.
00512 ** Whenever the CREATE TRIGGER keywords are seen, the statement
00513 ** must end with ";END;".
00514 **
00515 ** This implementation uses a state machine with 7 states:
00516 **
00517 **   (0) START     At the beginning or end of an SQL statement.  This routine
00518 **                 returns 1 if it ends in the START state and 0 if it ends
00519 **                 in any other state.
00520 **
00521 **   (1) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of 
00522 **                 a statement.
00523 **
00524 **   (2) CREATE    The keyword CREATE has been seen at the beginning of a
00525 **                 statement, possibly preceeded by EXPLAIN and/or followed by
00526 **                 TEMP or TEMPORARY
00527 **
00528 **   (3) NORMAL    We are in the middle of statement which ends with a single
00529 **                 semicolon.
00530 **
00531 **   (4) TRIGGER   We are in the middle of a trigger definition that must be
00532 **                 ended by a semicolon, the keyword END, and another semicolon.
00533 **
00534 **   (5) SEMI      We've seen the first semicolon in the ";END;" that occurs at
00535 **                 the end of a trigger definition.
00536 **
00537 **   (6) END       We've seen the ";END" of the ";END;" that occurs at the end
00538 **                 of a trigger difinition.
00539 **
00540 ** Transitions between states above are determined by tokens extracted
00541 ** from the input.  The following tokens are significant:
00542 **
00543 **   (0) tkEXPLAIN   The "explain" keyword.
00544 **   (1) tkCREATE    The "create" keyword.
00545 **   (2) tkTEMP      The "temp" or "temporary" keyword.
00546 **   (3) tkTRIGGER   The "trigger" keyword.
00547 **   (4) tkEND       The "end" keyword.
00548 **   (5) tkSEMI      A semicolon.
00549 **   (6) tkWS        Whitespace
00550 **   (7) tkOTHER     Any other SQL token.
00551 **
00552 ** Whitespace never causes a state transition and is always ignored.
00553 */
00554 int sqlite_complete(const char *zSql){
00555   u8 state = 0;   /* Current state, using numbers defined in header comment */
00556   u8 token;       /* Value of the next token */
00557 
00558   /* The following matrix defines the transition from one state to another
00559   ** according to what token is seen.  trans[state][token] returns the
00560   ** next state.
00561   */
00562   static const u8 trans[7][8] = {
00563                      /* Token:                                                */
00564      /* State:       **  EXPLAIN  CREATE  TEMP  TRIGGER  END  SEMI  WS  OTHER */
00565      /* 0   START: */ {       1,      2,    3,       3,   3,    0,  0,     3, },
00566      /* 1 EXPLAIN: */ {       3,      2,    3,       3,   3,    0,  1,     3, },
00567      /* 2  CREATE: */ {       3,      3,    2,       4,   3,    0,  2,     3, },
00568      /* 3  NORMAL: */ {       3,      3,    3,       3,   3,    0,  3,     3, },
00569      /* 4 TRIGGER: */ {       4,      4,    4,       4,   4,    5,  4,     4, },
00570      /* 5    SEMI: */ {       4,      4,    4,       4,   6,    5,  5,     4, },
00571      /* 6     END: */ {       4,      4,    4,       4,   4,    0,  6,     4, },
00572   };
00573 
00574   while( *zSql ){
00575     switch( *zSql ){
00576       case ';': {  /* A semicolon */
00577         token = tkSEMI;
00578         break;
00579       }
00580       case ' ':
00581       case '\r':
00582       case '\t':
00583       case '\n':
00584       case '\f': {  /* White space is ignored */
00585         token = tkWS;
00586         break;
00587       }
00588       case '/': {   /* C-style comments */
00589         if( zSql[1]!='*' ){
00590           token = tkOTHER;
00591           break;
00592         }
00593         zSql += 2;
00594         while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
00595         if( zSql[0]==0 ) return 0;
00596         zSql++;
00597         token = tkWS;
00598         break;
00599       }
00600       case '-': {   /* SQL-style comments from "--" to end of line */
00601         if( zSql[1]!='-' ){
00602           token = tkOTHER;
00603           break;
00604         }
00605         while( *zSql && *zSql!='\n' ){ zSql++; }
00606         if( *zSql==0 ) return state==0;
00607         token = tkWS;
00608         break;
00609       }
00610       case '[': {   /* Microsoft-style identifiers in [...] */
00611         zSql++;
00612         while( *zSql && *zSql!=']' ){ zSql++; }
00613         if( *zSql==0 ) return 0;
00614         token = tkOTHER;
00615         break;
00616       }
00617       case '"':     /* single- and double-quoted strings */
00618       case '\'': {
00619         int c = *zSql;
00620         zSql++;
00621         while( *zSql && *zSql!=c ){ zSql++; }
00622         if( *zSql==0 ) return 0;
00623         token = tkOTHER;
00624         break;
00625       }
00626       default: {
00627         if( isIdChar[(u8)*zSql] ){
00628           /* Keywords and unquoted identifiers */
00629           int nId;
00630           for(nId=1; isIdChar[(u8)zSql[nId]]; nId++){}
00631           switch( *zSql ){
00632             case 'c': case 'C': {
00633               if( nId==6 && sqliteStrNICmp(zSql, "create", 6)==0 ){
00634                 token = tkCREATE;
00635               }else{
00636                 token = tkOTHER;
00637               }
00638               break;
00639             }
00640             case 't': case 'T': {
00641               if( nId==7 && sqliteStrNICmp(zSql, "trigger", 7)==0 ){
00642                 token = tkTRIGGER;
00643               }else if( nId==4 && sqliteStrNICmp(zSql, "temp", 4)==0 ){
00644                 token = tkTEMP;
00645               }else if( nId==9 && sqliteStrNICmp(zSql, "temporary", 9)==0 ){
00646                 token = tkTEMP;
00647               }else{
00648                 token = tkOTHER;
00649               }
00650               break;
00651             }
00652             case 'e':  case 'E': {
00653               if( nId==3 && sqliteStrNICmp(zSql, "end", 3)==0 ){
00654                 token = tkEND;
00655               }else if( nId==7 && sqliteStrNICmp(zSql, "explain", 7)==0 ){
00656                 token = tkEXPLAIN;
00657               }else{
00658                 token = tkOTHER;
00659               }
00660               break;
00661             }
00662             default: {
00663               token = tkOTHER;
00664               break;
00665             }
00666           }
00667           zSql += nId-1;
00668         }else{
00669           /* Operators and special symbols */
00670           token = tkOTHER;
00671         }
00672         break;
00673       }
00674     }
00675     state = trans[state][token];
00676     zSql++;
00677   }
00678   return state==0;
00679 }