summaryrefslogtreecommitdiff
path: root/util/db_sql_codegen/preparser.c
blob: 05a73c110e66b5e5c0a461fbd24c989c3ced367b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 1996, 2015 Oracle and/or its affiliates.  All rights reserved.
 *
 */

#include "db_sql_codegen.h"

extern void bdb_create_database(Token *, Parse *pParse);

static void
preparserSyntaxError(t, pParse)
	Token *t;
	Parse *pParse;
{
	sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", t);
	pParse->parseError = 1;
}

/*
 * The pre-parser is invoked for each token found by the lexical
 * analyzer.  It passes most tokens on to the main SQLite parser
 * unchanged; however it maintains its own state machine so that it
 * can notice certain sequences of tokens.  In particular, it catches
 * CREATE DATABASE, which is a sequence that the SQLite parser does
 * not recognize.
 */
void preparser(pEngine, tokenType, token, pParse)
	void *pEngine;
	int tokenType;
	Token token;
	Parse *pParse;
{
	static enum preparserState {
		IDLE = 0, GOT_CREATE = 1, GOT_DATABASE = 2, GOT_NAME = 3
	} state = IDLE;

	switch (state) {

	    case IDLE:

		if (tokenType == TK_CREATE)
			state = GOT_CREATE;
		else    /* pass token to sqlite parser -- the common case */
			sqlite3Parser(pEngine, tokenType,
				      pParse->sLastToken, pParse);
		break;

	    case GOT_CREATE:

		if (tokenType == TK_DATABASE)
			state = GOT_DATABASE;
		else {  /* return to idle, pass the CREATE token, then
			 * the current token to the sqlite parser */
			state = IDLE;
			sqlite3Parser(pEngine, TK_CREATE,
				      pParse->sLastToken, pParse);
			sqlite3Parser(pEngine, tokenType,
				      pParse->sLastToken, pParse);
		}
		break;

	    case GOT_DATABASE:

		if (tokenType == TK_ID) {
			state = GOT_NAME;
			bdb_create_database(&token, pParse);
		} else
			preparserSyntaxError(&token, pParse);

		break;

	    case GOT_NAME:

		if (tokenType == TK_SEMI)
			state = IDLE;
		else
			preparserSyntaxError(&token, pParse);
		break;
	}
}