Annotation of embedaddon/php/ext/sqlite/libsqlite/src/tokenize.c, revision 1.1.1.1

1.1       misho       1: /*
                      2: ** 2001 September 15
                      3: **
                      4: ** The author disclaims copyright to this source code.  In place of
                      5: ** a legal notice, here is a blessing:
                      6: **
                      7: **    May you do good and not evil.
                      8: **    May you find forgiveness for yourself and forgive others.
                      9: **    May you share freely, never taking more than you give.
                     10: **
                     11: *************************************************************************
                     12: ** An tokenizer for SQL
                     13: **
                     14: ** This file contains C code that splits an SQL input string up into
                     15: ** individual tokens and sends those tokens one-by-one over to the
                     16: ** parser for analysis.
                     17: **
                     18: ** $Id: tokenize.c 195361 2005-09-07 15:11:33Z iliaa $
                     19: */
                     20: #include "sqliteInt.h"
                     21: #include "os.h"
                     22: #include <ctype.h>
                     23: #include <stdlib.h>
                     24: 
                     25: /*
                     26: ** All the keywords of the SQL language are stored as in a hash
                     27: ** table composed of instances of the following structure.
                     28: */
                     29: typedef struct Keyword Keyword;
                     30: struct Keyword {
                     31:   char *zName;             /* The keyword name */
                     32:   u8 tokenType;            /* Token value for this keyword */
                     33:   u8 len;                  /* Length of this keyword */
                     34:   u8 iNext;                /* Index in aKeywordTable[] of next with same hash */
                     35: };
                     36: 
                     37: /*
                     38: ** These are the keywords
                     39: */
                     40: static Keyword aKeywordTable[] = {
                     41:   { "ABORT",             TK_ABORT,        },
                     42:   { "AFTER",             TK_AFTER,        },
                     43:   { "ALL",               TK_ALL,          },
                     44:   { "AND",               TK_AND,          },
                     45:   { "AS",                TK_AS,           },
                     46:   { "ASC",               TK_ASC,          },
                     47:   { "ATTACH",            TK_ATTACH,       },
                     48:   { "BEFORE",            TK_BEFORE,       },
                     49:   { "BEGIN",             TK_BEGIN,        },
                     50:   { "BETWEEN",           TK_BETWEEN,      },
                     51:   { "BY",                TK_BY,           },
                     52:   { "CASCADE",           TK_CASCADE,      },
                     53:   { "CASE",              TK_CASE,         },
                     54:   { "CHECK",             TK_CHECK,        },
                     55:   { "CLUSTER",           TK_CLUSTER,      },
                     56:   { "COLLATE",           TK_COLLATE,      },
                     57:   { "COMMIT",            TK_COMMIT,       },
                     58:   { "CONFLICT",          TK_CONFLICT,     },
                     59:   { "CONSTRAINT",        TK_CONSTRAINT,   },
                     60:   { "COPY",              TK_COPY,         },
                     61:   { "CREATE",            TK_CREATE,       },
                     62:   { "CROSS",             TK_JOIN_KW,      },
                     63:   { "DATABASE",          TK_DATABASE,     },
                     64:   { "DEFAULT",           TK_DEFAULT,      },
                     65:   { "DEFERRED",          TK_DEFERRED,     },
                     66:   { "DEFERRABLE",        TK_DEFERRABLE,   },
                     67:   { "DELETE",            TK_DELETE,       },
                     68:   { "DELIMITERS",        TK_DELIMITERS,   },
                     69:   { "DESC",              TK_DESC,         },
                     70:   { "DETACH",            TK_DETACH,       },
                     71:   { "DISTINCT",          TK_DISTINCT,     },
                     72:   { "DROP",              TK_DROP,         },
                     73:   { "END",               TK_END,          },
                     74:   { "EACH",              TK_EACH,         },
                     75:   { "ELSE",              TK_ELSE,         },
                     76:   { "EXCEPT",            TK_EXCEPT,       },
                     77:   { "EXPLAIN",           TK_EXPLAIN,      },
                     78:   { "FAIL",              TK_FAIL,         },
                     79:   { "FOR",               TK_FOR,          },
                     80:   { "FOREIGN",           TK_FOREIGN,      },
                     81:   { "FROM",              TK_FROM,         },
                     82:   { "FULL",              TK_JOIN_KW,      },
                     83:   { "GLOB",              TK_GLOB,         },
                     84:   { "GROUP",             TK_GROUP,        },
                     85:   { "HAVING",            TK_HAVING,       },
                     86:   { "IGNORE",            TK_IGNORE,       },
                     87:   { "IMMEDIATE",         TK_IMMEDIATE,    },
                     88:   { "IN",                TK_IN,           },
                     89:   { "INDEX",             TK_INDEX,        },
                     90:   { "INITIALLY",         TK_INITIALLY,    },
                     91:   { "INNER",             TK_JOIN_KW,      },
                     92:   { "INSERT",            TK_INSERT,       },
                     93:   { "INSTEAD",           TK_INSTEAD,      },
                     94:   { "INTERSECT",         TK_INTERSECT,    },
                     95:   { "INTO",              TK_INTO,         },
                     96:   { "IS",                TK_IS,           },
                     97:   { "ISNULL",            TK_ISNULL,       },
                     98:   { "JOIN",              TK_JOIN,         },
                     99:   { "KEY",               TK_KEY,          },
                    100:   { "LEFT",              TK_JOIN_KW,      },
                    101:   { "LIKE",              TK_LIKE,         },
                    102:   { "LIMIT",             TK_LIMIT,        },
                    103:   { "MATCH",             TK_MATCH,        },
                    104:   { "NATURAL",           TK_JOIN_KW,      },
                    105:   { "NOT",               TK_NOT,          },
                    106:   { "NOTNULL",           TK_NOTNULL,      },
                    107:   { "NULL",              TK_NULL,         },
                    108:   { "OF",                TK_OF,           },
                    109:   { "OFFSET",            TK_OFFSET,       },
                    110:   { "ON",                TK_ON,           },
                    111:   { "OR",                TK_OR,           },
                    112:   { "ORDER",             TK_ORDER,        },
                    113:   { "OUTER",             TK_JOIN_KW,      },
                    114:   { "PRAGMA",            TK_PRAGMA,       },
                    115:   { "PRIMARY",           TK_PRIMARY,      },
                    116:   { "RAISE",             TK_RAISE,        },
                    117:   { "REFERENCES",        TK_REFERENCES,   },
                    118:   { "REPLACE",           TK_REPLACE,      },
                    119:   { "RESTRICT",          TK_RESTRICT,     },
                    120:   { "RIGHT",             TK_JOIN_KW,      },
                    121:   { "ROLLBACK",          TK_ROLLBACK,     },
                    122:   { "ROW",               TK_ROW,          },
                    123:   { "SELECT",            TK_SELECT,       },
                    124:   { "SET",               TK_SET,          },
                    125:   { "STATEMENT",         TK_STATEMENT,    },
                    126:   { "TABLE",             TK_TABLE,        },
                    127:   { "TEMP",              TK_TEMP,         },
                    128:   { "TEMPORARY",         TK_TEMP,         },
                    129:   { "THEN",              TK_THEN,         },
                    130:   { "TRANSACTION",       TK_TRANSACTION,  },
                    131:   { "TRIGGER",           TK_TRIGGER,      },
                    132:   { "UNION",             TK_UNION,        },
                    133:   { "UNIQUE",            TK_UNIQUE,       },
                    134:   { "UPDATE",            TK_UPDATE,       },
                    135:   { "USING",             TK_USING,        },
                    136:   { "VACUUM",            TK_VACUUM,       },
                    137:   { "VALUES",            TK_VALUES,       },
                    138:   { "VIEW",              TK_VIEW,         },
                    139:   { "WHEN",              TK_WHEN,         },
                    140:   { "WHERE",             TK_WHERE,        },
                    141: };
                    142: 
                    143: /*
                    144: ** This is the hash table
                    145: */
                    146: #define KEY_HASH_SIZE 101
                    147: static u8 aiHashTable[KEY_HASH_SIZE];
                    148: 
                    149: 
                    150: /*
                    151: ** This function looks up an identifier to determine if it is a
                    152: ** keyword.  If it is a keyword, the token code of that keyword is 
                    153: ** returned.  If the input is not a keyword, TK_ID is returned.
                    154: */
                    155: int sqliteKeywordCode(const char *z, int n){
                    156:   int h, i;
                    157:   Keyword *p;
                    158:   static char needInit = 1;
                    159:   if( needInit ){
                    160:     /* Initialize the keyword hash table */
                    161:     sqliteOsEnterMutex();
                    162:     if( needInit ){
                    163:       int nk;
                    164:       nk = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]);
                    165:       for(i=0; i<nk; i++){
                    166:         aKeywordTable[i].len = strlen(aKeywordTable[i].zName);
                    167:         h = sqliteHashNoCase(aKeywordTable[i].zName, aKeywordTable[i].len);
                    168:         h %= KEY_HASH_SIZE;
                    169:         aKeywordTable[i].iNext = aiHashTable[h];
                    170:         aiHashTable[h] = i+1;
                    171:       }
                    172:       needInit = 0;
                    173:     }
                    174:     sqliteOsLeaveMutex();
                    175:   }
                    176:   h = sqliteHashNoCase(z, n) % KEY_HASH_SIZE;
                    177:   for(i=aiHashTable[h]; i; i=p->iNext){
                    178:     p = &aKeywordTable[i-1];
                    179:     if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){
                    180:       return p->tokenType;
                    181:     }
                    182:   }
                    183:   return TK_ID;
                    184: }
                    185: 
                    186: 
                    187: /*
                    188: ** If X is a character that can be used in an identifier and
                    189: ** X&0x80==0 then isIdChar[X] will be 1.  If X&0x80==0x80 then
                    190: ** X is always an identifier character.  (Hence all UTF-8
                    191: ** characters can be part of an identifier).  isIdChar[X] will
                    192: ** be 0 for every character in the lower 128 ASCII characters
                    193: ** that cannot be used as part of an identifier.
                    194: **
                    195: ** In this implementation, an identifier can be a string of
                    196: ** alphabetic characters, digits, and "_" plus any character
                    197: ** with the high-order bit set.  The latter rule means that
                    198: ** any sequence of UTF-8 characters or characters taken from
                    199: ** an extended ISO8859 character set can form an identifier.
                    200: */
                    201: static const char isIdChar[] = {
                    202: /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
                    203:     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */
                    204:     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
                    205:     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
                    206:     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
                    207:     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
                    208:     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
                    209:     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 6x */
                    210:     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */
                    211: };
                    212: 
                    213: 
                    214: /*
                    215: ** Return the length of the token that begins at z[0]. 
                    216: ** Store the token type in *tokenType before returning.
                    217: */
                    218: static int sqliteGetToken(const unsigned char *z, int *tokenType){
                    219:   int i;
                    220:   switch( *z ){
                    221:     case ' ': case '\t': case '\n': case '\f': case '\r': {
                    222:       for(i=1; isspace(z[i]); i++){}
                    223:       *tokenType = TK_SPACE;
                    224:       return i;
                    225:     }
                    226:     case '-': {
                    227:       if( z[1]=='-' ){
                    228:         for(i=2; z[i] && z[i]!='\n'; i++){}
                    229:         *tokenType = TK_COMMENT;
                    230:         return i;
                    231:       }
                    232:       *tokenType = TK_MINUS;
                    233:       return 1;
                    234:     }
                    235:     case '(': {
                    236:       *tokenType = TK_LP;
                    237:       return 1;
                    238:     }
                    239:     case ')': {
                    240:       *tokenType = TK_RP;
                    241:       return 1;
                    242:     }
                    243:     case ';': {
                    244:       *tokenType = TK_SEMI;
                    245:       return 1;
                    246:     }
                    247:     case '+': {
                    248:       *tokenType = TK_PLUS;
                    249:       return 1;
                    250:     }
                    251:     case '*': {
                    252:       *tokenType = TK_STAR;
                    253:       return 1;
                    254:     }
                    255:     case '/': {
                    256:       if( z[1]!='*' || z[2]==0 ){
                    257:         *tokenType = TK_SLASH;
                    258:         return 1;
                    259:       }
                    260:       for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){}
                    261:       if( z[i] ) i++;
                    262:       *tokenType = TK_COMMENT;
                    263:       return i;
                    264:     }
                    265:     case '%': {
                    266:       *tokenType = TK_REM;
                    267:       return 1;
                    268:     }
                    269:     case '=': {
                    270:       *tokenType = TK_EQ;
                    271:       return 1 + (z[1]=='=');
                    272:     }
                    273:     case '<': {
                    274:       if( z[1]=='=' ){
                    275:         *tokenType = TK_LE;
                    276:         return 2;
                    277:       }else if( z[1]=='>' ){
                    278:         *tokenType = TK_NE;
                    279:         return 2;
                    280:       }else if( z[1]=='<' ){
                    281:         *tokenType = TK_LSHIFT;
                    282:         return 2;
                    283:       }else{
                    284:         *tokenType = TK_LT;
                    285:         return 1;
                    286:       }
                    287:     }
                    288:     case '>': {
                    289:       if( z[1]=='=' ){
                    290:         *tokenType = TK_GE;
                    291:         return 2;
                    292:       }else if( z[1]=='>' ){
                    293:         *tokenType = TK_RSHIFT;
                    294:         return 2;
                    295:       }else{
                    296:         *tokenType = TK_GT;
                    297:         return 1;
                    298:       }
                    299:     }
                    300:     case '!': {
                    301:       if( z[1]!='=' ){
                    302:         *tokenType = TK_ILLEGAL;
                    303:         return 2;
                    304:       }else{
                    305:         *tokenType = TK_NE;
                    306:         return 2;
                    307:       }
                    308:     }
                    309:     case '|': {
                    310:       if( z[1]!='|' ){
                    311:         *tokenType = TK_BITOR;
                    312:         return 1;
                    313:       }else{
                    314:         *tokenType = TK_CONCAT;
                    315:         return 2;
                    316:       }
                    317:     }
                    318:     case ',': {
                    319:       *tokenType = TK_COMMA;
                    320:       return 1;
                    321:     }
                    322:     case '&': {
                    323:       *tokenType = TK_BITAND;
                    324:       return 1;
                    325:     }
                    326:     case '~': {
                    327:       *tokenType = TK_BITNOT;
                    328:       return 1;
                    329:     }
                    330:     case '\'': case '"': {
                    331:       int delim = z[0];
                    332:       for(i=1; z[i]; i++){
                    333:         if( z[i]==delim ){
                    334:           if( z[i+1]==delim ){
                    335:             i++;
                    336:           }else{
                    337:             break;
                    338:           }
                    339:         }
                    340:       }
                    341:       if( z[i] ) i++;
                    342:       *tokenType = TK_STRING;
                    343:       return i;
                    344:     }
                    345:     case '.': {
                    346:       *tokenType = TK_DOT;
                    347:       return 1;
                    348:     }
                    349:     case '0': case '1': case '2': case '3': case '4':
                    350:     case '5': case '6': case '7': case '8': case '9': {
                    351:       *tokenType = TK_INTEGER;
                    352:       for(i=1; isdigit(z[i]); i++){}
                    353:       if( z[i]=='.' && isdigit(z[i+1]) ){
                    354:         i += 2;
                    355:         while( isdigit(z[i]) ){ i++; }
                    356:         *tokenType = TK_FLOAT;
                    357:       }
                    358:       if( (z[i]=='e' || z[i]=='E') &&
                    359:            ( isdigit(z[i+1]) 
                    360:             || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2]))
                    361:            )
                    362:       ){
                    363:         i += 2;
                    364:         while( isdigit(z[i]) ){ i++; }
                    365:         *tokenType = TK_FLOAT;
                    366:       }
                    367:       return i;
                    368:     }
                    369:     case '[': {
                    370:       for(i=1; z[i] && z[i-1]!=']'; i++){}
                    371:       *tokenType = TK_ID;
                    372:       return i;
                    373:     }
                    374:     case '?': {
                    375:       *tokenType = TK_VARIABLE;
                    376:       return 1;
                    377:     }
                    378:     default: {
                    379:       if( (*z&0x80)==0 && !isIdChar[*z] ){
                    380:         break;
                    381:       }
                    382:       for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){}
                    383:       *tokenType = sqliteKeywordCode((char*)z, i);
                    384:       return i;
                    385:     }
                    386:   }
                    387:   *tokenType = TK_ILLEGAL;
                    388:   return 1;
                    389: }
                    390: 
                    391: /*
                    392: ** Run the parser on the given SQL string.  The parser structure is
                    393: ** passed in.  An SQLITE_ status code is returned.  If an error occurs
                    394: ** and pzErrMsg!=NULL then an error message might be written into 
                    395: ** memory obtained from malloc() and *pzErrMsg made to point to that
                    396: ** error message.  Or maybe not.
                    397: */
                    398: int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
                    399:   int nErr = 0;
                    400:   int i;
                    401:   void *pEngine;
                    402:   int tokenType;
                    403:   int lastTokenParsed = -1;
                    404:   sqlite *db = pParse->db;
                    405:   extern void *sqliteParserAlloc(void*(*)(int));
                    406:   extern void sqliteParserFree(void*, void(*)(void*));
                    407:   extern int sqliteParser(void*, int, Token, Parse*);
                    408: 
                    409:   db->flags &= ~SQLITE_Interrupt;
                    410:   pParse->rc = SQLITE_OK;
                    411:   i = 0;
                    412:   pEngine = sqliteParserAlloc((void*(*)(int))malloc);
                    413:   if( pEngine==0 ){
                    414:     sqliteSetString(pzErrMsg, "out of memory", (char*)0);
                    415:     return 1;
                    416:   }
                    417:   pParse->sLastToken.dyn = 0;
                    418:   pParse->zTail = zSql;
                    419:   while( sqlite_malloc_failed==0 && zSql[i]!=0 ){
                    420:     assert( i>=0 );
                    421:     pParse->sLastToken.z = &zSql[i];
                    422:     assert( pParse->sLastToken.dyn==0 );
                    423:     pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
                    424:     i += pParse->sLastToken.n;
                    425:     switch( tokenType ){
                    426:       case TK_SPACE:
                    427:       case TK_COMMENT: {
                    428:         if( (db->flags & SQLITE_Interrupt)!=0 ){
                    429:           pParse->rc = SQLITE_INTERRUPT;
                    430:           sqliteSetString(pzErrMsg, "interrupt", (char*)0);
                    431:           goto abort_parse;
                    432:         }
                    433:         break;
                    434:       }
                    435:       case TK_ILLEGAL: {
                    436:         sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, 
                    437:            pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0);
                    438:         nErr++;
                    439:         goto abort_parse;
                    440:       }
                    441:       case TK_SEMI: {
                    442:         pParse->zTail = &zSql[i];
                    443:         /* Fall thru into the default case */
                    444:       }
                    445:       default: {
                    446:         sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse);
                    447:         lastTokenParsed = tokenType;
                    448:         if( pParse->rc!=SQLITE_OK ){
                    449:           goto abort_parse;
                    450:         }
                    451:         break;
                    452:       }
                    453:     }
                    454:   }
                    455: abort_parse:
                    456:   if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
                    457:     if( lastTokenParsed!=TK_SEMI ){
                    458:       sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
                    459:       pParse->zTail = &zSql[i];
                    460:     }
                    461:     sqliteParser(pEngine, 0, pParse->sLastToken, pParse);
                    462:   }
                    463:   sqliteParserFree(pEngine, free);
                    464:   if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
                    465:     sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc),
                    466:                     (char*)0);
                    467:   }
                    468:   if( pParse->zErrMsg ){
                    469:     if( pzErrMsg && *pzErrMsg==0 ){
                    470:       *pzErrMsg = pParse->zErrMsg;
                    471:     }else{
                    472:       sqliteFree(pParse->zErrMsg);
                    473:     }
                    474:     pParse->zErrMsg = 0;
                    475:     if( !nErr ) nErr++;
                    476:   }
                    477:   if( pParse->pVdbe && pParse->nErr>0 ){
                    478:     sqliteVdbeDelete(pParse->pVdbe);
                    479:     pParse->pVdbe = 0;
                    480:   }
                    481:   if( pParse->pNewTable ){
                    482:     sqliteDeleteTable(pParse->db, pParse->pNewTable);
                    483:     pParse->pNewTable = 0;
                    484:   }
                    485:   if( pParse->pNewTrigger ){
                    486:     sqliteDeleteTrigger(pParse->pNewTrigger);
                    487:     pParse->pNewTrigger = 0;
                    488:   }
                    489:   if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
                    490:     pParse->rc = SQLITE_ERROR;
                    491:   }
                    492:   return nErr;
                    493: }
                    494: 
                    495: /*
                    496: ** Token types used by the sqlite_complete() routine.  See the header
                    497: ** comments on that procedure for additional information.
                    498: */
                    499: #define tkEXPLAIN 0
                    500: #define tkCREATE  1
                    501: #define tkTEMP    2
                    502: #define tkTRIGGER 3
                    503: #define tkEND     4
                    504: #define tkSEMI    5
                    505: #define tkWS      6
                    506: #define tkOTHER   7
                    507: 
                    508: /*
                    509: ** Return TRUE if the given SQL string ends in a semicolon.
                    510: **
                    511: ** Special handling is require for CREATE TRIGGER statements.
                    512: ** Whenever the CREATE TRIGGER keywords are seen, the statement
                    513: ** must end with ";END;".
                    514: **
                    515: ** This implementation uses a state machine with 7 states:
                    516: **
                    517: **   (0) START     At the beginning or end of an SQL statement.  This routine
                    518: **                 returns 1 if it ends in the START state and 0 if it ends
                    519: **                 in any other state.
                    520: **
                    521: **   (1) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of 
                    522: **                 a statement.
                    523: **
                    524: **   (2) CREATE    The keyword CREATE has been seen at the beginning of a
                    525: **                 statement, possibly preceeded by EXPLAIN and/or followed by
                    526: **                 TEMP or TEMPORARY
                    527: **
                    528: **   (3) NORMAL    We are in the middle of statement which ends with a single
                    529: **                 semicolon.
                    530: **
                    531: **   (4) TRIGGER   We are in the middle of a trigger definition that must be
                    532: **                 ended by a semicolon, the keyword END, and another semicolon.
                    533: **
                    534: **   (5) SEMI      We've seen the first semicolon in the ";END;" that occurs at
                    535: **                 the end of a trigger definition.
                    536: **
                    537: **   (6) END       We've seen the ";END" of the ";END;" that occurs at the end
                    538: **                 of a trigger difinition.
                    539: **
                    540: ** Transitions between states above are determined by tokens extracted
                    541: ** from the input.  The following tokens are significant:
                    542: **
                    543: **   (0) tkEXPLAIN   The "explain" keyword.
                    544: **   (1) tkCREATE    The "create" keyword.
                    545: **   (2) tkTEMP      The "temp" or "temporary" keyword.
                    546: **   (3) tkTRIGGER   The "trigger" keyword.
                    547: **   (4) tkEND       The "end" keyword.
                    548: **   (5) tkSEMI      A semicolon.
                    549: **   (6) tkWS        Whitespace
                    550: **   (7) tkOTHER     Any other SQL token.
                    551: **
                    552: ** Whitespace never causes a state transition and is always ignored.
                    553: */
                    554: int sqlite_complete(const char *zSql){
                    555:   u8 state = 0;   /* Current state, using numbers defined in header comment */
                    556:   u8 token;       /* Value of the next token */
                    557: 
                    558:   /* The following matrix defines the transition from one state to another
                    559:   ** according to what token is seen.  trans[state][token] returns the
                    560:   ** next state.
                    561:   */
                    562:   static const u8 trans[7][8] = {
                    563:                      /* Token:                                                */
                    564:      /* State:       **  EXPLAIN  CREATE  TEMP  TRIGGER  END  SEMI  WS  OTHER */
                    565:      /* 0   START: */ {       1,      2,    3,       3,   3,    0,  0,     3, },
                    566:      /* 1 EXPLAIN: */ {       3,      2,    3,       3,   3,    0,  1,     3, },
                    567:      /* 2  CREATE: */ {       3,      3,    2,       4,   3,    0,  2,     3, },
                    568:      /* 3  NORMAL: */ {       3,      3,    3,       3,   3,    0,  3,     3, },
                    569:      /* 4 TRIGGER: */ {       4,      4,    4,       4,   4,    5,  4,     4, },
                    570:      /* 5    SEMI: */ {       4,      4,    4,       4,   6,    5,  5,     4, },
                    571:      /* 6     END: */ {       4,      4,    4,       4,   4,    0,  6,     4, },
                    572:   };
                    573: 
                    574:   while( *zSql ){
                    575:     switch( *zSql ){
                    576:       case ';': {  /* A semicolon */
                    577:         token = tkSEMI;
                    578:         break;
                    579:       }
                    580:       case ' ':
                    581:       case '\r':
                    582:       case '\t':
                    583:       case '\n':
                    584:       case '\f': {  /* White space is ignored */
                    585:         token = tkWS;
                    586:         break;
                    587:       }
                    588:       case '/': {   /* C-style comments */
                    589:         if( zSql[1]!='*' ){
                    590:           token = tkOTHER;
                    591:           break;
                    592:         }
                    593:         zSql += 2;
                    594:         while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
                    595:         if( zSql[0]==0 ) return 0;
                    596:         zSql++;
                    597:         token = tkWS;
                    598:         break;
                    599:       }
                    600:       case '-': {   /* SQL-style comments from "--" to end of line */
                    601:         if( zSql[1]!='-' ){
                    602:           token = tkOTHER;
                    603:           break;
                    604:         }
                    605:         while( *zSql && *zSql!='\n' ){ zSql++; }
                    606:         if( *zSql==0 ) return state==0;
                    607:         token = tkWS;
                    608:         break;
                    609:       }
                    610:       case '[': {   /* Microsoft-style identifiers in [...] */
                    611:         zSql++;
                    612:         while( *zSql && *zSql!=']' ){ zSql++; }
                    613:         if( *zSql==0 ) return 0;
                    614:         token = tkOTHER;
                    615:         break;
                    616:       }
                    617:       case '"':     /* single- and double-quoted strings */
                    618:       case '\'': {
                    619:         int c = *zSql;
                    620:         zSql++;
                    621:         while( *zSql && *zSql!=c ){ zSql++; }
                    622:         if( *zSql==0 ) return 0;
                    623:         token = tkOTHER;
                    624:         break;
                    625:       }
                    626:       default: {
                    627:         if( isIdChar[(u8)*zSql] ){
                    628:           /* Keywords and unquoted identifiers */
                    629:           int nId;
                    630:           for(nId=1; isIdChar[(u8)zSql[nId]]; nId++){}
                    631:           switch( *zSql ){
                    632:             case 'c': case 'C': {
                    633:               if( nId==6 && sqliteStrNICmp(zSql, "create", 6)==0 ){
                    634:                 token = tkCREATE;
                    635:               }else{
                    636:                 token = tkOTHER;
                    637:               }
                    638:               break;
                    639:             }
                    640:             case 't': case 'T': {
                    641:               if( nId==7 && sqliteStrNICmp(zSql, "trigger", 7)==0 ){
                    642:                 token = tkTRIGGER;
                    643:               }else if( nId==4 && sqliteStrNICmp(zSql, "temp", 4)==0 ){
                    644:                 token = tkTEMP;
                    645:               }else if( nId==9 && sqliteStrNICmp(zSql, "temporary", 9)==0 ){
                    646:                 token = tkTEMP;
                    647:               }else{
                    648:                 token = tkOTHER;
                    649:               }
                    650:               break;
                    651:             }
                    652:             case 'e':  case 'E': {
                    653:               if( nId==3 && sqliteStrNICmp(zSql, "end", 3)==0 ){
                    654:                 token = tkEND;
                    655:               }else if( nId==7 && sqliteStrNICmp(zSql, "explain", 7)==0 ){
                    656:                 token = tkEXPLAIN;
                    657:               }else{
                    658:                 token = tkOTHER;
                    659:               }
                    660:               break;
                    661:             }
                    662:             default: {
                    663:               token = tkOTHER;
                    664:               break;
                    665:             }
                    666:           }
                    667:           zSql += nId-1;
                    668:         }else{
                    669:           /* Operators and special symbols */
                    670:           token = tkOTHER;
                    671:         }
                    672:         break;
                    673:       }
                    674:     }
                    675:     state = trans[state][token];
                    676:     zSql++;
                    677:   }
                    678:   return state==0;
                    679: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>