tp: switch tokenizer to real SQLite tokenizer + grammar

This CL prepares the ground for having a proper LALR parser by switching
to using the real sqlite tokenize function (instead of some franken
version of them) and also generating the token definitions directly
from SQLite instead of hacking it as "generic keyword".

All of this stuff will be used in the upcoming parser.

Change-Id: I0c62d9c3700f2e585609400e5d4b7742aed7825c
diff --git a/Android.bp b/Android.bp
index 2d05823..9a581b7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2503,6 +2503,7 @@
         ":perfetto_src_trace_processor_metatrace",
         ":perfetto_src_trace_processor_metrics_metrics",
         ":perfetto_src_trace_processor_perfetto_sql_engine_engine",
+        ":perfetto_src_trace_processor_perfetto_sql_grammar_grammar",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_functions",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_interface",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_operators_operators",
@@ -2512,6 +2513,7 @@
         ":perfetto_src_trace_processor_perfetto_sql_parser_parser",
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_grammar",
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_preprocessor",
+        ":perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
         ":perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenizer",
         ":perfetto_src_trace_processor_sorter_sorter",
         ":perfetto_src_trace_processor_sqlite_bindings_bindings",
@@ -13244,6 +13246,14 @@
     ],
 }
 
+// GN: //src/trace_processor/perfetto_sql/grammar:grammar
+filegroup {
+    name: "perfetto_src_trace_processor_perfetto_sql_grammar_grammar",
+    srcs: [
+        "src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.c",
+    ],
+}
+
 // GN: //src/trace_processor/perfetto_sql/intrinsics/functions:functions
 filegroup {
     name: "perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_functions",
@@ -13611,6 +13621,14 @@
     ],
 }
 
+// GN: //src/trace_processor/perfetto_sql/tokenizer:tokenize_internal
+filegroup {
+    name: "perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
+    srcs: [
+        "src/trace_processor/perfetto_sql/tokenizer/tokenize_internal.c",
+    ],
+}
+
 // GN: //src/trace_processor/perfetto_sql/tokenizer:tokenizer
 filegroup {
     name: "perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenizer",
@@ -15582,6 +15600,7 @@
         ":perfetto_src_trace_processor_metrics_unittests",
         ":perfetto_src_trace_processor_perfetto_sql_engine_engine",
         ":perfetto_src_trace_processor_perfetto_sql_engine_unittests",
+        ":perfetto_src_trace_processor_perfetto_sql_grammar_grammar",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_functions",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_interface",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_unittests",
@@ -15597,6 +15616,7 @@
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_grammar",
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_preprocessor",
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_unittests",
+        ":perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
         ":perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenizer",
         ":perfetto_src_trace_processor_perfetto_sql_tokenizer_unittests",
         ":perfetto_src_trace_processor_rpc_rpc",
@@ -16638,6 +16658,7 @@
         ":perfetto_src_trace_processor_metatrace",
         ":perfetto_src_trace_processor_metrics_metrics",
         ":perfetto_src_trace_processor_perfetto_sql_engine_engine",
+        ":perfetto_src_trace_processor_perfetto_sql_grammar_grammar",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_functions",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_interface",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_operators_operators",
@@ -16647,6 +16668,7 @@
         ":perfetto_src_trace_processor_perfetto_sql_parser_parser",
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_grammar",
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_preprocessor",
+        ":perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
         ":perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenizer",
         ":perfetto_src_trace_processor_rpc_httpd",
         ":perfetto_src_trace_processor_rpc_rpc",
@@ -17053,6 +17075,7 @@
         ":perfetto_src_trace_processor_metatrace",
         ":perfetto_src_trace_processor_metrics_metrics",
         ":perfetto_src_trace_processor_perfetto_sql_engine_engine",
+        ":perfetto_src_trace_processor_perfetto_sql_grammar_grammar",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_functions",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_functions_interface",
         ":perfetto_src_trace_processor_perfetto_sql_intrinsics_operators_operators",
@@ -17062,6 +17085,7 @@
         ":perfetto_src_trace_processor_perfetto_sql_parser_parser",
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_grammar",
         ":perfetto_src_trace_processor_perfetto_sql_preprocessor_preprocessor",
+        ":perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
         ":perfetto_src_trace_processor_perfetto_sql_tokenizer_tokenizer",
         ":perfetto_src_trace_processor_sorter_sorter",
         ":perfetto_src_trace_processor_sqlite_bindings_bindings",
diff --git a/BUILD b/BUILD
index 1d59aae..b49eafa 100644
--- a/BUILD
+++ b/BUILD
@@ -259,6 +259,7 @@
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_metrics",
         ":src_trace_processor_perfetto_sql_engine_engine",
+        ":src_trace_processor_perfetto_sql_grammar_grammar",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_functions",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_interface",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_tables",
@@ -270,6 +271,7 @@
         ":src_trace_processor_perfetto_sql_parser_parser",
         ":src_trace_processor_perfetto_sql_preprocessor_grammar",
         ":src_trace_processor_perfetto_sql_preprocessor_preprocessor",
+        ":src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
         ":src_trace_processor_perfetto_sql_tokenizer_tokenizer",
         ":src_trace_processor_rpc_rpc",
         ":src_trace_processor_sorter_sorter",
@@ -2430,6 +2432,17 @@
     ],
 )
 
+# GN target: //src/trace_processor/perfetto_sql/grammar:grammar
+perfetto_filegroup(
+    name = "src_trace_processor_perfetto_sql_grammar_grammar",
+    srcs = [
+        "src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.c",
+        "src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.h",
+        "src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash.h",
+        "src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash_helper.h",
+    ],
+)
+
 # GN target: //src/trace_processor/perfetto_sql/intrinsics/functions:functions
 perfetto_filegroup(
     name = "src_trace_processor_perfetto_sql_intrinsics_functions_functions",
@@ -3014,6 +3027,15 @@
     namespace = "stdlib",
 )
 
+# GN target: //src/trace_processor/perfetto_sql/tokenizer:tokenize_internal
+perfetto_filegroup(
+    name = "src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
+    srcs = [
+        "src/trace_processor/perfetto_sql/tokenizer/tokenize_internal.c",
+        "src/trace_processor/perfetto_sql/tokenizer/tokenize_internal_helper.h",
+    ],
+)
+
 # GN target: //src/trace_processor/perfetto_sql/tokenizer:tokenizer
 perfetto_filegroup(
     name = "src_trace_processor_perfetto_sql_tokenizer_tokenizer",
@@ -6326,6 +6348,7 @@
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_metrics",
         ":src_trace_processor_perfetto_sql_engine_engine",
+        ":src_trace_processor_perfetto_sql_grammar_grammar",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_functions",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_interface",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_tables",
@@ -6337,6 +6360,7 @@
         ":src_trace_processor_perfetto_sql_parser_parser",
         ":src_trace_processor_perfetto_sql_preprocessor_grammar",
         ":src_trace_processor_perfetto_sql_preprocessor_preprocessor",
+        ":src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
         ":src_trace_processor_perfetto_sql_tokenizer_tokenizer",
         ":src_trace_processor_sorter_sorter",
         ":src_trace_processor_sqlite_bindings_bindings",
@@ -6521,6 +6545,7 @@
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_metrics",
         ":src_trace_processor_perfetto_sql_engine_engine",
+        ":src_trace_processor_perfetto_sql_grammar_grammar",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_functions",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_interface",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_tables",
@@ -6532,6 +6557,7 @@
         ":src_trace_processor_perfetto_sql_parser_parser",
         ":src_trace_processor_perfetto_sql_preprocessor_grammar",
         ":src_trace_processor_perfetto_sql_preprocessor_preprocessor",
+        ":src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
         ":src_trace_processor_perfetto_sql_tokenizer_tokenizer",
         ":src_trace_processor_rpc_httpd",
         ":src_trace_processor_rpc_rpc",
@@ -6773,6 +6799,7 @@
         ":src_trace_processor_metatrace",
         ":src_trace_processor_metrics_metrics",
         ":src_trace_processor_perfetto_sql_engine_engine",
+        ":src_trace_processor_perfetto_sql_grammar_grammar",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_functions",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_interface",
         ":src_trace_processor_perfetto_sql_intrinsics_functions_tables",
@@ -6784,6 +6811,7 @@
         ":src_trace_processor_perfetto_sql_parser_parser",
         ":src_trace_processor_perfetto_sql_preprocessor_grammar",
         ":src_trace_processor_perfetto_sql_preprocessor_preprocessor",
+        ":src_trace_processor_perfetto_sql_tokenizer_tokenize_internal",
         ":src_trace_processor_perfetto_sql_tokenizer_tokenizer",
         ":src_trace_processor_sorter_sorter",
         ":src_trace_processor_sqlite_bindings_bindings",
diff --git a/src/trace_processor/perfetto_sql/grammar/BUILD.gn b/src/trace_processor/perfetto_sql/grammar/BUILD.gn
new file mode 100644
index 0000000..8dec0d1
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/grammar/BUILD.gn
@@ -0,0 +1,43 @@
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("../../../../gn/test.gni")
+
+assert(enable_perfetto_trace_processor_sqlite)
+
+source_set("grammar") {
+  sources = [
+    "perfettosql_grammar.c",
+    "perfettosql_grammar.h",
+    "perfettosql_keywordhash.h",
+    "perfettosql_keywordhash_helper.h",
+  ]
+  deps = [
+    "../../../../gn:default_deps",
+    "../../../base",
+  ]
+  visibility = [
+    "../parser",
+    "../tokenizer",
+    "../tokenizer:tokenize_internal",
+  ]
+  if (perfetto_build_standalone) {
+    configs -= [ "//gn/standalone:extra_warnings" ]  # nogncheck
+  } else {
+    cflags_c = [
+      "-Wno-unused-parameter",
+      "-Wno-unreachable-code",
+    ]
+  }
+}
diff --git a/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.c b/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.c
new file mode 100644
index 0000000..194dc5a
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.c
@@ -0,0 +1,3972 @@
+/* This file is automatically generated by Lemon from input grammar
+** source file "src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.y".
+*/
+/*
+** 2000-05-29
+**
+** 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.
+**
+*************************************************************************
+** Driver template for the LEMON parser generator.
+**
+** The "lemon" program processes an LALR(1) input grammar file, then uses
+** this template to construct a parser.  The "lemon" program inserts text
+** at each "%%" line.  Also, any "P-a-r-s-e" identifer prefix (without the
+** interstitial "-" characters) contained in this template is changed into
+** the value of the %name directive from the grammar.  Otherwise, the content
+** of this template is copied straight through into the generate parser
+** source file.
+**
+** The following is the concatenation of all %include directives from the
+** input grammar file:
+*/
+/************ Begin %include sections from the grammar ************************/
+#include <stddef.h>
+
+#define YYNOERRORRECOVERY 1
+/**************** End of %include directives **********************************/
+/* These constants specify the various numeric values for terminal symbols.
+***************** Begin token definitions *************************************/
+#ifndef TK_OR
+#define TK_OR                              1
+#define TK_AND                             2
+#define TK_NOT                             3
+#define TK_IS                              4
+#define TK_MATCH                           5
+#define TK_LIKE_KW                         6
+#define TK_BETWEEN                         7
+#define TK_IN                              8
+#define TK_ISNULL                          9
+#define TK_NOTNULL                        10
+#define TK_NE                             11
+#define TK_EQ                             12
+#define TK_GT                             13
+#define TK_LE                             14
+#define TK_LT                             15
+#define TK_GE                             16
+#define TK_ESCAPE                         17
+#define TK_BITAND                         18
+#define TK_BITOR                          19
+#define TK_LSHIFT                         20
+#define TK_RSHIFT                         21
+#define TK_PLUS                           22
+#define TK_MINUS                          23
+#define TK_STAR                           24
+#define TK_SLASH                          25
+#define TK_REM                            26
+#define TK_CONCAT                         27
+#define TK_PTR                            28
+#define TK_COLLATE                        29
+#define TK_BITNOT                         30
+#define TK_ON                             31
+#define TK_ID                             32
+#define TK_ABORT                          33
+#define TK_ACTION                         34
+#define TK_AFTER                          35
+#define TK_ANALYZE                        36
+#define TK_ASC                            37
+#define TK_ATTACH                         38
+#define TK_BEFORE                         39
+#define TK_BEGIN                          40
+#define TK_BY                             41
+#define TK_CASCADE                        42
+#define TK_CAST                           43
+#define TK_COLUMNKW                       44
+#define TK_CONFLICT                       45
+#define TK_DATABASE                       46
+#define TK_DEFERRED                       47
+#define TK_DESC                           48
+#define TK_DETACH                         49
+#define TK_DO                             50
+#define TK_EACH                           51
+#define TK_END                            52
+#define TK_EXCLUSIVE                      53
+#define TK_EXPLAIN                        54
+#define TK_FAIL                           55
+#define TK_FOR                            56
+#define TK_IGNORE                         57
+#define TK_IMMEDIATE                      58
+#define TK_INITIALLY                      59
+#define TK_INSTEAD                        60
+#define TK_NO                             61
+#define TK_PLAN                           62
+#define TK_QUERY                          63
+#define TK_KEY                            64
+#define TK_OF                             65
+#define TK_OFFSET                         66
+#define TK_PRAGMA                         67
+#define TK_RAISE                          68
+#define TK_RECURSIVE                      69
+#define TK_RELEASE                        70
+#define TK_REPLACE                        71
+#define TK_RESTRICT                       72
+#define TK_ROW                            73
+#define TK_ROWS                           74
+#define TK_ROLLBACK                       75
+#define TK_SAVEPOINT                      76
+#define TK_TEMP                           77
+#define TK_TRIGGER                        78
+#define TK_VACUUM                         79
+#define TK_VIEW                           80
+#define TK_VIRTUAL                        81
+#define TK_WITH                           82
+#define TK_WITHOUT                        83
+#define TK_NULLS                          84
+#define TK_FIRST                          85
+#define TK_LAST                           86
+#define TK_EXCEPT                         87
+#define TK_INTERSECT                      88
+#define TK_UNION                          89
+#define TK_CURRENT                        90
+#define TK_FOLLOWING                      91
+#define TK_PARTITION                      92
+#define TK_PRECEDING                      93
+#define TK_RANGE                          94
+#define TK_UNBOUNDED                      95
+#define TK_EXCLUDE                        96
+#define TK_GROUPS                         97
+#define TK_OTHERS                         98
+#define TK_TIES                           99
+#define TK_WITHIN                         100
+#define TK_GENERATED                      101
+#define TK_ALWAYS                         102
+#define TK_MATERIALIZED                   103
+#define TK_REINDEX                        104
+#define TK_RENAME                         105
+#define TK_CTIME_KW                       106
+#define TK_IF                             107
+#define TK_ANY                            108
+#define TK_COMMIT                         109
+#define TK_TO                             110
+#define TK_TABLE                          111
+#define TK_CREATE                         112
+#define TK_EXISTS                         113
+#define TK_LP                             114
+#define TK_RP                             115
+#define TK_AS                             116
+#define TK_COMMA                          117
+#define TK_STRING                         118
+#define TK_CONSTRAINT                     119
+#define TK_DEFAULT                        120
+#define TK_INDEXED                        121
+#define TK_NULL                           122
+#define TK_PRIMARY                        123
+#define TK_UNIQUE                         124
+#define TK_CHECK                          125
+#define TK_REFERENCES                     126
+#define TK_AUTOINCR                       127
+#define TK_INSERT                         128
+#define TK_DELETE                         129
+#define TK_UPDATE                         130
+#define TK_SET                            131
+#define TK_DEFERRABLE                     132
+#define TK_FOREIGN                        133
+#define TK_DROP                           134
+#define TK_ALL                            135
+#define TK_SELECT                         136
+#define TK_VALUES                         137
+#define TK_DISTINCT                       138
+#define TK_DOT                            139
+#define TK_FROM                           140
+#define TK_JOIN                           141
+#define TK_JOIN_KW                        142
+#define TK_USING                          143
+#define TK_ORDER                          144
+#define TK_GROUP                          145
+#define TK_HAVING                         146
+#define TK_LIMIT                          147
+#define TK_WHERE                          148
+#define TK_RETURNING                      149
+#define TK_INTO                           150
+#define TK_NOTHING                        151
+#define TK_FLOAT                          152
+#define TK_BLOB                           153
+#define TK_INTEGER                        154
+#define TK_VARIABLE                       155
+#define TK_CASE                           156
+#define TK_WHEN                           157
+#define TK_THEN                           158
+#define TK_ELSE                           159
+#define TK_INDEX                          160
+#define TK_SEMI                           161
+#define TK_ALTER                          162
+#define TK_ADD                            163
+#define TK_WINDOW                         164
+#define TK_OVER                           165
+#define TK_FILTER                         166
+#define TK_TRANSACTION                    167
+#define TK_SPACE                          168
+#define TK_ILLEGAL                        169
+#endif
+/**************** End token definitions ***************************************/
+
+/* The next sections is a series of control #defines.
+** various aspects of the generated parser.
+**    YYCODETYPE         is the data type used to store the integer codes
+**                       that represent terminal and non-terminal symbols.
+**                       "unsigned char" is used if there are fewer than
+**                       256 symbols.  Larger types otherwise.
+**    YYNOCODE           is a number of type YYCODETYPE that is not used for
+**                       any terminal or nonterminal symbol.
+**    YYFALLBACK         If defined, this indicates that one or more tokens
+**                       (also known as: "terminal symbols") have fall-back
+**                       values which should be used if the original symbol
+**                       would not parse.  This permits keywords to sometimes
+**                       be used as identifiers, for example.
+**    YYACTIONTYPE       is the data type used for "action codes" - numbers
+**                       that indicate what to do in response to the next
+**                       token.
+**    PerfettoSqlParserTOKENTYPE     is the data type used for minor type for terminal
+**                       symbols.  Background: A "minor type" is a semantic
+**                       value associated with a terminal or non-terminal
+**                       symbols.  For example, for an "ID" terminal symbol,
+**                       the minor type might be the name of the identifier.
+**                       Each non-terminal can have a different minor type.
+**                       Terminal symbols all have the same minor type, though.
+**                       This macros defines the minor type for terminal 
+**                       symbols.
+**    YYMINORTYPE        is the data type used for all minor types.
+**                       This is typically a union of many types, one of
+**                       which is PerfettoSqlParserTOKENTYPE.  The entry in the union
+**                       for terminal symbols is called "yy0".
+**    YYSTACKDEPTH       is the maximum depth of the parser's stack.  If
+**                       zero the stack is dynamically sized using realloc()
+**    PerfettoSqlParserARG_SDECL     A static variable declaration for the %extra_argument
+**    PerfettoSqlParserARG_PDECL     A parameter declaration for the %extra_argument
+**    PerfettoSqlParserARG_PARAM     Code to pass %extra_argument as a subroutine parameter
+**    PerfettoSqlParserARG_STORE     Code to store %extra_argument into yypParser
+**    PerfettoSqlParserARG_FETCH     Code to extract %extra_argument from yypParser
+**    PerfettoSqlParserCTX_*         As PerfettoSqlParserARG_ except for %extra_context
+**    YYERRORSYMBOL      is the code number of the error symbol.  If not
+**                       defined, then do no error processing.
+**    YYNSTATE           the combined number of states.
+**    YYNRULE            the number of rules in the grammar
+**    YYNTOKEN           Number of terminal symbols
+**    YY_MAX_SHIFT       Maximum value for shift actions
+**    YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
+**    YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
+**    YY_ERROR_ACTION    The yy_action[] code for syntax error
+**    YY_ACCEPT_ACTION   The yy_action[] code for accept
+**    YY_NO_ACTION       The yy_action[] code for no-op
+**    YY_MIN_REDUCE      Minimum value for reduce actions
+**    YY_MAX_REDUCE      Maximum value for reduce actions
+*/
+#ifndef INTERFACE
+# define INTERFACE 1
+#endif
+/************* Begin control #defines *****************************************/
+#define YYCODETYPE unsigned short int
+#define YYNOCODE 303
+#define YYACTIONTYPE unsigned short int
+#define YYWILDCARD 108
+#define PerfettoSqlParserTOKENTYPE void*
+typedef union {
+  int yyinit;
+  PerfettoSqlParserTOKENTYPE yy0;
+} YYMINORTYPE;
+#ifndef YYSTACKDEPTH
+#define YYSTACKDEPTH 100
+#endif
+#define PerfettoSqlParserARG_SDECL
+#define PerfettoSqlParserARG_PDECL
+#define PerfettoSqlParserARG_PARAM
+#define PerfettoSqlParserARG_FETCH
+#define PerfettoSqlParserARG_STORE
+#define PerfettoSqlParserCTX_SDECL
+#define PerfettoSqlParserCTX_PDECL
+#define PerfettoSqlParserCTX_PARAM
+#define PerfettoSqlParserCTX_FETCH
+#define PerfettoSqlParserCTX_STORE
+#define YYFALLBACK 1
+#define YYNSTATE             579
+#define YYNRULE              405
+#define YYNRULE_WITH_ACTION  0
+#define YYNTOKEN             170
+#define YY_MAX_SHIFT         578
+#define YY_MIN_SHIFTREDUCE   838
+#define YY_MAX_SHIFTREDUCE   1242
+#define YY_ERROR_ACTION      1243
+#define YY_ACCEPT_ACTION     1244
+#define YY_NO_ACTION         1245
+#define YY_MIN_REDUCE        1246
+#define YY_MAX_REDUCE        1650
+/************* End control #defines *******************************************/
+#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
+
+/* Define the yytestcase() macro to be a no-op if is not already defined
+** otherwise.
+**
+** Applications can choose to define yytestcase() in the %include section
+** to a macro that can assist in verifying code coverage.  For production
+** code the yytestcase() macro should be turned off.  But it is useful
+** for testing.
+*/
+#ifndef yytestcase
+# define yytestcase(X)
+#endif
+
+
+/* Next are the 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 <= YY_MAX_SHIFT             Shift N.  That is, push the lookahead
+**                                      token onto the stack and goto state N.
+**
+**   N between YY_MIN_SHIFTREDUCE       Shift to an arbitrary state then
+**     and YY_MAX_SHIFTREDUCE           reduce by rule N-YY_MIN_SHIFTREDUCE.
+**
+**   N == YY_ERROR_ACTION               A syntax error has occurred.
+**
+**   N == YY_ACCEPT_ACTION              The parser accepts its input.
+**
+**   N == YY_NO_ACTION                  No such action.  Denotes unused
+**                                      slots in the yy_action[] table.
+**
+**   N between YY_MIN_REDUCE            Reduce by rule N-YY_MIN_REDUCE
+**     and YY_MAX_REDUCE
+**
+** The action table is constructed as a single large table named yy_action[].
+** Given state S and lookahead X, the action is computed as either:
+**
+**    (A)   N = yy_action[ yy_shift_ofst[S] + X ]
+**    (B)   N = yy_default[S]
+**
+** The (A) formula is preferred.  The B formula is used instead if
+** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X.
+**
+** The formulas above are 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.
+**
+** 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.
+**
+*********** Begin parsing tables **********************************************/
+#define YY_ACTTAB_COUNT (2094)
+static const YYACTIONTYPE yy_action[] = {
+ /*     0 */  1279,  126,  128,  411,   81, 1217, 1217, 1054, 1057, 1044,
+ /*    10 */  1044,  124,  124,  125,  125,  125,  125,   12,  123,  123,
+ /*    20 */   123,  123,  122,  122,  121,  121,  121,  120,  117,  449,
+ /*    30 */   121,  121,  121,  120,  117,  449,  208,  974,  122,  122,
+ /*    40 */   121,  121,  121,  120,  117,  449, 1563,    6,  975,  405,
+ /*    50 */   126,  128,  411,   81, 1217, 1217, 1054, 1057, 1044, 1044,
+ /*    60 */   124,  124,  125,  125,  125,  125,  449,  123,  123,  123,
+ /*    70 */   123,  122,  122,  121,  121,  121,  120,  117,  449,  126,
+ /*    80 */   128,  411,   81, 1217, 1217, 1054, 1057, 1044, 1044,  124,
+ /*    90 */   124,  125,  125,  125,  125,  503,  123,  123,  123,  123,
+ /*   100 */   122,  122,  121,  121,  121,  120,  117,  449,  126,  128,
+ /*   110 */   411,   81, 1217, 1217, 1054, 1057, 1044, 1044,  124,  124,
+ /*   120 */   125,  125,  125,  125, 1282,  123,  123,  123,  123,  122,
+ /*   130 */   122,  121,  121,  121,  120,  117,  449,  376, 1281,  284,
+ /*   140 */  1164,  960, 1164, 1613,  129,  125,  125,  125,  125,  118,
+ /*   150 */   123,  123,  123,  123,  122,  122,  121,  121,  121,  120,
+ /*   160 */   117,  449,  119,  116,  231,  960,  229,  125,  125,  125,
+ /*   170 */   125,   87,  123,  123,  123,  123,  122,  122,  121,  121,
+ /*   180 */   121,  120,  117,  449,  487,  359, 1529, 1138,  230,  536,
+ /*   190 */   119,  116,  231, 1140, 1642,  100, 1642,  126,  128,  411,
+ /*   200 */    81, 1217, 1217, 1054, 1057, 1044, 1044,  124,  124,  125,
+ /*   210 */   125,  125,  125,  342,  123,  123,  123,  123,  122,  122,
+ /*   220 */   121,  121,  121,  120,  117,  449,  126,  128,  411,   81,
+ /*   230 */  1217, 1217, 1054, 1057, 1044, 1044,  124,  124,  125,  125,
+ /*   240 */   125,  125, 1193,  123,  123,  123,  123,  122,  122,  121,
+ /*   250 */   121,  121,  120,  117,  449,  126,  128,  411,   81, 1217,
+ /*   260 */  1217, 1054, 1057, 1044, 1044,  124,  124,  125,  125,  125,
+ /*   270 */   125,  377,  123,  123,  123,  123,  122,  122,  121,  121,
+ /*   280 */   121,  120,  117,  449,  411,   81, 1217, 1217, 1054, 1057,
+ /*   290 */  1044, 1044,  124,  124,  125,  125,  125,  125, 1493,  123,
+ /*   300 */   123,  123,  123,  122,  122,  121,  121,  121,  120,  117,
+ /*   310 */   449,  321,  123,  123,  123,  123,  122,  122,  121,  121,
+ /*   320 */   121,  120,  117,  449,  119,  116,  231,  407, 1194,  233,
+ /*   330 */  1138, 1193,  529,  458,  455,  454, 1140, 1643, 1098, 1643,
+ /*   340 */   464,  518, 1098,  453,  570,  233,  570, 1644,  400,  458,
+ /*   350 */   455,  454, 1193,  119,  116,  231,  178,  974,  288,  453,
+ /*   360 */   288,   16,   16,  508,   42,   42,   42,   42,  975,  879,
+ /*   370 */   567,  126,  128,  411,   81, 1217, 1217, 1054, 1057, 1044,
+ /*   380 */  1044,  124,  124,  125,  125,  125,  125,  494,  123,  123,
+ /*   390 */   123,  123,  122,  122,  121,  121,  121,  120,  117,  449,
+ /*   400 */   126,  128,  411,   81, 1217, 1217, 1054, 1057, 1044, 1044,
+ /*   410 */   124,  124,  125,  125,  125,  125,  282,  123,  123,  123,
+ /*   420 */   123,  122,  122,  121,  121,  121,  120,  117,  449,  126,
+ /*   430 */   128,  411,   81, 1217, 1217, 1054, 1057, 1044, 1044,  124,
+ /*   440 */   124,  125,  125,  125,  125, 1557,  123,  123,  123,  123,
+ /*   450 */   122,  122,  121,  121,  121,  120,  117,  449,  570, 1118,
+ /*   460 */   519,  375,  843,  297,  375,  374,  374,  570,  845,  531,
+ /*   470 */   527,  527,    6,  844,  368,  119,  116,  231,   51,   51,
+ /*   480 */   459, 1119,  450,  915,  238,  872,  895,  134,  134,  498,
+ /*   490 */   459,  288,  459,  288,  288, 1300,  288,  916,  444,  443,
+ /*   500 */   288, 1117,  288,  567,  569,  467,  567,  261,  227,  418,
+ /*   510 */   415,  432,  567,  532,  427,   88,  896,  126,  128,  411,
+ /*   520 */    81, 1217, 1217, 1054, 1057, 1044, 1044,  124,  124,  125,
+ /*   530 */   125,  125,  125, 1193,  123,  123,  123,  123,  122,  122,
+ /*   540 */   121,  121,  121,  120,  117,  449,  126,  128,  411,   81,
+ /*   550 */  1217, 1217, 1054, 1057, 1044, 1044,  124,  124,  125,  125,
+ /*   560 */   125,  125, 1320,  123,  123,  123,  123,  122,  122,  121,
+ /*   570 */   121,  121,  120,  117,  449,  422,  432,  216,  344,  126,
+ /*   580 */   128,  411,   81, 1217, 1217, 1054, 1057, 1044, 1044,  124,
+ /*   590 */   124,  125,  125,  125,  125,  570,  123,  123,  123,  123,
+ /*   600 */   122,  122,  121,  121,  121,  120,  117,  449, 1317, 1031,
+ /*   610 */  1296,  328,  570,  433,  570,   74,   74, 1317,  570, 1194,
+ /*   620 */   570, 1020, 1193, 1320, 1159, 1019, 1355,  314, 1225,  370,
+ /*   630 */  1225, 1032,   13,   13,   13,   13,  225,  144,   13,   13,
+ /*   640 */    13,   13,  540, 1193, 1159, 1607,  419, 1159,  292, 1268,
+ /*   650 */   553,   90,  430, 1607,  435, 1019, 1019, 1021,  520,  219,
+ /*   660 */  1015, 1268,  126,  128,  411,   81, 1217, 1217, 1054, 1057,
+ /*   670 */  1044, 1044,  124,  124,  125,  125,  125,  125,  433,  123,
+ /*   680 */   123,  123,  123,  122,  122,  121,  121,  121,  120,  117,
+ /*   690 */   449,  319,  571, 1177,  539,  126,  128,  411,   81, 1217,
+ /*   700 */  1217, 1054, 1057, 1044, 1044,  124,  124,  125,  125,  125,
+ /*   710 */   125,   97,  123,  123,  123,  123,  122,  122,  121,  121,
+ /*   720 */   121,  120,  117,  449,  126,  128,  411,   81, 1217, 1217,
+ /*   730 */  1054, 1057, 1044, 1044,  124,  124,  125,  125,  125,  125,
+ /*   740 */  1556,  123,  123,  123,  123,  122,  122,  121,  121,  121,
+ /*   750 */   120,  117,  449,  126,  128,  411,   81, 1217, 1217, 1054,
+ /*   760 */  1057, 1044, 1044,  124,  124,  125,  125,  125,  125, 1096,
+ /*   770 */   123,  123,  123,  123,  122,  122,  121,  121,  121,  120,
+ /*   780 */   117,  449,  126,  115,  411,   81, 1217, 1217, 1054, 1057,
+ /*   790 */  1044, 1044,  124,  124,  125,  125,  125,  125,  502,  123,
+ /*   800 */   123,  123,  123,  122,  122,  121,  121,  121,  120,  117,
+ /*   810 */   449,  570, 1041, 1041, 1055, 1058,  208,  371,  529,  106,
+ /*   820 */   570,  496,  570,  523,  324,  444,  443, 1010,  570,  396,
+ /*   830 */   570,   13,   13,  570, 1222, 1193, 1193, 1322,  144,  211,
+ /*   840 */    72,   72,  136,  136,  502,  440,  487,  359,   74,   74,
+ /*   850 */    74,   74,  109,   74,   74,  128,  411,   81, 1217, 1217,
+ /*   860 */  1054, 1057, 1044, 1044,  124,  124,  125,  125,  125,  125,
+ /*   870 */   113,  123,  123,  123,  123,  122,  122,  121,  121,  121,
+ /*   880 */   120,  117,  449,  525,  357,  315, 1193,  234,  553,  111,
+ /*   890 */   111,  299,  319,  571,  301,  570,  552,  112, 1322,  447,
+ /*   900 */   381, 1193,  461,  461,    2,  462,  462,  570,  293,  153,
+ /*   910 */   565,  293,  153,  867,  113,   42,   42,  461,    8,  521,
+ /*   920 */   462, 1194, 1194, 1224, 1193, 1193,  368,   74,   74, 1045,
+ /*   930 */   530,  530, 1223,  111,  111,  559, 1271,  416,  148,  524,
+ /*   940 */   356,  112,  228,  447,  570, 1193, 1193,   97,  288,  144,
+ /*   950 */   288,  288,  478,  288,  565, 1225,  478, 1225,  475,  178,
+ /*   960 */   567,  438,  553,  567,   13,   13, 1193,  346,  193,  348,
+ /*   970 */   442,  570, 1194, 1031,  251, 1193, 1213,  251,  203,  559,
+ /*   980 */   562,    4,  281, 1266,  281,  568, 1584, 1194,  447, 1019,
+ /*   990 */  1193,   13,   13, 1193,  567,  152, 1193, 1193, 1334,  867,
+ /*  1000 */   349,  542, 1586,  319,  571,  204,  541,  570,  567,  447,
+ /*  1010 */   463, 1193,  544,  463,  288,  544,  288, 1031,  380, 1019,
+ /*  1020 */  1019, 1021, 1022,   28,  562,    4,  567,   13,   13,  568,
+ /*  1030 */   149,  940,  447, 1019,  427, 1587, 1233,  522,  245, 1193,
+ /*  1040 */   340,  547,  290,  855,  475,  474,  475,  485,  194,  347,
+ /*  1050 */   570,  339, 1194,  447,  394, 1193,  578, 1193, 1193,  523,
+ /*  1060 */   264,  554, 1213, 1019, 1019, 1021, 1022,   28,  113,  247,
+ /*  1070 */    74,   74,  391,  537,  537,    6, 1193,  393,  275, 1194,
+ /*  1080 */   570,  172, 1193, 1194,  143,  320, 1193,  111,  111, 1159,
+ /*  1090 */  1076, 1193,  288, 1313,  288,  112, 1193,  447,  209, 1159,
+ /*  1100 */    74,   74,  244, 1193,  567,  553,  246, 1193,  565, 1159,
+ /*  1110 */   570,  394, 1159,  555,  852,  424,  434,  549,  382, 1159,
+ /*  1120 */   373,  208, 1159,  300, 1498, 1194, 1485,  300, 1193, 1269,
+ /*  1130 */    74,   74,  103,  559,  397,  316,  412, 1299,  319,  571,
+ /*  1140 */     5,  421,  548, 1194, 1194, 1298, 1193, 1193,  513, 1193,
+ /*  1150 */     2,  462,  462, 1159,  291,  542,  496,  293,  153,  521,
+ /*  1160 */   543, 1193,  150, 1181,  473,  446,  462, 1193, 1193,  538,
+ /*  1170 */   144, 1031,  570, 1159, 1193,  113, 1159, 1194,  562,    4,
+ /*  1180 */  1193,  434, 1194,  568,  875, 1193,  447, 1019,  425,  120,
+ /*  1190 */   117,  449,   74,   74,  111,  111,  366,  288,  388,  288,
+ /*  1200 */   962, 1193,  112,  509,  447,  961, 1193,  447,  476,  567,
+ /*  1210 */  1498, 1500, 1498,  466, 1297,  565,  546, 1019, 1019, 1021,
+ /*  1220 */  1022,   28,  306,  251,  319,  571,  302,  448,  325,  390,
+ /*  1230 */   127,  240,  278,  515,  327,  469,  330,  468,  239, 1010,
+ /*  1240 */   559,  496,  513,   35,  328,  545,  370, 1194,  291,  471,
+ /*  1250 */  1193,  404,  403,  288, 1170,  288,    3,  548, 1031,  463,
+ /*  1260 */  1194, 1438,  542, 1193,  288,  567,  288,  541,  509,  329,
+ /*  1270 */  1020, 1193, 1278,  875, 1019,  564,  567,  522, 1031, 1244,
+ /*  1280 */     1,    1, 1528,  445, 1193,  562,    4,  155,  561, 1612,
+ /*  1290 */   568,  904, 1213,  447, 1019,  513,  357,  482,  345,  245,
+ /*  1300 */  1170,  340,  570,  290, 1019, 1019, 1021,  496,  378, 1438,
+ /*  1310 */  1118,  305,  339, 1539,  447,  394,  570,  578, 1541,  288,
+ /*  1320 */  1328,  288,   44,   44, 1019, 1019, 1021, 1022,   28,  113,
+ /*  1330 */   247,  567, 1119,  391,  558, 1492,   45,   45,  393,  275,
+ /*  1340 */   570,  492,  172,   85,  570,  143,  564,  564,  111,  111,
+ /*  1350 */   939,  288, 1117,  288,  445,  445,  112,  155,  447,  570,
+ /*  1360 */    46,   46,  570,  567,   47,   47,  500,  246,  570,  565,
+ /*  1370 */   570,  502,  394,  427,    9,  852,  264,  307, 1213,   56,
+ /*  1380 */    56,  370,   57,   57,  570,  370,  570,  513,   15,   15,
+ /*  1390 */    48,   48,  570,  513,  559,  570,  439,  412,  570,  319,
+ /*  1400 */   571,  113,  472,  533,   58,   58,   49,   49, 1353, 1101,
+ /*  1410 */  1101,  510,   59,   59,  570,   60,   60,  488,   61,   61,
+ /*  1420 */   111,  111,  158, 1212, 1181,  473,  154, 1329,  112,  570,
+ /*  1430 */   447,  570, 1031, 1325,   62,   62,  570,  210,  354,  562,
+ /*  1440 */     4,  565,  570, 1196,  568,   80,  219,  447, 1019,   63,
+ /*  1450 */    63,   64,   64, 1437,  370,  570,   65,   65,  289,  218,
+ /*  1460 */   289,  439,   66,   66,  111,  111,  559,  308,  447,  570,
+ /*  1470 */   567, 1537,  112,  570,  447,   67,   67,  570, 1019, 1019,
+ /*  1480 */  1021, 1022,   28, 1436,  501,  565,  570,  882,  570,   50,
+ /*  1490 */    50,  337,  158,   52,   52,  156,  154,   14,   14,   12,
+ /*  1500 */   378, 1437,  570,  960, 1031,  570,  132,  132,  133,  133,
+ /*  1510 */   559,  562,    4,  570,  935,  338,  568,  934,  570,  447,
+ /*  1520 */  1019,  570,   69,   69,  570,   53,   53,  960,  229, 1196,
+ /*  1530 */   378, 1436,  901,   70,   70,  238,  551,  570,   71,   71,
+ /*  1540 */   447,   54,   54,  902,  165,  165,  570,  110, 1031,  108,
+ /*  1550 */  1019, 1019, 1021, 1022,   28,  562,    4,  166,  166,  113,
+ /*  1560 */   568,  415,  570,  447, 1019,  156,   78,   78,  417,  929,
+ /*  1570 */   929,  572,  205,  882,  237,  236,  235,  486,  111,  111,
+ /*  1580 */   550,  570,   55,   55,  447,  341,  112,  245,  447,  340,
+ /*  1590 */   570,  290,  570,  296, 1019, 1019, 1021, 1022,   28,  565,
+ /*  1600 */   339,  135,  135,  394,  479, 1561,    6, 1367,  570,  480,
+ /*  1610 */    73,   73,  163,  163,  410,  570,  563,  416,  247,  410,
+ /*  1620 */   570,  391,  336,  570,  559,  570,  393,  275,  137,  137,
+ /*  1630 */   172,  570,  146,  143,   37,  131,  131, 1366,  570,  513,
+ /*  1640 */   164,  164, 1239,  157,  157,  141,  141,  507,  399, 1238,
+ /*  1650 */   517,  140,  140,  504,  103,  246,  199,   32,  138,  138,
+ /*  1660 */   394,  570, 1031,  852,  886, 1239, 1562,    6,  477,  562,
+ /*  1670 */     4,  399, 1139,  570,  568,  319,  571,  447, 1019,  364,
+ /*  1680 */   570,  139,  139,  570,  428,  412,  570,  319,  571, 1560,
+ /*  1690 */     6, 1559,    6,   76,   76,  570,  319,  571,  447, 1083,
+ /*  1700 */    68,   68,  225,   77,   77,  248,   75,   75, 1019, 1019,
+ /*  1710 */  1021, 1022,   28,  473,  489,   43,   43,  420,  180, 1023,
+ /*  1720 */   493,  318,  286,  227,  410,   91,  215,  451,  250,  260,
+ /*  1730 */   410,  410,  935,   98,  322,  934,  103, 1135,  894,  401,
+ /*  1740 */   893,  490,  334,  355, 1012,  103,  263,  495,   19,  263,
+ /*  1750 */  1144,  497,  333,  263,  360, 1079,  103,  260,  965,   31,
+ /*  1760 */   263,  161,  303,  103,  977,  978,  162, 1095, 1094, 1095,
+ /*  1770 */  1094,  865,  933,  151,  127,  287,  481,  932, 1544,  127,
+ /*  1780 */   350, 1517, 1516,  505,  361, 1083,  201, 1575, 1363,  365,
+ /*  1790 */   557,  221,  369,  514,  279,  534, 1376,  213, 1421, 1349,
+ /*  1800 */  1601,  556, 1426, 1346,  311, 1023,  387,  312, 1361,  224,
+ /*  1810 */   389,   11, 1257, 1256,  313,  243, 1258, 1594, 1408,  352,
+ /*  1820 */  1403,  395,  298, 1358,  456, 1396, 1597,  353, 1413, 1359,
+ /*  1830 */   499, 1412,  408,  304, 1296, 1357,  198,  470,   33,   83,
+ /*  1840 */   423,  886, 1233,  560,  182,  241,  272,  332, 1230,   90,
+ /*  1850 */  1489, 1488,   86,  460, 1494,  217, 1536,  191,  177, 1534,
+ /*  1860 */   483, 1316, 1315,  398,   89, 1314,  426,  575, 1609, 1611,
+ /*  1870 */  1286,  253,  358, 1610,  402, 1285,  484,  331, 1307,  220,
+ /*  1880 */  1284,  206,  385, 1306,  207,   98,  506,   96,  257,  512,
+ /*  1890 */  1356,  280,  259,  436,  437,  130,  548,  184,  265,  266,
+ /*  1900 */   186,  441,  187,  188,  189,  230,   10,  107,   99,  379,
+ /*  1910 */   526, 1417, 1187,  367,  195,  406,  277,  386,  271,  491,
+ /*  1920 */  1259,  273,  274,  409,  179, 1483,  333,  276,  576,   36,
+ /*  1930 */  1409, 1254, 1249,  232,  573,  452,   82,   17,  457,  323,
+ /*  1940 */    18, 1183, 1415, 1414,   38, 1339,  372,  170,  145,  142,
+ /*  1950 */  1182,  214,  884,  465,  222,  326,  384,  212, 1338,  383,
+ /*  1960 */   294,  223, 1521, 1522, 1520, 1381, 1380, 1519,   79,  897,
+ /*  1970 */   309,  295, 1505,   84,  310,  171,  335,  363,  242, 1093,
+ /*  1980 */   147, 1470, 1091,  343,  173,  317,  918, 1212,  183,  516,
+ /*  1990 */   185,  249,  252,  351,  190,  429, 1107,  174,  431,   92,
+ /*  2000 */    93,   94,  192,  175,   95, 1110,  254,  176, 1106, 1566,
+ /*  2010 */   159,   20, 1565,  256, 1099,  362,  255,  263,  511,  196,
+ /*  2020 */   167, 1227,  168, 1146, 1580,  258,  197,   39, 1145,  413,
+ /*  2030 */   226,  283,  285,  969,  262,  200,  963,  181,   21,  414,
+ /*  2040 */   127,  169, 1150,   34,  528,   22,  102, 1060,  202,  160,
+ /*  2050 */   101,  535,   23, 1175,   24,   25, 1161, 1165,    7, 1163,
+ /*  2060 */  1168,  103,   26, 1169,   27, 1074,  104, 1061,  267, 1064,
+ /*  2070 */  1059, 1116, 1115,  268,  928, 1063,  105,   41,   40, 1602,
+ /*  2080 */   269, 1024,  270,  574,  866,  114,   29,  392,   30,  854,
+ /*  2090 */   566,  839, 1245,  577,
+};
+static const YYCODETYPE yy_lookahead[] = {
+ /*     0 */   195,    1,    2,    3,    4,    5,    6,    7,    8,    9,
+ /*    10 */    10,   11,   12,   13,   14,   15,   16,  192,   18,   19,
+ /*    20 */    20,   21,   22,   23,   24,   25,   26,   27,   28,   29,
+ /*    30 */    24,   25,   26,   27,   28,   29,  175,   37,   22,   23,
+ /*    40 */    24,   25,   26,   27,   28,   29,  290,  291,   48,  188,
+ /*    50 */     1,    2,    3,    4,    5,    6,    7,    8,    9,   10,
+ /*    60 */    11,   12,   13,   14,   15,   16,   29,   18,   19,   20,
+ /*    70 */    21,   22,   23,   24,   25,   26,   27,   28,   29,    1,
+ /*    80 */     2,    3,    4,    5,    6,    7,    8,    9,   10,   11,
+ /*    90 */    12,   13,   14,   15,   16,  270,   18,   19,   20,   21,
+ /*   100 */    22,   23,   24,   25,   26,   27,   28,   29,    1,    2,
+ /*   110 */     3,    4,    5,    6,    7,    8,    9,   10,   11,   12,
+ /*   120 */    13,   14,   15,   16,  195,   18,   19,   20,   21,   22,
+ /*   130 */    23,   24,   25,   26,   27,   28,   29,  198,  195,  115,
+ /*   140 */    91,  117,   93,  208,   66,   13,   14,   15,   16,   17,
+ /*   150 */    18,   19,   20,   21,   22,   23,   24,   25,   26,   27,
+ /*   160 */    28,   29,  251,  252,  253,  141,  142,   13,   14,   15,
+ /*   170 */    16,   64,   18,   19,   20,   21,   22,   23,   24,   25,
+ /*   180 */    26,   27,   28,   29,  129,  130,  275,  108,  165,  166,
+ /*   190 */   251,  252,  253,  114,  115,  117,  117,    1,    2,    3,
+ /*   200 */     4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
+ /*   210 */    14,   15,   16,  175,   18,   19,   20,   21,   22,   23,
+ /*   220 */    24,   25,   26,   27,   28,   29,    1,    2,    3,    4,
+ /*   230 */     5,    6,    7,    8,    9,   10,   11,   12,   13,   14,
+ /*   240 */    15,   16,   32,   18,   19,   20,   21,   22,   23,   24,
+ /*   250 */    25,   26,   27,   28,   29,    1,    2,    3,    4,    5,
+ /*   260 */     6,    7,    8,    9,   10,   11,   12,   13,   14,   15,
+ /*   270 */    16,  198,   18,   19,   20,   21,   22,   23,   24,   25,
+ /*   280 */    26,   27,   28,   29,    3,    4,    5,    6,    7,    8,
+ /*   290 */     9,   10,   11,   12,   13,   14,   15,   16,  260,   18,
+ /*   300 */    19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+ /*   310 */    29,  115,   18,   19,   20,   21,   22,   23,   24,   25,
+ /*   320 */    26,   27,   28,   29,  251,  252,  253,  186,  118,  119,
+ /*   330 */   108,  121,  175,  123,  124,  125,  114,  115,   35,  117,
+ /*   340 */   115,  175,   39,  133,  175,  119,  175,  282,  283,  123,
+ /*   350 */   124,  125,  142,  251,  252,  253,  175,   37,  217,  133,
+ /*   360 */   219,  195,  196,   60,  195,  196,  195,  196,   48,  115,
+ /*   370 */   229,    1,    2,    3,    4,    5,    6,    7,    8,    9,
+ /*   380 */    10,   11,   12,   13,   14,   15,   16,  246,   18,   19,
+ /*   390 */    20,   21,   22,   23,   24,   25,   26,   27,   28,   29,
+ /*   400 */     1,    2,    3,    4,    5,    6,    7,    8,    9,   10,
+ /*   410 */    11,   12,   13,   14,   15,   16,  192,   18,   19,   20,
+ /*   420 */    21,   22,   23,   24,   25,   26,   27,   28,   29,    1,
+ /*   430 */     2,    3,    4,    5,    6,    7,    8,    9,   10,   11,
+ /*   440 */    12,   13,   14,   15,   16,  288,   18,   19,   20,   21,
+ /*   450 */    22,   23,   24,   25,   26,   27,   28,   29,  175,   33,
+ /*   460 */   186,  292,   47,  186,  295,  294,  295,  175,   53,  186,
+ /*   470 */   289,  290,  291,   58,  175,  251,  252,  253,  195,  196,
+ /*   480 */   175,   55,    3,   57,    5,  115,   42,  195,  196,  175,
+ /*   490 */   185,  217,  187,  219,  217,  205,  219,   71,   22,   23,
+ /*   500 */   217,   75,  219,  229,  175,   61,  229,  233,  234,  210,
+ /*   510 */    31,  175,  229,  230,  175,  116,   72,    1,    2,    3,
+ /*   520 */     4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
+ /*   530 */    14,   15,   16,   32,   18,   19,   20,   21,   22,   23,
+ /*   540 */    24,   25,   26,   27,   28,   29,    1,    2,    3,    4,
+ /*   550 */     5,    6,    7,    8,    9,   10,   11,   12,   13,   14,
+ /*   560 */    15,   16,  212,   18,   19,   20,   21,   22,   23,   24,
+ /*   570 */    25,   26,   27,   28,   29,  131,  240,  149,  239,    1,
+ /*   580 */     2,    3,    4,    5,    6,    7,    8,    9,   10,   11,
+ /*   590 */    12,   13,   14,   15,   16,  175,   18,   19,   20,   21,
+ /*   600 */    22,   23,   24,   25,   26,   27,   28,   29,  202,  106,
+ /*   610 */   204,  132,  175,  175,  175,  195,  196,  211,  175,  118,
+ /*   620 */   175,  118,  121,  273,   74,  122,  236,  237,  152,  175,
+ /*   630 */   154,  115,  195,  196,  195,  196,  117,   82,  195,  196,
+ /*   640 */   195,  196,   92,  142,   94,  194,  209,   97,  209,  175,
+ /*   650 */   230,  150,  209,  202,  209,  152,  153,  154,  238,  140,
+ /*   660 */   115,  187,    1,    2,    3,    4,    5,    6,    7,    8,
+ /*   670 */     9,   10,   11,   12,   13,   14,   15,   16,  240,   18,
+ /*   680 */    19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+ /*   690 */    29,  136,  137,  115,  144,    1,    2,    3,    4,    5,
+ /*   700 */     6,    7,    8,    9,   10,   11,   12,   13,   14,   15,
+ /*   710 */    16,   31,   18,   19,   20,   21,   22,   23,   24,   25,
+ /*   720 */    26,   27,   28,   29,    1,    2,    3,    4,    5,    6,
+ /*   730 */     7,    8,    9,   10,   11,   12,   13,   14,   15,   16,
+ /*   740 */   286,   18,   19,   20,   21,   22,   23,   24,   25,   26,
+ /*   750 */    27,   28,   29,    1,    2,    3,    4,    5,    6,    7,
+ /*   760 */     8,    9,   10,   11,   12,   13,   14,   15,   16,   52,
+ /*   770 */    18,   19,   20,   21,   22,   23,   24,   25,   26,   27,
+ /*   780 */    28,   29,    1,    2,    3,    4,    5,    6,    7,    8,
+ /*   790 */     9,   10,   11,   12,   13,   14,   15,   16,  175,   18,
+ /*   800 */    19,   20,   21,   22,   23,   24,   25,   26,   27,   28,
+ /*   810 */    29,  175,    5,    6,    7,    8,  175,  175,  175,  158,
+ /*   820 */   175,  175,  175,  143,  183,   22,   23,   71,  175,  188,
+ /*   830 */   175,  195,  196,  175,   31,   32,   32,  212,   82,  116,
+ /*   840 */   195,  196,  195,  196,  175,  209,  129,  130,  195,  196,
+ /*   850 */   195,  196,  158,  195,  196,    2,    3,    4,    5,    6,
+ /*   860 */     7,    8,    9,   10,   11,   12,   13,   14,   15,   16,
+ /*   870 */     3,   18,   19,   20,   21,   22,   23,   24,   25,   26,
+ /*   880 */    27,   28,   29,  230,  128,  230,   32,   83,  230,   22,
+ /*   890 */    23,  245,  136,  137,  271,  175,  238,   30,  273,   32,
+ /*   900 */   255,   32,  171,  172,  170,  171,  172,  175,  177,  178,
+ /*   910 */    43,  177,  178,   32,    3,  195,  196,  186,    7,    3,
+ /*   920 */   186,  118,  118,  120,  121,  121,  175,  195,  196,  122,
+ /*   930 */   287,  288,  129,   22,   23,   68,  189,  190,   69,  175,
+ /*   940 */   271,   30,  175,   32,  175,  142,  142,   31,  217,   82,
+ /*   950 */   219,  217,  237,  219,   43,  152,  241,  154,  175,  175,
+ /*   960 */   229,  210,  230,  229,  195,  196,   32,   78,  114,   80,
+ /*   970 */   238,  175,  118,  106,  243,  121,   32,  243,  209,   68,
+ /*   980 */   113,  114,  217,  186,  219,  118,  175,  118,  121,  122,
+ /*   990 */   121,  195,  196,   32,  229,  114,  142,   32,  219,  118,
+ /*  1000 */   111,   90,    0,  136,  137,  209,   95,  175,  229,  142,
+ /*  1010 */   279,  142,  292,  279,  217,  295,  219,  106,  175,  152,
+ /*  1020 */   153,  154,  155,  156,  113,  114,  229,  195,  196,  118,
+ /*  1030 */    69,   24,  121,  122,  175,  301,   44,  121,   36,   32,
+ /*  1040 */    38,  209,   40,   77,  261,  262,  263,   81,  114,  160,
+ /*  1050 */   175,   49,  118,  142,   52,  121,   54,   32,   32,  143,
+ /*  1060 */   116,  186,  118,  152,  153,  154,  155,  156,    3,   67,
+ /*  1070 */   195,  196,   70,  289,  290,  291,  142,   75,   76,  118,
+ /*  1080 */   175,   79,  121,  118,   82,  175,  121,   22,   23,   74,
+ /*  1090 */   124,   32,  217,  175,  219,   30,   32,   32,  239,   74,
+ /*  1100 */   195,  196,  110,  142,  229,  230,  104,  142,   43,   94,
+ /*  1110 */   175,  109,   97,  238,  112,    3,  175,   92,  226,   94,
+ /*  1120 */   228,  175,   97,  237,  175,  118,  160,  241,  121,  175,
+ /*  1130 */   195,  196,  117,   68,  188,  230,  134,  205,  136,  137,
+ /*  1140 */   114,   29,  144,  118,  118,  205,  121,  121,  175,  142,
+ /*  1150 */   170,  171,  172,   74,  208,   90,  175,  177,  178,    3,
+ /*  1160 */    95,   32,  164,  161,  162,  230,  186,  142,  142,  144,
+ /*  1170 */    82,  106,  175,   94,   32,    3,   97,  118,  113,  114,
+ /*  1180 */   121,  240,  118,  118,   32,  121,  121,  122,  215,   27,
+ /*  1190 */    28,   29,  195,  196,   22,   23,   78,  217,   80,  219,
+ /*  1200 */   141,  142,   30,  175,   32,  141,  142,  142,  120,  229,
+ /*  1210 */   261,  262,  263,  101,  175,   43,   61,  152,  153,  154,
+ /*  1220 */   155,  156,  186,  243,  136,  137,  245,  230,  116,  111,
+ /*  1230 */   117,  119,  120,  186,  122,  123,  124,  125,  126,   71,
+ /*  1240 */    68,  175,  175,  114,  132,   90,  175,  118,  302,  276,
+ /*  1250 */   121,   22,   23,  217,   99,  219,  114,  144,  106,  279,
+ /*  1260 */   118,  250,   90,  121,  217,  229,  219,   95,  240,  175,
+ /*  1270 */   118,  142,  175,  121,  122,  191,  229,  121,  106,  299,
+ /*  1280 */   300,  301,  215,  191,  142,  113,  114,  216,  186,  115,
+ /*  1290 */   118,  117,   32,  121,  122,  175,  128,  129,  130,   36,
+ /*  1300 */   145,   38,  175,   40,  152,  153,  154,  175,  297,  298,
+ /*  1310 */    33,  245,   49,  175,  142,   52,  175,   54,  175,  217,
+ /*  1320 */   186,  219,  195,  196,  152,  153,  154,  155,  156,    3,
+ /*  1330 */    67,  229,   55,   70,   57,  215,  195,  196,   75,   76,
+ /*  1340 */   175,   31,   79,  114,  175,   82,  262,  263,   22,   23,
+ /*  1350 */    24,  217,   75,  219,  262,  263,   30,  286,   32,  175,
+ /*  1360 */   195,  196,  175,  229,  195,  196,    3,  104,  175,   43,
+ /*  1370 */   175,  175,  109,  175,  114,  112,  116,  245,  118,  195,
+ /*  1380 */   196,  175,  195,  196,  175,  175,  175,  175,  195,  196,
+ /*  1390 */   195,  196,  175,  175,   68,  175,  175,  134,  175,  136,
+ /*  1400 */   137,    3,  175,   24,  195,  196,  195,  196,  235,  128,
+ /*  1410 */   129,  130,  195,  196,  175,  195,  196,  130,  195,  196,
+ /*  1420 */    22,   23,  216,  117,  161,  162,  216,  215,   30,  175,
+ /*  1430 */    32,  175,  106,  215,  195,  196,  175,  239,  151,  113,
+ /*  1440 */   114,   43,  175,   32,  118,    3,  140,  121,  122,  195,
+ /*  1450 */   196,  195,  196,  250,  175,  175,  195,  196,  217,  149,
+ /*  1460 */   219,  240,  195,  196,   22,   23,   68,  271,  142,  175,
+ /*  1470 */   229,  175,   30,  175,   32,  195,  196,  175,  152,  153,
+ /*  1480 */   154,  155,  156,  250,  121,   43,  175,   32,  175,  195,
+ /*  1490 */   196,  175,  286,  195,  196,  216,  286,  195,  196,  192,
+ /*  1500 */   297,  298,  175,  117,  106,  175,  195,  196,  195,  196,
+ /*  1510 */    68,  113,  114,  175,  135,  175,  118,  138,  175,  121,
+ /*  1520 */   122,  175,  195,  196,  175,  195,  196,  141,  142,  118,
+ /*  1530 */   297,  298,   47,  195,  196,    5,  138,  175,  195,  196,
+ /*  1540 */   142,  195,  196,   58,  195,  196,  175,  157,  106,  159,
+ /*  1550 */   152,  153,  154,  155,  156,  113,  114,  195,  196,    3,
+ /*  1560 */   118,   31,  175,  121,  122,  286,  195,  196,  179,   87,
+ /*  1570 */    88,   89,  265,  118,  128,  129,  130,  270,   22,   23,
+ /*  1580 */   138,  175,  195,  196,  142,  175,   30,   36,   32,   38,
+ /*  1590 */   175,   40,  175,  105,  152,  153,  154,  155,  156,   43,
+ /*  1600 */    49,  195,  196,   52,  221,  290,  291,  175,  175,  221,
+ /*  1610 */   195,  196,  195,  196,  231,  175,  189,  190,   67,  231,
+ /*  1620 */   175,   70,  134,  175,   68,  175,   75,   76,  195,  196,
+ /*  1630 */    79,  175,  114,   82,  116,  195,  196,  175,  175,  175,
+ /*  1640 */   195,  196,  108,  195,  196,  195,  196,  258,  114,  115,
+ /*  1650 */     3,  195,  196,  264,  117,  104,  117,   12,  195,  196,
+ /*  1660 */   109,  175,  106,  112,  127,  108,  290,  291,  246,  113,
+ /*  1670 */   114,  114,  115,  175,  118,  136,  137,  121,  122,  215,
+ /*  1680 */   175,  195,  196,  175,   50,  134,  175,  136,  137,  290,
+ /*  1690 */   291,  290,  291,  195,  196,  175,  136,  137,  142,   32,
+ /*  1700 */   195,  196,  117,  195,  196,  116,  195,  196,  152,  153,
+ /*  1710 */   154,  155,  156,  162,  221,  195,  196,  280,  281,   32,
+ /*  1720 */   221,  221,  233,  234,  231,  148,  149,  115,  139,  117,
+ /*  1730 */   231,  231,  135,  148,  115,  138,  117,  115,  120,  117,
+ /*  1740 */   122,  130,  122,  115,  115,  117,  117,  115,  114,  117,
+ /*  1750 */   103,  115,  132,  117,  115,  115,  117,  117,  115,  114,
+ /*  1760 */   117,  115,  151,  117,   85,   86,  115,  152,  152,  154,
+ /*  1770 */   154,  115,  115,  117,  117,  114,  175,  115,  175,  117,
+ /*  1780 */   175,  175,  175,  175,  175,  118,  232,  296,  175,  175,
+ /*  1790 */   273,  193,  175,  267,  266,  144,  175,  218,  175,  175,
+ /*  1800 */   139,  175,  175,  232,  232,  118,  175,  232,  175,  207,
+ /*  1810 */   175,  220,  175,  175,  232,  277,  175,  175,  248,  272,
+ /*  1820 */   244,  173,  222,  236,  199,  244,  182,  223,  248,  236,
+ /*  1830 */   272,  248,  248,  223,  204,  236,  114,   31,  117,  114,
+ /*  1840 */    59,  127,   44,  257,  277,  277,  139,  198,   46,  150,
+ /*  1850 */   198,  198,  274,  184,  260,  149,  181,  114,    1,  181,
+ /*  1860 */   107,  197,  197,  200,  274,  197,  181,  107,  197,  203,
+ /*  1870 */   197,  180,  222,  203,  200,  199,  181,  197,  206,  220,
+ /*  1880 */   197,  226,  222,  206,  226,  148,  181,  157,  180,   56,
+ /*  1890 */   236,  181,  180,  116,   29,  147,  144,  213,  181,   96,
+ /*  1900 */   214,   84,  214,  214,  214,  165,  114,  157,  146,  181,
+ /*  1910 */   145,  213,   76,  200,  213,  223,  167,  181,  180,  223,
+ /*  1920 */   181,  180,  176,  223,  114,  223,  132,  176,  174,  247,
+ /*  1930 */   249,  174,  174,  126,  200,   64,  114,  114,   64,  115,
+ /*  1940 */   114,  161,  249,  249,  247,  227,  226,  117,  201,  115,
+ /*  1950 */   161,  114,   32,  102,  193,  116,  223,  225,  227,  224,
+ /*  1960 */   201,  193,  192,  192,  192,  242,  242,  192,  192,   34,
+ /*  1970 */   259,   64,  269,  114,  259,   45,  163,  268,  110,  115,
+ /*  1980 */   111,  254,  115,  137,  131,  256,  113,  117,  150,  285,
+ /*  1990 */   140,  116,  143,  111,  140,   50,  161,  131,   45,   12,
+ /*  2000 */    12,   12,  150,  131,   12,  121,   41,  131,  161,  293,
+ /*  2010 */    40,  114,  293,   31,   65,  160,  139,  117,   51,   65,
+ /*  2020 */   278,   73,  278,  115,  298,  139,   31,  114,  103,  284,
+ /*  2030 */   139,  115,  115,  121,   41,  114,  141,  281,   41,  284,
+ /*  2040 */   117,  278,  115,  114,  116,   41,  148,  115,  117,  115,
+ /*  2050 */   117,  114,   41,  115,   41,   41,   93,   73,    2,   91,
+ /*  2060 */    98,  117,   41,   73,   41,  115,  140,  115,  117,   52,
+ /*  2070 */   115,  115,  115,  114,  135,  115,  140,  116,  114,  139,
+ /*  2080 */   139,  115,  139,    3,  115,  114,  114,  110,  114,  113,
+ /*  2090 */   117,   62,  303,   63,  303,  303,  303,  303,  303,  303,
+ /*  2100 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2110 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2120 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2130 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2140 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2150 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2160 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2170 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2180 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2190 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2200 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2210 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2220 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2230 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2240 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2250 */   303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+ /*  2260 */   303,  303,  303,  303,
+};
+#define YY_SHIFT_COUNT    (578)
+#define YY_SHIFT_MIN      (0)
+#define YY_SHIFT_MAX      (2080)
+static const unsigned short int yy_shift_ofst[] = {
+ /*     0 */  1263, 1002, 1551,  867,  867,  555,  911, 1065, 1172, 1556,
+ /*    10 */  1556, 1556,  756,    0,    0,  107,  752, 1556, 1556, 1556,
+ /*    20 */  1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556,
+ /*    30 */  1556,  803,  803,  210, 1025, 1025, 1088,  555,  555,  555,
+ /*    40 */   555,  555,   49,   78,  196,  225,  254,  370,  399,  428,
+ /*    50 */   516,  545,  578,  661,  694,  723,  752,  752,  752,  752,
+ /*    60 */   752,  752,  752,  752,  752,  752,  752,  752,  752,  752,
+ /*    70 */   752,  752,  752,  781,  752,  752,  853,  281,  281, 1326,
+ /*    80 */  1398, 1442, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556,
+ /*    90 */  1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556,
+ /*   100 */  1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556,
+ /*   110 */  1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556,
+ /*   120 */  1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556, 1556,
+ /*   130 */  1556,  132,  154,  154,  154,  154,  154,  154,  154,  294,
+ /*   140 */    16,    6,  804,  869,  961,  479,  965,  965,  965,  965,
+ /*   150 */   965,  476,  476,  966, 1539, 1539, 1539, 1162, 1539,   55,
+ /*   160 */    23,   23,   23,   37,   37, 2094, 2094, 1112, 1112, 1112,
+ /*   170 */   804,  426,  501,  854,  854,  854,  854,  426,  550,  965,
+ /*   180 */    79,  222,  965,  965,  965,  965,  965,  965,  965,  965,
+ /*   190 */   965,  965,  965,  965,  965,  965,  965,  965,  965,  965,
+ /*   200 */   965,  916,  965, 1015, 1015,  717, 1079, 1079, 1411, 1156,
+ /*   210 */  1156, 1411,  998, 1560, 2094, 2094, 2094, 2094, 2094, 2094,
+ /*   220 */  2094, 1152,  503,  503,  226,  934, 1007, 1026, 1059, 1064,
+ /*   230 */  1129, 1142,  965,  965,  965,  444,  444,  444,  965,  965,
+ /*   240 */   965,  965,  965,  965,  965,  965,  965,  965,  965,  965,
+ /*   250 */   965, 1168,  965,  965,  965,  965,  965,  965,  965,  965,
+ /*   260 */   965,   24,  965,  965,  965, 1260, 1155,  965, 1277,  965,
+ /*   270 */   965,  965,  965,  965,  965,  965,  965,  965, 1229, 1281,
+ /*   280 */   303, 1482,  944,  944,  944,  944, 1386, 1379, 1482, 1482,
+ /*   290 */   415, 1174, 1537, 1518, 1530,  320,  992, 1310, 1577,  519,
+ /*   300 */  1577, 1363, 1585, 1310, 1310, 1585, 1310,  519, 1363,  320,
+ /*   310 */   320,  680,  680,  680,  680, 1113, 1113, 1390, 1306, 1597,
+ /*   320 */  1722, 1806, 1806, 1806, 1721, 1725, 1725, 1806, 1781, 1722,
+ /*   330 */  1806, 1714, 1806, 1781, 1806, 1798, 1798, 1707, 1707, 1802,
+ /*   340 */  1802, 1707, 1699, 1706, 1743, 1857, 1753, 1753, 1753, 1753,
+ /*   350 */  1707, 1760, 1737, 1706, 1706, 1737, 1743, 1857, 1737, 1857,
+ /*   360 */  1737, 1707, 1760, 1730, 1833, 1707, 1760, 1777, 1865, 1865,
+ /*   370 */  1722, 1707, 1748, 1752, 1803, 1803, 1817, 1817, 1740, 1792,
+ /*   380 */  1707, 1750, 1748, 1762, 1765, 1737, 1722, 1707, 1760, 1707,
+ /*   390 */  1760, 1836, 1836, 1749, 1749, 1749, 2094, 2094, 2094, 2094,
+ /*   400 */  2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094, 2094,
+ /*   410 */  2094,  807,  889, 1534, 1557, 1446,  881, 1118, 1612, 1619,
+ /*   420 */  1622, 1455, 1618, 1485, 1620, 1488, 1645, 1589, 1287, 1611,
+ /*   430 */  1628, 1634, 1629, 1632, 1636, 1639, 1647, 1667, 1640, 1643,
+ /*   440 */  1646, 1679, 1651, 1615, 1616, 1656, 1657, 1661, 1662, 1687,
+ /*   450 */  1794, 1807, 1810, 1871, 1822, 1823, 1824, 1826, 1874, 1830,
+ /*   460 */  1834, 1780, 1789, 1837, 1920, 1839, 1851, 1935, 1859, 1907,
+ /*   470 */  1930, 1813, 1868, 1869, 1864, 1867, 1846, 1838, 1853, 1870,
+ /*   480 */  1870, 1875, 1850, 1873, 1849, 1882, 1835, 1854, 1866, 1870,
+ /*   490 */  1872, 1945, 1953, 1870, 1852, 1987, 1988, 1989, 1992, 1876,
+ /*   500 */  1884, 1965, 1877, 1847, 1970, 1897, 1982, 1855, 1949, 1900,
+ /*   510 */  1954, 1948, 1967, 1886, 1995, 1908, 1913, 1925, 1891, 1916,
+ /*   520 */  1917, 1912, 1993, 1921, 1895, 1923, 1997, 1927, 1929, 1928,
+ /*   530 */  1931, 1932, 1933, 1934, 2004, 1898, 1937, 1938, 2011, 2013,
+ /*   540 */  2014, 1963, 1984, 1968, 2056, 1990, 1962, 1944, 2021, 2023,
+ /*   550 */  1926, 1936, 1950, 1923, 1952, 1955, 1956, 1951, 1957, 1959,
+ /*   560 */  2017, 1960, 1964, 1966, 1969, 1971, 1972, 1973, 1940, 1941,
+ /*   570 */  1943, 1974, 1939, 1961, 1976, 2080, 1977, 2029, 2030,
+};
+#define YY_REDUCE_COUNT (410)
+#define YY_REDUCE_MIN   (-244)
+#define YY_REDUCE_MAX   (1776)
+static const short yy_reduce_ofst[] = {
+ /*     0 */   980,  734,  731,  875,  283,  274,  169,  171,  720,  420,
+ /*    10 */   658,  732,  141,  -61,   73,  -89,  224,  437,  439,  443,
+ /*    20 */   445,  653,  636,  769,  796,  655,  832,  905,  645,  935,
+ /*    30 */   997,  783,  949,  946,  181,  784,  277,  797, 1036, 1047,
+ /*    40 */  1102, 1134,  102,  102,  102,  102,  102,  102,  102,  102,
+ /*    50 */   102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+ /*    60 */   102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+ /*    70 */   102,  102,  102,  102,  102,  102,  102,  102,  102,  166,
+ /*    80 */   292,  647, 1127, 1141, 1165, 1169, 1184, 1187, 1193, 1195,
+ /*    90 */  1209, 1211, 1217, 1220, 1223, 1239, 1254, 1256, 1261, 1267,
+ /*   100 */  1280, 1294, 1298, 1302, 1311, 1313, 1327, 1330, 1338, 1343,
+ /*   110 */  1346, 1349, 1362, 1371, 1387, 1406, 1415, 1417, 1433, 1440,
+ /*   120 */  1445, 1448, 1450, 1456, 1463, 1486, 1498, 1505, 1508, 1511,
+ /*   130 */  1520,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+ /*   140 */   102,  102,  305, 1071, 1206,  406,  641,  973, 1210, 1279,
+ /*   150 */   643, 1084, 1092, 1389,  765, 1241,  765,  102, 1241, 1307,
+ /*   160 */  1011, 1203, 1233,  102,  102,  102,  102,  451,  451,  451,
+ /*   170 */   474,  350,   38,  646,  981, 1066, 1132,  625, -244,  299,
+ /*   180 */    65,   65, -139,  339,  859, 1198, 1067, 1120, 1212, 1218,
+ /*   190 */   623,  336,  669,  438,  941, 1196, 1028, 1464,  751,  454,
+ /*   200 */  1221,  390,  157, 1315, 1376, -175, 1399, 1401,  747,  715,
+ /*   210 */   886, 1427,  892,  779, 1437, 1383, 1388, 1493, 1499, 1489,
+ /*   220 */  1500, -195,  -71,  -57,  -65,  314,  329,  642,  764,  767,
+ /*   230 */   811,  843,  910,  918,  954,  290,  932,  940, 1039, 1094,
+ /*   240 */  1097, 1138, 1143, 1227, 1296, 1316, 1340, 1410, 1432, 1462,
+ /*   250 */  1601, 1422, 1603, 1605, 1606, 1607, 1608, 1609, 1613, 1614,
+ /*   260 */  1617, 1173, 1621, 1623, 1624, 1554, 1491, 1626, 1517, 1627,
+ /*   270 */   329, 1631, 1633, 1635, 1637, 1638, 1641, 1642, 1598, 1526,
+ /*   280 */  1528, 1579, 1571, 1572, 1575, 1582, 1173, 1591, 1579, 1579,
+ /*   290 */  1648, 1602, 1625, 1644, 1630, 1649, 1538, 1570, 1576, 1600,
+ /*   300 */  1581, 1547, 1604, 1580, 1583, 1610, 1584, 1650, 1558, 1652,
+ /*   310 */  1653, 1587, 1593, 1599, 1654, 1655, 1658, 1586, 1660, 1659,
+ /*   320 */  1663, 1664, 1665, 1668, 1669, 1666, 1670, 1671, 1672, 1674,
+ /*   330 */  1673, 1676, 1680, 1677, 1683, 1567, 1568, 1675, 1678, 1578,
+ /*   340 */  1590, 1685, 1594, 1681, 1682, 1684, 1686, 1688, 1689, 1690,
+ /*   350 */  1695, 1691, 1692, 1693, 1694, 1696, 1697, 1698, 1700, 1701,
+ /*   360 */  1702, 1705, 1708, 1703, 1709, 1710, 1712, 1704, 1711, 1715,
+ /*   370 */  1713, 1717, 1718, 1720, 1716, 1719, 1723, 1724, 1726, 1727,
+ /*   380 */  1728, 1729, 1731, 1732, 1735, 1733, 1734, 1736, 1738, 1739,
+ /*   390 */  1741, 1746, 1751, 1754, 1757, 1758, 1742, 1744, 1747, 1745,
+ /*   400 */  1755, 1756, 1759, 1761, 1768, 1763, 1770, 1771, 1772, 1775,
+ /*   410 */  1776,
+};
+static const YYACTIONTYPE yy_default[] = {
+ /*     0 */  1648, 1648, 1648, 1478, 1243, 1354, 1243, 1243, 1243, 1478,
+ /*    10 */  1478, 1478, 1243, 1384, 1384, 1531, 1276, 1243, 1243, 1243,
+ /*    20 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1477, 1243,
+ /*    30 */  1243, 1243, 1243, 1243, 1564, 1564, 1243, 1243, 1243, 1243,
+ /*    40 */  1243, 1243, 1243, 1393, 1243, 1243, 1243, 1243, 1243, 1400,
+ /*    50 */  1479, 1480, 1243, 1243, 1243, 1243, 1530, 1532, 1495, 1407,
+ /*    60 */  1406, 1405, 1404, 1513, 1372, 1398, 1391, 1395, 1479, 1474,
+ /*    70 */  1475, 1473, 1626, 1243, 1480, 1394, 1442, 1441, 1458, 1243,
+ /*    80 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*    90 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   100 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   110 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   120 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   130 */  1243, 1450, 1457, 1456, 1455, 1464, 1454, 1451, 1444, 1443,
+ /*   140 */  1445, 1446, 1267, 1243, 1243, 1318, 1243, 1243, 1243, 1243,
+ /*   150 */  1243, 1243, 1243, 1264, 1550, 1549, 1243, 1447, 1243, 1276,
+ /*   160 */  1435, 1434, 1433, 1461, 1448, 1460, 1459, 1600, 1599, 1538,
+ /*   170 */  1243, 1243, 1496, 1243, 1243, 1243, 1243, 1243, 1564, 1243,
+ /*   180 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   190 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   200 */  1243, 1374, 1243, 1564, 1564, 1276, 1564, 1564, 1272, 1375,
+ /*   210 */  1375, 1272, 1378, 1243, 1545, 1345, 1345, 1345, 1345, 1354,
+ /*   220 */  1345, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   230 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   240 */  1243, 1243, 1243, 1243, 1243, 1535, 1533, 1243, 1243, 1243,
+ /*   250 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   260 */  1243, 1243, 1243, 1243, 1243, 1350, 1243, 1243, 1243, 1243,
+ /*   270 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1593, 1277, 1243,
+ /*   280 */  1508, 1332, 1350, 1350, 1350, 1350, 1352, 1344, 1333, 1331,
+ /*   290 */  1250, 1615, 1293, 1243, 1288, 1384, 1640, 1410, 1399, 1351,
+ /*   300 */  1399, 1637, 1397, 1410, 1410, 1397, 1410, 1351, 1637, 1384,
+ /*   310 */  1384, 1374, 1374, 1374, 1374, 1378, 1378, 1476, 1351, 1344,
+ /*   320 */  1486, 1319, 1319, 1319, 1311, 1243, 1243, 1319, 1308, 1486,
+ /*   330 */  1319, 1293, 1319, 1308, 1319, 1640, 1640, 1360, 1360, 1639,
+ /*   340 */  1639, 1360, 1496, 1623, 1419, 1321, 1327, 1327, 1327, 1327,
+ /*   350 */  1360, 1261, 1397, 1623, 1623, 1397, 1419, 1321, 1397, 1321,
+ /*   360 */  1397, 1360, 1261, 1512, 1634, 1360, 1261, 1243, 1490, 1490,
+ /*   370 */  1486, 1360, 1392, 1378, 1574, 1574, 1387, 1387, 1582, 1481,
+ /*   380 */  1360, 1243, 1392, 1390, 1388, 1397, 1486, 1360, 1261, 1360,
+ /*   390 */  1261, 1596, 1596, 1592, 1592, 1592, 1608, 1608, 1295, 1645,
+ /*   400 */  1645, 1545, 1295, 1277, 1277, 1608, 1276, 1276, 1276, 1276,
+ /*   410 */  1276, 1243, 1243, 1243, 1243, 1243, 1603, 1243, 1243, 1243,
+ /*   420 */  1243, 1243, 1243, 1243, 1243, 1540, 1497, 1364, 1243, 1243,
+ /*   430 */  1243, 1243, 1243, 1243, 1243, 1243, 1551, 1243, 1243, 1243,
+ /*   440 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1424, 1243, 1243,
+ /*   450 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1265,
+ /*   460 */  1243, 1243, 1243, 1542, 1291, 1243, 1243, 1243, 1243, 1243,
+ /*   470 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1401,
+ /*   480 */  1402, 1365, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1416,
+ /*   490 */  1243, 1243, 1243, 1411, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   500 */  1243, 1243, 1636, 1243, 1243, 1243, 1243, 1243, 1243, 1511,
+ /*   510 */  1510, 1243, 1243, 1362, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   520 */  1243, 1243, 1243, 1243, 1243, 1389, 1243, 1243, 1243, 1243,
+ /*   530 */  1579, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   540 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1379, 1243, 1243,
+ /*   550 */  1243, 1243, 1243, 1627, 1243, 1243, 1243, 1243, 1243, 1243,
+ /*   560 */  1243, 1243, 1243, 1243, 1243, 1243, 1243, 1619, 1428, 1425,
+ /*   570 */  1243, 1243, 1335, 1243, 1243, 1243, 1255, 1243, 1246,
+};
+/********** End of lemon-generated parsing tables *****************************/
+
+/* The next table maps tokens (terminal symbols) into fallback tokens.  
+** If a construct like the following:
+** 
+**      %fallback ID X Y Z.
+**
+** appears in the grammar, 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.
+**
+** This feature can be used, for example, to cause some keywords in a language
+** to revert to identifiers if they keyword does not apply in the context where
+** it appears.
+*/
+#ifdef YYFALLBACK
+static const YYCODETYPE yyFallback[] = {
+    0,  /*          $ => nothing */
+    0,  /*         OR => nothing */
+    0,  /*        AND => nothing */
+    0,  /*        NOT => nothing */
+    0,  /*         IS => nothing */
+   32,  /*      MATCH => ID */
+   32,  /*    LIKE_KW => ID */
+    0,  /*    BETWEEN => nothing */
+    0,  /*         IN => nothing */
+    0,  /*     ISNULL => nothing */
+    0,  /*    NOTNULL => nothing */
+    0,  /*         NE => nothing */
+    0,  /*         EQ => nothing */
+    0,  /*         GT => nothing */
+    0,  /*         LE => nothing */
+    0,  /*         LT => nothing */
+    0,  /*         GE => nothing */
+    0,  /*     ESCAPE => nothing */
+    0,  /*     BITAND => nothing */
+    0,  /*      BITOR => nothing */
+    0,  /*     LSHIFT => nothing */
+    0,  /*     RSHIFT => nothing */
+    0,  /*       PLUS => nothing */
+    0,  /*      MINUS => nothing */
+    0,  /*       STAR => nothing */
+    0,  /*      SLASH => nothing */
+    0,  /*        REM => nothing */
+    0,  /*     CONCAT => nothing */
+    0,  /*        PTR => nothing */
+    0,  /*    COLLATE => nothing */
+    0,  /*     BITNOT => nothing */
+    0,  /*         ON => nothing */
+    0,  /*         ID => nothing */
+   32,  /*      ABORT => ID */
+   32,  /*     ACTION => ID */
+   32,  /*      AFTER => ID */
+   32,  /*    ANALYZE => ID */
+   32,  /*        ASC => ID */
+   32,  /*     ATTACH => ID */
+   32,  /*     BEFORE => ID */
+   32,  /*      BEGIN => ID */
+   32,  /*         BY => ID */
+   32,  /*    CASCADE => ID */
+   32,  /*       CAST => ID */
+   32,  /*   COLUMNKW => ID */
+   32,  /*   CONFLICT => ID */
+   32,  /*   DATABASE => ID */
+   32,  /*   DEFERRED => ID */
+   32,  /*       DESC => ID */
+   32,  /*     DETACH => ID */
+   32,  /*         DO => ID */
+   32,  /*       EACH => ID */
+   32,  /*        END => ID */
+   32,  /*  EXCLUSIVE => ID */
+   32,  /*    EXPLAIN => ID */
+   32,  /*       FAIL => ID */
+   32,  /*        FOR => ID */
+   32,  /*     IGNORE => ID */
+   32,  /*  IMMEDIATE => ID */
+   32,  /*  INITIALLY => ID */
+   32,  /*    INSTEAD => ID */
+   32,  /*         NO => ID */
+   32,  /*       PLAN => ID */
+   32,  /*      QUERY => ID */
+   32,  /*        KEY => ID */
+   32,  /*         OF => ID */
+   32,  /*     OFFSET => ID */
+   32,  /*     PRAGMA => ID */
+   32,  /*      RAISE => ID */
+   32,  /*  RECURSIVE => ID */
+   32,  /*    RELEASE => ID */
+   32,  /*    REPLACE => ID */
+   32,  /*   RESTRICT => ID */
+   32,  /*        ROW => ID */
+   32,  /*       ROWS => ID */
+   32,  /*   ROLLBACK => ID */
+   32,  /*  SAVEPOINT => ID */
+   32,  /*       TEMP => ID */
+   32,  /*    TRIGGER => ID */
+   32,  /*     VACUUM => ID */
+   32,  /*       VIEW => ID */
+   32,  /*    VIRTUAL => ID */
+   32,  /*       WITH => ID */
+   32,  /*    WITHOUT => ID */
+   32,  /*      NULLS => ID */
+   32,  /*      FIRST => ID */
+   32,  /*       LAST => ID */
+   32,  /*     EXCEPT => ID */
+   32,  /*  INTERSECT => ID */
+   32,  /*      UNION => ID */
+   32,  /*    CURRENT => ID */
+   32,  /*  FOLLOWING => ID */
+   32,  /*  PARTITION => ID */
+   32,  /*  PRECEDING => ID */
+   32,  /*      RANGE => ID */
+   32,  /*  UNBOUNDED => ID */
+   32,  /*    EXCLUDE => ID */
+   32,  /*     GROUPS => ID */
+   32,  /*     OTHERS => ID */
+   32,  /*       TIES => ID */
+   32,  /*     WITHIN => ID */
+   32,  /*  GENERATED => ID */
+   32,  /*     ALWAYS => ID */
+   32,  /* MATERIALIZED => ID */
+   32,  /*    REINDEX => ID */
+   32,  /*     RENAME => ID */
+   32,  /*   CTIME_KW => ID */
+   32,  /*         IF => ID */
+    0,  /*        ANY => nothing */
+    0,  /*     COMMIT => nothing */
+    0,  /*         TO => nothing */
+    0,  /*      TABLE => nothing */
+    0,  /*     CREATE => nothing */
+    0,  /*     EXISTS => nothing */
+    0,  /*         LP => nothing */
+    0,  /*         RP => nothing */
+    0,  /*         AS => nothing */
+    0,  /*      COMMA => nothing */
+    0,  /*     STRING => nothing */
+    0,  /* CONSTRAINT => nothing */
+    0,  /*    DEFAULT => nothing */
+    0,  /*    INDEXED => nothing */
+    0,  /*       NULL => nothing */
+    0,  /*    PRIMARY => nothing */
+    0,  /*     UNIQUE => nothing */
+    0,  /*      CHECK => nothing */
+    0,  /* REFERENCES => nothing */
+    0,  /*   AUTOINCR => nothing */
+    0,  /*     INSERT => nothing */
+    0,  /*     DELETE => nothing */
+    0,  /*     UPDATE => nothing */
+    0,  /*        SET => nothing */
+    0,  /* DEFERRABLE => nothing */
+    0,  /*    FOREIGN => nothing */
+    0,  /*       DROP => nothing */
+    0,  /*        ALL => nothing */
+    0,  /*     SELECT => nothing */
+    0,  /*     VALUES => nothing */
+    0,  /*   DISTINCT => nothing */
+    0,  /*        DOT => nothing */
+    0,  /*       FROM => nothing */
+    0,  /*       JOIN => nothing */
+    0,  /*    JOIN_KW => nothing */
+    0,  /*      USING => nothing */
+    0,  /*      ORDER => nothing */
+    0,  /*      GROUP => nothing */
+    0,  /*     HAVING => nothing */
+    0,  /*      LIMIT => nothing */
+    0,  /*      WHERE => nothing */
+    0,  /*  RETURNING => nothing */
+    0,  /*       INTO => nothing */
+    0,  /*    NOTHING => nothing */
+    0,  /*      FLOAT => nothing */
+    0,  /*       BLOB => nothing */
+    0,  /*    INTEGER => nothing */
+    0,  /*   VARIABLE => nothing */
+    0,  /*       CASE => nothing */
+    0,  /*       WHEN => nothing */
+    0,  /*       THEN => nothing */
+    0,  /*       ELSE => nothing */
+    0,  /*      INDEX => nothing */
+    0,  /*       SEMI => nothing */
+    0,  /*      ALTER => nothing */
+    0,  /*        ADD => nothing */
+    0,  /*     WINDOW => nothing */
+    0,  /*       OVER => nothing */
+    0,  /*     FILTER => nothing */
+    0,  /* TRANSACTION => nothing */
+    0,  /*      SPACE => nothing */
+    0,  /*    ILLEGAL => nothing */
+};
+#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.
+**
+** After the "shift" half of a SHIFTREDUCE action, the stateno field
+** actually contains the reduce action for the second half of the
+** SHIFTREDUCE.
+*/
+struct yyStackEntry {
+  YYACTIONTYPE stateno;  /* The state-number, or reduce action in SHIFTREDUCE */
+  YYCODETYPE 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 {
+  yyStackEntry *yytos;          /* Pointer to top element of the stack */
+#ifdef YYTRACKMAXSTACKDEPTH
+  int yyhwm;                    /* High-water mark of the stack */
+#endif
+#ifndef YYNOERRORRECOVERY
+  int yyerrcnt;                 /* Shifts left before out of the error */
+#endif
+  PerfettoSqlParserARG_SDECL                /* A place to hold %extra_argument */
+  PerfettoSqlParserCTX_SDECL                /* A place to hold %extra_context */
+#if YYSTACKDEPTH<=0
+  int yystksz;                  /* Current side of the stack */
+  yyStackEntry *yystack;        /* The parser's stack */
+  yyStackEntry yystk0;          /* First stack entry */
+#else
+  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
+  yyStackEntry *yystackEnd;            /* Last entry in the stack */
+#endif
+};
+typedef struct yyParser yyParser;
+
+#include <assert.h>
+#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:
+** <ul>
+** <li> A FILE* to which trace output should be written.
+**      If NULL, then tracing is turned off.
+** <li> A prefix string written at the beginning of every
+**      line of trace output.  If NULL, then tracing is
+**      turned off.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+void PerfettoSqlParserTrace(FILE *TraceFILE, char *zTracePrompt){
+  yyTraceFILE = TraceFILE;
+  yyTracePrompt = zTracePrompt;
+  if( yyTraceFILE==0 ) yyTracePrompt = 0;
+  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
+}
+#endif /* NDEBUG */
+
+#if defined(YYCOVERAGE) || !defined(NDEBUG)
+/* For tracing shifts, the names of all terminals and nonterminals
+** are required.  The following table supplies these names */
+static const char *const yyTokenName[] = { 
+  /*    0 */ "$",
+  /*    1 */ "OR",
+  /*    2 */ "AND",
+  /*    3 */ "NOT",
+  /*    4 */ "IS",
+  /*    5 */ "MATCH",
+  /*    6 */ "LIKE_KW",
+  /*    7 */ "BETWEEN",
+  /*    8 */ "IN",
+  /*    9 */ "ISNULL",
+  /*   10 */ "NOTNULL",
+  /*   11 */ "NE",
+  /*   12 */ "EQ",
+  /*   13 */ "GT",
+  /*   14 */ "LE",
+  /*   15 */ "LT",
+  /*   16 */ "GE",
+  /*   17 */ "ESCAPE",
+  /*   18 */ "BITAND",
+  /*   19 */ "BITOR",
+  /*   20 */ "LSHIFT",
+  /*   21 */ "RSHIFT",
+  /*   22 */ "PLUS",
+  /*   23 */ "MINUS",
+  /*   24 */ "STAR",
+  /*   25 */ "SLASH",
+  /*   26 */ "REM",
+  /*   27 */ "CONCAT",
+  /*   28 */ "PTR",
+  /*   29 */ "COLLATE",
+  /*   30 */ "BITNOT",
+  /*   31 */ "ON",
+  /*   32 */ "ID",
+  /*   33 */ "ABORT",
+  /*   34 */ "ACTION",
+  /*   35 */ "AFTER",
+  /*   36 */ "ANALYZE",
+  /*   37 */ "ASC",
+  /*   38 */ "ATTACH",
+  /*   39 */ "BEFORE",
+  /*   40 */ "BEGIN",
+  /*   41 */ "BY",
+  /*   42 */ "CASCADE",
+  /*   43 */ "CAST",
+  /*   44 */ "COLUMNKW",
+  /*   45 */ "CONFLICT",
+  /*   46 */ "DATABASE",
+  /*   47 */ "DEFERRED",
+  /*   48 */ "DESC",
+  /*   49 */ "DETACH",
+  /*   50 */ "DO",
+  /*   51 */ "EACH",
+  /*   52 */ "END",
+  /*   53 */ "EXCLUSIVE",
+  /*   54 */ "EXPLAIN",
+  /*   55 */ "FAIL",
+  /*   56 */ "FOR",
+  /*   57 */ "IGNORE",
+  /*   58 */ "IMMEDIATE",
+  /*   59 */ "INITIALLY",
+  /*   60 */ "INSTEAD",
+  /*   61 */ "NO",
+  /*   62 */ "PLAN",
+  /*   63 */ "QUERY",
+  /*   64 */ "KEY",
+  /*   65 */ "OF",
+  /*   66 */ "OFFSET",
+  /*   67 */ "PRAGMA",
+  /*   68 */ "RAISE",
+  /*   69 */ "RECURSIVE",
+  /*   70 */ "RELEASE",
+  /*   71 */ "REPLACE",
+  /*   72 */ "RESTRICT",
+  /*   73 */ "ROW",
+  /*   74 */ "ROWS",
+  /*   75 */ "ROLLBACK",
+  /*   76 */ "SAVEPOINT",
+  /*   77 */ "TEMP",
+  /*   78 */ "TRIGGER",
+  /*   79 */ "VACUUM",
+  /*   80 */ "VIEW",
+  /*   81 */ "VIRTUAL",
+  /*   82 */ "WITH",
+  /*   83 */ "WITHOUT",
+  /*   84 */ "NULLS",
+  /*   85 */ "FIRST",
+  /*   86 */ "LAST",
+  /*   87 */ "EXCEPT",
+  /*   88 */ "INTERSECT",
+  /*   89 */ "UNION",
+  /*   90 */ "CURRENT",
+  /*   91 */ "FOLLOWING",
+  /*   92 */ "PARTITION",
+  /*   93 */ "PRECEDING",
+  /*   94 */ "RANGE",
+  /*   95 */ "UNBOUNDED",
+  /*   96 */ "EXCLUDE",
+  /*   97 */ "GROUPS",
+  /*   98 */ "OTHERS",
+  /*   99 */ "TIES",
+  /*  100 */ "WITHIN",
+  /*  101 */ "GENERATED",
+  /*  102 */ "ALWAYS",
+  /*  103 */ "MATERIALIZED",
+  /*  104 */ "REINDEX",
+  /*  105 */ "RENAME",
+  /*  106 */ "CTIME_KW",
+  /*  107 */ "IF",
+  /*  108 */ "ANY",
+  /*  109 */ "COMMIT",
+  /*  110 */ "TO",
+  /*  111 */ "TABLE",
+  /*  112 */ "CREATE",
+  /*  113 */ "EXISTS",
+  /*  114 */ "LP",
+  /*  115 */ "RP",
+  /*  116 */ "AS",
+  /*  117 */ "COMMA",
+  /*  118 */ "STRING",
+  /*  119 */ "CONSTRAINT",
+  /*  120 */ "DEFAULT",
+  /*  121 */ "INDEXED",
+  /*  122 */ "NULL",
+  /*  123 */ "PRIMARY",
+  /*  124 */ "UNIQUE",
+  /*  125 */ "CHECK",
+  /*  126 */ "REFERENCES",
+  /*  127 */ "AUTOINCR",
+  /*  128 */ "INSERT",
+  /*  129 */ "DELETE",
+  /*  130 */ "UPDATE",
+  /*  131 */ "SET",
+  /*  132 */ "DEFERRABLE",
+  /*  133 */ "FOREIGN",
+  /*  134 */ "DROP",
+  /*  135 */ "ALL",
+  /*  136 */ "SELECT",
+  /*  137 */ "VALUES",
+  /*  138 */ "DISTINCT",
+  /*  139 */ "DOT",
+  /*  140 */ "FROM",
+  /*  141 */ "JOIN",
+  /*  142 */ "JOIN_KW",
+  /*  143 */ "USING",
+  /*  144 */ "ORDER",
+  /*  145 */ "GROUP",
+  /*  146 */ "HAVING",
+  /*  147 */ "LIMIT",
+  /*  148 */ "WHERE",
+  /*  149 */ "RETURNING",
+  /*  150 */ "INTO",
+  /*  151 */ "NOTHING",
+  /*  152 */ "FLOAT",
+  /*  153 */ "BLOB",
+  /*  154 */ "INTEGER",
+  /*  155 */ "VARIABLE",
+  /*  156 */ "CASE",
+  /*  157 */ "WHEN",
+  /*  158 */ "THEN",
+  /*  159 */ "ELSE",
+  /*  160 */ "INDEX",
+  /*  161 */ "SEMI",
+  /*  162 */ "ALTER",
+  /*  163 */ "ADD",
+  /*  164 */ "WINDOW",
+  /*  165 */ "OVER",
+  /*  166 */ "FILTER",
+  /*  167 */ "TRANSACTION",
+  /*  168 */ "SPACE",
+  /*  169 */ "ILLEGAL",
+  /*  170 */ "explain",
+  /*  171 */ "cmdx",
+  /*  172 */ "cmd",
+  /*  173 */ "transtype",
+  /*  174 */ "trans_opt",
+  /*  175 */ "nm",
+  /*  176 */ "savepoint_opt",
+  /*  177 */ "create_table",
+  /*  178 */ "createkw",
+  /*  179 */ "temp",
+  /*  180 */ "ifnotexists",
+  /*  181 */ "dbnm",
+  /*  182 */ "create_table_args",
+  /*  183 */ "columnlist",
+  /*  184 */ "conslist_opt",
+  /*  185 */ "table_option_set",
+  /*  186 */ "select",
+  /*  187 */ "table_option",
+  /*  188 */ "columnname",
+  /*  189 */ "typetoken",
+  /*  190 */ "typename",
+  /*  191 */ "signed",
+  /*  192 */ "scanpt",
+  /*  193 */ "scantok",
+  /*  194 */ "ccons",
+  /*  195 */ "term",
+  /*  196 */ "expr",
+  /*  197 */ "onconf",
+  /*  198 */ "sortorder",
+  /*  199 */ "autoinc",
+  /*  200 */ "eidlist_opt",
+  /*  201 */ "refargs",
+  /*  202 */ "defer_subclause",
+  /*  203 */ "generated",
+  /*  204 */ "refarg",
+  /*  205 */ "refact",
+  /*  206 */ "init_deferred_pred_opt",
+  /*  207 */ "tconscomma",
+  /*  208 */ "tcons",
+  /*  209 */ "sortlist",
+  /*  210 */ "eidlist",
+  /*  211 */ "defer_subclause_opt",
+  /*  212 */ "resolvetype",
+  /*  213 */ "orconf",
+  /*  214 */ "ifexists",
+  /*  215 */ "fullname",
+  /*  216 */ "wqlist",
+  /*  217 */ "selectnowith",
+  /*  218 */ "multiselect_op",
+  /*  219 */ "oneselect",
+  /*  220 */ "distinct",
+  /*  221 */ "selcollist",
+  /*  222 */ "from",
+  /*  223 */ "where_opt",
+  /*  224 */ "groupby_opt",
+  /*  225 */ "having_opt",
+  /*  226 */ "orderby_opt",
+  /*  227 */ "limit_opt",
+  /*  228 */ "window_clause",
+  /*  229 */ "values",
+  /*  230 */ "nexprlist",
+  /*  231 */ "sclp",
+  /*  232 */ "as",
+  /*  233 */ "seltablist",
+  /*  234 */ "stl_prefix",
+  /*  235 */ "joinop",
+  /*  236 */ "on_using",
+  /*  237 */ "indexed_by",
+  /*  238 */ "exprlist",
+  /*  239 */ "xfullname",
+  /*  240 */ "idlist",
+  /*  241 */ "indexed_opt",
+  /*  242 */ "nulls",
+  /*  243 */ "with",
+  /*  244 */ "where_opt_ret",
+  /*  245 */ "setlist",
+  /*  246 */ "insert_cmd",
+  /*  247 */ "idlist_opt",
+  /*  248 */ "upsert",
+  /*  249 */ "returning",
+  /*  250 */ "filter_over",
+  /*  251 */ "likeop",
+  /*  252 */ "between_op",
+  /*  253 */ "in_op",
+  /*  254 */ "paren_exprlist",
+  /*  255 */ "case_operand",
+  /*  256 */ "case_exprlist",
+  /*  257 */ "case_else",
+  /*  258 */ "uniqueflag",
+  /*  259 */ "collate",
+  /*  260 */ "vinto",
+  /*  261 */ "nmnum",
+  /*  262 */ "minus_num",
+  /*  263 */ "plus_num",
+  /*  264 */ "trigger_decl",
+  /*  265 */ "trigger_cmd_list",
+  /*  266 */ "trigger_time",
+  /*  267 */ "trigger_event",
+  /*  268 */ "foreach_clause",
+  /*  269 */ "when_clause",
+  /*  270 */ "trigger_cmd",
+  /*  271 */ "trnm",
+  /*  272 */ "tridxby",
+  /*  273 */ "raisetype",
+  /*  274 */ "database_kw_opt",
+  /*  275 */ "key_opt",
+  /*  276 */ "add_column_fullname",
+  /*  277 */ "kwcolumn_opt",
+  /*  278 */ "carglist",
+  /*  279 */ "create_vtab",
+  /*  280 */ "vtabarglist",
+  /*  281 */ "vtabarg",
+  /*  282 */ "vtabargtoken",
+  /*  283 */ "lp",
+  /*  284 */ "anylist",
+  /*  285 */ "wqas",
+  /*  286 */ "wqitem",
+  /*  287 */ "windowdefn_list",
+  /*  288 */ "windowdefn",
+  /*  289 */ "window",
+  /*  290 */ "frame_opt",
+  /*  291 */ "range_or_rows",
+  /*  292 */ "frame_bound_s",
+  /*  293 */ "frame_exclude_opt",
+  /*  294 */ "frame_bound_e",
+  /*  295 */ "frame_bound",
+  /*  296 */ "frame_exclude",
+  /*  297 */ "filter_clause",
+  /*  298 */ "over_clause",
+  /*  299 */ "input",
+  /*  300 */ "cmdlist",
+  /*  301 */ "ecmd",
+  /*  302 */ "conslist",
+};
+#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
+
+#ifndef NDEBUG
+/* For tracing reduce actions, the names of all rules are required.
+*/
+static const char *const yyRuleName[] = {
+ /*   0 */ "explain ::= EXPLAIN",
+ /*   1 */ "explain ::= EXPLAIN QUERY PLAN",
+ /*   2 */ "cmdx ::= cmd",
+ /*   3 */ "cmd ::= BEGIN transtype trans_opt",
+ /*   4 */ "transtype ::=",
+ /*   5 */ "transtype ::= DEFERRED",
+ /*   6 */ "transtype ::= IMMEDIATE",
+ /*   7 */ "transtype ::= EXCLUSIVE",
+ /*   8 */ "cmd ::= COMMIT|END trans_opt",
+ /*   9 */ "cmd ::= ROLLBACK trans_opt",
+ /*  10 */ "cmd ::= SAVEPOINT nm",
+ /*  11 */ "cmd ::= RELEASE savepoint_opt nm",
+ /*  12 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm",
+ /*  13 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm",
+ /*  14 */ "createkw ::= CREATE",
+ /*  15 */ "ifnotexists ::=",
+ /*  16 */ "ifnotexists ::= IF NOT EXISTS",
+ /*  17 */ "temp ::= TEMP",
+ /*  18 */ "temp ::=",
+ /*  19 */ "create_table_args ::= LP columnlist conslist_opt RP table_option_set",
+ /*  20 */ "create_table_args ::= AS select",
+ /*  21 */ "table_option_set ::=",
+ /*  22 */ "table_option_set ::= table_option_set COMMA table_option",
+ /*  23 */ "table_option ::= WITHOUT nm",
+ /*  24 */ "table_option ::= nm",
+ /*  25 */ "columnname ::= nm typetoken",
+ /*  26 */ "typetoken ::=",
+ /*  27 */ "typetoken ::= typename LP signed RP",
+ /*  28 */ "typetoken ::= typename LP signed COMMA signed RP",
+ /*  29 */ "typename ::= typename ID|STRING",
+ /*  30 */ "scanpt ::=",
+ /*  31 */ "scantok ::=",
+ /*  32 */ "ccons ::= CONSTRAINT nm",
+ /*  33 */ "ccons ::= DEFAULT scantok term",
+ /*  34 */ "ccons ::= DEFAULT LP expr RP",
+ /*  35 */ "ccons ::= DEFAULT PLUS scantok term",
+ /*  36 */ "ccons ::= DEFAULT MINUS scantok term",
+ /*  37 */ "ccons ::= DEFAULT scantok ID|INDEXED",
+ /*  38 */ "ccons ::= NOT NULL onconf",
+ /*  39 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
+ /*  40 */ "ccons ::= UNIQUE onconf",
+ /*  41 */ "ccons ::= CHECK LP expr RP",
+ /*  42 */ "ccons ::= REFERENCES nm eidlist_opt refargs",
+ /*  43 */ "ccons ::= defer_subclause",
+ /*  44 */ "ccons ::= COLLATE ID|STRING",
+ /*  45 */ "generated ::= LP expr RP",
+ /*  46 */ "generated ::= LP expr RP ID",
+ /*  47 */ "autoinc ::=",
+ /*  48 */ "autoinc ::= AUTOINCR",
+ /*  49 */ "refargs ::=",
+ /*  50 */ "refargs ::= refargs refarg",
+ /*  51 */ "refarg ::= MATCH nm",
+ /*  52 */ "refarg ::= ON INSERT refact",
+ /*  53 */ "refarg ::= ON DELETE refact",
+ /*  54 */ "refarg ::= ON UPDATE refact",
+ /*  55 */ "refact ::= SET NULL",
+ /*  56 */ "refact ::= SET DEFAULT",
+ /*  57 */ "refact ::= CASCADE",
+ /*  58 */ "refact ::= RESTRICT",
+ /*  59 */ "refact ::= NO ACTION",
+ /*  60 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /*  61 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /*  62 */ "init_deferred_pred_opt ::=",
+ /*  63 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /*  64 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /*  65 */ "conslist_opt ::=",
+ /*  66 */ "tconscomma ::= COMMA",
+ /*  67 */ "tcons ::= CONSTRAINT nm",
+ /*  68 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
+ /*  69 */ "tcons ::= UNIQUE LP sortlist RP onconf",
+ /*  70 */ "tcons ::= CHECK LP expr RP onconf",
+ /*  71 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
+ /*  72 */ "defer_subclause_opt ::=",
+ /*  73 */ "onconf ::=",
+ /*  74 */ "onconf ::= ON CONFLICT resolvetype",
+ /*  75 */ "orconf ::=",
+ /*  76 */ "orconf ::= OR resolvetype",
+ /*  77 */ "resolvetype ::= IGNORE",
+ /*  78 */ "resolvetype ::= REPLACE",
+ /*  79 */ "cmd ::= DROP TABLE ifexists fullname",
+ /*  80 */ "ifexists ::= IF EXISTS",
+ /*  81 */ "ifexists ::=",
+ /*  82 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
+ /*  83 */ "cmd ::= DROP VIEW ifexists fullname",
+ /*  84 */ "cmd ::= select",
+ /*  85 */ "select ::= WITH wqlist selectnowith",
+ /*  86 */ "select ::= WITH RECURSIVE wqlist selectnowith",
+ /*  87 */ "select ::= selectnowith",
+ /*  88 */ "selectnowith ::= selectnowith multiselect_op oneselect",
+ /*  89 */ "multiselect_op ::= UNION",
+ /*  90 */ "multiselect_op ::= UNION ALL",
+ /*  91 */ "multiselect_op ::= EXCEPT|INTERSECT",
+ /*  92 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /*  93 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt",
+ /*  94 */ "values ::= VALUES LP nexprlist RP",
+ /*  95 */ "values ::= values COMMA LP nexprlist RP",
+ /*  96 */ "distinct ::= DISTINCT",
+ /*  97 */ "distinct ::= ALL",
+ /*  98 */ "distinct ::=",
+ /*  99 */ "sclp ::=",
+ /* 100 */ "selcollist ::= sclp scanpt expr scanpt as",
+ /* 101 */ "selcollist ::= sclp scanpt STAR",
+ /* 102 */ "selcollist ::= sclp scanpt nm DOT STAR",
+ /* 103 */ "as ::= AS nm",
+ /* 104 */ "as ::=",
+ /* 105 */ "from ::=",
+ /* 106 */ "from ::= FROM seltablist",
+ /* 107 */ "stl_prefix ::= seltablist joinop",
+ /* 108 */ "stl_prefix ::=",
+ /* 109 */ "seltablist ::= stl_prefix nm dbnm as on_using",
+ /* 110 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using",
+ /* 111 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using",
+ /* 112 */ "seltablist ::= stl_prefix LP select RP as on_using",
+ /* 113 */ "seltablist ::= stl_prefix LP seltablist RP as on_using",
+ /* 114 */ "dbnm ::=",
+ /* 115 */ "dbnm ::= DOT nm",
+ /* 116 */ "fullname ::= nm",
+ /* 117 */ "fullname ::= nm DOT nm",
+ /* 118 */ "xfullname ::= nm",
+ /* 119 */ "xfullname ::= nm DOT nm",
+ /* 120 */ "xfullname ::= nm DOT nm AS nm",
+ /* 121 */ "xfullname ::= nm AS nm",
+ /* 122 */ "joinop ::= COMMA|JOIN",
+ /* 123 */ "joinop ::= JOIN_KW JOIN",
+ /* 124 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 125 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 126 */ "on_using ::= ON expr",
+ /* 127 */ "on_using ::= USING LP idlist RP",
+ /* 128 */ "on_using ::=",
+ /* 129 */ "indexed_opt ::=",
+ /* 130 */ "indexed_by ::= INDEXED BY nm",
+ /* 131 */ "indexed_by ::= NOT INDEXED",
+ /* 132 */ "orderby_opt ::=",
+ /* 133 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 134 */ "sortlist ::= sortlist COMMA expr sortorder nulls",
+ /* 135 */ "sortlist ::= expr sortorder nulls",
+ /* 136 */ "sortorder ::= ASC",
+ /* 137 */ "sortorder ::= DESC",
+ /* 138 */ "sortorder ::=",
+ /* 139 */ "nulls ::= NULLS FIRST",
+ /* 140 */ "nulls ::= NULLS LAST",
+ /* 141 */ "nulls ::=",
+ /* 142 */ "groupby_opt ::=",
+ /* 143 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 144 */ "having_opt ::=",
+ /* 145 */ "having_opt ::= HAVING expr",
+ /* 146 */ "limit_opt ::=",
+ /* 147 */ "limit_opt ::= LIMIT expr",
+ /* 148 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 149 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 150 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret",
+ /* 151 */ "where_opt ::=",
+ /* 152 */ "where_opt ::= WHERE expr",
+ /* 153 */ "where_opt_ret ::=",
+ /* 154 */ "where_opt_ret ::= WHERE expr",
+ /* 155 */ "where_opt_ret ::= RETURNING selcollist",
+ /* 156 */ "where_opt_ret ::= WHERE expr RETURNING selcollist",
+ /* 157 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret",
+ /* 158 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 159 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
+ /* 160 */ "setlist ::= nm EQ expr",
+ /* 161 */ "setlist ::= LP idlist RP EQ expr",
+ /* 162 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
+ /* 163 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning",
+ /* 164 */ "upsert ::=",
+ /* 165 */ "upsert ::= RETURNING selcollist",
+ /* 166 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert",
+ /* 167 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert",
+ /* 168 */ "upsert ::= ON CONFLICT DO NOTHING returning",
+ /* 169 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning",
+ /* 170 */ "returning ::= RETURNING selcollist",
+ /* 171 */ "insert_cmd ::= INSERT orconf",
+ /* 172 */ "insert_cmd ::= REPLACE",
+ /* 173 */ "idlist_opt ::=",
+ /* 174 */ "idlist_opt ::= LP idlist RP",
+ /* 175 */ "idlist ::= idlist COMMA nm",
+ /* 176 */ "idlist ::= nm",
+ /* 177 */ "expr ::= LP expr RP",
+ /* 178 */ "expr ::= ID|INDEXED|JOIN_KW",
+ /* 179 */ "expr ::= nm DOT nm",
+ /* 180 */ "expr ::= nm DOT nm DOT nm",
+ /* 181 */ "term ::= NULL|FLOAT|BLOB",
+ /* 182 */ "term ::= STRING",
+ /* 183 */ "term ::= INTEGER",
+ /* 184 */ "expr ::= VARIABLE",
+ /* 185 */ "expr ::= expr COLLATE ID|STRING",
+ /* 186 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 187 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP",
+ /* 188 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP",
+ /* 189 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP",
+ /* 190 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over",
+ /* 191 */ "expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over",
+ /* 192 */ "expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over",
+ /* 193 */ "term ::= CTIME_KW",
+ /* 194 */ "expr ::= LP nexprlist COMMA expr RP",
+ /* 195 */ "expr ::= expr AND expr",
+ /* 196 */ "expr ::= expr OR expr",
+ /* 197 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 198 */ "expr ::= expr EQ|NE expr",
+ /* 199 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 200 */ "expr ::= expr PLUS|MINUS expr",
+ /* 201 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 202 */ "expr ::= expr CONCAT expr",
+ /* 203 */ "likeop ::= NOT LIKE_KW|MATCH",
+ /* 204 */ "expr ::= expr likeop expr",
+ /* 205 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 206 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 207 */ "expr ::= expr NOT NULL",
+ /* 208 */ "expr ::= expr IS expr",
+ /* 209 */ "expr ::= expr IS NOT expr",
+ /* 210 */ "expr ::= expr IS NOT DISTINCT FROM expr",
+ /* 211 */ "expr ::= expr IS DISTINCT FROM expr",
+ /* 212 */ "expr ::= NOT expr",
+ /* 213 */ "expr ::= BITNOT expr",
+ /* 214 */ "expr ::= PLUS|MINUS expr",
+ /* 215 */ "expr ::= expr PTR expr",
+ /* 216 */ "between_op ::= BETWEEN",
+ /* 217 */ "between_op ::= NOT BETWEEN",
+ /* 218 */ "expr ::= expr between_op expr AND expr",
+ /* 219 */ "in_op ::= IN",
+ /* 220 */ "in_op ::= NOT IN",
+ /* 221 */ "expr ::= expr in_op LP exprlist RP",
+ /* 222 */ "expr ::= LP select RP",
+ /* 223 */ "expr ::= expr in_op LP select RP",
+ /* 224 */ "expr ::= expr in_op nm dbnm paren_exprlist",
+ /* 225 */ "expr ::= EXISTS LP select RP",
+ /* 226 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 227 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 228 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 229 */ "case_else ::= ELSE expr",
+ /* 230 */ "case_else ::=",
+ /* 231 */ "case_operand ::=",
+ /* 232 */ "exprlist ::=",
+ /* 233 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 234 */ "nexprlist ::= expr",
+ /* 235 */ "paren_exprlist ::=",
+ /* 236 */ "paren_exprlist ::= LP exprlist RP",
+ /* 237 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
+ /* 238 */ "uniqueflag ::= UNIQUE",
+ /* 239 */ "uniqueflag ::=",
+ /* 240 */ "eidlist_opt ::=",
+ /* 241 */ "eidlist_opt ::= LP eidlist RP",
+ /* 242 */ "eidlist ::= eidlist COMMA nm collate sortorder",
+ /* 243 */ "eidlist ::= nm collate sortorder",
+ /* 244 */ "collate ::=",
+ /* 245 */ "collate ::= COLLATE ID|STRING",
+ /* 246 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 247 */ "cmd ::= VACUUM vinto",
+ /* 248 */ "cmd ::= VACUUM nm vinto",
+ /* 249 */ "vinto ::= INTO expr",
+ /* 250 */ "vinto ::=",
+ /* 251 */ "cmd ::= PRAGMA nm dbnm",
+ /* 252 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 253 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 254 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 255 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 256 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 257 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 258 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 259 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 260 */ "trigger_time ::= BEFORE|AFTER",
+ /* 261 */ "trigger_time ::= INSTEAD OF",
+ /* 262 */ "trigger_time ::=",
+ /* 263 */ "trigger_event ::= DELETE|INSERT",
+ /* 264 */ "trigger_event ::= UPDATE",
+ /* 265 */ "trigger_event ::= UPDATE OF idlist",
+ /* 266 */ "when_clause ::=",
+ /* 267 */ "when_clause ::= WHEN expr",
+ /* 268 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 269 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 270 */ "trnm ::= nm DOT nm",
+ /* 271 */ "tridxby ::= INDEXED BY nm",
+ /* 272 */ "tridxby ::= NOT INDEXED",
+ /* 273 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
+ /* 274 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
+ /* 275 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
+ /* 276 */ "trigger_cmd ::= scanpt select scanpt",
+ /* 277 */ "expr ::= RAISE LP IGNORE RP",
+ /* 278 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 279 */ "raisetype ::= ROLLBACK",
+ /* 280 */ "raisetype ::= ABORT",
+ /* 281 */ "raisetype ::= FAIL",
+ /* 282 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 283 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 284 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 285 */ "key_opt ::=",
+ /* 286 */ "key_opt ::= KEY expr",
+ /* 287 */ "cmd ::= REINDEX",
+ /* 288 */ "cmd ::= REINDEX nm dbnm",
+ /* 289 */ "cmd ::= ANALYZE",
+ /* 290 */ "cmd ::= ANALYZE nm dbnm",
+ /* 291 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 292 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 293 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm",
+ /* 294 */ "add_column_fullname ::= fullname",
+ /* 295 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
+ /* 296 */ "cmd ::= create_vtab",
+ /* 297 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 298 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 299 */ "vtabarg ::=",
+ /* 300 */ "vtabargtoken ::= ANY",
+ /* 301 */ "vtabargtoken ::= lp anylist RP",
+ /* 302 */ "lp ::= LP",
+ /* 303 */ "with ::= WITH wqlist",
+ /* 304 */ "with ::= WITH RECURSIVE wqlist",
+ /* 305 */ "wqas ::= AS",
+ /* 306 */ "wqas ::= AS MATERIALIZED",
+ /* 307 */ "wqas ::= AS NOT MATERIALIZED",
+ /* 308 */ "wqitem ::= nm eidlist_opt wqas LP select RP",
+ /* 309 */ "wqlist ::= wqitem",
+ /* 310 */ "wqlist ::= wqlist COMMA wqitem",
+ /* 311 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
+ /* 312 */ "windowdefn ::= nm AS LP window RP",
+ /* 313 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
+ /* 314 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
+ /* 315 */ "window ::= ORDER BY sortlist frame_opt",
+ /* 316 */ "window ::= nm ORDER BY sortlist frame_opt",
+ /* 317 */ "window ::= nm frame_opt",
+ /* 318 */ "frame_opt ::=",
+ /* 319 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
+ /* 320 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
+ /* 321 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
+ /* 322 */ "frame_bound_s ::= frame_bound",
+ /* 323 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
+ /* 324 */ "frame_bound_e ::= frame_bound",
+ /* 325 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
+ /* 326 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
+ /* 327 */ "frame_bound ::= CURRENT ROW",
+ /* 328 */ "frame_exclude_opt ::=",
+ /* 329 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
+ /* 330 */ "frame_exclude ::= NO OTHERS",
+ /* 331 */ "frame_exclude ::= CURRENT ROW",
+ /* 332 */ "frame_exclude ::= GROUP|TIES",
+ /* 333 */ "window_clause ::= WINDOW windowdefn_list",
+ /* 334 */ "filter_over ::= filter_clause over_clause",
+ /* 335 */ "filter_over ::= over_clause",
+ /* 336 */ "filter_over ::= filter_clause",
+ /* 337 */ "over_clause ::= OVER LP window RP",
+ /* 338 */ "over_clause ::= OVER nm",
+ /* 339 */ "filter_clause ::= FILTER LP WHERE expr RP",
+ /* 340 */ "input ::= cmdlist",
+ /* 341 */ "cmdlist ::= cmdlist ecmd",
+ /* 342 */ "cmdlist ::= ecmd",
+ /* 343 */ "ecmd ::= SEMI",
+ /* 344 */ "ecmd ::= cmdx SEMI",
+ /* 345 */ "ecmd ::= explain cmdx SEMI",
+ /* 346 */ "trans_opt ::=",
+ /* 347 */ "trans_opt ::= TRANSACTION",
+ /* 348 */ "trans_opt ::= TRANSACTION nm",
+ /* 349 */ "savepoint_opt ::= SAVEPOINT",
+ /* 350 */ "savepoint_opt ::=",
+ /* 351 */ "cmd ::= create_table create_table_args",
+ /* 352 */ "table_option_set ::= table_option",
+ /* 353 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 354 */ "columnlist ::= columnname carglist",
+ /* 355 */ "nm ::= ID|INDEXED|JOIN_KW",
+ /* 356 */ "nm ::= STRING",
+ /* 357 */ "typetoken ::= typename",
+ /* 358 */ "typename ::= ID|STRING",
+ /* 359 */ "signed ::= plus_num",
+ /* 360 */ "signed ::= minus_num",
+ /* 361 */ "carglist ::= carglist ccons",
+ /* 362 */ "carglist ::=",
+ /* 363 */ "ccons ::= NULL onconf",
+ /* 364 */ "ccons ::= GENERATED ALWAYS AS generated",
+ /* 365 */ "ccons ::= AS generated",
+ /* 366 */ "conslist_opt ::= COMMA conslist",
+ /* 367 */ "conslist ::= conslist tconscomma tcons",
+ /* 368 */ "conslist ::= tcons",
+ /* 369 */ "tconscomma ::=",
+ /* 370 */ "defer_subclause_opt ::= defer_subclause",
+ /* 371 */ "resolvetype ::= raisetype",
+ /* 372 */ "selectnowith ::= oneselect",
+ /* 373 */ "oneselect ::= values",
+ /* 374 */ "sclp ::= selcollist COMMA",
+ /* 375 */ "as ::= ID|STRING",
+ /* 376 */ "indexed_opt ::= indexed_by",
+ /* 377 */ "returning ::=",
+ /* 378 */ "expr ::= term",
+ /* 379 */ "likeop ::= LIKE_KW|MATCH",
+ /* 380 */ "case_operand ::= expr",
+ /* 381 */ "exprlist ::= nexprlist",
+ /* 382 */ "nmnum ::= plus_num",
+ /* 383 */ "nmnum ::= nm",
+ /* 384 */ "nmnum ::= ON",
+ /* 385 */ "nmnum ::= DELETE",
+ /* 386 */ "nmnum ::= DEFAULT",
+ /* 387 */ "plus_num ::= INTEGER|FLOAT",
+ /* 388 */ "foreach_clause ::=",
+ /* 389 */ "foreach_clause ::= FOR EACH ROW",
+ /* 390 */ "trnm ::= nm",
+ /* 391 */ "tridxby ::=",
+ /* 392 */ "database_kw_opt ::= DATABASE",
+ /* 393 */ "database_kw_opt ::=",
+ /* 394 */ "kwcolumn_opt ::=",
+ /* 395 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 396 */ "vtabarglist ::= vtabarg",
+ /* 397 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 398 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 399 */ "anylist ::=",
+ /* 400 */ "anylist ::= anylist LP anylist RP",
+ /* 401 */ "anylist ::= anylist ANY",
+ /* 402 */ "with ::=",
+ /* 403 */ "windowdefn_list ::= windowdefn",
+ /* 404 */ "window ::= frame_opt",
+};
+#endif /* NDEBUG */
+
+
+#if YYSTACKDEPTH<=0
+/*
+** Try to increase the size of the parser stack.  Return the number
+** of errors.  Return 0 on success.
+*/
+static int yyGrowStack(yyParser *p){
+  int newSize;
+  int idx;
+  yyStackEntry *pNew;
+
+  newSize = p->yystksz*2 + 100;
+  idx = p->yytos ? (int)(p->yytos - p->yystack) : 0;
+  if( p->yystack==&p->yystk0 ){
+    pNew = malloc(newSize*sizeof(pNew[0]));
+    if( pNew ) pNew[0] = p->yystk0;
+  }else{
+    pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
+  }
+  if( pNew ){
+    p->yystack = pNew;
+    p->yytos = &p->yystack[idx];
+#ifndef NDEBUG
+    if( yyTraceFILE ){
+      fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
+              yyTracePrompt, p->yystksz, newSize);
+    }
+#endif
+    p->yystksz = newSize;
+  }
+  return pNew==0; 
+}
+#endif
+
+/* Datatype of the argument to the memory allocated passed as the
+** second argument to PerfettoSqlParserAlloc() below.  This can be changed by
+** putting an appropriate #define in the %include section of the input
+** grammar.
+*/
+#ifndef YYMALLOCARGTYPE
+# define YYMALLOCARGTYPE size_t
+#endif
+
+/* Initialize a new parser that has already been allocated.
+*/
+void PerfettoSqlParserInit(void *yypRawParser PerfettoSqlParserCTX_PDECL){
+  yyParser *yypParser = (yyParser*)yypRawParser;
+  PerfettoSqlParserCTX_STORE
+#ifdef YYTRACKMAXSTACKDEPTH
+  yypParser->yyhwm = 0;
+#endif
+#if YYSTACKDEPTH<=0
+  yypParser->yytos = NULL;
+  yypParser->yystack = NULL;
+  yypParser->yystksz = 0;
+  if( yyGrowStack(yypParser) ){
+    yypParser->yystack = &yypParser->yystk0;
+    yypParser->yystksz = 1;
+  }
+#endif
+#ifndef YYNOERRORRECOVERY
+  yypParser->yyerrcnt = -1;
+#endif
+  yypParser->yytos = yypParser->yystack;
+  yypParser->yystack[0].stateno = 0;
+  yypParser->yystack[0].major = 0;
+#if YYSTACKDEPTH>0
+  yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
+#endif
+}
+
+#ifndef PerfettoSqlParser_ENGINEALWAYSONSTACK
+/* 
+** 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 PerfettoSqlParser and PerfettoSqlParserFree.
+*/
+void *PerfettoSqlParserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) PerfettoSqlParserCTX_PDECL){
+  yyParser *yypParser;
+  yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
+  if( yypParser ){
+    PerfettoSqlParserCTX_STORE
+    PerfettoSqlParserInit(yypParser PerfettoSqlParserCTX_PARAM);
+  }
+  return (void*)yypParser;
+}
+#endif /* PerfettoSqlParser_ENGINEALWAYSONSTACK */
+
+
+/* The following function deletes the "minor type" or semantic 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 to be deleted.  The code used to do the 
+** deletions is derived from the %destructor and/or %token_destructor
+** directives of the input grammar.
+*/
+static void yy_destructor(
+  yyParser *yypParser,    /* The parser */
+  YYCODETYPE yymajor,     /* Type code for object to destroy */
+  YYMINORTYPE *yypminor   /* The object to be destroyed */
+){
+  PerfettoSqlParserARG_FETCH
+  PerfettoSqlParserCTX_FETCH
+  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.
+    */
+/********* Begin destructor definitions ***************************************/
+/********* End destructor definitions *****************************************/
+    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.
+*/
+static void yy_pop_parser_stack(yyParser *pParser){
+  yyStackEntry *yytos;
+  assert( pParser->yytos!=0 );
+  assert( pParser->yytos > pParser->yystack );
+  yytos = pParser->yytos--;
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sPopping %s\n",
+      yyTracePrompt,
+      yyTokenName[yytos->major]);
+  }
+#endif
+  yy_destructor(pParser, yytos->major, &yytos->minor);
+}
+
+/*
+** Clear all secondary memory allocations from the parser
+*/
+void PerfettoSqlParserFinalize(void *p){
+  yyParser *pParser = (yyParser*)p;
+  while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
+#if YYSTACKDEPTH<=0
+  if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
+#endif
+}
+
+#ifndef PerfettoSqlParser_ENGINEALWAYSONSTACK
+/* 
+** Deallocate and destroy a parser.  Destructors are called for
+** all stack elements before shutting the parser down.
+**
+** If the YYPARSEFREENEVERNULL macro exists (for example because it
+** is defined in a %include section of the input grammar) then it is
+** assumed that the input pointer is never NULL.
+*/
+void PerfettoSqlParserFree(
+  void *p,                    /* The parser to be deleted */
+  void (*freeProc)(void*)     /* Function used to reclaim memory */
+){
+#ifndef YYPARSEFREENEVERNULL
+  if( p==0 ) return;
+#endif
+  PerfettoSqlParserFinalize(p);
+  (*freeProc)(p);
+}
+#endif /* PerfettoSqlParser_ENGINEALWAYSONSTACK */
+
+/*
+** Return the peak depth of the stack for a parser.
+*/
+#ifdef YYTRACKMAXSTACKDEPTH
+int PerfettoSqlParserStackPeak(void *p){
+  yyParser *pParser = (yyParser*)p;
+  return pParser->yyhwm;
+}
+#endif
+
+/* This array of booleans keeps track of the parser statement
+** coverage.  The element yycoverage[X][Y] is set when the parser
+** is in state X and has a lookahead token Y.  In a well-tested
+** systems, every element of this matrix should end up being set.
+*/
+#if defined(YYCOVERAGE)
+static unsigned char yycoverage[YYNSTATE][YYNTOKEN];
+#endif
+
+/*
+** Write into out a description of every state/lookahead combination that
+**
+**   (1)  has not been used by the parser, and
+**   (2)  is not a syntax error.
+**
+** Return the number of missed state/lookahead combinations.
+*/
+#if defined(YYCOVERAGE)
+int PerfettoSqlParserCoverage(FILE *out){
+  int stateno, iLookAhead, i;
+  int nMissed = 0;
+  for(stateno=0; stateno<YYNSTATE; stateno++){
+    i = yy_shift_ofst[stateno];
+    for(iLookAhead=0; iLookAhead<YYNTOKEN; iLookAhead++){
+      if( yy_lookahead[i+iLookAhead]!=iLookAhead ) continue;
+      if( yycoverage[stateno][iLookAhead]==0 ) nMissed++;
+      if( out ){
+        fprintf(out,"State %d lookahead %s %s\n", stateno,
+                yyTokenName[iLookAhead],
+                yycoverage[stateno][iLookAhead] ? "ok" : "missed");
+      }
+    }
+  }
+  return nMissed;
+}
+#endif
+
+/*
+** Find the appropriate action for a parser given the terminal
+** look-ahead token iLookAhead.
+*/
+static YYACTIONTYPE yy_find_shift_action(
+  YYCODETYPE iLookAhead,    /* The look-ahead token */
+  YYACTIONTYPE stateno      /* Current state number */
+){
+  int i;
+
+  if( stateno>YY_MAX_SHIFT ) return stateno;
+  assert( stateno <= YY_SHIFT_COUNT );
+#if defined(YYCOVERAGE)
+  yycoverage[stateno][iLookAhead] = 1;
+#endif
+  do{
+    i = yy_shift_ofst[stateno];
+    assert( i>=0 );
+    assert( i<=YY_ACTTAB_COUNT );
+    assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD );
+    assert( iLookAhead!=YYNOCODE );
+    assert( iLookAhead < YYNTOKEN );
+    i += iLookAhead;
+    assert( i<(int)YY_NLOOKAHEAD );
+    if( yy_lookahead[i]!=iLookAhead ){
+#ifdef YYFALLBACK
+      YYCODETYPE iFallback;            /* Fallback token */
+      assert( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) );
+      iFallback = yyFallback[iLookAhead];
+      if( iFallback!=0 ){
+#ifndef NDEBUG
+        if( yyTraceFILE ){
+          fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
+             yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
+        }
+#endif
+        assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
+        iLookAhead = iFallback;
+        continue;
+      }
+#endif
+#ifdef YYWILDCARD
+      {
+        int j = i - iLookAhead + YYWILDCARD;
+        assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) );
+        if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){
+#ifndef NDEBUG
+          if( yyTraceFILE ){
+            fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
+               yyTracePrompt, yyTokenName[iLookAhead],
+               yyTokenName[YYWILDCARD]);
+          }
+#endif /* NDEBUG */
+          return yy_action[j];
+        }
+      }
+#endif /* YYWILDCARD */
+      return yy_default[stateno];
+    }else{
+      assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) );
+      return yy_action[i];
+    }
+  }while(1);
+}
+
+/*
+** Find the appropriate action for a parser given the non-terminal
+** look-ahead token iLookAhead.
+*/
+static YYACTIONTYPE yy_find_reduce_action(
+  YYACTIONTYPE stateno,     /* Current state number */
+  YYCODETYPE iLookAhead     /* The look-ahead token */
+){
+  int i;
+#ifdef YYERRORSYMBOL
+  if( stateno>YY_REDUCE_COUNT ){
+    return yy_default[stateno];
+  }
+#else
+  assert( stateno<=YY_REDUCE_COUNT );
+#endif
+  i = yy_reduce_ofst[stateno];
+  assert( iLookAhead!=YYNOCODE );
+  i += iLookAhead;
+#ifdef YYERRORSYMBOL
+  if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
+    return yy_default[stateno];
+  }
+#else
+  assert( i>=0 && i<YY_ACTTAB_COUNT );
+  assert( yy_lookahead[i]==iLookAhead );
+#endif
+  return yy_action[i];
+}
+
+/*
+** The following routine is called if the stack overflows.
+*/
+static void yyStackOverflow(yyParser *yypParser){
+   PerfettoSqlParserARG_FETCH
+   PerfettoSqlParserCTX_FETCH
+#ifndef NDEBUG
+   if( yyTraceFILE ){
+     fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
+   }
+#endif
+   while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
+   /* Here code is inserted which will execute if the parser
+   ** stack every overflows */
+/******** Begin %stack_overflow code ******************************************/
+/******** End %stack_overflow code ********************************************/
+   PerfettoSqlParserARG_STORE /* Suppress warning about unused %extra_argument var */
+   PerfettoSqlParserCTX_STORE
+}
+
+/*
+** Print tracing information for a SHIFT action
+*/
+#ifndef NDEBUG
+static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){
+  if( yyTraceFILE ){
+    if( yyNewState<YYNSTATE ){
+      fprintf(yyTraceFILE,"%s%s '%s', go to state %d\n",
+         yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major],
+         yyNewState);
+    }else{
+      fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n",
+         yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major],
+         yyNewState - YY_MIN_REDUCE);
+    }
+  }
+}
+#else
+# define yyTraceShift(X,Y,Z)
+#endif
+
+/*
+** Perform a shift action.
+*/
+static void yy_shift(
+  yyParser *yypParser,          /* The parser to be shifted */
+  YYACTIONTYPE yyNewState,      /* The new state to shift in */
+  YYCODETYPE yyMajor,           /* The major token to shift in */
+  PerfettoSqlParserTOKENTYPE yyMinor        /* The minor token to shift in */
+){
+  yyStackEntry *yytos;
+  yypParser->yytos++;
+#ifdef YYTRACKMAXSTACKDEPTH
+  if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
+    yypParser->yyhwm++;
+    assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
+  }
+#endif
+#if YYSTACKDEPTH>0 
+  if( yypParser->yytos>yypParser->yystackEnd ){
+    yypParser->yytos--;
+    yyStackOverflow(yypParser);
+    return;
+  }
+#else
+  if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
+    if( yyGrowStack(yypParser) ){
+      yypParser->yytos--;
+      yyStackOverflow(yypParser);
+      return;
+    }
+  }
+#endif
+  if( yyNewState > YY_MAX_SHIFT ){
+    yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
+  }
+  yytos = yypParser->yytos;
+  yytos->stateno = yyNewState;
+  yytos->major = yyMajor;
+  yytos->minor.yy0 = yyMinor;
+  yyTraceShift(yypParser, yyNewState, "Shift");
+}
+
+/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
+** of that rule */
+static const YYCODETYPE yyRuleInfoLhs[] = {
+   170,  /* (0) explain ::= EXPLAIN */
+   170,  /* (1) explain ::= EXPLAIN QUERY PLAN */
+   171,  /* (2) cmdx ::= cmd */
+   172,  /* (3) cmd ::= BEGIN transtype trans_opt */
+   173,  /* (4) transtype ::= */
+   173,  /* (5) transtype ::= DEFERRED */
+   173,  /* (6) transtype ::= IMMEDIATE */
+   173,  /* (7) transtype ::= EXCLUSIVE */
+   172,  /* (8) cmd ::= COMMIT|END trans_opt */
+   172,  /* (9) cmd ::= ROLLBACK trans_opt */
+   172,  /* (10) cmd ::= SAVEPOINT nm */
+   172,  /* (11) cmd ::= RELEASE savepoint_opt nm */
+   172,  /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+   177,  /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+   178,  /* (14) createkw ::= CREATE */
+   180,  /* (15) ifnotexists ::= */
+   180,  /* (16) ifnotexists ::= IF NOT EXISTS */
+   179,  /* (17) temp ::= TEMP */
+   179,  /* (18) temp ::= */
+   182,  /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */
+   182,  /* (20) create_table_args ::= AS select */
+   185,  /* (21) table_option_set ::= */
+   185,  /* (22) table_option_set ::= table_option_set COMMA table_option */
+   187,  /* (23) table_option ::= WITHOUT nm */
+   187,  /* (24) table_option ::= nm */
+   188,  /* (25) columnname ::= nm typetoken */
+   189,  /* (26) typetoken ::= */
+   189,  /* (27) typetoken ::= typename LP signed RP */
+   189,  /* (28) typetoken ::= typename LP signed COMMA signed RP */
+   190,  /* (29) typename ::= typename ID|STRING */
+   192,  /* (30) scanpt ::= */
+   193,  /* (31) scantok ::= */
+   194,  /* (32) ccons ::= CONSTRAINT nm */
+   194,  /* (33) ccons ::= DEFAULT scantok term */
+   194,  /* (34) ccons ::= DEFAULT LP expr RP */
+   194,  /* (35) ccons ::= DEFAULT PLUS scantok term */
+   194,  /* (36) ccons ::= DEFAULT MINUS scantok term */
+   194,  /* (37) ccons ::= DEFAULT scantok ID|INDEXED */
+   194,  /* (38) ccons ::= NOT NULL onconf */
+   194,  /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+   194,  /* (40) ccons ::= UNIQUE onconf */
+   194,  /* (41) ccons ::= CHECK LP expr RP */
+   194,  /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */
+   194,  /* (43) ccons ::= defer_subclause */
+   194,  /* (44) ccons ::= COLLATE ID|STRING */
+   203,  /* (45) generated ::= LP expr RP */
+   203,  /* (46) generated ::= LP expr RP ID */
+   199,  /* (47) autoinc ::= */
+   199,  /* (48) autoinc ::= AUTOINCR */
+   201,  /* (49) refargs ::= */
+   201,  /* (50) refargs ::= refargs refarg */
+   204,  /* (51) refarg ::= MATCH nm */
+   204,  /* (52) refarg ::= ON INSERT refact */
+   204,  /* (53) refarg ::= ON DELETE refact */
+   204,  /* (54) refarg ::= ON UPDATE refact */
+   205,  /* (55) refact ::= SET NULL */
+   205,  /* (56) refact ::= SET DEFAULT */
+   205,  /* (57) refact ::= CASCADE */
+   205,  /* (58) refact ::= RESTRICT */
+   205,  /* (59) refact ::= NO ACTION */
+   202,  /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+   202,  /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+   206,  /* (62) init_deferred_pred_opt ::= */
+   206,  /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+   206,  /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+   184,  /* (65) conslist_opt ::= */
+   207,  /* (66) tconscomma ::= COMMA */
+   208,  /* (67) tcons ::= CONSTRAINT nm */
+   208,  /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+   208,  /* (69) tcons ::= UNIQUE LP sortlist RP onconf */
+   208,  /* (70) tcons ::= CHECK LP expr RP onconf */
+   208,  /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+   211,  /* (72) defer_subclause_opt ::= */
+   197,  /* (73) onconf ::= */
+   197,  /* (74) onconf ::= ON CONFLICT resolvetype */
+   213,  /* (75) orconf ::= */
+   213,  /* (76) orconf ::= OR resolvetype */
+   212,  /* (77) resolvetype ::= IGNORE */
+   212,  /* (78) resolvetype ::= REPLACE */
+   172,  /* (79) cmd ::= DROP TABLE ifexists fullname */
+   214,  /* (80) ifexists ::= IF EXISTS */
+   214,  /* (81) ifexists ::= */
+   172,  /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+   172,  /* (83) cmd ::= DROP VIEW ifexists fullname */
+   172,  /* (84) cmd ::= select */
+   186,  /* (85) select ::= WITH wqlist selectnowith */
+   186,  /* (86) select ::= WITH RECURSIVE wqlist selectnowith */
+   186,  /* (87) select ::= selectnowith */
+   217,  /* (88) selectnowith ::= selectnowith multiselect_op oneselect */
+   218,  /* (89) multiselect_op ::= UNION */
+   218,  /* (90) multiselect_op ::= UNION ALL */
+   218,  /* (91) multiselect_op ::= EXCEPT|INTERSECT */
+   219,  /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+   219,  /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+   229,  /* (94) values ::= VALUES LP nexprlist RP */
+   229,  /* (95) values ::= values COMMA LP nexprlist RP */
+   220,  /* (96) distinct ::= DISTINCT */
+   220,  /* (97) distinct ::= ALL */
+   220,  /* (98) distinct ::= */
+   231,  /* (99) sclp ::= */
+   221,  /* (100) selcollist ::= sclp scanpt expr scanpt as */
+   221,  /* (101) selcollist ::= sclp scanpt STAR */
+   221,  /* (102) selcollist ::= sclp scanpt nm DOT STAR */
+   232,  /* (103) as ::= AS nm */
+   232,  /* (104) as ::= */
+   222,  /* (105) from ::= */
+   222,  /* (106) from ::= FROM seltablist */
+   234,  /* (107) stl_prefix ::= seltablist joinop */
+   234,  /* (108) stl_prefix ::= */
+   233,  /* (109) seltablist ::= stl_prefix nm dbnm as on_using */
+   233,  /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
+   233,  /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
+   233,  /* (112) seltablist ::= stl_prefix LP select RP as on_using */
+   233,  /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */
+   181,  /* (114) dbnm ::= */
+   181,  /* (115) dbnm ::= DOT nm */
+   215,  /* (116) fullname ::= nm */
+   215,  /* (117) fullname ::= nm DOT nm */
+   239,  /* (118) xfullname ::= nm */
+   239,  /* (119) xfullname ::= nm DOT nm */
+   239,  /* (120) xfullname ::= nm DOT nm AS nm */
+   239,  /* (121) xfullname ::= nm AS nm */
+   235,  /* (122) joinop ::= COMMA|JOIN */
+   235,  /* (123) joinop ::= JOIN_KW JOIN */
+   235,  /* (124) joinop ::= JOIN_KW nm JOIN */
+   235,  /* (125) joinop ::= JOIN_KW nm nm JOIN */
+   236,  /* (126) on_using ::= ON expr */
+   236,  /* (127) on_using ::= USING LP idlist RP */
+   236,  /* (128) on_using ::= */
+   241,  /* (129) indexed_opt ::= */
+   237,  /* (130) indexed_by ::= INDEXED BY nm */
+   237,  /* (131) indexed_by ::= NOT INDEXED */
+   226,  /* (132) orderby_opt ::= */
+   226,  /* (133) orderby_opt ::= ORDER BY sortlist */
+   209,  /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */
+   209,  /* (135) sortlist ::= expr sortorder nulls */
+   198,  /* (136) sortorder ::= ASC */
+   198,  /* (137) sortorder ::= DESC */
+   198,  /* (138) sortorder ::= */
+   242,  /* (139) nulls ::= NULLS FIRST */
+   242,  /* (140) nulls ::= NULLS LAST */
+   242,  /* (141) nulls ::= */
+   224,  /* (142) groupby_opt ::= */
+   224,  /* (143) groupby_opt ::= GROUP BY nexprlist */
+   225,  /* (144) having_opt ::= */
+   225,  /* (145) having_opt ::= HAVING expr */
+   227,  /* (146) limit_opt ::= */
+   227,  /* (147) limit_opt ::= LIMIT expr */
+   227,  /* (148) limit_opt ::= LIMIT expr OFFSET expr */
+   227,  /* (149) limit_opt ::= LIMIT expr COMMA expr */
+   172,  /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
+   223,  /* (151) where_opt ::= */
+   223,  /* (152) where_opt ::= WHERE expr */
+   244,  /* (153) where_opt_ret ::= */
+   244,  /* (154) where_opt_ret ::= WHERE expr */
+   244,  /* (155) where_opt_ret ::= RETURNING selcollist */
+   244,  /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */
+   172,  /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
+   245,  /* (158) setlist ::= setlist COMMA nm EQ expr */
+   245,  /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */
+   245,  /* (160) setlist ::= nm EQ expr */
+   245,  /* (161) setlist ::= LP idlist RP EQ expr */
+   172,  /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+   172,  /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
+   248,  /* (164) upsert ::= */
+   248,  /* (165) upsert ::= RETURNING selcollist */
+   248,  /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+   248,  /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+   248,  /* (168) upsert ::= ON CONFLICT DO NOTHING returning */
+   248,  /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+   249,  /* (170) returning ::= RETURNING selcollist */
+   246,  /* (171) insert_cmd ::= INSERT orconf */
+   246,  /* (172) insert_cmd ::= REPLACE */
+   247,  /* (173) idlist_opt ::= */
+   247,  /* (174) idlist_opt ::= LP idlist RP */
+   240,  /* (175) idlist ::= idlist COMMA nm */
+   240,  /* (176) idlist ::= nm */
+   196,  /* (177) expr ::= LP expr RP */
+   196,  /* (178) expr ::= ID|INDEXED|JOIN_KW */
+   196,  /* (179) expr ::= nm DOT nm */
+   196,  /* (180) expr ::= nm DOT nm DOT nm */
+   195,  /* (181) term ::= NULL|FLOAT|BLOB */
+   195,  /* (182) term ::= STRING */
+   195,  /* (183) term ::= INTEGER */
+   196,  /* (184) expr ::= VARIABLE */
+   196,  /* (185) expr ::= expr COLLATE ID|STRING */
+   196,  /* (186) expr ::= CAST LP expr AS typetoken RP */
+   196,  /* (187) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */
+   196,  /* (188) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */
+   196,  /* (189) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */
+   196,  /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */
+   196,  /* (191) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */
+   196,  /* (192) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */
+   195,  /* (193) term ::= CTIME_KW */
+   196,  /* (194) expr ::= LP nexprlist COMMA expr RP */
+   196,  /* (195) expr ::= expr AND expr */
+   196,  /* (196) expr ::= expr OR expr */
+   196,  /* (197) expr ::= expr LT|GT|GE|LE expr */
+   196,  /* (198) expr ::= expr EQ|NE expr */
+   196,  /* (199) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+   196,  /* (200) expr ::= expr PLUS|MINUS expr */
+   196,  /* (201) expr ::= expr STAR|SLASH|REM expr */
+   196,  /* (202) expr ::= expr CONCAT expr */
+   251,  /* (203) likeop ::= NOT LIKE_KW|MATCH */
+   196,  /* (204) expr ::= expr likeop expr */
+   196,  /* (205) expr ::= expr likeop expr ESCAPE expr */
+   196,  /* (206) expr ::= expr ISNULL|NOTNULL */
+   196,  /* (207) expr ::= expr NOT NULL */
+   196,  /* (208) expr ::= expr IS expr */
+   196,  /* (209) expr ::= expr IS NOT expr */
+   196,  /* (210) expr ::= expr IS NOT DISTINCT FROM expr */
+   196,  /* (211) expr ::= expr IS DISTINCT FROM expr */
+   196,  /* (212) expr ::= NOT expr */
+   196,  /* (213) expr ::= BITNOT expr */
+   196,  /* (214) expr ::= PLUS|MINUS expr */
+   196,  /* (215) expr ::= expr PTR expr */
+   252,  /* (216) between_op ::= BETWEEN */
+   252,  /* (217) between_op ::= NOT BETWEEN */
+   196,  /* (218) expr ::= expr between_op expr AND expr */
+   253,  /* (219) in_op ::= IN */
+   253,  /* (220) in_op ::= NOT IN */
+   196,  /* (221) expr ::= expr in_op LP exprlist RP */
+   196,  /* (222) expr ::= LP select RP */
+   196,  /* (223) expr ::= expr in_op LP select RP */
+   196,  /* (224) expr ::= expr in_op nm dbnm paren_exprlist */
+   196,  /* (225) expr ::= EXISTS LP select RP */
+   196,  /* (226) expr ::= CASE case_operand case_exprlist case_else END */
+   256,  /* (227) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+   256,  /* (228) case_exprlist ::= WHEN expr THEN expr */
+   257,  /* (229) case_else ::= ELSE expr */
+   257,  /* (230) case_else ::= */
+   255,  /* (231) case_operand ::= */
+   238,  /* (232) exprlist ::= */
+   230,  /* (233) nexprlist ::= nexprlist COMMA expr */
+   230,  /* (234) nexprlist ::= expr */
+   254,  /* (235) paren_exprlist ::= */
+   254,  /* (236) paren_exprlist ::= LP exprlist RP */
+   172,  /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+   258,  /* (238) uniqueflag ::= UNIQUE */
+   258,  /* (239) uniqueflag ::= */
+   200,  /* (240) eidlist_opt ::= */
+   200,  /* (241) eidlist_opt ::= LP eidlist RP */
+   210,  /* (242) eidlist ::= eidlist COMMA nm collate sortorder */
+   210,  /* (243) eidlist ::= nm collate sortorder */
+   259,  /* (244) collate ::= */
+   259,  /* (245) collate ::= COLLATE ID|STRING */
+   172,  /* (246) cmd ::= DROP INDEX ifexists fullname */
+   172,  /* (247) cmd ::= VACUUM vinto */
+   172,  /* (248) cmd ::= VACUUM nm vinto */
+   260,  /* (249) vinto ::= INTO expr */
+   260,  /* (250) vinto ::= */
+   172,  /* (251) cmd ::= PRAGMA nm dbnm */
+   172,  /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */
+   172,  /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+   172,  /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */
+   172,  /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+   263,  /* (256) plus_num ::= PLUS INTEGER|FLOAT */
+   262,  /* (257) minus_num ::= MINUS INTEGER|FLOAT */
+   172,  /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+   264,  /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+   266,  /* (260) trigger_time ::= BEFORE|AFTER */
+   266,  /* (261) trigger_time ::= INSTEAD OF */
+   266,  /* (262) trigger_time ::= */
+   267,  /* (263) trigger_event ::= DELETE|INSERT */
+   267,  /* (264) trigger_event ::= UPDATE */
+   267,  /* (265) trigger_event ::= UPDATE OF idlist */
+   269,  /* (266) when_clause ::= */
+   269,  /* (267) when_clause ::= WHEN expr */
+   265,  /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+   265,  /* (269) trigger_cmd_list ::= trigger_cmd SEMI */
+   271,  /* (270) trnm ::= nm DOT nm */
+   272,  /* (271) tridxby ::= INDEXED BY nm */
+   272,  /* (272) tridxby ::= NOT INDEXED */
+   270,  /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
+   270,  /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+   270,  /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+   270,  /* (276) trigger_cmd ::= scanpt select scanpt */
+   196,  /* (277) expr ::= RAISE LP IGNORE RP */
+   196,  /* (278) expr ::= RAISE LP raisetype COMMA nm RP */
+   273,  /* (279) raisetype ::= ROLLBACK */
+   273,  /* (280) raisetype ::= ABORT */
+   273,  /* (281) raisetype ::= FAIL */
+   172,  /* (282) cmd ::= DROP TRIGGER ifexists fullname */
+   172,  /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+   172,  /* (284) cmd ::= DETACH database_kw_opt expr */
+   275,  /* (285) key_opt ::= */
+   275,  /* (286) key_opt ::= KEY expr */
+   172,  /* (287) cmd ::= REINDEX */
+   172,  /* (288) cmd ::= REINDEX nm dbnm */
+   172,  /* (289) cmd ::= ANALYZE */
+   172,  /* (290) cmd ::= ANALYZE nm dbnm */
+   172,  /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */
+   172,  /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+   172,  /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
+   276,  /* (294) add_column_fullname ::= fullname */
+   172,  /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+   172,  /* (296) cmd ::= create_vtab */
+   172,  /* (297) cmd ::= create_vtab LP vtabarglist RP */
+   279,  /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+   281,  /* (299) vtabarg ::= */
+   282,  /* (300) vtabargtoken ::= ANY */
+   282,  /* (301) vtabargtoken ::= lp anylist RP */
+   283,  /* (302) lp ::= LP */
+   243,  /* (303) with ::= WITH wqlist */
+   243,  /* (304) with ::= WITH RECURSIVE wqlist */
+   285,  /* (305) wqas ::= AS */
+   285,  /* (306) wqas ::= AS MATERIALIZED */
+   285,  /* (307) wqas ::= AS NOT MATERIALIZED */
+   286,  /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */
+   216,  /* (309) wqlist ::= wqitem */
+   216,  /* (310) wqlist ::= wqlist COMMA wqitem */
+   287,  /* (311) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+   288,  /* (312) windowdefn ::= nm AS LP window RP */
+   289,  /* (313) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+   289,  /* (314) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+   289,  /* (315) window ::= ORDER BY sortlist frame_opt */
+   289,  /* (316) window ::= nm ORDER BY sortlist frame_opt */
+   289,  /* (317) window ::= nm frame_opt */
+   290,  /* (318) frame_opt ::= */
+   290,  /* (319) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+   290,  /* (320) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+   291,  /* (321) range_or_rows ::= RANGE|ROWS|GROUPS */
+   292,  /* (322) frame_bound_s ::= frame_bound */
+   292,  /* (323) frame_bound_s ::= UNBOUNDED PRECEDING */
+   294,  /* (324) frame_bound_e ::= frame_bound */
+   294,  /* (325) frame_bound_e ::= UNBOUNDED FOLLOWING */
+   295,  /* (326) frame_bound ::= expr PRECEDING|FOLLOWING */
+   295,  /* (327) frame_bound ::= CURRENT ROW */
+   293,  /* (328) frame_exclude_opt ::= */
+   293,  /* (329) frame_exclude_opt ::= EXCLUDE frame_exclude */
+   296,  /* (330) frame_exclude ::= NO OTHERS */
+   296,  /* (331) frame_exclude ::= CURRENT ROW */
+   296,  /* (332) frame_exclude ::= GROUP|TIES */
+   228,  /* (333) window_clause ::= WINDOW windowdefn_list */
+   250,  /* (334) filter_over ::= filter_clause over_clause */
+   250,  /* (335) filter_over ::= over_clause */
+   250,  /* (336) filter_over ::= filter_clause */
+   298,  /* (337) over_clause ::= OVER LP window RP */
+   298,  /* (338) over_clause ::= OVER nm */
+   297,  /* (339) filter_clause ::= FILTER LP WHERE expr RP */
+   299,  /* (340) input ::= cmdlist */
+   300,  /* (341) cmdlist ::= cmdlist ecmd */
+   300,  /* (342) cmdlist ::= ecmd */
+   301,  /* (343) ecmd ::= SEMI */
+   301,  /* (344) ecmd ::= cmdx SEMI */
+   301,  /* (345) ecmd ::= explain cmdx SEMI */
+   174,  /* (346) trans_opt ::= */
+   174,  /* (347) trans_opt ::= TRANSACTION */
+   174,  /* (348) trans_opt ::= TRANSACTION nm */
+   176,  /* (349) savepoint_opt ::= SAVEPOINT */
+   176,  /* (350) savepoint_opt ::= */
+   172,  /* (351) cmd ::= create_table create_table_args */
+   185,  /* (352) table_option_set ::= table_option */
+   183,  /* (353) columnlist ::= columnlist COMMA columnname carglist */
+   183,  /* (354) columnlist ::= columnname carglist */
+   175,  /* (355) nm ::= ID|INDEXED|JOIN_KW */
+   175,  /* (356) nm ::= STRING */
+   189,  /* (357) typetoken ::= typename */
+   190,  /* (358) typename ::= ID|STRING */
+   191,  /* (359) signed ::= plus_num */
+   191,  /* (360) signed ::= minus_num */
+   278,  /* (361) carglist ::= carglist ccons */
+   278,  /* (362) carglist ::= */
+   194,  /* (363) ccons ::= NULL onconf */
+   194,  /* (364) ccons ::= GENERATED ALWAYS AS generated */
+   194,  /* (365) ccons ::= AS generated */
+   184,  /* (366) conslist_opt ::= COMMA conslist */
+   302,  /* (367) conslist ::= conslist tconscomma tcons */
+   302,  /* (368) conslist ::= tcons */
+   207,  /* (369) tconscomma ::= */
+   211,  /* (370) defer_subclause_opt ::= defer_subclause */
+   212,  /* (371) resolvetype ::= raisetype */
+   217,  /* (372) selectnowith ::= oneselect */
+   219,  /* (373) oneselect ::= values */
+   231,  /* (374) sclp ::= selcollist COMMA */
+   232,  /* (375) as ::= ID|STRING */
+   241,  /* (376) indexed_opt ::= indexed_by */
+   249,  /* (377) returning ::= */
+   196,  /* (378) expr ::= term */
+   251,  /* (379) likeop ::= LIKE_KW|MATCH */
+   255,  /* (380) case_operand ::= expr */
+   238,  /* (381) exprlist ::= nexprlist */
+   261,  /* (382) nmnum ::= plus_num */
+   261,  /* (383) nmnum ::= nm */
+   261,  /* (384) nmnum ::= ON */
+   261,  /* (385) nmnum ::= DELETE */
+   261,  /* (386) nmnum ::= DEFAULT */
+   263,  /* (387) plus_num ::= INTEGER|FLOAT */
+   268,  /* (388) foreach_clause ::= */
+   268,  /* (389) foreach_clause ::= FOR EACH ROW */
+   271,  /* (390) trnm ::= nm */
+   272,  /* (391) tridxby ::= */
+   274,  /* (392) database_kw_opt ::= DATABASE */
+   274,  /* (393) database_kw_opt ::= */
+   277,  /* (394) kwcolumn_opt ::= */
+   277,  /* (395) kwcolumn_opt ::= COLUMNKW */
+   280,  /* (396) vtabarglist ::= vtabarg */
+   280,  /* (397) vtabarglist ::= vtabarglist COMMA vtabarg */
+   281,  /* (398) vtabarg ::= vtabarg vtabargtoken */
+   284,  /* (399) anylist ::= */
+   284,  /* (400) anylist ::= anylist LP anylist RP */
+   284,  /* (401) anylist ::= anylist ANY */
+   243,  /* (402) with ::= */
+   287,  /* (403) windowdefn_list ::= windowdefn */
+   289,  /* (404) window ::= frame_opt */
+};
+
+/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
+** of symbols on the right-hand side of that rule. */
+static const signed char yyRuleInfoNRhs[] = {
+   -1,  /* (0) explain ::= EXPLAIN */
+   -3,  /* (1) explain ::= EXPLAIN QUERY PLAN */
+   -1,  /* (2) cmdx ::= cmd */
+   -3,  /* (3) cmd ::= BEGIN transtype trans_opt */
+    0,  /* (4) transtype ::= */
+   -1,  /* (5) transtype ::= DEFERRED */
+   -1,  /* (6) transtype ::= IMMEDIATE */
+   -1,  /* (7) transtype ::= EXCLUSIVE */
+   -2,  /* (8) cmd ::= COMMIT|END trans_opt */
+   -2,  /* (9) cmd ::= ROLLBACK trans_opt */
+   -2,  /* (10) cmd ::= SAVEPOINT nm */
+   -3,  /* (11) cmd ::= RELEASE savepoint_opt nm */
+   -5,  /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+   -6,  /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+   -1,  /* (14) createkw ::= CREATE */
+    0,  /* (15) ifnotexists ::= */
+   -3,  /* (16) ifnotexists ::= IF NOT EXISTS */
+   -1,  /* (17) temp ::= TEMP */
+    0,  /* (18) temp ::= */
+   -5,  /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */
+   -2,  /* (20) create_table_args ::= AS select */
+    0,  /* (21) table_option_set ::= */
+   -3,  /* (22) table_option_set ::= table_option_set COMMA table_option */
+   -2,  /* (23) table_option ::= WITHOUT nm */
+   -1,  /* (24) table_option ::= nm */
+   -2,  /* (25) columnname ::= nm typetoken */
+    0,  /* (26) typetoken ::= */
+   -4,  /* (27) typetoken ::= typename LP signed RP */
+   -6,  /* (28) typetoken ::= typename LP signed COMMA signed RP */
+   -2,  /* (29) typename ::= typename ID|STRING */
+    0,  /* (30) scanpt ::= */
+    0,  /* (31) scantok ::= */
+   -2,  /* (32) ccons ::= CONSTRAINT nm */
+   -3,  /* (33) ccons ::= DEFAULT scantok term */
+   -4,  /* (34) ccons ::= DEFAULT LP expr RP */
+   -4,  /* (35) ccons ::= DEFAULT PLUS scantok term */
+   -4,  /* (36) ccons ::= DEFAULT MINUS scantok term */
+   -3,  /* (37) ccons ::= DEFAULT scantok ID|INDEXED */
+   -3,  /* (38) ccons ::= NOT NULL onconf */
+   -5,  /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+   -2,  /* (40) ccons ::= UNIQUE onconf */
+   -4,  /* (41) ccons ::= CHECK LP expr RP */
+   -4,  /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */
+   -1,  /* (43) ccons ::= defer_subclause */
+   -2,  /* (44) ccons ::= COLLATE ID|STRING */
+   -3,  /* (45) generated ::= LP expr RP */
+   -4,  /* (46) generated ::= LP expr RP ID */
+    0,  /* (47) autoinc ::= */
+   -1,  /* (48) autoinc ::= AUTOINCR */
+    0,  /* (49) refargs ::= */
+   -2,  /* (50) refargs ::= refargs refarg */
+   -2,  /* (51) refarg ::= MATCH nm */
+   -3,  /* (52) refarg ::= ON INSERT refact */
+   -3,  /* (53) refarg ::= ON DELETE refact */
+   -3,  /* (54) refarg ::= ON UPDATE refact */
+   -2,  /* (55) refact ::= SET NULL */
+   -2,  /* (56) refact ::= SET DEFAULT */
+   -1,  /* (57) refact ::= CASCADE */
+   -1,  /* (58) refact ::= RESTRICT */
+   -2,  /* (59) refact ::= NO ACTION */
+   -3,  /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+   -2,  /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+    0,  /* (62) init_deferred_pred_opt ::= */
+   -2,  /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+   -2,  /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+    0,  /* (65) conslist_opt ::= */
+   -1,  /* (66) tconscomma ::= COMMA */
+   -2,  /* (67) tcons ::= CONSTRAINT nm */
+   -7,  /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+   -5,  /* (69) tcons ::= UNIQUE LP sortlist RP onconf */
+   -5,  /* (70) tcons ::= CHECK LP expr RP onconf */
+  -10,  /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+    0,  /* (72) defer_subclause_opt ::= */
+    0,  /* (73) onconf ::= */
+   -3,  /* (74) onconf ::= ON CONFLICT resolvetype */
+    0,  /* (75) orconf ::= */
+   -2,  /* (76) orconf ::= OR resolvetype */
+   -1,  /* (77) resolvetype ::= IGNORE */
+   -1,  /* (78) resolvetype ::= REPLACE */
+   -4,  /* (79) cmd ::= DROP TABLE ifexists fullname */
+   -2,  /* (80) ifexists ::= IF EXISTS */
+    0,  /* (81) ifexists ::= */
+   -9,  /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+   -4,  /* (83) cmd ::= DROP VIEW ifexists fullname */
+   -1,  /* (84) cmd ::= select */
+   -3,  /* (85) select ::= WITH wqlist selectnowith */
+   -4,  /* (86) select ::= WITH RECURSIVE wqlist selectnowith */
+   -1,  /* (87) select ::= selectnowith */
+   -3,  /* (88) selectnowith ::= selectnowith multiselect_op oneselect */
+   -1,  /* (89) multiselect_op ::= UNION */
+   -2,  /* (90) multiselect_op ::= UNION ALL */
+   -1,  /* (91) multiselect_op ::= EXCEPT|INTERSECT */
+   -9,  /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+  -10,  /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+   -4,  /* (94) values ::= VALUES LP nexprlist RP */
+   -5,  /* (95) values ::= values COMMA LP nexprlist RP */
+   -1,  /* (96) distinct ::= DISTINCT */
+   -1,  /* (97) distinct ::= ALL */
+    0,  /* (98) distinct ::= */
+    0,  /* (99) sclp ::= */
+   -5,  /* (100) selcollist ::= sclp scanpt expr scanpt as */
+   -3,  /* (101) selcollist ::= sclp scanpt STAR */
+   -5,  /* (102) selcollist ::= sclp scanpt nm DOT STAR */
+   -2,  /* (103) as ::= AS nm */
+    0,  /* (104) as ::= */
+    0,  /* (105) from ::= */
+   -2,  /* (106) from ::= FROM seltablist */
+   -2,  /* (107) stl_prefix ::= seltablist joinop */
+    0,  /* (108) stl_prefix ::= */
+   -5,  /* (109) seltablist ::= stl_prefix nm dbnm as on_using */
+   -6,  /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
+   -8,  /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
+   -6,  /* (112) seltablist ::= stl_prefix LP select RP as on_using */
+   -6,  /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */
+    0,  /* (114) dbnm ::= */
+   -2,  /* (115) dbnm ::= DOT nm */
+   -1,  /* (116) fullname ::= nm */
+   -3,  /* (117) fullname ::= nm DOT nm */
+   -1,  /* (118) xfullname ::= nm */
+   -3,  /* (119) xfullname ::= nm DOT nm */
+   -5,  /* (120) xfullname ::= nm DOT nm AS nm */
+   -3,  /* (121) xfullname ::= nm AS nm */
+   -1,  /* (122) joinop ::= COMMA|JOIN */
+   -2,  /* (123) joinop ::= JOIN_KW JOIN */
+   -3,  /* (124) joinop ::= JOIN_KW nm JOIN */
+   -4,  /* (125) joinop ::= JOIN_KW nm nm JOIN */
+   -2,  /* (126) on_using ::= ON expr */
+   -4,  /* (127) on_using ::= USING LP idlist RP */
+    0,  /* (128) on_using ::= */
+    0,  /* (129) indexed_opt ::= */
+   -3,  /* (130) indexed_by ::= INDEXED BY nm */
+   -2,  /* (131) indexed_by ::= NOT INDEXED */
+    0,  /* (132) orderby_opt ::= */
+   -3,  /* (133) orderby_opt ::= ORDER BY sortlist */
+   -5,  /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */
+   -3,  /* (135) sortlist ::= expr sortorder nulls */
+   -1,  /* (136) sortorder ::= ASC */
+   -1,  /* (137) sortorder ::= DESC */
+    0,  /* (138) sortorder ::= */
+   -2,  /* (139) nulls ::= NULLS FIRST */
+   -2,  /* (140) nulls ::= NULLS LAST */
+    0,  /* (141) nulls ::= */
+    0,  /* (142) groupby_opt ::= */
+   -3,  /* (143) groupby_opt ::= GROUP BY nexprlist */
+    0,  /* (144) having_opt ::= */
+   -2,  /* (145) having_opt ::= HAVING expr */
+    0,  /* (146) limit_opt ::= */
+   -2,  /* (147) limit_opt ::= LIMIT expr */
+   -4,  /* (148) limit_opt ::= LIMIT expr OFFSET expr */
+   -4,  /* (149) limit_opt ::= LIMIT expr COMMA expr */
+   -6,  /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
+    0,  /* (151) where_opt ::= */
+   -2,  /* (152) where_opt ::= WHERE expr */
+    0,  /* (153) where_opt_ret ::= */
+   -2,  /* (154) where_opt_ret ::= WHERE expr */
+   -2,  /* (155) where_opt_ret ::= RETURNING selcollist */
+   -4,  /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */
+   -9,  /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
+   -5,  /* (158) setlist ::= setlist COMMA nm EQ expr */
+   -7,  /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */
+   -3,  /* (160) setlist ::= nm EQ expr */
+   -5,  /* (161) setlist ::= LP idlist RP EQ expr */
+   -7,  /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+   -8,  /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
+    0,  /* (164) upsert ::= */
+   -2,  /* (165) upsert ::= RETURNING selcollist */
+  -12,  /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+   -9,  /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+   -5,  /* (168) upsert ::= ON CONFLICT DO NOTHING returning */
+   -8,  /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+   -2,  /* (170) returning ::= RETURNING selcollist */
+   -2,  /* (171) insert_cmd ::= INSERT orconf */
+   -1,  /* (172) insert_cmd ::= REPLACE */
+    0,  /* (173) idlist_opt ::= */
+   -3,  /* (174) idlist_opt ::= LP idlist RP */
+   -3,  /* (175) idlist ::= idlist COMMA nm */
+   -1,  /* (176) idlist ::= nm */
+   -3,  /* (177) expr ::= LP expr RP */
+   -1,  /* (178) expr ::= ID|INDEXED|JOIN_KW */
+   -3,  /* (179) expr ::= nm DOT nm */
+   -5,  /* (180) expr ::= nm DOT nm DOT nm */
+   -1,  /* (181) term ::= NULL|FLOAT|BLOB */
+   -1,  /* (182) term ::= STRING */
+   -1,  /* (183) term ::= INTEGER */
+   -1,  /* (184) expr ::= VARIABLE */
+   -3,  /* (185) expr ::= expr COLLATE ID|STRING */
+   -6,  /* (186) expr ::= CAST LP expr AS typetoken RP */
+   -5,  /* (187) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */
+   -8,  /* (188) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */
+   -4,  /* (189) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */
+   -6,  /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */
+   -9,  /* (191) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */
+   -5,  /* (192) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */
+   -1,  /* (193) term ::= CTIME_KW */
+   -5,  /* (194) expr ::= LP nexprlist COMMA expr RP */
+   -3,  /* (195) expr ::= expr AND expr */
+   -3,  /* (196) expr ::= expr OR expr */
+   -3,  /* (197) expr ::= expr LT|GT|GE|LE expr */
+   -3,  /* (198) expr ::= expr EQ|NE expr */
+   -3,  /* (199) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+   -3,  /* (200) expr ::= expr PLUS|MINUS expr */
+   -3,  /* (201) expr ::= expr STAR|SLASH|REM expr */
+   -3,  /* (202) expr ::= expr CONCAT expr */
+   -2,  /* (203) likeop ::= NOT LIKE_KW|MATCH */
+   -3,  /* (204) expr ::= expr likeop expr */
+   -5,  /* (205) expr ::= expr likeop expr ESCAPE expr */
+   -2,  /* (206) expr ::= expr ISNULL|NOTNULL */
+   -3,  /* (207) expr ::= expr NOT NULL */
+   -3,  /* (208) expr ::= expr IS expr */
+   -4,  /* (209) expr ::= expr IS NOT expr */
+   -6,  /* (210) expr ::= expr IS NOT DISTINCT FROM expr */
+   -5,  /* (211) expr ::= expr IS DISTINCT FROM expr */
+   -2,  /* (212) expr ::= NOT expr */
+   -2,  /* (213) expr ::= BITNOT expr */
+   -2,  /* (214) expr ::= PLUS|MINUS expr */
+   -3,  /* (215) expr ::= expr PTR expr */
+   -1,  /* (216) between_op ::= BETWEEN */
+   -2,  /* (217) between_op ::= NOT BETWEEN */
+   -5,  /* (218) expr ::= expr between_op expr AND expr */
+   -1,  /* (219) in_op ::= IN */
+   -2,  /* (220) in_op ::= NOT IN */
+   -5,  /* (221) expr ::= expr in_op LP exprlist RP */
+   -3,  /* (222) expr ::= LP select RP */
+   -5,  /* (223) expr ::= expr in_op LP select RP */
+   -5,  /* (224) expr ::= expr in_op nm dbnm paren_exprlist */
+   -4,  /* (225) expr ::= EXISTS LP select RP */
+   -5,  /* (226) expr ::= CASE case_operand case_exprlist case_else END */
+   -5,  /* (227) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+   -4,  /* (228) case_exprlist ::= WHEN expr THEN expr */
+   -2,  /* (229) case_else ::= ELSE expr */
+    0,  /* (230) case_else ::= */
+    0,  /* (231) case_operand ::= */
+    0,  /* (232) exprlist ::= */
+   -3,  /* (233) nexprlist ::= nexprlist COMMA expr */
+   -1,  /* (234) nexprlist ::= expr */
+    0,  /* (235) paren_exprlist ::= */
+   -3,  /* (236) paren_exprlist ::= LP exprlist RP */
+  -12,  /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+   -1,  /* (238) uniqueflag ::= UNIQUE */
+    0,  /* (239) uniqueflag ::= */
+    0,  /* (240) eidlist_opt ::= */
+   -3,  /* (241) eidlist_opt ::= LP eidlist RP */
+   -5,  /* (242) eidlist ::= eidlist COMMA nm collate sortorder */
+   -3,  /* (243) eidlist ::= nm collate sortorder */
+    0,  /* (244) collate ::= */
+   -2,  /* (245) collate ::= COLLATE ID|STRING */
+   -4,  /* (246) cmd ::= DROP INDEX ifexists fullname */
+   -2,  /* (247) cmd ::= VACUUM vinto */
+   -3,  /* (248) cmd ::= VACUUM nm vinto */
+   -2,  /* (249) vinto ::= INTO expr */
+    0,  /* (250) vinto ::= */
+   -3,  /* (251) cmd ::= PRAGMA nm dbnm */
+   -5,  /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */
+   -6,  /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+   -5,  /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */
+   -6,  /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+   -2,  /* (256) plus_num ::= PLUS INTEGER|FLOAT */
+   -2,  /* (257) minus_num ::= MINUS INTEGER|FLOAT */
+   -5,  /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+  -11,  /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+   -1,  /* (260) trigger_time ::= BEFORE|AFTER */
+   -2,  /* (261) trigger_time ::= INSTEAD OF */
+    0,  /* (262) trigger_time ::= */
+   -1,  /* (263) trigger_event ::= DELETE|INSERT */
+   -1,  /* (264) trigger_event ::= UPDATE */
+   -3,  /* (265) trigger_event ::= UPDATE OF idlist */
+    0,  /* (266) when_clause ::= */
+   -2,  /* (267) when_clause ::= WHEN expr */
+   -3,  /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+   -2,  /* (269) trigger_cmd_list ::= trigger_cmd SEMI */
+   -3,  /* (270) trnm ::= nm DOT nm */
+   -3,  /* (271) tridxby ::= INDEXED BY nm */
+   -2,  /* (272) tridxby ::= NOT INDEXED */
+   -9,  /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
+   -8,  /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+   -6,  /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+   -3,  /* (276) trigger_cmd ::= scanpt select scanpt */
+   -4,  /* (277) expr ::= RAISE LP IGNORE RP */
+   -6,  /* (278) expr ::= RAISE LP raisetype COMMA nm RP */
+   -1,  /* (279) raisetype ::= ROLLBACK */
+   -1,  /* (280) raisetype ::= ABORT */
+   -1,  /* (281) raisetype ::= FAIL */
+   -4,  /* (282) cmd ::= DROP TRIGGER ifexists fullname */
+   -6,  /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+   -3,  /* (284) cmd ::= DETACH database_kw_opt expr */
+    0,  /* (285) key_opt ::= */
+   -2,  /* (286) key_opt ::= KEY expr */
+   -1,  /* (287) cmd ::= REINDEX */
+   -3,  /* (288) cmd ::= REINDEX nm dbnm */
+   -1,  /* (289) cmd ::= ANALYZE */
+   -3,  /* (290) cmd ::= ANALYZE nm dbnm */
+   -6,  /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */
+   -7,  /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+   -6,  /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
+   -1,  /* (294) add_column_fullname ::= fullname */
+   -8,  /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+   -1,  /* (296) cmd ::= create_vtab */
+   -4,  /* (297) cmd ::= create_vtab LP vtabarglist RP */
+   -8,  /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+    0,  /* (299) vtabarg ::= */
+   -1,  /* (300) vtabargtoken ::= ANY */
+   -3,  /* (301) vtabargtoken ::= lp anylist RP */
+   -1,  /* (302) lp ::= LP */
+   -2,  /* (303) with ::= WITH wqlist */
+   -3,  /* (304) with ::= WITH RECURSIVE wqlist */
+   -1,  /* (305) wqas ::= AS */
+   -2,  /* (306) wqas ::= AS MATERIALIZED */
+   -3,  /* (307) wqas ::= AS NOT MATERIALIZED */
+   -6,  /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */
+   -1,  /* (309) wqlist ::= wqitem */
+   -3,  /* (310) wqlist ::= wqlist COMMA wqitem */
+   -3,  /* (311) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+   -5,  /* (312) windowdefn ::= nm AS LP window RP */
+   -5,  /* (313) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+   -6,  /* (314) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+   -4,  /* (315) window ::= ORDER BY sortlist frame_opt */
+   -5,  /* (316) window ::= nm ORDER BY sortlist frame_opt */
+   -2,  /* (317) window ::= nm frame_opt */
+    0,  /* (318) frame_opt ::= */
+   -3,  /* (319) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+   -6,  /* (320) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+   -1,  /* (321) range_or_rows ::= RANGE|ROWS|GROUPS */
+   -1,  /* (322) frame_bound_s ::= frame_bound */
+   -2,  /* (323) frame_bound_s ::= UNBOUNDED PRECEDING */
+   -1,  /* (324) frame_bound_e ::= frame_bound */
+   -2,  /* (325) frame_bound_e ::= UNBOUNDED FOLLOWING */
+   -2,  /* (326) frame_bound ::= expr PRECEDING|FOLLOWING */
+   -2,  /* (327) frame_bound ::= CURRENT ROW */
+    0,  /* (328) frame_exclude_opt ::= */
+   -2,  /* (329) frame_exclude_opt ::= EXCLUDE frame_exclude */
+   -2,  /* (330) frame_exclude ::= NO OTHERS */
+   -2,  /* (331) frame_exclude ::= CURRENT ROW */
+   -1,  /* (332) frame_exclude ::= GROUP|TIES */
+   -2,  /* (333) window_clause ::= WINDOW windowdefn_list */
+   -2,  /* (334) filter_over ::= filter_clause over_clause */
+   -1,  /* (335) filter_over ::= over_clause */
+   -1,  /* (336) filter_over ::= filter_clause */
+   -4,  /* (337) over_clause ::= OVER LP window RP */
+   -2,  /* (338) over_clause ::= OVER nm */
+   -5,  /* (339) filter_clause ::= FILTER LP WHERE expr RP */
+   -1,  /* (340) input ::= cmdlist */
+   -2,  /* (341) cmdlist ::= cmdlist ecmd */
+   -1,  /* (342) cmdlist ::= ecmd */
+   -1,  /* (343) ecmd ::= SEMI */
+   -2,  /* (344) ecmd ::= cmdx SEMI */
+   -3,  /* (345) ecmd ::= explain cmdx SEMI */
+    0,  /* (346) trans_opt ::= */
+   -1,  /* (347) trans_opt ::= TRANSACTION */
+   -2,  /* (348) trans_opt ::= TRANSACTION nm */
+   -1,  /* (349) savepoint_opt ::= SAVEPOINT */
+    0,  /* (350) savepoint_opt ::= */
+   -2,  /* (351) cmd ::= create_table create_table_args */
+   -1,  /* (352) table_option_set ::= table_option */
+   -4,  /* (353) columnlist ::= columnlist COMMA columnname carglist */
+   -2,  /* (354) columnlist ::= columnname carglist */
+   -1,  /* (355) nm ::= ID|INDEXED|JOIN_KW */
+   -1,  /* (356) nm ::= STRING */
+   -1,  /* (357) typetoken ::= typename */
+   -1,  /* (358) typename ::= ID|STRING */
+   -1,  /* (359) signed ::= plus_num */
+   -1,  /* (360) signed ::= minus_num */
+   -2,  /* (361) carglist ::= carglist ccons */
+    0,  /* (362) carglist ::= */
+   -2,  /* (363) ccons ::= NULL onconf */
+   -4,  /* (364) ccons ::= GENERATED ALWAYS AS generated */
+   -2,  /* (365) ccons ::= AS generated */
+   -2,  /* (366) conslist_opt ::= COMMA conslist */
+   -3,  /* (367) conslist ::= conslist tconscomma tcons */
+   -1,  /* (368) conslist ::= tcons */
+    0,  /* (369) tconscomma ::= */
+   -1,  /* (370) defer_subclause_opt ::= defer_subclause */
+   -1,  /* (371) resolvetype ::= raisetype */
+   -1,  /* (372) selectnowith ::= oneselect */
+   -1,  /* (373) oneselect ::= values */
+   -2,  /* (374) sclp ::= selcollist COMMA */
+   -1,  /* (375) as ::= ID|STRING */
+   -1,  /* (376) indexed_opt ::= indexed_by */
+    0,  /* (377) returning ::= */
+   -1,  /* (378) expr ::= term */
+   -1,  /* (379) likeop ::= LIKE_KW|MATCH */
+   -1,  /* (380) case_operand ::= expr */
+   -1,  /* (381) exprlist ::= nexprlist */
+   -1,  /* (382) nmnum ::= plus_num */
+   -1,  /* (383) nmnum ::= nm */
+   -1,  /* (384) nmnum ::= ON */
+   -1,  /* (385) nmnum ::= DELETE */
+   -1,  /* (386) nmnum ::= DEFAULT */
+   -1,  /* (387) plus_num ::= INTEGER|FLOAT */
+    0,  /* (388) foreach_clause ::= */
+   -3,  /* (389) foreach_clause ::= FOR EACH ROW */
+   -1,  /* (390) trnm ::= nm */
+    0,  /* (391) tridxby ::= */
+   -1,  /* (392) database_kw_opt ::= DATABASE */
+    0,  /* (393) database_kw_opt ::= */
+    0,  /* (394) kwcolumn_opt ::= */
+   -1,  /* (395) kwcolumn_opt ::= COLUMNKW */
+   -1,  /* (396) vtabarglist ::= vtabarg */
+   -3,  /* (397) vtabarglist ::= vtabarglist COMMA vtabarg */
+   -2,  /* (398) vtabarg ::= vtabarg vtabargtoken */
+    0,  /* (399) anylist ::= */
+   -4,  /* (400) anylist ::= anylist LP anylist RP */
+   -2,  /* (401) anylist ::= anylist ANY */
+    0,  /* (402) with ::= */
+   -1,  /* (403) windowdefn_list ::= windowdefn */
+   -1,  /* (404) window ::= frame_opt */
+};
+
+static void yy_accept(yyParser*);  /* Forward Declaration */
+
+/*
+** Perform a reduce action and the shift that must immediately
+** follow the reduce.
+**
+** The yyLookahead and yyLookaheadToken parameters provide reduce actions
+** access to the lookahead token (if any).  The yyLookahead will be YYNOCODE
+** if the lookahead token has already been consumed.  As this procedure is
+** only called from one place, optimizing compilers will in-line it, which
+** means that the extra parameters have no performance impact.
+*/
+static YYACTIONTYPE yy_reduce(
+  yyParser *yypParser,         /* The parser */
+  unsigned int yyruleno,       /* Number of the rule by which to reduce */
+  int yyLookahead,             /* Lookahead token, or YYNOCODE if none */
+  PerfettoSqlParserTOKENTYPE yyLookaheadToken  /* Value of the lookahead token */
+  PerfettoSqlParserCTX_PDECL                   /* %extra_context */
+){
+  int yygoto;                     /* The next state */
+  YYACTIONTYPE yyact;             /* The next action */
+  yyStackEntry *yymsp;            /* The top of the parser's stack */
+  int yysize;                     /* Amount to pop the stack */
+  PerfettoSqlParserARG_FETCH
+  (void)yyLookahead;
+  (void)yyLookaheadToken;
+  yymsp = yypParser->yytos;
+
+  switch( yyruleno ){
+  /* Beginning here are the reduction cases.  A typical example
+  ** follows:
+  **   case 0:
+  **  #line <lineno> <grammarfile>
+  **     { ... }           // User supplied code
+  **  #line <lineno> <thisfile>
+  **     break;
+  */
+/********** Begin reduce actions **********************************************/
+      default:
+      /* (0) explain ::= EXPLAIN */ yytestcase(yyruleno==0);
+      /* (1) explain ::= EXPLAIN QUERY PLAN */ yytestcase(yyruleno==1);
+      /* (2) cmdx ::= cmd (OPTIMIZED OUT) */ assert(yyruleno!=2);
+      /* (3) cmd ::= BEGIN transtype trans_opt */ yytestcase(yyruleno==3);
+      /* (4) transtype ::= */ yytestcase(yyruleno==4);
+      /* (5) transtype ::= DEFERRED */ yytestcase(yyruleno==5);
+      /* (6) transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
+      /* (7) transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
+      /* (8) cmd ::= COMMIT|END trans_opt */ yytestcase(yyruleno==8);
+      /* (9) cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
+      /* (10) cmd ::= SAVEPOINT nm */ yytestcase(yyruleno==10);
+      /* (11) cmd ::= RELEASE savepoint_opt nm */ yytestcase(yyruleno==11);
+      /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ yytestcase(yyruleno==12);
+      /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ yytestcase(yyruleno==13);
+      /* (14) createkw ::= CREATE */ yytestcase(yyruleno==14);
+      /* (15) ifnotexists ::= */ yytestcase(yyruleno==15);
+      /* (16) ifnotexists ::= IF NOT EXISTS */ yytestcase(yyruleno==16);
+      /* (17) temp ::= TEMP */ yytestcase(yyruleno==17);
+      /* (18) temp ::= */ yytestcase(yyruleno==18);
+      /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ yytestcase(yyruleno==19);
+      /* (20) create_table_args ::= AS select */ yytestcase(yyruleno==20);
+      /* (21) table_option_set ::= */ yytestcase(yyruleno==21);
+      /* (22) table_option_set ::= table_option_set COMMA table_option */ yytestcase(yyruleno==22);
+      /* (23) table_option ::= WITHOUT nm */ yytestcase(yyruleno==23);
+      /* (24) table_option ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=24);
+      /* (25) columnname ::= nm typetoken */ yytestcase(yyruleno==25);
+      /* (26) typetoken ::= */ yytestcase(yyruleno==26);
+      /* (27) typetoken ::= typename LP signed RP */ yytestcase(yyruleno==27);
+      /* (28) typetoken ::= typename LP signed COMMA signed RP */ yytestcase(yyruleno==28);
+      /* (29) typename ::= typename ID|STRING */ yytestcase(yyruleno==29);
+      /* (30) scanpt ::= */ yytestcase(yyruleno==30);
+      /* (31) scantok ::= */ yytestcase(yyruleno==31);
+      /* (32) ccons ::= CONSTRAINT nm */ yytestcase(yyruleno==32);
+      /* (33) ccons ::= DEFAULT scantok term */ yytestcase(yyruleno==33);
+      /* (34) ccons ::= DEFAULT LP expr RP */ yytestcase(yyruleno==34);
+      /* (35) ccons ::= DEFAULT PLUS scantok term */ yytestcase(yyruleno==35);
+      /* (36) ccons ::= DEFAULT MINUS scantok term */ yytestcase(yyruleno==36);
+      /* (37) ccons ::= DEFAULT scantok ID|INDEXED */ yytestcase(yyruleno==37);
+      /* (38) ccons ::= NOT NULL onconf */ yytestcase(yyruleno==38);
+      /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */ yytestcase(yyruleno==39);
+      /* (40) ccons ::= UNIQUE onconf */ yytestcase(yyruleno==40);
+      /* (41) ccons ::= CHECK LP expr RP */ yytestcase(yyruleno==41);
+      /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */ yytestcase(yyruleno==42);
+      /* (43) ccons ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=43);
+      /* (44) ccons ::= COLLATE ID|STRING */ yytestcase(yyruleno==44);
+      /* (45) generated ::= LP expr RP */ yytestcase(yyruleno==45);
+      /* (46) generated ::= LP expr RP ID */ yytestcase(yyruleno==46);
+      /* (47) autoinc ::= */ yytestcase(yyruleno==47);
+      /* (48) autoinc ::= AUTOINCR */ yytestcase(yyruleno==48);
+      /* (49) refargs ::= */ yytestcase(yyruleno==49);
+      /* (50) refargs ::= refargs refarg */ yytestcase(yyruleno==50);
+      /* (51) refarg ::= MATCH nm */ yytestcase(yyruleno==51);
+      /* (52) refarg ::= ON INSERT refact */ yytestcase(yyruleno==52);
+      /* (53) refarg ::= ON DELETE refact */ yytestcase(yyruleno==53);
+      /* (54) refarg ::= ON UPDATE refact */ yytestcase(yyruleno==54);
+      /* (55) refact ::= SET NULL */ yytestcase(yyruleno==55);
+      /* (56) refact ::= SET DEFAULT */ yytestcase(yyruleno==56);
+      /* (57) refact ::= CASCADE */ yytestcase(yyruleno==57);
+      /* (58) refact ::= RESTRICT */ yytestcase(yyruleno==58);
+      /* (59) refact ::= NO ACTION */ yytestcase(yyruleno==59);
+      /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==60);
+      /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==61);
+      /* (62) init_deferred_pred_opt ::= */ yytestcase(yyruleno==62);
+      /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==63);
+      /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==64);
+      /* (65) conslist_opt ::= */ yytestcase(yyruleno==65);
+      /* (66) tconscomma ::= COMMA */ yytestcase(yyruleno==66);
+      /* (67) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==67);
+      /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ yytestcase(yyruleno==68);
+      /* (69) tcons ::= UNIQUE LP sortlist RP onconf */ yytestcase(yyruleno==69);
+      /* (70) tcons ::= CHECK LP expr RP onconf */ yytestcase(yyruleno==70);
+      /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ yytestcase(yyruleno==71);
+      /* (72) defer_subclause_opt ::= */ yytestcase(yyruleno==72);
+      /* (73) onconf ::= */ yytestcase(yyruleno==73);
+      /* (74) onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==74);
+      /* (75) orconf ::= */ yytestcase(yyruleno==75);
+      /* (76) orconf ::= OR resolvetype */ yytestcase(yyruleno==76);
+      /* (77) resolvetype ::= IGNORE */ yytestcase(yyruleno==77);
+      /* (78) resolvetype ::= REPLACE */ yytestcase(yyruleno==78);
+      /* (79) cmd ::= DROP TABLE ifexists fullname */ yytestcase(yyruleno==79);
+      /* (80) ifexists ::= IF EXISTS */ yytestcase(yyruleno==80);
+      /* (81) ifexists ::= */ yytestcase(yyruleno==81);
+      /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ yytestcase(yyruleno==82);
+      /* (83) cmd ::= DROP VIEW ifexists fullname */ yytestcase(yyruleno==83);
+      /* (84) cmd ::= select (OPTIMIZED OUT) */ assert(yyruleno!=84);
+      /* (85) select ::= WITH wqlist selectnowith */ yytestcase(yyruleno==85);
+      /* (86) select ::= WITH RECURSIVE wqlist selectnowith */ yytestcase(yyruleno==86);
+      /* (87) select ::= selectnowith */ yytestcase(yyruleno==87);
+      /* (88) selectnowith ::= selectnowith multiselect_op oneselect */ yytestcase(yyruleno==88);
+      /* (89) multiselect_op ::= UNION */ yytestcase(yyruleno==89);
+      /* (90) multiselect_op ::= UNION ALL */ yytestcase(yyruleno==90);
+      /* (91) multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91);
+      /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ yytestcase(yyruleno==92);
+      /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ yytestcase(yyruleno==93);
+      /* (94) values ::= VALUES LP nexprlist RP */ yytestcase(yyruleno==94);
+      /* (95) values ::= values COMMA LP nexprlist RP */ yytestcase(yyruleno==95);
+      /* (96) distinct ::= DISTINCT */ yytestcase(yyruleno==96);
+      /* (97) distinct ::= ALL */ yytestcase(yyruleno==97);
+      /* (98) distinct ::= */ yytestcase(yyruleno==98);
+      /* (99) sclp ::= */ yytestcase(yyruleno==99);
+      /* (100) selcollist ::= sclp scanpt expr scanpt as */ yytestcase(yyruleno==100);
+      /* (101) selcollist ::= sclp scanpt STAR */ yytestcase(yyruleno==101);
+      /* (102) selcollist ::= sclp scanpt nm DOT STAR */ yytestcase(yyruleno==102);
+      /* (103) as ::= AS nm */ yytestcase(yyruleno==103);
+      /* (104) as ::= */ yytestcase(yyruleno==104);
+      /* (105) from ::= */ yytestcase(yyruleno==105);
+      /* (106) from ::= FROM seltablist */ yytestcase(yyruleno==106);
+      /* (107) stl_prefix ::= seltablist joinop */ yytestcase(yyruleno==107);
+      /* (108) stl_prefix ::= */ yytestcase(yyruleno==108);
+      /* (109) seltablist ::= stl_prefix nm dbnm as on_using */ yytestcase(yyruleno==109);
+      /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ yytestcase(yyruleno==110);
+      /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ yytestcase(yyruleno==111);
+      /* (112) seltablist ::= stl_prefix LP select RP as on_using */ yytestcase(yyruleno==112);
+      /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */ yytestcase(yyruleno==113);
+      /* (114) dbnm ::= */ yytestcase(yyruleno==114);
+      /* (115) dbnm ::= DOT nm */ yytestcase(yyruleno==115);
+      /* (116) fullname ::= nm */ yytestcase(yyruleno==116);
+      /* (117) fullname ::= nm DOT nm */ yytestcase(yyruleno==117);
+      /* (118) xfullname ::= nm */ yytestcase(yyruleno==118);
+      /* (119) xfullname ::= nm DOT nm */ yytestcase(yyruleno==119);
+      /* (120) xfullname ::= nm DOT nm AS nm */ yytestcase(yyruleno==120);
+      /* (121) xfullname ::= nm AS nm */ yytestcase(yyruleno==121);
+      /* (122) joinop ::= COMMA|JOIN */ yytestcase(yyruleno==122);
+      /* (123) joinop ::= JOIN_KW JOIN */ yytestcase(yyruleno==123);
+      /* (124) joinop ::= JOIN_KW nm JOIN */ yytestcase(yyruleno==124);
+      /* (125) joinop ::= JOIN_KW nm nm JOIN */ yytestcase(yyruleno==125);
+      /* (126) on_using ::= ON expr */ yytestcase(yyruleno==126);
+      /* (127) on_using ::= USING LP idlist RP */ yytestcase(yyruleno==127);
+      /* (128) on_using ::= */ yytestcase(yyruleno==128);
+      /* (129) indexed_opt ::= */ yytestcase(yyruleno==129);
+      /* (130) indexed_by ::= INDEXED BY nm */ yytestcase(yyruleno==130);
+      /* (131) indexed_by ::= NOT INDEXED */ yytestcase(yyruleno==131);
+      /* (132) orderby_opt ::= */ yytestcase(yyruleno==132);
+      /* (133) orderby_opt ::= ORDER BY sortlist */ yytestcase(yyruleno==133);
+      /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */ yytestcase(yyruleno==134);
+      /* (135) sortlist ::= expr sortorder nulls */ yytestcase(yyruleno==135);
+      /* (136) sortorder ::= ASC */ yytestcase(yyruleno==136);
+      /* (137) sortorder ::= DESC */ yytestcase(yyruleno==137);
+      /* (138) sortorder ::= */ yytestcase(yyruleno==138);
+      /* (139) nulls ::= NULLS FIRST */ yytestcase(yyruleno==139);
+      /* (140) nulls ::= NULLS LAST */ yytestcase(yyruleno==140);
+      /* (141) nulls ::= */ yytestcase(yyruleno==141);
+      /* (142) groupby_opt ::= */ yytestcase(yyruleno==142);
+      /* (143) groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==143);
+      /* (144) having_opt ::= */ yytestcase(yyruleno==144);
+      /* (145) having_opt ::= HAVING expr */ yytestcase(yyruleno==145);
+      /* (146) limit_opt ::= */ yytestcase(yyruleno==146);
+      /* (147) limit_opt ::= LIMIT expr */ yytestcase(yyruleno==147);
+      /* (148) limit_opt ::= LIMIT expr OFFSET expr */ yytestcase(yyruleno==148);
+      /* (149) limit_opt ::= LIMIT expr COMMA expr */ yytestcase(yyruleno==149);
+      /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ yytestcase(yyruleno==150);
+      /* (151) where_opt ::= */ yytestcase(yyruleno==151);
+      /* (152) where_opt ::= WHERE expr */ yytestcase(yyruleno==152);
+      /* (153) where_opt_ret ::= */ yytestcase(yyruleno==153);
+      /* (154) where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==154);
+      /* (155) where_opt_ret ::= RETURNING selcollist */ yytestcase(yyruleno==155);
+      /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */ yytestcase(yyruleno==156);
+      /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ yytestcase(yyruleno==157);
+      /* (158) setlist ::= setlist COMMA nm EQ expr */ yytestcase(yyruleno==158);
+      /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */ yytestcase(yyruleno==159);
+      /* (160) setlist ::= nm EQ expr */ yytestcase(yyruleno==160);
+      /* (161) setlist ::= LP idlist RP EQ expr */ yytestcase(yyruleno==161);
+      /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ yytestcase(yyruleno==162);
+      /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ yytestcase(yyruleno==163);
+      /* (164) upsert ::= */ yytestcase(yyruleno==164);
+      /* (165) upsert ::= RETURNING selcollist */ yytestcase(yyruleno==165);
+      /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ yytestcase(yyruleno==166);
+      /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ yytestcase(yyruleno==167);
+      /* (168) upsert ::= ON CONFLICT DO NOTHING returning */ yytestcase(yyruleno==168);
+      /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ yytestcase(yyruleno==169);
+      /* (170) returning ::= RETURNING selcollist */ yytestcase(yyruleno==170);
+      /* (171) insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==171);
+      /* (172) insert_cmd ::= REPLACE */ yytestcase(yyruleno==172);
+      /* (173) idlist_opt ::= */ yytestcase(yyruleno==173);
+      /* (174) idlist_opt ::= LP idlist RP */ yytestcase(yyruleno==174);
+      /* (175) idlist ::= idlist COMMA nm */ yytestcase(yyruleno==175);
+      /* (176) idlist ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=176);
+      /* (177) expr ::= LP expr RP */ yytestcase(yyruleno==177);
+      /* (178) expr ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==178);
+      /* (179) expr ::= nm DOT nm */ yytestcase(yyruleno==179);
+      /* (180) expr ::= nm DOT nm DOT nm */ yytestcase(yyruleno==180);
+      /* (181) term ::= NULL|FLOAT|BLOB */ yytestcase(yyruleno==181);
+      /* (182) term ::= STRING */ yytestcase(yyruleno==182);
+      /* (183) term ::= INTEGER */ yytestcase(yyruleno==183);
+      /* (184) expr ::= VARIABLE */ yytestcase(yyruleno==184);
+      /* (185) expr ::= expr COLLATE ID|STRING */ yytestcase(yyruleno==185);
+      /* (186) expr ::= CAST LP expr AS typetoken RP */ yytestcase(yyruleno==186);
+      /* (187) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP */ yytestcase(yyruleno==187);
+      /* (188) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP */ yytestcase(yyruleno==188);
+      /* (189) expr ::= ID|INDEXED|JOIN_KW LP STAR RP */ yytestcase(yyruleno==189);
+      /* (190) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over */ yytestcase(yyruleno==190);
+      /* (191) expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over */ yytestcase(yyruleno==191);
+      /* (192) expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over */ yytestcase(yyruleno==192);
+      /* (193) term ::= CTIME_KW */ yytestcase(yyruleno==193);
+      /* (194) expr ::= LP nexprlist COMMA expr RP */ yytestcase(yyruleno==194);
+      /* (195) expr ::= expr AND expr */ yytestcase(yyruleno==195);
+      /* (196) expr ::= expr OR expr */ yytestcase(yyruleno==196);
+      /* (197) expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==197);
+      /* (198) expr ::= expr EQ|NE expr */ yytestcase(yyruleno==198);
+      /* (199) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==199);
+      /* (200) expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==200);
+      /* (201) expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==201);
+      /* (202) expr ::= expr CONCAT expr */ yytestcase(yyruleno==202);
+      /* (203) likeop ::= NOT LIKE_KW|MATCH */ yytestcase(yyruleno==203);
+      /* (204) expr ::= expr likeop expr */ yytestcase(yyruleno==204);
+      /* (205) expr ::= expr likeop expr ESCAPE expr */ yytestcase(yyruleno==205);
+      /* (206) expr ::= expr ISNULL|NOTNULL */ yytestcase(yyruleno==206);
+      /* (207) expr ::= expr NOT NULL */ yytestcase(yyruleno==207);
+      /* (208) expr ::= expr IS expr */ yytestcase(yyruleno==208);
+      /* (209) expr ::= expr IS NOT expr */ yytestcase(yyruleno==209);
+      /* (210) expr ::= expr IS NOT DISTINCT FROM expr */ yytestcase(yyruleno==210);
+      /* (211) expr ::= expr IS DISTINCT FROM expr */ yytestcase(yyruleno==211);
+      /* (212) expr ::= NOT expr */ yytestcase(yyruleno==212);
+      /* (213) expr ::= BITNOT expr */ yytestcase(yyruleno==213);
+      /* (214) expr ::= PLUS|MINUS expr */ yytestcase(yyruleno==214);
+      /* (215) expr ::= expr PTR expr */ yytestcase(yyruleno==215);
+      /* (216) between_op ::= BETWEEN */ yytestcase(yyruleno==216);
+      /* (217) between_op ::= NOT BETWEEN */ yytestcase(yyruleno==217);
+      /* (218) expr ::= expr between_op expr AND expr */ yytestcase(yyruleno==218);
+      /* (219) in_op ::= IN */ yytestcase(yyruleno==219);
+      /* (220) in_op ::= NOT IN */ yytestcase(yyruleno==220);
+      /* (221) expr ::= expr in_op LP exprlist RP */ yytestcase(yyruleno==221);
+      /* (222) expr ::= LP select RP */ yytestcase(yyruleno==222);
+      /* (223) expr ::= expr in_op LP select RP */ yytestcase(yyruleno==223);
+      /* (224) expr ::= expr in_op nm dbnm paren_exprlist */ yytestcase(yyruleno==224);
+      /* (225) expr ::= EXISTS LP select RP */ yytestcase(yyruleno==225);
+      /* (226) expr ::= CASE case_operand case_exprlist case_else END */ yytestcase(yyruleno==226);
+      /* (227) case_exprlist ::= case_exprlist WHEN expr THEN expr */ yytestcase(yyruleno==227);
+      /* (228) case_exprlist ::= WHEN expr THEN expr */ yytestcase(yyruleno==228);
+      /* (229) case_else ::= ELSE expr */ yytestcase(yyruleno==229);
+      /* (230) case_else ::= */ yytestcase(yyruleno==230);
+      /* (231) case_operand ::= */ yytestcase(yyruleno==231);
+      /* (232) exprlist ::= */ yytestcase(yyruleno==232);
+      /* (233) nexprlist ::= nexprlist COMMA expr */ yytestcase(yyruleno==233);
+      /* (234) nexprlist ::= expr */ yytestcase(yyruleno==234);
+      /* (235) paren_exprlist ::= */ yytestcase(yyruleno==235);
+      /* (236) paren_exprlist ::= LP exprlist RP */ yytestcase(yyruleno==236);
+      /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ yytestcase(yyruleno==237);
+      /* (238) uniqueflag ::= UNIQUE */ yytestcase(yyruleno==238);
+      /* (239) uniqueflag ::= */ yytestcase(yyruleno==239);
+      /* (240) eidlist_opt ::= */ yytestcase(yyruleno==240);
+      /* (241) eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==241);
+      /* (242) eidlist ::= eidlist COMMA nm collate sortorder */ yytestcase(yyruleno==242);
+      /* (243) eidlist ::= nm collate sortorder */ yytestcase(yyruleno==243);
+      /* (244) collate ::= */ yytestcase(yyruleno==244);
+      /* (245) collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==245);
+      /* (246) cmd ::= DROP INDEX ifexists fullname */ yytestcase(yyruleno==246);
+      /* (247) cmd ::= VACUUM vinto */ yytestcase(yyruleno==247);
+      /* (248) cmd ::= VACUUM nm vinto */ yytestcase(yyruleno==248);
+      /* (249) vinto ::= INTO expr */ yytestcase(yyruleno==249);
+      /* (250) vinto ::= */ yytestcase(yyruleno==250);
+      /* (251) cmd ::= PRAGMA nm dbnm */ yytestcase(yyruleno==251);
+      /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */ yytestcase(yyruleno==252);
+      /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */ yytestcase(yyruleno==253);
+      /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */ yytestcase(yyruleno==254);
+      /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */ yytestcase(yyruleno==255);
+      /* (256) plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==256);
+      /* (257) minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==257);
+      /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ yytestcase(yyruleno==258);
+      /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ yytestcase(yyruleno==259);
+      /* (260) trigger_time ::= BEFORE|AFTER */ yytestcase(yyruleno==260);
+      /* (261) trigger_time ::= INSTEAD OF */ yytestcase(yyruleno==261);
+      /* (262) trigger_time ::= */ yytestcase(yyruleno==262);
+      /* (263) trigger_event ::= DELETE|INSERT */ yytestcase(yyruleno==263);
+      /* (264) trigger_event ::= UPDATE */ yytestcase(yyruleno==264);
+      /* (265) trigger_event ::= UPDATE OF idlist */ yytestcase(yyruleno==265);
+      /* (266) when_clause ::= */ yytestcase(yyruleno==266);
+      /* (267) when_clause ::= WHEN expr */ yytestcase(yyruleno==267);
+      /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ yytestcase(yyruleno==268);
+      /* (269) trigger_cmd_list ::= trigger_cmd SEMI */ yytestcase(yyruleno==269);
+      /* (270) trnm ::= nm DOT nm */ yytestcase(yyruleno==270);
+      /* (271) tridxby ::= INDEXED BY nm */ yytestcase(yyruleno==271);
+      /* (272) tridxby ::= NOT INDEXED */ yytestcase(yyruleno==272);
+      /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ yytestcase(yyruleno==273);
+      /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ yytestcase(yyruleno==274);
+      /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ yytestcase(yyruleno==275);
+      /* (276) trigger_cmd ::= scanpt select scanpt */ yytestcase(yyruleno==276);
+      /* (277) expr ::= RAISE LP IGNORE RP */ yytestcase(yyruleno==277);
+      /* (278) expr ::= RAISE LP raisetype COMMA nm RP */ yytestcase(yyruleno==278);
+      /* (279) raisetype ::= ROLLBACK */ yytestcase(yyruleno==279);
+      /* (280) raisetype ::= ABORT */ yytestcase(yyruleno==280);
+      /* (281) raisetype ::= FAIL */ yytestcase(yyruleno==281);
+      /* (282) cmd ::= DROP TRIGGER ifexists fullname */ yytestcase(yyruleno==282);
+      /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ yytestcase(yyruleno==283);
+      /* (284) cmd ::= DETACH database_kw_opt expr */ yytestcase(yyruleno==284);
+      /* (285) key_opt ::= */ yytestcase(yyruleno==285);
+      /* (286) key_opt ::= KEY expr */ yytestcase(yyruleno==286);
+      /* (287) cmd ::= REINDEX */ yytestcase(yyruleno==287);
+      /* (288) cmd ::= REINDEX nm dbnm */ yytestcase(yyruleno==288);
+      /* (289) cmd ::= ANALYZE */ yytestcase(yyruleno==289);
+      /* (290) cmd ::= ANALYZE nm dbnm */ yytestcase(yyruleno==290);
+      /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */ yytestcase(yyruleno==291);
+      /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ yytestcase(yyruleno==292);
+      /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ yytestcase(yyruleno==293);
+      /* (294) add_column_fullname ::= fullname */ yytestcase(yyruleno==294);
+      /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ yytestcase(yyruleno==295);
+      /* (296) cmd ::= create_vtab */ yytestcase(yyruleno==296);
+      /* (297) cmd ::= create_vtab LP vtabarglist RP */ yytestcase(yyruleno==297);
+      /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ yytestcase(yyruleno==298);
+      /* (299) vtabarg ::= */ yytestcase(yyruleno==299);
+      /* (300) vtabargtoken ::= ANY */ yytestcase(yyruleno==300);
+      /* (301) vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==301);
+      /* (302) lp ::= LP */ yytestcase(yyruleno==302);
+      /* (303) with ::= WITH wqlist */ yytestcase(yyruleno==303);
+      /* (304) with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==304);
+      /* (305) wqas ::= AS */ yytestcase(yyruleno==305);
+      /* (306) wqas ::= AS MATERIALIZED */ yytestcase(yyruleno==306);
+      /* (307) wqas ::= AS NOT MATERIALIZED */ yytestcase(yyruleno==307);
+      /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */ yytestcase(yyruleno==308);
+      /* (309) wqlist ::= wqitem (OPTIMIZED OUT) */ assert(yyruleno!=309);
+      /* (310) wqlist ::= wqlist COMMA wqitem */ yytestcase(yyruleno==310);
+      /* (311) windowdefn_list ::= windowdefn_list COMMA windowdefn */ yytestcase(yyruleno==311);
+      /* (312) windowdefn ::= nm AS LP window RP */ yytestcase(yyruleno==312);
+      /* (313) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ yytestcase(yyruleno==313);
+      /* (314) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ yytestcase(yyruleno==314);
+      /* (315) window ::= ORDER BY sortlist frame_opt */ yytestcase(yyruleno==315);
+      /* (316) window ::= nm ORDER BY sortlist frame_opt */ yytestcase(yyruleno==316);
+      /* (317) window ::= nm frame_opt */ yytestcase(yyruleno==317);
+      /* (318) frame_opt ::= */ yytestcase(yyruleno==318);
+      /* (319) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ yytestcase(yyruleno==319);
+      /* (320) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ yytestcase(yyruleno==320);
+      /* (321) range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==321);
+      /* (322) frame_bound_s ::= frame_bound (OPTIMIZED OUT) */ assert(yyruleno!=322);
+      /* (323) frame_bound_s ::= UNBOUNDED PRECEDING */ yytestcase(yyruleno==323);
+      /* (324) frame_bound_e ::= frame_bound (OPTIMIZED OUT) */ assert(yyruleno!=324);
+      /* (325) frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==325);
+      /* (326) frame_bound ::= expr PRECEDING|FOLLOWING */ yytestcase(yyruleno==326);
+      /* (327) frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==327);
+      /* (328) frame_exclude_opt ::= */ yytestcase(yyruleno==328);
+      /* (329) frame_exclude_opt ::= EXCLUDE frame_exclude */ yytestcase(yyruleno==329);
+      /* (330) frame_exclude ::= NO OTHERS */ yytestcase(yyruleno==330);
+      /* (331) frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==331);
+      /* (332) frame_exclude ::= GROUP|TIES */ yytestcase(yyruleno==332);
+      /* (333) window_clause ::= WINDOW windowdefn_list */ yytestcase(yyruleno==333);
+      /* (334) filter_over ::= filter_clause over_clause */ yytestcase(yyruleno==334);
+      /* (335) filter_over ::= over_clause (OPTIMIZED OUT) */ assert(yyruleno!=335);
+      /* (336) filter_over ::= filter_clause */ yytestcase(yyruleno==336);
+      /* (337) over_clause ::= OVER LP window RP */ yytestcase(yyruleno==337);
+      /* (338) over_clause ::= OVER nm */ yytestcase(yyruleno==338);
+      /* (339) filter_clause ::= FILTER LP WHERE expr RP */ yytestcase(yyruleno==339);
+      /* (340) input ::= cmdlist */ yytestcase(yyruleno==340);
+      /* (341) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==341);
+      /* (342) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=342);
+      /* (343) ecmd ::= SEMI */ yytestcase(yyruleno==343);
+      /* (344) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==344);
+      /* (345) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==345);
+      /* (346) trans_opt ::= */ yytestcase(yyruleno==346);
+      /* (347) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==347);
+      /* (348) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==348);
+      /* (349) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==349);
+      /* (350) savepoint_opt ::= */ yytestcase(yyruleno==350);
+      /* (351) cmd ::= create_table create_table_args */ yytestcase(yyruleno==351);
+      /* (352) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=352);
+      /* (353) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==353);
+      /* (354) columnlist ::= columnname carglist */ yytestcase(yyruleno==354);
+      /* (355) nm ::= ID|INDEXED|JOIN_KW */ yytestcase(yyruleno==355);
+      /* (356) nm ::= STRING */ yytestcase(yyruleno==356);
+      /* (357) typetoken ::= typename */ yytestcase(yyruleno==357);
+      /* (358) typename ::= ID|STRING */ yytestcase(yyruleno==358);
+      /* (359) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=359);
+      /* (360) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=360);
+      /* (361) carglist ::= carglist ccons */ yytestcase(yyruleno==361);
+      /* (362) carglist ::= */ yytestcase(yyruleno==362);
+      /* (363) ccons ::= NULL onconf */ yytestcase(yyruleno==363);
+      /* (364) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==364);
+      /* (365) ccons ::= AS generated */ yytestcase(yyruleno==365);
+      /* (366) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==366);
+      /* (367) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==367);
+      /* (368) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=368);
+      /* (369) tconscomma ::= */ yytestcase(yyruleno==369);
+      /* (370) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=370);
+      /* (371) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=371);
+      /* (372) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=372);
+      /* (373) oneselect ::= values */ yytestcase(yyruleno==373);
+      /* (374) sclp ::= selcollist COMMA */ yytestcase(yyruleno==374);
+      /* (375) as ::= ID|STRING */ yytestcase(yyruleno==375);
+      /* (376) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=376);
+      /* (377) returning ::= */ yytestcase(yyruleno==377);
+      /* (378) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=378);
+      /* (379) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==379);
+      /* (380) case_operand ::= expr */ yytestcase(yyruleno==380);
+      /* (381) exprlist ::= nexprlist */ yytestcase(yyruleno==381);
+      /* (382) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=382);
+      /* (383) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=383);
+      /* (384) nmnum ::= ON */ yytestcase(yyruleno==384);
+      /* (385) nmnum ::= DELETE */ yytestcase(yyruleno==385);
+      /* (386) nmnum ::= DEFAULT */ yytestcase(yyruleno==386);
+      /* (387) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==387);
+      /* (388) foreach_clause ::= */ yytestcase(yyruleno==388);
+      /* (389) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==389);
+      /* (390) trnm ::= nm */ yytestcase(yyruleno==390);
+      /* (391) tridxby ::= */ yytestcase(yyruleno==391);
+      /* (392) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==392);
+      /* (393) database_kw_opt ::= */ yytestcase(yyruleno==393);
+      /* (394) kwcolumn_opt ::= */ yytestcase(yyruleno==394);
+      /* (395) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==395);
+      /* (396) vtabarglist ::= vtabarg */ yytestcase(yyruleno==396);
+      /* (397) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==397);
+      /* (398) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==398);
+      /* (399) anylist ::= */ yytestcase(yyruleno==399);
+      /* (400) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==400);
+      /* (401) anylist ::= anylist ANY */ yytestcase(yyruleno==401);
+      /* (402) with ::= */ yytestcase(yyruleno==402);
+      /* (403) windowdefn_list ::= windowdefn (OPTIMIZED OUT) */ assert(yyruleno!=403);
+      /* (404) window ::= frame_opt (OPTIMIZED OUT) */ assert(yyruleno!=404);
+        break;
+/********** End reduce actions ************************************************/
+  };
+  assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
+  yygoto = yyRuleInfoLhs[yyruleno];
+  yysize = yyRuleInfoNRhs[yyruleno];
+  yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
+
+  /* There are no SHIFTREDUCE actions on nonterminals because the table
+  ** generator has simplified them to pure REDUCE actions. */
+  assert( !(yyact>YY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) );
+
+  /* It is not possible for a REDUCE to be followed by an error */
+  assert( yyact!=YY_ERROR_ACTION );
+
+  yymsp += yysize+1;
+  yypParser->yytos = yymsp;
+  yymsp->stateno = (YYACTIONTYPE)yyact;
+  yymsp->major = (YYCODETYPE)yygoto;
+  yyTraceShift(yypParser, yyact, "... then shift");
+  return yyact;
+}
+
+/*
+** The following code executes when the parse fails
+*/
+#ifndef YYNOERRORRECOVERY
+static void yy_parse_failed(
+  yyParser *yypParser           /* The parser */
+){
+  PerfettoSqlParserARG_FETCH
+  PerfettoSqlParserCTX_FETCH
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
+  }
+#endif
+  while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
+  /* Here code is inserted which will be executed whenever the
+  ** parser fails */
+/************ Begin %parse_failure code ***************************************/
+/************ End %parse_failure code *****************************************/
+  PerfettoSqlParserARG_STORE /* Suppress warning about unused %extra_argument variable */
+  PerfettoSqlParserCTX_STORE
+}
+#endif /* YYNOERRORRECOVERY */
+
+/*
+** 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 */
+  PerfettoSqlParserTOKENTYPE yyminor         /* The minor type of the error token */
+){
+  PerfettoSqlParserARG_FETCH
+  PerfettoSqlParserCTX_FETCH
+#define TOKEN yyminor
+/************ Begin %syntax_error code ****************************************/
+/************ End %syntax_error code ******************************************/
+  PerfettoSqlParserARG_STORE /* Suppress warning about unused %extra_argument variable */
+  PerfettoSqlParserCTX_STORE
+}
+
+/*
+** The following is executed when the parser accepts
+*/
+static void yy_accept(
+  yyParser *yypParser           /* The parser */
+){
+  PerfettoSqlParserARG_FETCH
+  PerfettoSqlParserCTX_FETCH
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
+  }
+#endif
+#ifndef YYNOERRORRECOVERY
+  yypParser->yyerrcnt = -1;
+#endif
+  assert( yypParser->yytos==yypParser->yystack );
+  /* Here code is inserted which will be executed whenever the
+  ** parser accepts */
+/*********** Begin %parse_accept code *****************************************/
+/*********** End %parse_accept code *******************************************/
+  PerfettoSqlParserARG_STORE /* Suppress warning about unused %extra_argument variable */
+  PerfettoSqlParserCTX_STORE
+}
+
+/* The main parser program.
+** The first argument is a pointer to a structure obtained from
+** "PerfettoSqlParserAlloc" 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:
+** <ul>
+** <li> A pointer to the parser (an opaque structure.)
+** <li> The major token number.
+** <li> The minor token number.
+** <li> An option argument of a grammar-specified type.
+** </ul>
+**
+** Outputs:
+** None.
+*/
+void PerfettoSqlParser(
+  void *yyp,                   /* The parser */
+  int yymajor,                 /* The major token code number */
+  PerfettoSqlParserTOKENTYPE yyminor       /* The value for the token */
+  PerfettoSqlParserARG_PDECL               /* Optional %extra_argument parameter */
+){
+  YYMINORTYPE yyminorunion;
+  YYACTIONTYPE yyact;   /* The parser action. */
+#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
+  int yyendofinput;     /* True if we are at the end of input */
+#endif
+#ifdef YYERRORSYMBOL
+  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
+#endif
+  yyParser *yypParser = (yyParser*)yyp;  /* The parser */
+  PerfettoSqlParserCTX_FETCH
+  PerfettoSqlParserARG_STORE
+
+  assert( yypParser->yytos!=0 );
+#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
+  yyendofinput = (yymajor==0);
+#endif
+
+  yyact = yypParser->yytos->stateno;
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    if( yyact < YY_MIN_REDUCE ){
+      fprintf(yyTraceFILE,"%sInput '%s' in state %d\n",
+              yyTracePrompt,yyTokenName[yymajor],yyact);
+    }else{
+      fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n",
+              yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE);
+    }
+  }
+#endif
+
+  while(1){ /* Exit by "break" */
+    assert( yypParser->yytos>=yypParser->yystack );
+    assert( yyact==yypParser->yytos->stateno );
+    yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
+    if( yyact >= YY_MIN_REDUCE ){
+      unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
+#ifndef NDEBUG
+      assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
+      if( yyTraceFILE ){
+        int yysize = yyRuleInfoNRhs[yyruleno];
+        if( yysize ){
+          fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
+            yyTracePrompt,
+            yyruleno, yyRuleName[yyruleno],
+            yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
+            yypParser->yytos[yysize].stateno);
+        }else{
+          fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
+            yyTracePrompt, yyruleno, yyRuleName[yyruleno],
+            yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
+        }
+      }
+#endif /* NDEBUG */
+
+      /* Check that the stack is large enough to grow by a single entry
+      ** if the RHS of the rule is empty.  This ensures that there is room
+      ** enough on the stack to push the LHS value */
+      if( yyRuleInfoNRhs[yyruleno]==0 ){
+#ifdef YYTRACKMAXSTACKDEPTH
+        if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
+          yypParser->yyhwm++;
+          assert( yypParser->yyhwm ==
+                  (int)(yypParser->yytos - yypParser->yystack));
+        }
+#endif
+#if YYSTACKDEPTH>0 
+        if( yypParser->yytos>=yypParser->yystackEnd ){
+          yyStackOverflow(yypParser);
+          break;
+        }
+#else
+        if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
+          if( yyGrowStack(yypParser) ){
+            yyStackOverflow(yypParser);
+            break;
+          }
+        }
+#endif
+      }
+      yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor PerfettoSqlParserCTX_PARAM);
+    }else if( yyact <= YY_MAX_SHIFTREDUCE ){
+      yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
+#ifndef YYNOERRORRECOVERY
+      yypParser->yyerrcnt--;
+#endif
+      break;
+    }else if( yyact==YY_ACCEPT_ACTION ){
+      yypParser->yytos--;
+      yy_accept(yypParser);
+      return;
+    }else{
+      assert( yyact == YY_ERROR_ACTION );
+      yyminorunion.yy0 = yyminor;
+#ifdef YYERRORSYMBOL
+      int yymx;
+#endif
+#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,yyminor);
+      }
+      yymx = yypParser->yytos->major;
+      if( yymx==YYERRORSYMBOL || yyerrorhit ){
+#ifndef NDEBUG
+        if( yyTraceFILE ){
+          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
+             yyTracePrompt,yyTokenName[yymajor]);
+        }
+#endif
+        yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
+        yymajor = YYNOCODE;
+      }else{
+        while( yypParser->yytos > yypParser->yystack ){
+          yyact = yy_find_reduce_action(yypParser->yytos->stateno,
+                                        YYERRORSYMBOL);
+          if( yyact<=YY_MAX_SHIFTREDUCE ) break;
+          yy_pop_parser_stack(yypParser);
+        }
+        if( yypParser->yytos <= yypParser->yystack || yymajor==0 ){
+          yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+          yy_parse_failed(yypParser);
+#ifndef YYNOERRORRECOVERY
+          yypParser->yyerrcnt = -1;
+#endif
+          yymajor = YYNOCODE;
+        }else if( yymx!=YYERRORSYMBOL ){
+          yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor);
+        }
+      }
+      yypParser->yyerrcnt = 3;
+      yyerrorhit = 1;
+      if( yymajor==YYNOCODE ) break;
+      yyact = yypParser->yytos->stateno;
+#elif defined(YYNOERRORRECOVERY)
+      /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
+      ** do any kind of error recovery.  Instead, simply invoke the syntax
+      ** error routine and continue going as if nothing had happened.
+      **
+      ** Applications can set this macro (for example inside %include) if
+      ** they intend to abandon the parse upon the first syntax error seen.
+      */
+      yy_syntax_error(yypParser,yymajor, yyminor);
+      yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+      break;
+#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, yyminor);
+      }
+      yypParser->yyerrcnt = 3;
+      yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+      if( yyendofinput ){
+        yy_parse_failed(yypParser);
+#ifndef YYNOERRORRECOVERY
+        yypParser->yyerrcnt = -1;
+#endif
+      }
+      break;
+#endif
+    }
+  }
+#ifndef NDEBUG
+  if( yyTraceFILE ){
+    yyStackEntry *i;
+    char cDiv = '[';
+    fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
+    for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){
+      fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]);
+      cDiv = ' ';
+    }
+    fprintf(yyTraceFILE,"]\n");
+  }
+#endif
+  return;
+}
+
+/*
+** Return the fallback token corresponding to canonical token iToken, or
+** 0 if iToken has no fallback.
+*/
+int PerfettoSqlParserFallback(int iToken){
+#ifdef YYFALLBACK
+  assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
+  return yyFallback[iToken];
+#else
+  (void)iToken;
+  return 0;
+#endif
+}
diff --git a/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.h b/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.h
new file mode 100644
index 0000000..7533b81
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.h
@@ -0,0 +1,169 @@
+#define TK_OR 1
+#define TK_AND 2
+#define TK_NOT 3
+#define TK_IS 4
+#define TK_MATCH 5
+#define TK_LIKE_KW 6
+#define TK_BETWEEN 7
+#define TK_IN 8
+#define TK_ISNULL 9
+#define TK_NOTNULL 10
+#define TK_NE 11
+#define TK_EQ 12
+#define TK_GT 13
+#define TK_LE 14
+#define TK_LT 15
+#define TK_GE 16
+#define TK_ESCAPE 17
+#define TK_BITAND 18
+#define TK_BITOR 19
+#define TK_LSHIFT 20
+#define TK_RSHIFT 21
+#define TK_PLUS 22
+#define TK_MINUS 23
+#define TK_STAR 24
+#define TK_SLASH 25
+#define TK_REM 26
+#define TK_CONCAT 27
+#define TK_PTR 28
+#define TK_COLLATE 29
+#define TK_BITNOT 30
+#define TK_ON 31
+#define TK_ID 32
+#define TK_ABORT 33
+#define TK_ACTION 34
+#define TK_AFTER 35
+#define TK_ANALYZE 36
+#define TK_ASC 37
+#define TK_ATTACH 38
+#define TK_BEFORE 39
+#define TK_BEGIN 40
+#define TK_BY 41
+#define TK_CASCADE 42
+#define TK_CAST 43
+#define TK_COLUMNKW 44
+#define TK_CONFLICT 45
+#define TK_DATABASE 46
+#define TK_DEFERRED 47
+#define TK_DESC 48
+#define TK_DETACH 49
+#define TK_DO 50
+#define TK_EACH 51
+#define TK_END 52
+#define TK_EXCLUSIVE 53
+#define TK_EXPLAIN 54
+#define TK_FAIL 55
+#define TK_FOR 56
+#define TK_IGNORE 57
+#define TK_IMMEDIATE 58
+#define TK_INITIALLY 59
+#define TK_INSTEAD 60
+#define TK_NO 61
+#define TK_PLAN 62
+#define TK_QUERY 63
+#define TK_KEY 64
+#define TK_OF 65
+#define TK_OFFSET 66
+#define TK_PRAGMA 67
+#define TK_RAISE 68
+#define TK_RECURSIVE 69
+#define TK_RELEASE 70
+#define TK_REPLACE 71
+#define TK_RESTRICT 72
+#define TK_ROW 73
+#define TK_ROWS 74
+#define TK_ROLLBACK 75
+#define TK_SAVEPOINT 76
+#define TK_TEMP 77
+#define TK_TRIGGER 78
+#define TK_VACUUM 79
+#define TK_VIEW 80
+#define TK_VIRTUAL 81
+#define TK_WITH 82
+#define TK_WITHOUT 83
+#define TK_NULLS 84
+#define TK_FIRST 85
+#define TK_LAST 86
+#define TK_EXCEPT 87
+#define TK_INTERSECT 88
+#define TK_UNION 89
+#define TK_CURRENT 90
+#define TK_FOLLOWING 91
+#define TK_PARTITION 92
+#define TK_PRECEDING 93
+#define TK_RANGE 94
+#define TK_UNBOUNDED 95
+#define TK_EXCLUDE 96
+#define TK_GROUPS 97
+#define TK_OTHERS 98
+#define TK_TIES 99
+#define TK_WITHIN 100
+#define TK_GENERATED 101
+#define TK_ALWAYS 102
+#define TK_MATERIALIZED 103
+#define TK_REINDEX 104
+#define TK_RENAME 105
+#define TK_CTIME_KW 106
+#define TK_IF 107
+#define TK_ANY 108
+#define TK_COMMIT 109
+#define TK_TO 110
+#define TK_TABLE 111
+#define TK_CREATE 112
+#define TK_EXISTS 113
+#define TK_LP 114
+#define TK_RP 115
+#define TK_AS 116
+#define TK_COMMA 117
+#define TK_STRING 118
+#define TK_CONSTRAINT 119
+#define TK_DEFAULT 120
+#define TK_INDEXED 121
+#define TK_NULL 122
+#define TK_PRIMARY 123
+#define TK_UNIQUE 124
+#define TK_CHECK 125
+#define TK_REFERENCES 126
+#define TK_AUTOINCR 127
+#define TK_INSERT 128
+#define TK_DELETE 129
+#define TK_UPDATE 130
+#define TK_SET 131
+#define TK_DEFERRABLE 132
+#define TK_FOREIGN 133
+#define TK_DROP 134
+#define TK_ALL 135
+#define TK_SELECT 136
+#define TK_VALUES 137
+#define TK_DISTINCT 138
+#define TK_DOT 139
+#define TK_FROM 140
+#define TK_JOIN 141
+#define TK_JOIN_KW 142
+#define TK_USING 143
+#define TK_ORDER 144
+#define TK_GROUP 145
+#define TK_HAVING 146
+#define TK_LIMIT 147
+#define TK_WHERE 148
+#define TK_RETURNING 149
+#define TK_INTO 150
+#define TK_NOTHING 151
+#define TK_FLOAT 152
+#define TK_BLOB 153
+#define TK_INTEGER 154
+#define TK_VARIABLE 155
+#define TK_CASE 156
+#define TK_WHEN 157
+#define TK_THEN 158
+#define TK_ELSE 159
+#define TK_INDEX 160
+#define TK_SEMI 161
+#define TK_ALTER 162
+#define TK_ADD 163
+#define TK_WINDOW 164
+#define TK_OVER 165
+#define TK_FILTER 166
+#define TK_TRANSACTION 167
+#define TK_SPACE 168
+#define TK_ILLEGAL 169
diff --git a/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.y b/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.y
new file mode 100644
index 0000000..cf71a4d
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.y
@@ -0,0 +1,611 @@
+%name PerfettoSqlParser
+%token_prefix TK_
+%start_symbol input
+
+%include {
+#include <stddef.h>
+
+#define YYNOERRORRECOVERY 1
+}
+
+%left OR.
+%left AND.
+%right NOT.
+%left IS MATCH 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 PTR.
+%left COLLATE.
+%right BITNOT.
+%nonassoc ON.
+
+%fallback ID
+  ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
+  CONFLICT DATABASE DEFERRED DESC DETACH DO
+  EACH END EXCLUSIVE EXPLAIN FAIL FOR
+  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
+  QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS
+  ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
+  NULLS FIRST LAST
+  EXCEPT INTERSECT UNION
+  CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
+  EXCLUDE GROUPS OTHERS TIES
+  WITHIN
+  GENERATED ALWAYS
+  MATERIALIZED
+  REINDEX RENAME CTIME_KW IF
+  .
+%wildcard ANY.
+
+// Reprint of input file "buildtools/sqlite_src/src/parse.y".
+// Symbols:
+//   0 $                      160 ELSE                  
+//   1 SEMI                   161 INDEX                 
+//   2 EXPLAIN                162 ALTER                 
+//   3 QUERY                  163 ADD                   
+//   4 PLAN                   164 WINDOW                
+//   5 BEGIN                  165 OVER                  
+//   6 TRANSACTION            166 FILTER                
+//   7 DEFERRED               167 COLUMN                
+//   8 IMMEDIATE              168 AGG_FUNCTION          
+//   9 EXCLUSIVE              169 AGG_COLUMN            
+//  10 COMMIT                 170 TRUEFALSE             
+//  11 END                    171 ISNOT                 
+//  12 ROLLBACK               172 FUNCTION              
+//  13 SAVEPOINT              173 UMINUS                
+//  14 RELEASE                174 UPLUS                 
+//  15 TO                     175 TRUTH                 
+//  16 TABLE                  176 REGISTER              
+//  17 CREATE                 177 VECTOR                
+//  18 IF                     178 SELECT_COLUMN         
+//  19 NOT                    179 IF_NULL_ROW           
+//  20 EXISTS                 180 ASTERISK              
+//  21 TEMP                   181 SPAN                  
+//  22 LP                     182 ERROR                 
+//  23 RP                     183 SPACE                 
+//  24 AS                     184 ILLEGAL               
+//  25 COMMA                  185 input                 
+//  26 WITHOUT                186 cmdlist               
+//  27 ABORT                  187 ecmd                  
+//  28 ACTION                 188 cmdx                  
+//  29 AFTER                  189 explain               
+//  30 ANALYZE                190 cmd                   
+//  31 ASC                    191 transtype             
+//  32 ATTACH                 192 trans_opt             
+//  33 BEFORE                 193 nm                    
+//  34 BY                     194 savepoint_opt         
+//  35 CASCADE                195 create_table          
+//  36 CAST                   196 create_table_args     
+//  37 CONFLICT               197 createkw              
+//  38 DATABASE               198 temp                  
+//  39 DESC                   199 ifnotexists           
+//  40 DETACH                 200 dbnm                  
+//  41 EACH                   201 columnlist            
+//  42 FAIL                   202 conslist_opt          
+//  43 OR                     203 table_option_set      
+//  44 AND                    204 select                
+//  45 IS                     205 table_option          
+//  46 MATCH                  206 columnname            
+//  47 LIKE_KW                207 carglist              
+//  48 BETWEEN                208 typetoken             
+//  49 IN                     209 typename              
+//  50 ISNULL                 210 signed                
+//  51 NOTNULL                211 plus_num              
+//  52 NE                     212 minus_num             
+//  53 EQ                     213 scanpt                
+//  54 GT                     214 scantok               
+//  55 LE                     215 ccons                 
+//  56 LT                     216 term                  
+//  57 GE                     217 expr                  
+//  58 ESCAPE                 218 onconf                
+//  59 ID                     219 sortorder             
+//  60 COLUMNKW               220 autoinc               
+//  61 DO                     221 eidlist_opt           
+//  62 FOR                    222 refargs               
+//  63 IGNORE                 223 defer_subclause       
+//  64 INITIALLY              224 generated             
+//  65 INSTEAD                225 refarg                
+//  66 NO                     226 refact                
+//  67 KEY                    227 init_deferred_pred_opt
+//  68 OF                     228 conslist              
+//  69 OFFSET                 229 tconscomma            
+//  70 PRAGMA                 230 tcons                 
+//  71 RAISE                  231 sortlist              
+//  72 RECURSIVE              232 eidlist               
+//  73 REPLACE                233 defer_subclause_opt   
+//  74 RESTRICT               234 orconf                
+//  75 ROW                    235 resolvetype           
+//  76 ROWS                   236 raisetype             
+//  77 TRIGGER                237 ifexists              
+//  78 VACUUM                 238 fullname              
+//  79 VIEW                   239 selectnowith          
+//  80 VIRTUAL                240 oneselect             
+//  81 WITH                   241 wqlist                
+//  82 NULLS                  242 multiselect_op        
+//  83 FIRST                  243 distinct              
+//  84 LAST                   244 selcollist            
+//  85 CURRENT                245 from                  
+//  86 FOLLOWING              246 where_opt             
+//  87 PARTITION              247 groupby_opt           
+//  88 PRECEDING              248 having_opt            
+//  89 RANGE                  249 orderby_opt           
+//  90 UNBOUNDED              250 limit_opt             
+//  91 EXCLUDE                251 window_clause         
+//  92 GROUPS                 252 values                
+//  93 OTHERS                 253 nexprlist             
+//  94 TIES                   254 sclp                  
+//  95 GENERATED              255 as                    
+//  96 ALWAYS                 256 seltablist            
+//  97 MATERIALIZED           257 stl_prefix            
+//  98 REINDEX                258 joinop                
+//  99 RENAME                 259 on_using              
+// 100 CTIME_KW               260 indexed_by            
+// 101 ANY                    261 exprlist              
+// 102 BITAND                 262 xfullname             
+// 103 BITOR                  263 idlist                
+// 104 LSHIFT                 264 indexed_opt           
+// 105 RSHIFT                 265 nulls                 
+// 106 PLUS                   266 with                  
+// 107 MINUS                  267 where_opt_ret         
+// 108 STAR                   268 setlist               
+// 109 SLASH                  269 insert_cmd            
+// 110 REM                    270 idlist_opt            
+// 111 CONCAT                 271 upsert                
+// 112 PTR                    272 returning             
+// 113 COLLATE                273 filter_over           
+// 114 BITNOT                 274 likeop                
+// 115 ON                     275 between_op            
+// 116 INDEXED                276 in_op                 
+// 117 STRING                 277 paren_exprlist        
+// 118 JOIN_KW                278 case_operand          
+// 119 CONSTRAINT             279 case_exprlist         
+// 120 DEFAULT                280 case_else             
+// 121 NULL                   281 uniqueflag            
+// 122 PRIMARY                282 collate               
+// 123 UNIQUE                 283 vinto                 
+// 124 CHECK                  284 nmnum                 
+// 125 REFERENCES             285 trigger_decl          
+// 126 AUTOINCR               286 trigger_cmd_list      
+// 127 INSERT                 287 trigger_time          
+// 128 DELETE                 288 trigger_event         
+// 129 UPDATE                 289 foreach_clause        
+// 130 SET                    290 when_clause           
+// 131 DEFERRABLE             291 trigger_cmd           
+// 132 FOREIGN                292 trnm                  
+// 133 DROP                   293 tridxby               
+// 134 UNION                  294 database_kw_opt       
+// 135 ALL                    295 key_opt               
+// 136 EXCEPT                 296 add_column_fullname   
+// 137 INTERSECT              297 kwcolumn_opt          
+// 138 SELECT                 298 create_vtab           
+// 139 VALUES                 299 vtabarglist           
+// 140 DISTINCT               300 vtabarg               
+// 141 DOT                    301 vtabargtoken          
+// 142 FROM                   302 lp                    
+// 143 JOIN                   303 anylist               
+// 144 USING                  304 wqitem                
+// 145 ORDER                  305 wqas                  
+// 146 GROUP                  306 windowdefn_list       
+// 147 HAVING                 307 windowdefn            
+// 148 LIMIT                  308 window                
+// 149 WHERE                  309 frame_opt             
+// 150 RETURNING              310 part_opt              
+// 151 INTO                   311 filter_clause         
+// 152 NOTHING                312 over_clause           
+// 153 FLOAT                  313 range_or_rows         
+// 154 BLOB                   314 frame_bound           
+// 155 INTEGER                315 frame_bound_s         
+// 156 VARIABLE               316 frame_bound_e         
+// 157 CASE                   317 frame_exclude_opt     
+// 158 WHEN                   318 frame_exclude         
+// 159 THEN                  
+explain ::= EXPLAIN.
+explain ::= EXPLAIN QUERY PLAN.
+cmdx ::= cmd.
+cmd ::= BEGIN transtype trans_opt.
+transtype ::=.
+transtype ::= DEFERRED.
+transtype ::= IMMEDIATE.
+transtype ::= EXCLUSIVE.
+cmd ::= COMMIT|END trans_opt.
+cmd ::= ROLLBACK trans_opt.
+cmd ::= SAVEPOINT nm.
+cmd ::= RELEASE savepoint_opt nm.
+cmd ::= ROLLBACK trans_opt TO savepoint_opt nm.
+create_table ::= createkw temp TABLE ifnotexists nm dbnm.
+createkw ::= CREATE.
+ifnotexists ::=.
+ifnotexists ::= IF NOT EXISTS.
+temp ::= TEMP.
+temp ::=.
+create_table_args ::= LP columnlist conslist_opt RP table_option_set.
+create_table_args ::= AS select.
+table_option_set ::=.
+table_option_set ::= table_option_set COMMA table_option.
+table_option ::= WITHOUT nm.
+table_option ::= nm.
+columnname ::= nm typetoken.
+typetoken ::=.
+typetoken ::= typename LP signed RP.
+typetoken ::= typename LP signed COMMA signed RP.
+typename ::= typename ID|STRING.
+scanpt ::=.
+scantok ::=.
+ccons ::= CONSTRAINT nm.
+ccons ::= DEFAULT scantok term.
+ccons ::= DEFAULT LP expr RP.
+ccons ::= DEFAULT PLUS scantok term.
+ccons ::= DEFAULT MINUS scantok term.
+ccons ::= DEFAULT scantok ID|INDEXED.
+ccons ::= NOT NULL onconf.
+ccons ::= PRIMARY KEY sortorder onconf autoinc.
+ccons ::= UNIQUE onconf.
+ccons ::= CHECK LP expr RP.
+ccons ::= REFERENCES nm eidlist_opt refargs.
+ccons ::= defer_subclause.
+ccons ::= COLLATE ID|STRING.
+generated ::= LP expr RP.
+generated ::= LP expr RP ID.
+autoinc ::=.
+autoinc ::= AUTOINCR.
+refargs ::=.
+refargs ::= refargs refarg.
+refarg ::= MATCH nm.
+refarg ::= ON INSERT refact.
+refarg ::= ON DELETE refact.
+refarg ::= ON UPDATE refact.
+refact ::= SET NULL.
+refact ::= SET DEFAULT.
+refact ::= CASCADE.
+refact ::= RESTRICT.
+refact ::= NO ACTION.
+defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt.
+defer_subclause ::= DEFERRABLE init_deferred_pred_opt.
+init_deferred_pred_opt ::=.
+init_deferred_pred_opt ::= INITIALLY DEFERRED.
+init_deferred_pred_opt ::= INITIALLY IMMEDIATE.
+conslist_opt ::=.
+tconscomma ::= COMMA.
+tcons ::= CONSTRAINT nm.
+tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf.
+tcons ::= UNIQUE LP sortlist RP onconf.
+tcons ::= CHECK LP expr RP onconf.
+tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt.
+defer_subclause_opt ::=.
+onconf ::=.
+onconf ::= ON CONFLICT resolvetype.
+orconf ::=.
+orconf ::= OR resolvetype.
+resolvetype ::= IGNORE.
+resolvetype ::= REPLACE.
+cmd ::= DROP TABLE ifexists fullname.
+ifexists ::= IF EXISTS.
+ifexists ::=.
+cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select.
+cmd ::= DROP VIEW ifexists fullname.
+cmd ::= select.
+select ::= WITH wqlist selectnowith.
+select ::= WITH RECURSIVE wqlist selectnowith.
+select ::= selectnowith.
+selectnowith ::= selectnowith multiselect_op oneselect.
+multiselect_op ::= UNION.
+multiselect_op ::= UNION ALL.
+multiselect_op ::= EXCEPT|INTERSECT.
+oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt.
+oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt.
+values ::= VALUES LP nexprlist RP.
+values ::= values COMMA LP nexprlist RP.
+distinct ::= DISTINCT.
+distinct ::= ALL.
+distinct ::=.
+sclp ::=.
+selcollist ::= sclp scanpt expr scanpt as.
+selcollist ::= sclp scanpt STAR.
+selcollist ::= sclp scanpt nm DOT STAR.
+as ::= AS nm.
+as ::=.
+from ::=.
+from ::= FROM seltablist.
+stl_prefix ::= seltablist joinop.
+stl_prefix ::=.
+seltablist ::= stl_prefix nm dbnm as on_using.
+seltablist ::= stl_prefix nm dbnm as indexed_by on_using.
+seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using.
+seltablist ::= stl_prefix LP select RP as on_using.
+seltablist ::= stl_prefix LP seltablist RP as on_using.
+dbnm ::=.
+dbnm ::= DOT nm.
+fullname ::= nm.
+fullname ::= nm DOT nm.
+xfullname ::= nm.
+xfullname ::= nm DOT nm.
+xfullname ::= nm DOT nm AS nm.
+xfullname ::= nm AS nm.
+joinop ::= COMMA|JOIN.
+joinop ::= JOIN_KW JOIN.
+joinop ::= JOIN_KW nm JOIN.
+joinop ::= JOIN_KW nm nm JOIN.
+on_using ::= ON expr.
+on_using ::= USING LP idlist RP.
+on_using ::=. [OR]
+indexed_opt ::=.
+indexed_by ::= INDEXED BY nm.
+indexed_by ::= NOT INDEXED.
+orderby_opt ::=.
+orderby_opt ::= ORDER BY sortlist.
+sortlist ::= sortlist COMMA expr sortorder nulls.
+sortlist ::= expr sortorder nulls.
+sortorder ::= ASC.
+sortorder ::= DESC.
+sortorder ::=.
+nulls ::= NULLS FIRST.
+nulls ::= NULLS LAST.
+nulls ::=.
+groupby_opt ::=.
+groupby_opt ::= GROUP BY nexprlist.
+having_opt ::=.
+having_opt ::= HAVING expr.
+limit_opt ::=.
+limit_opt ::= LIMIT expr.
+limit_opt ::= LIMIT expr OFFSET expr.
+limit_opt ::= LIMIT expr COMMA expr.
+cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret.
+where_opt ::=.
+where_opt ::= WHERE expr.
+where_opt_ret ::=.
+where_opt_ret ::= WHERE expr.
+where_opt_ret ::= RETURNING selcollist.
+where_opt_ret ::= WHERE expr RETURNING selcollist.
+cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret.
+setlist ::= setlist COMMA nm EQ expr.
+setlist ::= setlist COMMA LP idlist RP EQ expr.
+setlist ::= nm EQ expr.
+setlist ::= LP idlist RP EQ expr.
+cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert.
+cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning.
+upsert ::=.
+upsert ::= RETURNING selcollist.
+upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert.
+upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert.
+upsert ::= ON CONFLICT DO NOTHING returning.
+upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning.
+returning ::= RETURNING selcollist.
+insert_cmd ::= INSERT orconf.
+insert_cmd ::= REPLACE.
+idlist_opt ::=.
+idlist_opt ::= LP idlist RP.
+idlist ::= idlist COMMA nm.
+idlist ::= nm.
+expr ::= LP expr RP.
+expr ::= ID|INDEXED|JOIN_KW.
+expr ::= nm DOT nm.
+expr ::= nm DOT nm DOT nm.
+term ::= NULL|FLOAT|BLOB.
+term ::= STRING.
+term ::= INTEGER.
+expr ::= VARIABLE.
+expr ::= expr COLLATE ID|STRING.
+expr ::= CAST LP expr AS typetoken RP.
+expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP.
+expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP.
+expr ::= ID|INDEXED|JOIN_KW LP STAR RP.
+expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist RP filter_over.
+expr ::= ID|INDEXED|JOIN_KW LP distinct exprlist ORDER BY sortlist RP filter_over.
+expr ::= ID|INDEXED|JOIN_KW LP STAR RP filter_over.
+term ::= CTIME_KW.
+expr ::= LP nexprlist COMMA expr RP.
+expr ::= expr AND expr.
+expr ::= expr OR expr.
+expr ::= expr LT|GT|GE|LE expr.
+expr ::= expr EQ|NE expr.
+expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr.
+expr ::= expr PLUS|MINUS expr.
+expr ::= expr STAR|SLASH|REM expr.
+expr ::= expr CONCAT expr.
+likeop ::= NOT LIKE_KW|MATCH.
+expr ::= expr likeop expr. [LIKE_KW]
+expr ::= expr likeop expr ESCAPE expr. [LIKE_KW]
+expr ::= expr ISNULL|NOTNULL.
+expr ::= expr NOT NULL.
+expr ::= expr IS expr.
+expr ::= expr IS NOT expr.
+expr ::= expr IS NOT DISTINCT FROM expr.
+expr ::= expr IS DISTINCT FROM expr.
+expr ::= NOT expr.
+expr ::= BITNOT expr.
+expr ::= PLUS|MINUS expr. [BITNOT]
+expr ::= expr PTR expr.
+between_op ::= BETWEEN.
+between_op ::= NOT BETWEEN.
+expr ::= expr between_op expr AND expr. [BETWEEN]
+in_op ::= IN.
+in_op ::= NOT IN.
+expr ::= expr in_op LP exprlist RP. [IN]
+expr ::= LP select RP.
+expr ::= expr in_op LP select RP. [IN]
+expr ::= expr in_op nm dbnm paren_exprlist. [IN]
+expr ::= EXISTS LP select RP.
+expr ::= CASE case_operand case_exprlist case_else END.
+case_exprlist ::= case_exprlist WHEN expr THEN expr.
+case_exprlist ::= WHEN expr THEN expr.
+case_else ::= ELSE expr.
+case_else ::=.
+case_operand ::=.
+exprlist ::=.
+nexprlist ::= nexprlist COMMA expr.
+nexprlist ::= expr.
+paren_exprlist ::=.
+paren_exprlist ::= LP exprlist RP.
+cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt.
+uniqueflag ::= UNIQUE.
+uniqueflag ::=.
+eidlist_opt ::=.
+eidlist_opt ::= LP eidlist RP.
+eidlist ::= eidlist COMMA nm collate sortorder.
+eidlist ::= nm collate sortorder.
+collate ::=.
+collate ::= COLLATE ID|STRING.
+cmd ::= DROP INDEX ifexists fullname.
+cmd ::= VACUUM vinto.
+cmd ::= VACUUM nm vinto.
+vinto ::= INTO expr.
+vinto ::=.
+cmd ::= PRAGMA nm dbnm.
+cmd ::= PRAGMA nm dbnm EQ nmnum.
+cmd ::= PRAGMA nm dbnm LP nmnum RP.
+cmd ::= PRAGMA nm dbnm EQ minus_num.
+cmd ::= PRAGMA nm dbnm LP minus_num RP.
+plus_num ::= PLUS INTEGER|FLOAT.
+minus_num ::= MINUS INTEGER|FLOAT.
+cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END.
+trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause.
+trigger_time ::= BEFORE|AFTER.
+trigger_time ::= INSTEAD OF.
+trigger_time ::=.
+trigger_event ::= DELETE|INSERT.
+trigger_event ::= UPDATE.
+trigger_event ::= UPDATE OF idlist.
+when_clause ::=.
+when_clause ::= WHEN expr.
+trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI.
+trigger_cmd_list ::= trigger_cmd SEMI.
+trnm ::= nm DOT nm.
+tridxby ::= INDEXED BY nm.
+tridxby ::= NOT INDEXED.
+trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt.
+trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt.
+trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt.
+trigger_cmd ::= scanpt select scanpt.
+expr ::= RAISE LP IGNORE RP.
+expr ::= RAISE LP raisetype COMMA nm RP.
+raisetype ::= ROLLBACK.
+raisetype ::= ABORT.
+raisetype ::= FAIL.
+cmd ::= DROP TRIGGER ifexists fullname.
+cmd ::= ATTACH database_kw_opt expr AS expr key_opt.
+cmd ::= DETACH database_kw_opt expr.
+key_opt ::=.
+key_opt ::= KEY expr.
+cmd ::= REINDEX.
+cmd ::= REINDEX nm dbnm.
+cmd ::= ANALYZE.
+cmd ::= ANALYZE nm dbnm.
+cmd ::= ALTER TABLE fullname RENAME TO nm.
+cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist.
+cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm.
+add_column_fullname ::= fullname.
+cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm.
+cmd ::= create_vtab.
+cmd ::= create_vtab LP vtabarglist RP.
+create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm.
+vtabarg ::=.
+vtabargtoken ::= ANY.
+vtabargtoken ::= lp anylist RP.
+lp ::= LP.
+with ::= WITH wqlist.
+with ::= WITH RECURSIVE wqlist.
+wqas ::= AS.
+wqas ::= AS MATERIALIZED.
+wqas ::= AS NOT MATERIALIZED.
+wqitem ::= nm eidlist_opt wqas LP select RP.
+wqlist ::= wqitem.
+wqlist ::= wqlist COMMA wqitem.
+windowdefn_list ::= windowdefn_list COMMA windowdefn.
+windowdefn ::= nm AS LP window RP.
+window ::= PARTITION BY nexprlist orderby_opt frame_opt.
+window ::= nm PARTITION BY nexprlist orderby_opt frame_opt.
+window ::= ORDER BY sortlist frame_opt.
+window ::= nm ORDER BY sortlist frame_opt.
+window ::= nm frame_opt.
+frame_opt ::=.
+frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt.
+frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt.
+range_or_rows ::= RANGE|ROWS|GROUPS.
+frame_bound_s ::= frame_bound.
+frame_bound_s ::= UNBOUNDED PRECEDING.
+frame_bound_e ::= frame_bound.
+frame_bound_e ::= UNBOUNDED FOLLOWING.
+frame_bound ::= expr PRECEDING|FOLLOWING.
+frame_bound ::= CURRENT ROW.
+frame_exclude_opt ::=.
+frame_exclude_opt ::= EXCLUDE frame_exclude.
+frame_exclude ::= NO OTHERS.
+frame_exclude ::= CURRENT ROW.
+frame_exclude ::= GROUP|TIES.
+window_clause ::= WINDOW windowdefn_list.
+filter_over ::= filter_clause over_clause.
+filter_over ::= over_clause.
+filter_over ::= filter_clause.
+over_clause ::= OVER LP window RP.
+over_clause ::= OVER nm.
+filter_clause ::= FILTER LP WHERE expr RP.
+input ::= cmdlist.
+cmdlist ::= cmdlist ecmd.
+cmdlist ::= ecmd.
+ecmd ::= SEMI.
+ecmd ::= cmdx SEMI.
+ecmd ::= explain cmdx SEMI.
+trans_opt ::=.
+trans_opt ::= TRANSACTION.
+trans_opt ::= TRANSACTION nm.
+savepoint_opt ::= SAVEPOINT.
+savepoint_opt ::=.
+cmd ::= create_table create_table_args.
+table_option_set ::= table_option.
+columnlist ::= columnlist COMMA columnname carglist.
+columnlist ::= columnname carglist.
+nm ::= ID|INDEXED|JOIN_KW.
+nm ::= STRING.
+typetoken ::= typename.
+typename ::= ID|STRING.
+signed ::= plus_num.
+signed ::= minus_num.
+carglist ::= carglist ccons.
+carglist ::=.
+ccons ::= NULL onconf.
+ccons ::= GENERATED ALWAYS AS generated.
+ccons ::= AS generated.
+conslist_opt ::= COMMA conslist.
+conslist ::= conslist tconscomma tcons.
+conslist ::= tcons.
+tconscomma ::=.
+defer_subclause_opt ::= defer_subclause.
+resolvetype ::= raisetype.
+selectnowith ::= oneselect.
+oneselect ::= values.
+sclp ::= selcollist COMMA.
+as ::= ID|STRING.
+indexed_opt ::= indexed_by.
+returning ::=.
+expr ::= term.
+likeop ::= LIKE_KW|MATCH.
+case_operand ::= expr.
+exprlist ::= nexprlist.
+nmnum ::= plus_num.
+nmnum ::= nm.
+nmnum ::= ON.
+nmnum ::= DELETE.
+nmnum ::= DEFAULT.
+plus_num ::= INTEGER|FLOAT.
+foreach_clause ::=.
+foreach_clause ::= FOR EACH ROW.
+trnm ::= nm.
+tridxby ::=.
+database_kw_opt ::= DATABASE.
+database_kw_opt ::=.
+kwcolumn_opt ::=.
+kwcolumn_opt ::= COLUMNKW.
+vtabarglist ::= vtabarg.
+vtabarglist ::= vtabarglist COMMA vtabarg.
+vtabarg ::= vtabarg vtabargtoken.
+anylist ::=.
+anylist ::= anylist LP anylist RP.
+anylist ::= anylist ANY.
+with ::=.
+windowdefn_list ::= windowdefn.
+window ::= frame_opt.
+
+%token SPACE ILLEGAL.
diff --git a/src/trace_processor/perfetto_sql/grammar/perfettosql_include.y b/src/trace_processor/perfetto_sql/grammar/perfettosql_include.y
new file mode 100644
index 0000000..40f6554
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/grammar/perfettosql_include.y
@@ -0,0 +1,42 @@
+%name PerfettoSqlParser
+%token_prefix TK_
+%start_symbol input
+
+%include {
+#include <stddef.h>
+
+#define YYNOERRORRECOVERY 1
+}
+
+%left OR.
+%left AND.
+%right NOT.
+%left IS MATCH 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 PTR.
+%left COLLATE.
+%right BITNOT.
+%nonassoc ON.
+
+%fallback ID
+  ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
+  CONFLICT DATABASE DEFERRED DESC DETACH DO
+  EACH END EXCLUSIVE EXPLAIN FAIL FOR
+  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
+  QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS
+  ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
+  NULLS FIRST LAST
+  EXCEPT INTERSECT UNION
+  CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
+  EXCLUDE GROUPS OTHERS TIES
+  WITHIN
+  GENERATED ALWAYS
+  MATERIALIZED
+  REINDEX RENAME CTIME_KW IF
+  .
+%wildcard ANY.
+
diff --git a/src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash.h b/src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash.h
new file mode 100644
index 0000000..971794d
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash.h
@@ -0,0 +1,599 @@
+
+#include "src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash_helper.h"
+/***** This file contains automatically generated code ******
+**
+** The code in this file has been automatically generated by
+**
+**   sqlite/tool/mkkeywordhash.c
+**
+** The code in this file implements a function that determines whether
+** or not a given identifier is really an SQL keyword.  The same thing
+** might be implemented more directly using a hand-written hash table.
+** But by using this automatically generated code, the size of the code
+** is substantially reduced.  This is important for embedded applications
+** on platforms with limited memory.
+*/
+/* Hash score: 231 */
+/* zKWText[] encodes 1007 bytes of keyword text in 667 bytes */
+/*   REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT       */
+/*   ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYISNULLSAVEPOINTERSECT       */
+/*   IESNOTNULLIKEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTS             */
+/*   CONSTRAINTOFFSETRIGGERANGENERATEDETACHAVINGLOBEGINNEREFERENCES     */
+/*   UNIQUERYWITHOUTERELEASEATTACHBETWEENOTHINGROUPSCASCADEFAULT        */
+/*   CASECOLLATECREATECURRENT_DATEIMMEDIATEJOINSERTMATCHPLANALYZE       */
+/*   PRAGMATERIALIZEDEFERREDISTINCTUPDATEVALUESVIRTUALWAYSWHENWHERE     */
+/*   CURSIVEABORTAFTERENAMEANDROPARTITIONAUTOINCREMENTCASTCOLUMN        */
+/*   COMMITCONFLICTCROSSCURRENT_TIMESTAMPRECEDINGFAILASTFILTER          */
+/*   EPLACEFIRSTFOLLOWINGFROMFULLIMITIFORDERESTRICTOTHERSOVER           */
+/*   ETURNINGRIGHTROLLBACKROWSUNBOUNDEDUNIONUSINGVACUUMVIEWINDOWBY      */
+/*   INITIALLYPRIMARY                                                   */
+static const char zKWText[666] = {
+    'R', 'E', 'I', 'N', 'D', 'E', 'X', 'E', 'D', 'E', 'S', 'C', 'A', 'P', 'E',
+    'A', 'C', 'H', 'E', 'C', 'K', 'E', 'Y', 'B', 'E', 'F', 'O', 'R', 'E', 'I',
+    'G', 'N', 'O', 'R', 'E', 'G', 'E', 'X', 'P', 'L', 'A', 'I', 'N', 'S', 'T',
+    'E', 'A', 'D', 'D', 'A', 'T', 'A', 'B', 'A', 'S', 'E', 'L', 'E', 'C', 'T',
+    'A', 'B', 'L', 'E', 'F', 'T', 'H', 'E', 'N', 'D', 'E', 'F', 'E', 'R', 'R',
+    'A', 'B', 'L', 'E', 'L', 'S', 'E', 'X', 'C', 'L', 'U', 'D', 'E', 'L', 'E',
+    'T', 'E', 'M', 'P', 'O', 'R', 'A', 'R', 'Y', 'I', 'S', 'N', 'U', 'L', 'L',
+    'S', 'A', 'V', 'E', 'P', 'O', 'I', 'N', 'T', 'E', 'R', 'S', 'E', 'C', 'T',
+    'I', 'E', 'S', 'N', 'O', 'T', 'N', 'U', 'L', 'L', 'I', 'K', 'E', 'X', 'C',
+    'E', 'P', 'T', 'R', 'A', 'N', 'S', 'A', 'C', 'T', 'I', 'O', 'N', 'A', 'T',
+    'U', 'R', 'A', 'L', 'T', 'E', 'R', 'A', 'I', 'S', 'E', 'X', 'C', 'L', 'U',
+    'S', 'I', 'V', 'E', 'X', 'I', 'S', 'T', 'S', 'C', 'O', 'N', 'S', 'T', 'R',
+    'A', 'I', 'N', 'T', 'O', 'F', 'F', 'S', 'E', 'T', 'R', 'I', 'G', 'G', 'E',
+    'R', 'A', 'N', 'G', 'E', 'N', 'E', 'R', 'A', 'T', 'E', 'D', 'E', 'T', 'A',
+    'C', 'H', 'A', 'V', 'I', 'N', 'G', 'L', 'O', 'B', 'E', 'G', 'I', 'N', 'N',
+    'E', 'R', 'E', 'F', 'E', 'R', 'E', 'N', 'C', 'E', 'S', 'U', 'N', 'I', 'Q',
+    'U', 'E', 'R', 'Y', 'W', 'I', 'T', 'H', 'O', 'U', 'T', 'E', 'R', 'E', 'L',
+    'E', 'A', 'S', 'E', 'A', 'T', 'T', 'A', 'C', 'H', 'B', 'E', 'T', 'W', 'E',
+    'E', 'N', 'O', 'T', 'H', 'I', 'N', 'G', 'R', 'O', 'U', 'P', 'S', 'C', 'A',
+    'S', 'C', 'A', 'D', 'E', 'F', 'A', 'U', 'L', 'T', 'C', 'A', 'S', 'E', 'C',
+    'O', 'L', 'L', 'A', 'T', 'E', 'C', 'R', 'E', 'A', 'T', 'E', 'C', 'U', 'R',
+    'R', 'E', 'N', 'T', '_', 'D', 'A', 'T', 'E', 'I', 'M', 'M', 'E', 'D', 'I',
+    'A', 'T', 'E', 'J', 'O', 'I', 'N', 'S', 'E', 'R', 'T', 'M', 'A', 'T', 'C',
+    'H', 'P', 'L', 'A', 'N', 'A', 'L', 'Y', 'Z', 'E', 'P', 'R', 'A', 'G', 'M',
+    'A', 'T', 'E', 'R', 'I', 'A', 'L', 'I', 'Z', 'E', 'D', 'E', 'F', 'E', 'R',
+    'R', 'E', 'D', 'I', 'S', 'T', 'I', 'N', 'C', 'T', 'U', 'P', 'D', 'A', 'T',
+    'E', 'V', 'A', 'L', 'U', 'E', 'S', 'V', 'I', 'R', 'T', 'U', 'A', 'L', 'W',
+    'A', 'Y', 'S', 'W', 'H', 'E', 'N', 'W', 'H', 'E', 'R', 'E', 'C', 'U', 'R',
+    'S', 'I', 'V', 'E', 'A', 'B', 'O', 'R', 'T', 'A', 'F', 'T', 'E', 'R', 'E',
+    'N', 'A', 'M', 'E', 'A', 'N', 'D', 'R', 'O', 'P', 'A', 'R', 'T', 'I', 'T',
+    'I', 'O', 'N', 'A', 'U', 'T', 'O', 'I', 'N', 'C', 'R', 'E', 'M', 'E', 'N',
+    'T', 'C', 'A', 'S', 'T', 'C', 'O', 'L', 'U', 'M', 'N', 'C', 'O', 'M', 'M',
+    'I', 'T', 'C', 'O', 'N', 'F', 'L', 'I', 'C', 'T', 'C', 'R', 'O', 'S', 'S',
+    'C', 'U', 'R', 'R', 'E', 'N', 'T', '_', 'T', 'I', 'M', 'E', 'S', 'T', 'A',
+    'M', 'P', 'R', 'E', 'C', 'E', 'D', 'I', 'N', 'G', 'F', 'A', 'I', 'L', 'A',
+    'S', 'T', 'F', 'I', 'L', 'T', 'E', 'R', 'E', 'P', 'L', 'A', 'C', 'E', 'F',
+    'I', 'R', 'S', 'T', 'F', 'O', 'L', 'L', 'O', 'W', 'I', 'N', 'G', 'F', 'R',
+    'O', 'M', 'F', 'U', 'L', 'L', 'I', 'M', 'I', 'T', 'I', 'F', 'O', 'R', 'D',
+    'E', 'R', 'E', 'S', 'T', 'R', 'I', 'C', 'T', 'O', 'T', 'H', 'E', 'R', 'S',
+    'O', 'V', 'E', 'R', 'E', 'T', 'U', 'R', 'N', 'I', 'N', 'G', 'R', 'I', 'G',
+    'H', 'T', 'R', 'O', 'L', 'L', 'B', 'A', 'C', 'K', 'R', 'O', 'W', 'S', 'U',
+    'N', 'B', 'O', 'U', 'N', 'D', 'E', 'D', 'U', 'N', 'I', 'O', 'N', 'U', 'S',
+    'I', 'N', 'G', 'V', 'A', 'C', 'U', 'U', 'M', 'V', 'I', 'E', 'W', 'I', 'N',
+    'D', 'O', 'W', 'B', 'Y', 'I', 'N', 'I', 'T', 'I', 'A', 'L', 'L', 'Y', 'P',
+    'R', 'I', 'M', 'A', 'R', 'Y',
+};
+/* aKWHash[i] is the hash value for the i-th keyword */
+static const unsigned char aKWHash[127] = {
+    84,  92,  134, 82,  105, 29,  0,   0,   94,  0,  85,  72,  0,   53,  35,
+    86,  15,  0,   42,  97,  54,  89,  135, 19,  0,  0,   140, 0,   40,  129,
+    0,   22,  107, 0,   9,   0,   0,   123, 80,  0,  78,  6,   0,   65,  103,
+    147, 0,   136, 115, 0,   0,   48,  0,   90,  24, 0,   17,  0,   27,  70,
+    23,  26,  5,   60,  142, 110, 122, 0,   73,  91, 71,  145, 61,  120, 74,
+    0,   49,  0,   11,  41,  0,   113, 0,   0,   0,  109, 10,  111, 116, 125,
+    14,  50,  124, 0,   100, 0,   18,  121, 144, 56, 130, 139, 88,  83,  37,
+    30,  126, 0,   0,   108, 51,  131, 128, 0,   34, 0,   0,   132, 0,   98,
+    38,  39,  0,   20,  45,  117, 93,
+};
+/* aKWNext[] forms the hash collision chain.  If aKWHash[i]==0
+** then the i-th keyword has no more hash collisions.  Otherwise,
+** the next keyword with the same hash is aKWHash[i]-1. */
+static const unsigned char aKWNext[148] = {
+    0,   0,   0, 0,   0,   4,   0,  43, 0,  0,   106, 114, 0,   0,   0,
+    2,   0,   0, 143, 0,   0,   0,  13, 0,  0,   0,   0,   141, 0,   0,
+    119, 52,  0, 0,   137, 12,  0,  0,  62, 0,   138, 0,   133, 0,   0,
+    36,  0,   0, 28,  77,  0,   0,  0,  0,  59,  0,   47,  0,   0,   0,
+    0,   0,   0, 0,   0,   0,   0,  69, 0,  0,   0,   0,   0,   146, 3,
+    0,   58,  0, 1,   75,  0,   0,  0,  31, 0,   0,   0,   0,   0,   127,
+    0,   104, 0, 64,  66,  63,  0,  0,  0,  0,   0,   46,  0,   16,  8,
+    0,   0,   0, 0,   0,   0,   0,  0,  0,  0,   81,  101, 0,   112, 21,
+    7,   67,  0, 79,  96,  118, 0,  0,  68, 0,   0,   99,  44,  0,   55,
+    0,   76,  0, 95,  32,  33,  57, 25, 0,  102, 0,   0,   87,
+};
+/* aKWLen[i] is the length (in bytes) of the i-th keyword */
+static const unsigned char aKWLen[148] = {
+    0, 7,  7,  5, 4,  6,  4,  5, 3, 6, 7, 3, 6, 6, 7, 7,  3, 8, 2,  6,  5,  4,
+    4, 3,  10, 4, 7,  6,  9,  4, 2, 6, 5, 9, 9, 4, 7, 3,  2, 4, 4,  6,  11, 6,
+    2, 7,  5,  5, 9,  6,  10, 4, 6, 2, 3, 7, 5, 9, 6, 6,  4, 5, 5,  10, 6,  5,
+    7, 4,  5,  7, 6,  7,  7,  6, 5, 7, 3, 7, 4, 7, 6, 12, 9, 4, 6,  5,  4,  7,
+    6, 12, 8,  8, 2,  6,  6,  7, 6, 4, 5, 9, 5, 5, 6, 3,  4, 9, 13, 2,  2,  4,
+    6, 6,  8,  5, 17, 12, 7,  9, 4, 4, 6, 7, 5, 9, 4, 4,  5, 2, 5,  8,  6,  4,
+    9, 5,  8,  4, 3,  9,  5,  5, 6, 4, 6, 2, 2, 9, 3, 7,
+};
+/* aKWOffset[i] is the index into zKWText[] of the start of
+** the text for the i-th keyword. */
+static const unsigned short int aKWOffset[148] = {
+    0,   0,   2,   2,   8,   9,   14,  16,  20,  23,  25,  25,  29,  33,  36,
+    41,  46,  48,  53,  54,  59,  62,  65,  67,  69,  78,  81,  86,  90,  90,
+    94,  99,  101, 105, 111, 119, 123, 123, 123, 126, 129, 132, 137, 142, 146,
+    147, 152, 156, 160, 168, 174, 181, 184, 184, 187, 189, 195, 198, 206, 211,
+    216, 219, 222, 226, 236, 239, 244, 244, 248, 252, 259, 265, 271, 277, 277,
+    283, 284, 288, 295, 299, 306, 312, 324, 333, 335, 341, 346, 348, 355, 359,
+    370, 377, 378, 385, 391, 397, 402, 408, 412, 415, 424, 429, 433, 439, 441,
+    444, 453, 455, 457, 466, 470, 476, 482, 490, 495, 495, 495, 511, 520, 523,
+    527, 532, 539, 544, 553, 557, 560, 565, 567, 571, 579, 585, 588, 597, 602,
+    610, 610, 614, 623, 628, 633, 639, 642, 645, 648, 650, 655, 659,
+};
+/* aKWCode[i] is the parser symbol code for the i-th keyword */
+static const unsigned char aKWCode[148] = {
+    0,
+    TK_REINDEX,
+    TK_INDEXED,
+    TK_INDEX,
+    TK_DESC,
+    TK_ESCAPE,
+    TK_EACH,
+    TK_CHECK,
+    TK_KEY,
+    TK_BEFORE,
+    TK_FOREIGN,
+    TK_FOR,
+    TK_IGNORE,
+    TK_LIKE_KW,
+    TK_EXPLAIN,
+    TK_INSTEAD,
+    TK_ADD,
+    TK_DATABASE,
+    TK_AS,
+    TK_SELECT,
+    TK_TABLE,
+    TK_JOIN_KW,
+    TK_THEN,
+    TK_END,
+    TK_DEFERRABLE,
+    TK_ELSE,
+    TK_EXCLUDE,
+    TK_DELETE,
+    TK_TEMP,
+    TK_TEMP,
+    TK_OR,
+    TK_ISNULL,
+    TK_NULLS,
+    TK_SAVEPOINT,
+    TK_INTERSECT,
+    TK_TIES,
+    TK_NOTNULL,
+    TK_NOT,
+    TK_NO,
+    TK_NULL,
+    TK_LIKE_KW,
+    TK_EXCEPT,
+    TK_TRANSACTION,
+    TK_ACTION,
+    TK_ON,
+    TK_JOIN_KW,
+    TK_ALTER,
+    TK_RAISE,
+    TK_EXCLUSIVE,
+    TK_EXISTS,
+    TK_CONSTRAINT,
+    TK_INTO,
+    TK_OFFSET,
+    TK_OF,
+    TK_SET,
+    TK_TRIGGER,
+    TK_RANGE,
+    TK_GENERATED,
+    TK_DETACH,
+    TK_HAVING,
+    TK_LIKE_KW,
+    TK_BEGIN,
+    TK_JOIN_KW,
+    TK_REFERENCES,
+    TK_UNIQUE,
+    TK_QUERY,
+    TK_WITHOUT,
+    TK_WITH,
+    TK_JOIN_KW,
+    TK_RELEASE,
+    TK_ATTACH,
+    TK_BETWEEN,
+    TK_NOTHING,
+    TK_GROUPS,
+    TK_GROUP,
+    TK_CASCADE,
+    TK_ASC,
+    TK_DEFAULT,
+    TK_CASE,
+    TK_COLLATE,
+    TK_CREATE,
+    TK_CTIME_KW,
+    TK_IMMEDIATE,
+    TK_JOIN,
+    TK_INSERT,
+    TK_MATCH,
+    TK_PLAN,
+    TK_ANALYZE,
+    TK_PRAGMA,
+    TK_MATERIALIZED,
+    TK_DEFERRED,
+    TK_DISTINCT,
+    TK_IS,
+    TK_UPDATE,
+    TK_VALUES,
+    TK_VIRTUAL,
+    TK_ALWAYS,
+    TK_WHEN,
+    TK_WHERE,
+    TK_RECURSIVE,
+    TK_ABORT,
+    TK_AFTER,
+    TK_RENAME,
+    TK_AND,
+    TK_DROP,
+    TK_PARTITION,
+    TK_AUTOINCR,
+    TK_TO,
+    TK_IN,
+    TK_CAST,
+    TK_COLUMNKW,
+    TK_COMMIT,
+    TK_CONFLICT,
+    TK_JOIN_KW,
+    TK_CTIME_KW,
+    TK_CTIME_KW,
+    TK_CURRENT,
+    TK_PRECEDING,
+    TK_FAIL,
+    TK_LAST,
+    TK_FILTER,
+    TK_REPLACE,
+    TK_FIRST,
+    TK_FOLLOWING,
+    TK_FROM,
+    TK_JOIN_KW,
+    TK_LIMIT,
+    TK_IF,
+    TK_ORDER,
+    TK_RESTRICT,
+    TK_OTHERS,
+    TK_OVER,
+    TK_RETURNING,
+    TK_JOIN_KW,
+    TK_ROLLBACK,
+    TK_ROWS,
+    TK_ROW,
+    TK_UNBOUNDED,
+    TK_UNION,
+    TK_USING,
+    TK_VACUUM,
+    TK_VIEW,
+    TK_WINDOW,
+    TK_DO,
+    TK_BY,
+    TK_INITIALLY,
+    TK_ALL,
+    TK_PRIMARY,
+};
+/* Hash table decoded:
+**   0: INSERT
+**   1: IS
+**   2: ROLLBACK TRIGGER
+**   3: IMMEDIATE
+**   4: PARTITION
+**   5: TEMP
+**   6:
+**   7:
+**   8: VALUES WITHOUT
+**   9:
+**  10: MATCH
+**  11: NOTHING
+**  12:
+**  13: OF
+**  14: TIES IGNORE
+**  15: PLAN
+**  16: INSTEAD INDEXED
+**  17:
+**  18: TRANSACTION RIGHT
+**  19: WHEN
+**  20: SET HAVING
+**  21: MATERIALIZED IF
+**  22: ROWS
+**  23: SELECT
+**  24:
+**  25:
+**  26: VACUUM SAVEPOINT
+**  27:
+**  28: LIKE UNION VIRTUAL REFERENCES
+**  29: RESTRICT
+**  30:
+**  31: THEN REGEXP
+**  32: TO
+**  33:
+**  34: BEFORE
+**  35:
+**  36:
+**  37: FOLLOWING COLLATE CASCADE
+**  38: CREATE
+**  39:
+**  40: CASE REINDEX
+**  41: EACH
+**  42:
+**  43: QUERY
+**  44: AND ADD
+**  45: PRIMARY ANALYZE
+**  46:
+**  47: ROW ASC DETACH
+**  48: CURRENT_TIME CURRENT_DATE
+**  49:
+**  50:
+**  51: EXCLUSIVE TEMPORARY
+**  52:
+**  53: DEFERRED
+**  54: DEFERRABLE
+**  55:
+**  56: DATABASE
+**  57:
+**  58: DELETE VIEW GENERATED
+**  59: ATTACH
+**  60: END
+**  61: EXCLUDE
+**  62: ESCAPE DESC
+**  63: GLOB
+**  64: WINDOW ELSE
+**  65: COLUMN
+**  66: FIRST
+**  67:
+**  68: GROUPS ALL
+**  69: DISTINCT DROP KEY
+**  70: BETWEEN
+**  71: INITIALLY
+**  72: BEGIN
+**  73: FILTER CHECK ACTION
+**  74: GROUP INDEX
+**  75:
+**  76: EXISTS DEFAULT
+**  77:
+**  78: FOR CURRENT_TIMESTAMP
+**  79: EXCEPT
+**  80:
+**  81: CROSS
+**  82:
+**  83:
+**  84:
+**  85: CAST
+**  86: FOREIGN AUTOINCREMENT
+**  87: COMMIT
+**  88: CURRENT AFTER ALTER
+**  89: FULL FAIL CONFLICT
+**  90: EXPLAIN
+**  91: CONSTRAINT
+**  92: FROM ALWAYS
+**  93:
+**  94: ABORT
+**  95:
+**  96: AS DO
+**  97: REPLACE WITH RELEASE
+**  98: BY RENAME
+**  99: RANGE RAISE
+** 100: OTHERS
+** 101: USING NULLS
+** 102: PRAGMA
+** 103: JOIN ISNULL OFFSET
+** 104: NOT
+** 105: OR LAST LEFT
+** 106: LIMIT
+** 107:
+** 108:
+** 109: IN
+** 110: INTO
+** 111: OVER RECURSIVE
+** 112: ORDER OUTER
+** 113:
+** 114: INTERSECT UNBOUNDED
+** 115:
+** 116:
+** 117: RETURNING ON
+** 118:
+** 119: WHERE
+** 120: NO INNER
+** 121: NULL
+** 122:
+** 123: TABLE
+** 124: NATURAL NOTNULL
+** 125: PRECEDING
+** 126: UPDATE UNIQUE
+*/
+/* Check to see if z[0..n-1] is a keyword. If it is, write the
+** parser symbol code for that keyword into *pType.  Always
+** return the integer n (the length of the token). */
+static int keywordCode(const char* z, int n, int* pType) {
+  int i, j;
+  const char* zKW;
+  assert(n >= 2);
+  i = ((charMap(z[0]) * 4) ^ (charMap(z[n - 1]) * 3) ^ n * 1) % 127;
+  for (i = (int)aKWHash[i]; i > 0; i = aKWNext[i]) {
+    if (aKWLen[i] != n)
+      continue;
+    zKW = &zKWText[aKWOffset[i]];
+#ifdef SQLITE_ASCII
+    if ((z[0] & ~0x20) != zKW[0])
+      continue;
+    if ((z[1] & ~0x20) != zKW[1])
+      continue;
+    j = 2;
+    while (j < n && (z[j] & ~0x20) == zKW[j]) {
+      j++;
+    }
+#endif
+#ifdef SQLITE_EBCDIC
+    if (toupper(z[0]) != zKW[0])
+      continue;
+    if (toupper(z[1]) != zKW[1])
+      continue;
+    j = 2;
+    while (j < n && toupper(z[j]) == zKW[j]) {
+      j++;
+    }
+#endif
+    if (j < n)
+      continue;
+    testcase(i == 1);   /* REINDEX */
+    testcase(i == 2);   /* INDEXED */
+    testcase(i == 3);   /* INDEX */
+    testcase(i == 4);   /* DESC */
+    testcase(i == 5);   /* ESCAPE */
+    testcase(i == 6);   /* EACH */
+    testcase(i == 7);   /* CHECK */
+    testcase(i == 8);   /* KEY */
+    testcase(i == 9);   /* BEFORE */
+    testcase(i == 10);  /* FOREIGN */
+    testcase(i == 11);  /* FOR */
+    testcase(i == 12);  /* IGNORE */
+    testcase(i == 13);  /* REGEXP */
+    testcase(i == 14);  /* EXPLAIN */
+    testcase(i == 15);  /* INSTEAD */
+    testcase(i == 16);  /* ADD */
+    testcase(i == 17);  /* DATABASE */
+    testcase(i == 18);  /* AS */
+    testcase(i == 19);  /* SELECT */
+    testcase(i == 20);  /* TABLE */
+    testcase(i == 21);  /* LEFT */
+    testcase(i == 22);  /* THEN */
+    testcase(i == 23);  /* END */
+    testcase(i == 24);  /* DEFERRABLE */
+    testcase(i == 25);  /* ELSE */
+    testcase(i == 26);  /* EXCLUDE */
+    testcase(i == 27);  /* DELETE */
+    testcase(i == 28);  /* TEMPORARY */
+    testcase(i == 29);  /* TEMP */
+    testcase(i == 30);  /* OR */
+    testcase(i == 31);  /* ISNULL */
+    testcase(i == 32);  /* NULLS */
+    testcase(i == 33);  /* SAVEPOINT */
+    testcase(i == 34);  /* INTERSECT */
+    testcase(i == 35);  /* TIES */
+    testcase(i == 36);  /* NOTNULL */
+    testcase(i == 37);  /* NOT */
+    testcase(i == 38);  /* NO */
+    testcase(i == 39);  /* NULL */
+    testcase(i == 40);  /* LIKE */
+    testcase(i == 41);  /* EXCEPT */
+    testcase(i == 42);  /* TRANSACTION */
+    testcase(i == 43);  /* ACTION */
+    testcase(i == 44);  /* ON */
+    testcase(i == 45);  /* NATURAL */
+    testcase(i == 46);  /* ALTER */
+    testcase(i == 47);  /* RAISE */
+    testcase(i == 48);  /* EXCLUSIVE */
+    testcase(i == 49);  /* EXISTS */
+    testcase(i == 50);  /* CONSTRAINT */
+    testcase(i == 51);  /* INTO */
+    testcase(i == 52);  /* OFFSET */
+    testcase(i == 53);  /* OF */
+    testcase(i == 54);  /* SET */
+    testcase(i == 55);  /* TRIGGER */
+    testcase(i == 56);  /* RANGE */
+    testcase(i == 57);  /* GENERATED */
+    testcase(i == 58);  /* DETACH */
+    testcase(i == 59);  /* HAVING */
+    testcase(i == 60);  /* GLOB */
+    testcase(i == 61);  /* BEGIN */
+    testcase(i == 62);  /* INNER */
+    testcase(i == 63);  /* REFERENCES */
+    testcase(i == 64);  /* UNIQUE */
+    testcase(i == 65);  /* QUERY */
+    testcase(i == 66);  /* WITHOUT */
+    testcase(i == 67);  /* WITH */
+    testcase(i == 68);  /* OUTER */
+    testcase(i == 69);  /* RELEASE */
+    testcase(i == 70);  /* ATTACH */
+    testcase(i == 71);  /* BETWEEN */
+    testcase(i == 72);  /* NOTHING */
+    testcase(i == 73);  /* GROUPS */
+    testcase(i == 74);  /* GROUP */
+    testcase(i == 75);  /* CASCADE */
+    testcase(i == 76);  /* ASC */
+    testcase(i == 77);  /* DEFAULT */
+    testcase(i == 78);  /* CASE */
+    testcase(i == 79);  /* COLLATE */
+    testcase(i == 80);  /* CREATE */
+    testcase(i == 81);  /* CURRENT_DATE */
+    testcase(i == 82);  /* IMMEDIATE */
+    testcase(i == 83);  /* JOIN */
+    testcase(i == 84);  /* INSERT */
+    testcase(i == 85);  /* MATCH */
+    testcase(i == 86);  /* PLAN */
+    testcase(i == 87);  /* ANALYZE */
+    testcase(i == 88);  /* PRAGMA */
+    testcase(i == 89);  /* MATERIALIZED */
+    testcase(i == 90);  /* DEFERRED */
+    testcase(i == 91);  /* DISTINCT */
+    testcase(i == 92);  /* IS */
+    testcase(i == 93);  /* UPDATE */
+    testcase(i == 94);  /* VALUES */
+    testcase(i == 95);  /* VIRTUAL */
+    testcase(i == 96);  /* ALWAYS */
+    testcase(i == 97);  /* WHEN */
+    testcase(i == 98);  /* WHERE */
+    testcase(i == 99);  /* RECURSIVE */
+    testcase(i == 100); /* ABORT */
+    testcase(i == 101); /* AFTER */
+    testcase(i == 102); /* RENAME */
+    testcase(i == 103); /* AND */
+    testcase(i == 104); /* DROP */
+    testcase(i == 105); /* PARTITION */
+    testcase(i == 106); /* AUTOINCREMENT */
+    testcase(i == 107); /* TO */
+    testcase(i == 108); /* IN */
+    testcase(i == 109); /* CAST */
+    testcase(i == 110); /* COLUMN */
+    testcase(i == 111); /* COMMIT */
+    testcase(i == 112); /* CONFLICT */
+    testcase(i == 113); /* CROSS */
+    testcase(i == 114); /* CURRENT_TIMESTAMP */
+    testcase(i == 115); /* CURRENT_TIME */
+    testcase(i == 116); /* CURRENT */
+    testcase(i == 117); /* PRECEDING */
+    testcase(i == 118); /* FAIL */
+    testcase(i == 119); /* LAST */
+    testcase(i == 120); /* FILTER */
+    testcase(i == 121); /* REPLACE */
+    testcase(i == 122); /* FIRST */
+    testcase(i == 123); /* FOLLOWING */
+    testcase(i == 124); /* FROM */
+    testcase(i == 125); /* FULL */
+    testcase(i == 126); /* LIMIT */
+    testcase(i == 127); /* IF */
+    testcase(i == 128); /* ORDER */
+    testcase(i == 129); /* RESTRICT */
+    testcase(i == 130); /* OTHERS */
+    testcase(i == 131); /* OVER */
+    testcase(i == 132); /* RETURNING */
+    testcase(i == 133); /* RIGHT */
+    testcase(i == 134); /* ROLLBACK */
+    testcase(i == 135); /* ROWS */
+    testcase(i == 136); /* ROW */
+    testcase(i == 137); /* UNBOUNDED */
+    testcase(i == 138); /* UNION */
+    testcase(i == 139); /* USING */
+    testcase(i == 140); /* VACUUM */
+    testcase(i == 141); /* VIEW */
+    testcase(i == 142); /* WINDOW */
+    testcase(i == 143); /* DO */
+    testcase(i == 144); /* BY */
+    testcase(i == 145); /* INITIALLY */
+    testcase(i == 146); /* ALL */
+    testcase(i == 147); /* PRIMARY */
+    *pType = aKWCode[i];
+    break;
+  }
+  return n;
+}
+int sqlite3KeywordCode(const unsigned char* z, int n) {
+  int id = TK_ID;
+  if (n >= 2)
+    keywordCode((char*)z, n, &id);
+  return id;
+}
diff --git a/src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash_helper.h b/src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash_helper.h
new file mode 100644
index 0000000..e50bcb0
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash_helper.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_PERFETTO_SQL_GRAMMAR_PERFETTOSQL_KEYWORDHASH_HELPER_H_
+#define SRC_TRACE_PROCESSOR_PERFETTO_SQL_GRAMMAR_PERFETTOSQL_KEYWORDHASH_HELPER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ctype.h>
+
+typedef unsigned char u8;
+
+#define SQLITE_OK 0
+#define SQLITE_ERROR 1
+#define SQLITE_ASCII 1
+
+static inline int charMap(char c) {
+  return tolower(c);
+}
+
+static inline void testcase(int X) {}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // SRC_TRACE_PROCESSOR_PERFETTO_SQL_GRAMMAR_PERFETTOSQL_KEYWORDHASH_HELPER_H_
diff --git a/src/trace_processor/perfetto_sql/parser/perfetto_sql_parser.cc b/src/trace_processor/perfetto_sql/parser/perfetto_sql_parser.cc
index 4af83ea..90a829e 100644
--- a/src/trace_processor/perfetto_sql/parser/perfetto_sql_parser.cc
+++ b/src/trace_processor/perfetto_sql/parser/perfetto_sql_parser.cc
@@ -21,6 +21,7 @@
 #include <functional>
 #include <optional>
 #include <string>
+#include <string_view>
 #include <utility>
 #include <vector>
 
@@ -62,13 +63,8 @@
                     [](char a, char b) { return a == tolower(b); });
 }
 
-bool TokenIsSqliteKeyword(std::string_view keyword, SqliteTokenizer::Token t) {
-  return t.token_type == SqliteTokenType::TK_GENERIC_KEYWORD &&
-         KeywordEqual(keyword, t.str);
-}
-
 bool TokenIsCustomKeyword(std::string_view keyword, SqliteTokenizer::Token t) {
-  return t.token_type == SqliteTokenType::TK_ID && KeywordEqual(keyword, t.str);
+  return t.token_type == TK_ID && KeywordEqual(keyword, t.str);
 }
 
 bool IsValidModuleWord(const std::string& word) {
@@ -120,7 +116,7 @@
   for (Token token = tokenizer_.Next();; token = tokenizer_.Next()) {
     // Space should always be completely ignored by any logic below as it will
     // never change the current state in the state machine.
-    if (token.token_type == SqliteTokenType::TK_SPACE) {
+    if (token.token_type == TK_SPACE) {
       continue;
     }
 
@@ -134,7 +130,7 @@
       }
       // This means we've seen a semi-colon without any non-space content. Just
       // try and find the next statement as this "statement" is a noop.
-      if (token.token_type == SqliteTokenType::TK_SEMI) {
+      if (token.token_type == TK_SEMI) {
         continue;
       }
       // This means we've reached the end of the SQL.
@@ -153,11 +149,11 @@
         statement_sql_ = preprocessor_.statement();
         return true;
       case State::kStmtStart:
-        if (TokenIsSqliteKeyword("create", token)) {
+        if (token.token_type == TK_CREATE) {
           state = State::kCreate;
         } else if (TokenIsCustomKeyword("include", token)) {
           state = State::kInclude;
-        } else if (TokenIsSqliteKeyword("drop", token)) {
+        } else if (token.token_type == TK_DROP) {
           state = State::kDrop;
         } else {
           state = State::kPassthrough;
@@ -186,13 +182,13 @@
         }
         break;
       case State::kDropPerfetto:
-        if (TokenIsSqliteKeyword("index", token)) {
+        if (token.token_type == TK_INDEX) {
           return ParseDropPerfettoIndex(*first_non_space_token);
         } else {
           return ErrorAtToken(token, "Only Perfetto index can be dropped");
         }
       case State::kCreate:
-        if (TokenIsSqliteKeyword("trigger", token)) {
+        if (token.token_type == TK_TRIGGER) {
           // TODO(lalitm): add this to the "errors" documentation page
           // explaining why this is the case.
           return ErrorAtToken(
@@ -200,15 +196,15 @@
         }
         if (TokenIsCustomKeyword("perfetto", token)) {
           state = State::kCreatePerfetto;
-        } else if (TokenIsSqliteKeyword("or", token)) {
+        } else if (token.token_type == TK_OR) {
           state = State::kCreateOr;
         } else {
           state = State::kPassthrough;
         }
         break;
       case State::kCreateOr:
-        state = TokenIsSqliteKeyword("replace", token) ? State::kCreateOrReplace
-                                                       : State::kPassthrough;
+        state = token.token_type == TK_REPLACE ? State::kCreateOrReplace
+                                               : State::kPassthrough;
         break;
       case State::kCreateOrReplace:
         state = TokenIsCustomKeyword("perfetto", token)
@@ -221,18 +217,18 @@
         if (TokenIsCustomKeyword("function", token)) {
           return ParseCreatePerfettoFunction(replace, *first_non_space_token);
         }
-        if (TokenIsSqliteKeyword("table", token)) {
+        if (token.token_type == TK_TABLE) {
           return ParseCreatePerfettoTableOrView(replace, *first_non_space_token,
                                                 TableOrView::kTable);
         }
-        if (TokenIsSqliteKeyword("view", token)) {
+        if (token.token_type == TK_VIEW) {
           return ParseCreatePerfettoTableOrView(replace, *first_non_space_token,
                                                 TableOrView::kView);
         }
         if (TokenIsCustomKeyword("macro", token)) {
           return ParseCreatePerfettoMacro(replace);
         }
-        if (TokenIsSqliteKeyword("index", token)) {
+        if (token.token_type == TK_INDEX) {
           return ParseCreatePerfettoIndex(replace, *first_non_space_token);
         }
         base::StackString<1024> err(
@@ -268,7 +264,7 @@
     Token first_non_space_token,
     TableOrView table_or_view) {
   Token table_name = tokenizer_.NextNonWhitespace();
-  if (table_name.token_type != SqliteTokenType::TK_ID) {
+  if (table_name.token_type != TK_ID) {
     base::StackString<1024> err("Invalid table name %.*s",
                                 static_cast<int>(table_name.str.size()),
                                 table_name.str.data());
@@ -281,14 +277,14 @@
 
   // If the next token is a left parenthesis, then the table or view have a
   // schema.
-  if (token.token_type == SqliteTokenType::TK_LP) {
+  if (token.token_type == TK_LP) {
     if (!ParseArguments(schema)) {
       return false;
     }
     token = tokenizer_.NextNonWhitespace();
   }
 
-  if (!TokenIsSqliteKeyword("as", token)) {
+  if (token.token_type != TK_AS) {
     base::StackString<1024> err(
         "Expected 'AS' after table_name, received "
         "%*s.",
@@ -323,7 +319,7 @@
 bool PerfettoSqlParser::ParseCreatePerfettoIndex(bool replace,
                                                  Token first_non_space_token) {
   Token index_name_tok = tokenizer_.NextNonWhitespace();
-  if (index_name_tok.token_type != SqliteTokenType::TK_ID) {
+  if (index_name_tok.token_type != TK_ID) {
     base::StackString<1024> err("Invalid index name %.*s",
                                 static_cast<int>(index_name_tok.str.size()),
                                 index_name_tok.str.data());
@@ -332,7 +328,7 @@
   std::string index_name(index_name_tok.str);
 
   auto token = tokenizer_.NextNonWhitespace();
-  if (!TokenIsSqliteKeyword("on", token)) {
+  if (token.token_type != TK_ON) {
     base::StackString<1024> err("Expected 'ON' after index name, received %*s.",
                                 static_cast<int>(token.str.size()),
                                 token.str.data());
@@ -340,7 +336,7 @@
   }
 
   Token table_name_tok = tokenizer_.NextNonWhitespace();
-  if (table_name_tok.token_type != SqliteTokenType::TK_ID) {
+  if (table_name_tok.token_type != TK_ID) {
     base::StackString<1024> err("Invalid table name %.*s",
                                 static_cast<int>(table_name_tok.str.size()),
                                 table_name_tok.str.data());
@@ -349,7 +345,7 @@
   std::string table_name(table_name_tok.str);
 
   token = tokenizer_.NextNonWhitespace();
-  if (token.token_type != SqliteTokenType::TK_LP) {
+  if (token.token_type != TK_LP) {
     base::StackString<1024> err(
         "Expected parenthesis after table name, received '%*s'.",
         static_cast<int>(token.str.size()), token.str.data());
@@ -362,9 +358,9 @@
     Token col_name_tok = tokenizer_.NextNonWhitespace();
     cols.push_back(std::string(col_name_tok.str));
     token = tokenizer_.NextNonWhitespace();
-  } while (token.token_type == SqliteTokenType::TK_COMMA);
+  } while (token.token_type == TK_COMMA);
 
-  if (token.token_type != SqliteTokenType::TK_RP) {
+  if (token.token_type != TK_RP) {
     base::StackString<1024> err("Expected closed parenthesis, received '%*s'.",
                                 static_cast<int>(token.str.size()),
                                 token.str.data());
@@ -386,7 +382,7 @@
 bool PerfettoSqlParser::ParseDropPerfettoIndex(
     SqliteTokenizer::Token first_non_space_token) {
   Token index_name_tok = tokenizer_.NextNonWhitespace();
-  if (index_name_tok.token_type != SqliteTokenType::TK_ID) {
+  if (index_name_tok.token_type != TK_ID) {
     base::StackString<1024> err("Invalid index name %.*s",
                                 static_cast<int>(index_name_tok.str.size()),
                                 index_name_tok.str.data());
@@ -395,7 +391,7 @@
   std::string index_name(index_name_tok.str);
 
   auto token = tokenizer_.NextNonWhitespace();
-  if (!TokenIsSqliteKeyword("on", token)) {
+  if (token.token_type != TK_ON) {
     base::StackString<1024> err("Expected 'ON' after index name, received %*s.",
                                 static_cast<int>(token.str.size()),
                                 token.str.data());
@@ -403,7 +399,7 @@
   }
 
   Token table_name_tok = tokenizer_.NextNonWhitespace();
-  if (table_name_tok.token_type != SqliteTokenType::TK_ID) {
+  if (table_name_tok.token_type != TK_ID) {
     base::StackString<1024> err("Invalid table name %.*s",
                                 static_cast<int>(table_name_tok.str.size()),
                                 table_name_tok.str.data());
@@ -425,7 +421,7 @@
     bool replace,
     Token first_non_space_token) {
   Token function_name = tokenizer_.NextNonWhitespace();
-  if (function_name.token_type != SqliteTokenType::TK_ID) {
+  if (function_name.token_type != TK_ID) {
     // TODO(lalitm): add a link to create function documentation.
     base::StackString<1024> err("Invalid function name %.*s",
                                 static_cast<int>(function_name.str.size()),
@@ -434,8 +430,7 @@
   }
 
   // TK_LP == '(' (i.e. left parenthesis).
-  if (Token lp = tokenizer_.NextNonWhitespace();
-      lp.token_type != SqliteTokenType::TK_LP) {
+  if (Token lp = tokenizer_.NextNonWhitespace(); lp.token_type != TK_LP) {
     // TODO(lalitm): add a link to create function documentation.
     return ErrorAtToken(lp, "Malformed function prototype: '(' expected");
   }
@@ -453,10 +448,9 @@
 
   Token ret_token = tokenizer_.NextNonWhitespace();
   std::string ret;
-  bool table_return = TokenIsSqliteKeyword("table", ret_token);
+  bool table_return = ret_token.token_type == TK_TABLE;
   if (table_return) {
-    if (Token lp = tokenizer_.NextNonWhitespace();
-        lp.token_type != SqliteTokenType::TK_LP) {
+    if (Token lp = tokenizer_.NextNonWhitespace(); lp.token_type != TK_LP) {
       // TODO(lalitm): add a link to create function documentation.
       return ErrorAtToken(lp, "Malformed table return: '(' expected");
     }
@@ -466,7 +460,7 @@
       return false;
     }
     ret = sql_argument::SerializeArguments(ret_args);
-  } else if (ret_token.token_type != SqliteTokenType::TK_ID) {
+  } else if (ret_token.token_type != TK_ID) {
     // TODO(lalitm): add a link to create function documentation.
     return ErrorAtToken(ret_token, "Invalid return type");
   } else {
@@ -475,7 +469,7 @@
   }
 
   if (Token as_token = tokenizer_.NextNonWhitespace();
-      !TokenIsSqliteKeyword("as", as_token)) {
+      as_token.token_type != TK_AS) {
     // TODO(lalitm): add a link to create function documentation.
     return ErrorAtToken(as_token, "Expected keyword 'as'");
   }
@@ -492,7 +486,7 @@
 
 bool PerfettoSqlParser::ParseCreatePerfettoMacro(bool replace) {
   Token name = tokenizer_.NextNonWhitespace();
-  if (name.token_type != SqliteTokenType::TK_ID) {
+  if (name.token_type != TK_ID) {
     // TODO(lalitm): add a link to create macro documentation.
     base::StackString<1024> err("Invalid macro name %.*s",
                                 static_cast<int>(name.str.size()),
@@ -501,8 +495,7 @@
   }
 
   // TK_LP == '(' (i.e. left parenthesis).
-  if (Token lp = tokenizer_.NextNonWhitespace();
-      lp.token_type != SqliteTokenType::TK_LP) {
+  if (Token lp = tokenizer_.NextNonWhitespace(); lp.token_type != TK_LP) {
     // TODO(lalitm): add a link to create macro documentation.
     return ErrorAtToken(lp, "Malformed macro prototype: '(' expected");
   }
@@ -524,13 +517,13 @@
   }
 
   Token returns_value = tokenizer_.NextNonWhitespace();
-  if (returns_value.token_type != SqliteTokenType::TK_ID) {
+  if (returns_value.token_type != TK_ID) {
     // TODO(lalitm): add a link to create function documentation.
     return ErrorAtToken(returns_value, "Expected return type");
   }
 
   if (Token as_token = tokenizer_.NextNonWhitespace();
-      !TokenIsSqliteKeyword("as", as_token)) {
+      as_token.token_type != TK_AS) {
     // TODO(lalitm): add a link to create macro documentation.
     return ErrorAtToken(as_token, "Expected keyword 'as'");
   }
@@ -555,34 +548,19 @@
   TokenType expected = kIdOrRp;
   for (Token tok = tokenizer_.NextNonWhitespace();;
        tok = tokenizer_.NextNonWhitespace()) {
-    // Keywords can be used as names accidentally so have an explicit error
-    // message for those.
-    if (tok.token_type == SqliteTokenType::TK_GENERIC_KEYWORD) {
-      // Ignore "key" which, while being a keyword, is also harmless in
-      // practice.
-      if (base::ToLower(std::string(tok.str)) == "key") {
-        tok.token_type = SqliteTokenType::TK_ID;
-      } else {
-        base::StackString<1024> err(
-            "Malformed function/macro prototype: %.*s is a SQL keyword so "
-            "cannot appear in a prototype",
-            static_cast<int>(tok.str.size()), tok.str.data());
-        return ErrorAtToken(tok, err.c_str());
-      }
-    }
     if (expected == kCommaOrRp) {
       PERFETTO_CHECK(expected == kCommaOrRp);
-      if (tok.token_type == SqliteTokenType::TK_RP) {
+      if (tok.token_type == TK_RP) {
         return true;
       }
-      if (tok.token_type == SqliteTokenType::TK_COMMA) {
+      if (tok.token_type == TK_COMMA) {
         expected = kId;
         continue;
       }
       return ErrorAtToken(tok, "')' or ',' expected");
     }
     if (expected == kType) {
-      if (tok.token_type != SqliteTokenType::TK_ID) {
+      if (tok.token_type != TK_ID) {
         // TODO(lalitm): add a link to documentation.
         base::StackString<1024> err("%.*s is not a valid argument type",
                                     static_cast<int>(tok.str.size()),
@@ -597,11 +575,11 @@
     }
 
     // kIdOrRp only happens on the very first token.
-    if (tok.token_type == SqliteTokenType::TK_RP && expected == kIdOrRp) {
+    if (tok.token_type == TK_RP && expected == kIdOrRp) {
       return true;
     }
 
-    if (tok.token_type != SqliteTokenType::TK_ID) {
+    if (tok.token_type != TK_ID && tok.token_type != TK_KEY) {
       // TODO(lalitm): add a link to documentation.
       base::StackString<1024> err("%.*s is not a valid argument name",
                                   static_cast<int>(tok.str.size()),
diff --git a/src/trace_processor/perfetto_sql/preprocessor/perfetto_sql_preprocessor.cc b/src/trace_processor/perfetto_sql/preprocessor/perfetto_sql_preprocessor.cc
index 510cb00..2ae8a8e 100644
--- a/src/trace_processor/perfetto_sql/preprocessor/perfetto_sql_preprocessor.cc
+++ b/src/trace_processor/perfetto_sql/preprocessor/perfetto_sql_preprocessor.cc
@@ -138,7 +138,7 @@
 SqliteTokenizer::Token GrammarTokenToTokenizerToken(
     const PreprocessorGrammarToken& token) {
   return SqliteTokenizer::Token{std::string_view(token.ptr, token.n),
-                                SqliteTokenType::TK_ILLEGAL};
+                                TK_ILLEGAL};
 }
 
 base::Status ErrorAtToken(const SqliteTokenizer& tokenizer,
@@ -454,13 +454,13 @@
 
   // Skip through any number of semi-colons (representing empty statements).
   SqliteTokenizer::Token tok = global_tokenizer_.NextNonWhitespace();
-  while (tok.token_type == SqliteTokenType::TK_SEMI) {
+  while (tok.token_type == TK_SEMI) {
     tok = global_tokenizer_.NextNonWhitespace();
   }
 
   // If we still see a terminal token at this point, we must have hit EOF.
   if (tok.IsTerminal()) {
-    PERFETTO_DCHECK(tok.token_type != SqliteTokenType::TK_SEMI);
+    PERFETTO_DCHECK(tok.token_type != TK_SEMI);
     return false;
   }
 
@@ -477,25 +477,25 @@
     if (t.str.empty()) {
       token_type = frame->seen_semicolon ? 0 : PPTK_SEMI;
       frame->seen_semicolon = true;
-    } else if (t.token_type == SqliteTokenType::TK_SEMI) {
+    } else if (t.token_type == TK_SEMI) {
       token_type = PPTK_SEMI;
       frame->seen_semicolon = true;
-    } else if (t.token_type == SqliteTokenType::TK_ILLEGAL) {
+    } else if (t.token_type == TK_ILLEGAL) {
       if (t.str.size() == 1 && t.str[0] == '!') {
         token_type = PPTK_EXCLAIM;
       } else {
         status_ = ErrorAtToken(tk, t, "illegal token");
         return false;
       }
-    } else if (t.token_type == SqliteTokenType::TK_ID) {
+    } else if (t.token_type == TK_ID) {
       token_type = PPTK_ID;
-    } else if (t.token_type == SqliteTokenType::TK_LP) {
+    } else if (t.token_type == TK_LP) {
       token_type = PPTK_LP;
-    } else if (t.token_type == SqliteTokenType::TK_RP) {
+    } else if (t.token_type == TK_RP) {
       token_type = PPTK_RP;
-    } else if (t.token_type == SqliteTokenType::TK_COMMA) {
+    } else if (t.token_type == TK_COMMA) {
       token_type = PPTK_COMMA;
-    } else if (t.token_type == SqliteTokenType::TK_VARIABLE) {
+    } else if (t.token_type == TK_VARIABLE) {
       token_type = PPTK_VARIABLE;
     } else {
       token_type = PPTK_OPAQUE;
diff --git a/src/trace_processor/perfetto_sql/tokenizer/BUILD.gn b/src/trace_processor/perfetto_sql/tokenizer/BUILD.gn
index 1fbbd8f..53b034e 100644
--- a/src/trace_processor/perfetto_sql/tokenizer/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/tokenizer/BUILD.gn
@@ -22,13 +22,35 @@
     "sqlite_tokenizer.h",
   ]
   deps = [
+    ":tokenize_internal",
     "../../../../gn:default_deps",
     "../../../../gn:sqlite",
     "../../../base",
     "../../sqlite",
+    "../grammar",
   ]
 }
 
+source_set("tokenize_internal") {
+  sources = [
+    "tokenize_internal.c",
+    "tokenize_internal_helper.h",
+  ]
+  deps = [
+    "../../../../gn:default_deps",
+    "../grammar",
+  ]
+  visibility = [ ":tokenizer" ]
+  if (perfetto_build_standalone) {
+    configs -= [ "//gn/standalone:extra_warnings" ]  # nogncheck
+  } else {
+    cflags_c = [
+      "-Wno-unused-parameter",
+      "-Wno-unreachable-code",
+    ]
+  }
+}
+
 perfetto_unittest_source_set("unittests") {
   testonly = true
   sources = [ "sqlite_tokenizer_unittest.cc" ]
diff --git a/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.cc b/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.cc
index fb1b3f2..4929026 100644
--- a/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.cc
+++ b/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.cc
@@ -16,425 +16,27 @@
 
 #include "src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.h"
 
-#include <ctype.h>
-#include <sqlite3.h>
 #include <cstdint>
-#include <optional>
+#include <string>
 #include <string_view>
+#include <utility>
 
-#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
+#include "src/trace_processor/sqlite/sql_source.h"
 
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
+extern "C" {
 
-// The contents of this file are ~copied from SQLite with some modifications to
-// minimize the amount copied: i.e. if we can call a libc function/public SQLite
-// API instead of a private one.
-//
-// The changes are as follows:
-// 1. Remove all ifdefs to only keep branches we actually use
-// 2. Change handling of |CC_KYWD0| to remove distinction between different
-//    SQLite kewords, reducing how many things we need to copy over.
-// 3. Constants are changed from be macro defines to be values in
-//    |SqliteTokenType|.
-
-namespace {
-
-const unsigned char sqlite3CtypeMap[256] = {
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07    ........ */
-    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f    ........ */
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17    ........ */
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f    ........ */
-    0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27     !"#$%&' */
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f    ()*+,-./ */
-    0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37    01234567 */
-    0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f    89:;<=>? */
-
-    0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47    @ABCDEFG */
-    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f    HIJKLMNO */
-    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57    PQRSTUVW */
-    0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f    XYZ[\]^_ */
-    0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67    `abcdefg */
-    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f    hijklmno */
-    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77    pqrstuvw */
-    0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f    xyz{|}~. */
-
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf    ........ */
-
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7    ........ */
-    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40  /* f8..ff    ........ */
-};
-
-#define CC_X 0        /* The letter 'x', or start of BLOB literal */
-#define CC_KYWD0 1    /* First letter of a keyword */
-#define CC_KYWD 2     /* Alphabetics or '_'.  Usable in a keyword */
-#define CC_DIGIT 3    /* Digits */
-#define CC_DOLLAR 4   /* '$' */
-#define CC_VARALPHA 5 /* '@', '#', ':'.  Alphabetic SQL variables */
-#define CC_VARNUM 6   /* '?'.  Numeric SQL variables */
-#define CC_SPACE 7    /* Space characters */
-#define CC_QUOTE 8    /* '"', '\'', or '`'.  String literals, quoted ids */
-#define CC_QUOTE2 9   /* '['.   [...] style quoted ids */
-#define CC_PIPE 10    /* '|'.   Bitwise OR or concatenate */
-#define CC_MINUS 11   /* '-'.  Minus or SQL-style comment */
-#define CC_LT 12      /* '<'.  Part of < or <= or <> */
-#define CC_GT 13      /* '>'.  Part of > or >= */
-#define CC_EQ 14      /* '='.  Part of = or == */
-#define CC_BANG 15    /* '!'.  Part of != */
-#define CC_SLASH 16   /* '/'.  / or c-style comment */
-#define CC_LP 17      /* '(' */
-#define CC_RP 18      /* ')' */
-#define CC_SEMI 19    /* ';' */
-#define CC_PLUS 20    /* '+' */
-#define CC_STAR 21    /* '*' */
-#define CC_PERCENT 22 /* '%' */
-#define CC_COMMA 23   /* ',' */
-#define CC_AND 24     /* '&' */
-#define CC_TILDA 25   /* '~' */
-#define CC_DOT 26     /* '.' */
-#define CC_ID 27      /* unicode characters usable in IDs */
-#define CC_NUL 29     /* 0x00 */
-#define CC_BOM 30     /* First byte of UTF8 BOM:  0xEF 0xBB 0xBF */
-
-// clang-format off
-static const unsigned char aiClass[] = {
-/*         x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf */
-/* 0x */   29, 28, 28, 28, 28, 28, 28, 28, 28,  7,  7, 28,  7,  7, 28, 28,
-/* 1x */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-/* 2x */    7, 15,  8,  5,  4, 22, 24,  8, 17, 18, 21, 20, 23, 11, 26, 16,
-/* 3x */    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  5, 19, 12, 14, 13,  6,
-/* 4x */    5,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-/* 5x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2,  9, 28, 28, 28,  2,
-/* 6x */    8,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-/* 7x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2, 28, 10, 28, 25, 28,
-/* 8x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 9x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* Ax */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* Bx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* Cx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* Dx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* Ex */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30,
-/* Fx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27
-};
-// clang-format on
-
-#define IdChar(C) ((sqlite3CtypeMap[static_cast<unsigned char>(C)] & 0x46) != 0)
-
-// Copy of |sqlite3GetToken| for use by the PerfettoSql transpiler.
-//
-// We copy this function because |sqlite3GetToken| is static to sqlite3.c
-// in most distributions of SQLite so we cannot call it from our code.
-//
-// While we could redefine SQLITE_PRIVATE, pragmatically that will not fly in
-// all the places we build trace processor so we need to resort to making a
-// copy.
-int GetSqliteToken(const unsigned char* z, SqliteTokenType* tokenType) {
-  int i, c;
-  switch (aiClass[*z]) { /* Switch on the character-class of the first byte
-                         ** of the token. See the comment on the CC_ defines
-                         ** above. */
-    case CC_SPACE: {
-      for (i = 1; isspace(z[i]); i++) {
-      }
-      *tokenType = SqliteTokenType::TK_SPACE;
-      return i;
-    }
-    case CC_MINUS: {
-      if (z[1] == '-') {
-        for (i = 2; (c = z[i]) != 0 && c != '\n'; i++) {
-        }
-        *tokenType = SqliteTokenType::TK_SPACE; /* IMP: R-22934-25134 */
-        return i;
-      } else if (z[1] == '>') {
-        *tokenType = SqliteTokenType::TK_PTR;
-        return 2 + (z[2] == '>');
-      }
-      *tokenType = SqliteTokenType::TK_MINUS;
-      return 1;
-    }
-    case CC_LP: {
-      *tokenType = SqliteTokenType::TK_LP;
-      return 1;
-    }
-    case CC_RP: {
-      *tokenType = SqliteTokenType::TK_RP;
-      return 1;
-    }
-    case CC_SEMI: {
-      *tokenType = SqliteTokenType::TK_SEMI;
-      return 1;
-    }
-    case CC_PLUS: {
-      *tokenType = SqliteTokenType::TK_PLUS;
-      return 1;
-    }
-    case CC_STAR: {
-      *tokenType = SqliteTokenType::TK_STAR;
-      return 1;
-    }
-    case CC_SLASH: {
-      if (z[1] != '*' || z[2] == 0) {
-        *tokenType = SqliteTokenType::TK_SLASH;
-        return 1;
-      }
-      for (i = 3, c = z[2]; (c != '*' || z[i] != '/') && (c = z[i]) != 0; i++) {
-      }
-      if (c)
-        i++;
-      *tokenType = SqliteTokenType::TK_SPACE; /* IMP: R-22934-25134 */
-      return i;
-    }
-    case CC_PERCENT: {
-      *tokenType = SqliteTokenType::TK_REM;
-      return 1;
-    }
-    case CC_EQ: {
-      *tokenType = SqliteTokenType::TK_EQ;
-      return 1 + (z[1] == '=');
-    }
-    case CC_LT: {
-      if ((c = z[1]) == '=') {
-        *tokenType = SqliteTokenType::TK_LE;
-        return 2;
-      } else if (c == '>') {
-        *tokenType = SqliteTokenType::TK_NE;
-        return 2;
-      } else if (c == '<') {
-        *tokenType = SqliteTokenType::TK_LSHIFT;
-        return 2;
-      } else {
-        *tokenType = SqliteTokenType::TK_LT;
-        return 1;
-      }
-    }
-    case CC_GT: {
-      if ((c = z[1]) == '=') {
-        *tokenType = SqliteTokenType::TK_GE;
-        return 2;
-      } else if (c == '>') {
-        *tokenType = SqliteTokenType::TK_RSHIFT;
-        return 2;
-      } else {
-        *tokenType = SqliteTokenType::TK_GT;
-        return 1;
-      }
-    }
-    case CC_BANG: {
-      if (z[1] != '=') {
-        *tokenType = SqliteTokenType::TK_ILLEGAL;
-        return 1;
-      } else {
-        *tokenType = SqliteTokenType::TK_NE;
-        return 2;
-      }
-    }
-    case CC_PIPE: {
-      if (z[1] != '|') {
-        *tokenType = SqliteTokenType::TK_BITOR;
-        return 1;
-      } else {
-        *tokenType = SqliteTokenType::TK_CONCAT;
-        return 2;
-      }
-    }
-    case CC_COMMA: {
-      *tokenType = SqliteTokenType::TK_COMMA;
-      return 1;
-    }
-    case CC_AND: {
-      *tokenType = SqliteTokenType::TK_BITAND;
-      return 1;
-    }
-    case CC_TILDA: {
-      *tokenType = SqliteTokenType::TK_BITNOT;
-      return 1;
-    }
-    case CC_QUOTE: {
-      int delim = z[0];
-      for (i = 1; (c = z[i]) != 0; i++) {
-        if (c == delim) {
-          if (z[i + 1] == delim) {
-            i++;
-          } else {
-            break;
-          }
-        }
-      }
-      if (c == '\'') {
-        *tokenType = SqliteTokenType::TK_STRING;
-        return i + 1;
-      } else if (c != 0) {
-        *tokenType = SqliteTokenType::TK_ID;
-        return i + 1;
-      } else {
-        *tokenType = SqliteTokenType::TK_ILLEGAL;
-        return i;
-      }
-    }
-    case CC_DOT: {
-      if (!isdigit(z[1])) {
-        *tokenType = SqliteTokenType::TK_DOT;
-        return 1;
-      }
-      [[fallthrough]];
-    }
-    case CC_DIGIT: {
-      *tokenType = SqliteTokenType::TK_INTEGER;
-      if (z[0] == '0' && (z[1] == 'x' || z[1] == 'X') && isxdigit(z[2])) {
-        for (i = 3; isxdigit(z[i]); i++) {
-        }
-        return i;
-      }
-      for (i = 0; isxdigit(z[i]); i++) {
-      }
-      if (z[i] == '.') {
-        i++;
-        while (isxdigit(z[i])) {
-          i++;
-        }
-        *tokenType = SqliteTokenType::TK_FLOAT;
-      }
-      if ((z[i] == 'e' || z[i] == 'E') &&
-          (isdigit(z[i + 1]) ||
-           ((z[i + 1] == '+' || z[i + 1] == '-') && isdigit(z[i + 2])))) {
-        i += 2;
-        while (isdigit(z[i])) {
-          i++;
-        }
-        *tokenType = SqliteTokenType::TK_FLOAT;
-      }
-      while (IdChar(z[i])) {
-        *tokenType = SqliteTokenType::TK_ILLEGAL;
-        i++;
-      }
-      return i;
-    }
-    case CC_QUOTE2: {
-      for (i = 1, c = z[0]; c != ']' && (c = z[i]) != 0; i++) {
-      }
-      *tokenType =
-          c == ']' ? SqliteTokenType::TK_ID : SqliteTokenType::TK_ILLEGAL;
-      return i;
-    }
-    case CC_VARNUM: {
-      *tokenType = SqliteTokenType::TK_VARIABLE;
-      for (i = 1; isdigit(z[i]); i++) {
-      }
-      return i;
-    }
-    case CC_DOLLAR:
-    case CC_VARALPHA: {
-      int n = 0;
-      *tokenType = SqliteTokenType::TK_VARIABLE;
-      for (i = 1; (c = z[i]) != 0; i++) {
-        if (IdChar(c)) {
-          n++;
-        } else if (c == '(' && n > 0) {
-          do {
-            i++;
-          } while ((c = z[i]) != 0 && !isspace(c) && c != ')');
-          if (c == ')') {
-            i++;
-          } else {
-            *tokenType = SqliteTokenType::TK_ILLEGAL;
-          }
-          break;
-        } else if (c == ':' && z[i + 1] == ':') {
-          i++;
-        } else {
-          break;
-        }
-      }
-      if (n == 0)
-        *tokenType = SqliteTokenType::TK_ILLEGAL;
-      return i;
-    }
-    case CC_KYWD0: {
-      for (i = 1; aiClass[z[i]] <= CC_KYWD; i++) {
-      }
-      if (IdChar(z[i])) {
-        /* This token started out using characters that can appear in keywords,
-        ** but z[i] is a character not allowed within keywords, so this must
-        ** be an identifier instead */
-        i++;
-        break;
-      }
-      if (sqlite3_keyword_check(reinterpret_cast<const char*>(z), i)) {
-        *tokenType = SqliteTokenType::TK_GENERIC_KEYWORD;
-      } else {
-        *tokenType = SqliteTokenType::TK_ID;
-      }
-      return i;
-    }
-    case CC_X: {
-      if (z[1] == '\'') {
-        *tokenType = SqliteTokenType::TK_BLOB;
-        for (i = 2; isxdigit(z[i]); i++) {
-        }
-        if (z[i] != '\'' || i % 2) {
-          *tokenType = SqliteTokenType::TK_ILLEGAL;
-          while (z[i] && z[i] != '\'') {
-            i++;
-          }
-        }
-        if (z[i])
-          i++;
-        return i;
-      }
-      [[fallthrough]];
-    }
-    case CC_KYWD:
-    case CC_ID: {
-      i = 1;
-      break;
-    }
-    case CC_BOM: {
-      if (z[1] == 0xbb && z[2] == 0xbf) {
-        *tokenType = SqliteTokenType::TK_SPACE;
-        return 3;
-      }
-      i = 1;
-      break;
-    }
-    case CC_NUL: {
-      *tokenType = SqliteTokenType::TK_ILLEGAL;
-      return 0;
-    }
-    default: {
-      *tokenType = SqliteTokenType::TK_ILLEGAL;
-      return 1;
-    }
-  }
-  while (IdChar(z[i])) {
-    i++;
-  }
-  *tokenType = SqliteTokenType::TK_ID;
-  return i;
+int sqlite3GetToken(const unsigned char* z, int* tokenType);
 }
 
-}  // namespace
-
 SqliteTokenizer::SqliteTokenizer(SqlSource sql) : source_(std::move(sql)) {}
 
 SqliteTokenizer::Token SqliteTokenizer::Next() {
   Token token;
   const char* start = source_.sql().data() + offset_;
-  int n = GetSqliteToken(reinterpret_cast<const unsigned char*>(start),
-                         &token.token_type);
+  int n = sqlite3GetToken(reinterpret_cast<const unsigned char*>(start),
+                          &token.token_type);
   offset_ += static_cast<uint32_t>(n);
   token.str = std::string_view(start, static_cast<uint32_t>(n));
   return token;
@@ -442,7 +44,7 @@
 
 SqliteTokenizer::Token SqliteTokenizer::NextNonWhitespace() {
   Token t;
-  for (t = Next(); t.token_type == SqliteTokenType::TK_SPACE; t = Next()) {
+  for (t = Next(); t.token_type == TK_SPACE; t = Next()) {
   }
   return t;
 }
@@ -458,19 +60,17 @@
 SqlSource SqliteTokenizer::Substr(const Token& start,
                                   const Token& end,
                                   EndToken end_token) const {
-  uint32_t offset =
-      static_cast<uint32_t>(start.str.data() - source_.sql().c_str());
+  auto offset = static_cast<uint32_t>(start.str.data() - source_.sql().c_str());
   const char* e =
       end.str.data() +
       (end_token == SqliteTokenizer::EndToken::kInclusive ? end.str.size() : 0);
-  uint32_t len = static_cast<uint32_t>(e - start.str.data());
+  auto len = static_cast<uint32_t>(e - start.str.data());
   return source_.Substr(offset, len);
 }
 
 SqlSource SqliteTokenizer::SubstrToken(const Token& token) const {
-  uint32_t offset =
-      static_cast<uint32_t>(token.str.data() - source_.sql().c_str());
-  uint32_t len = static_cast<uint32_t>(token.str.size());
+  auto offset = static_cast<uint32_t>(token.str.data() - source_.sql().c_str());
+  auto len = static_cast<uint32_t>(token.str.size());
   return source_.Substr(offset, len);
 }
 
@@ -478,8 +78,7 @@
   PERFETTO_CHECK(source_.sql().c_str() <= token.str.data());
   PERFETTO_CHECK(token.str.data() <=
                  source_.sql().c_str() + source_.sql().size());
-  uint32_t offset =
-      static_cast<uint32_t>(token.str.data() - source_.sql().c_str());
+  auto offset = static_cast<uint32_t>(token.str.data() - source_.sql().c_str());
   return source_.AsTraceback(offset);
 }
 
@@ -488,10 +87,8 @@
                               const Token& end,
                               SqlSource rewrite,
                               EndToken end_token) const {
-  uint32_t s_off =
-      static_cast<uint32_t>(start.str.data() - source_.sql().c_str());
-  uint32_t e_off =
-      static_cast<uint32_t>(end.str.data() - source_.sql().c_str());
+  auto s_off = static_cast<uint32_t>(start.str.data() - source_.sql().c_str());
+  auto e_off = static_cast<uint32_t>(end.str.data() - source_.sql().c_str());
   uint32_t e_diff = end_token == EndToken::kInclusive
                         ? static_cast<uint32_t>(end.str.size())
                         : 0;
@@ -501,12 +98,10 @@
 void SqliteTokenizer::RewriteToken(SqlSource::Rewriter& rewriter,
                                    const Token& token,
                                    SqlSource rewrite) const {
-  uint32_t s_off =
-      static_cast<uint32_t>(token.str.data() - source_.sql().c_str());
-  uint32_t e_off = static_cast<uint32_t>(token.str.data() + token.str.size() -
-                                         source_.sql().c_str());
+  auto s_off = static_cast<uint32_t>(token.str.data() - source_.sql().c_str());
+  auto e_off = static_cast<uint32_t>(token.str.data() + token.str.size() -
+                                     source_.sql().c_str());
   rewriter.Rewrite(s_off, e_off, std::move(rewrite));
 }
 
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.h b/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.h
index 64019fb..809092b 100644
--- a/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.h
+++ b/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.h
@@ -17,52 +17,14 @@
 #ifndef SRC_TRACE_PROCESSOR_PERFETTO_SQL_TOKENIZER_SQLITE_TOKENIZER_H_
 #define SRC_TRACE_PROCESSOR_PERFETTO_SQL_TOKENIZER_SQLITE_TOKENIZER_H_
 
-#include <optional>
+#include <cstdint>
 #include <string_view>
+#include <utility>
+
+#include "src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.h"
 #include "src/trace_processor/sqlite/sql_source.h"
 
-namespace perfetto {
-namespace trace_processor {
-
-// List of token types returnable by |SqliteTokenizer|
-// 1:1 matches the defintions in SQLite.
-enum class SqliteTokenType : uint32_t {
-  TK_SEMI = 1,
-  TK_LP = 22,
-  TK_RP = 23,
-  TK_COMMA = 25,
-  TK_NE = 52,
-  TK_EQ = 53,
-  TK_GT = 54,
-  TK_LE = 55,
-  TK_LT = 56,
-  TK_GE = 57,
-  TK_ID = 59,
-  TK_BITAND = 102,
-  TK_BITOR = 103,
-  TK_LSHIFT = 104,
-  TK_RSHIFT = 105,
-  TK_PLUS = 106,
-  TK_MINUS = 107,
-  TK_STAR = 108,
-  TK_SLASH = 109,
-  TK_REM = 110,
-  TK_CONCAT = 111,
-  TK_PTR = 112,
-  TK_BITNOT = 114,
-  TK_STRING = 117,
-  TK_DOT = 141,
-  TK_FLOAT = 153,
-  TK_BLOB = 154,
-  TK_INTEGER = 155,
-  TK_VARIABLE = 156,
-  TK_SPACE = 183,
-  TK_ILLEGAL = 184,
-
-  // Generic constant which replaces all the keywords in SQLite as we do not
-  // care about the distinguishing between the vast majority of them.
-  TK_GENERIC_KEYWORD = 1000,
-};
+namespace perfetto::trace_processor {
 
 // Tokenizes SQL statements according to SQLite SQL language specification:
 // https://www2.sqlite.org/hlr40000.html
@@ -80,16 +42,14 @@
     std::string_view str;
 
     // The type of the token.
-    SqliteTokenType token_type = SqliteTokenType::TK_ILLEGAL;
+    int token_type = TK_ILLEGAL;
 
     bool operator==(const Token& o) const {
       return str == o.str && token_type == o.token_type;
     }
 
     // Returns if the token is empty or semicolon.
-    bool IsTerminal() {
-      return token_type == SqliteTokenType::TK_SEMI || str.empty();
-    }
+    bool IsTerminal() const { return token_type == TK_SEMI || str.empty(); }
   };
 
   enum class EndToken {
@@ -100,6 +60,12 @@
   // Creates a tokenizer which tokenizes |sql|.
   explicit SqliteTokenizer(SqlSource sql);
 
+  SqliteTokenizer(const SqliteTokenizer&) = delete;
+  SqliteTokenizer& operator=(const SqliteTokenizer&) = delete;
+
+  SqliteTokenizer(SqliteTokenizer&&) = delete;
+  SqliteTokenizer& operator=(SqliteTokenizer&&) = delete;
+
   // Returns the next SQL token.
   Token Next();
 
@@ -153,17 +119,10 @@
   }
 
  private:
-  SqliteTokenizer(const SqliteTokenizer&) = delete;
-  SqliteTokenizer& operator=(const SqliteTokenizer&) = delete;
-
-  SqliteTokenizer(SqliteTokenizer&&) = delete;
-  SqliteTokenizer& operator=(SqliteTokenizer&&) = delete;
-
   SqlSource source_;
   uint32_t offset_ = 0;
 };
 
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
 
 #endif  // SRC_TRACE_PROCESSOR_PERFETTO_SQL_TOKENIZER_SQLITE_TOKENIZER_H_
diff --git a/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer_unittest.cc b/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer_unittest.cc
index 9fc950b..ba46d03 100644
--- a/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer_unittest.cc
+++ b/src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer_unittest.cc
@@ -15,18 +15,16 @@
  */
 
 #include "src/trace_processor/perfetto_sql/tokenizer/sqlite_tokenizer.h"
+
 #include <vector>
 
-#include "perfetto/base/logging.h"
 #include "src/trace_processor/sqlite/sql_source.h"
 #include "test/gtest_and_gmock.h"
 
-namespace perfetto {
-namespace trace_processor {
+namespace perfetto::trace_processor {
 namespace {
 
 using Token = SqliteTokenizer::Token;
-using Type = SqliteTokenType;
 
 class SqliteTokenizerTest : public ::testing::Test {
  protected:
@@ -47,30 +45,29 @@
 }
 
 TEST_F(SqliteTokenizerTest, OnlySpace) {
-  ASSERT_THAT(Tokenize(" "), testing::ElementsAre(Token{" ", Type::TK_SPACE}));
+  ASSERT_THAT(Tokenize(" "), testing::ElementsAre(Token{" ", TK_SPACE}));
 }
 
 TEST_F(SqliteTokenizerTest, SpaceColon) {
-  ASSERT_THAT(Tokenize(" ;"), testing::ElementsAre(Token{" ", Type::TK_SPACE},
-                                                   Token{";", Type::TK_SEMI}));
+  ASSERT_THAT(Tokenize(" ;"),
+              testing::ElementsAre(Token{" ", TK_SPACE}, Token{";", TK_SEMI}));
 }
 
 TEST_F(SqliteTokenizerTest, Select) {
   ASSERT_THAT(
       Tokenize("SELECT * FROM slice;"),
-      testing::ElementsAre(
-          Token{"SELECT", Type::TK_GENERIC_KEYWORD}, Token{" ", Type::TK_SPACE},
-          Token{"*", Type::TK_STAR}, Token{" ", Type::TK_SPACE},
-          Token{"FROM", Type::TK_GENERIC_KEYWORD}, Token{" ", Type::TK_SPACE},
-          Token{"slice", Type::TK_ID}, Token{";", Type::TK_SEMI}));
+      testing::ElementsAre(Token{"SELECT", TK_SELECT}, Token{" ", TK_SPACE},
+                           Token{"*", TK_STAR}, Token{" ", TK_SPACE},
+                           Token{"FROM", TK_FROM}, Token{" ", TK_SPACE},
+                           Token{"slice", TK_ID}, Token{";", TK_SEMI}));
 }
 
 TEST_F(SqliteTokenizerTest, PastEndErrorToken) {
   tokenizer_.Reset(SqlSource::FromTraceProcessorImplementation("S"));
-  ASSERT_EQ(tokenizer_.Next(), (Token{"S", Type::TK_ID}));
+  ASSERT_EQ(tokenizer_.Next(), (Token{"S", TK_ID}));
 
   auto end_token = tokenizer_.Next();
-  ASSERT_EQ(end_token, (Token{"", Type::TK_ILLEGAL}));
+  ASSERT_EQ(end_token, (Token{"", TK_ILLEGAL}));
   ASSERT_EQ(tokenizer_.AsTraceback(end_token),
             "  Trace Processor Internal line 1 col 2\n"
             "    S\n"
@@ -78,5 +75,4 @@
 }
 
 }  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
+}  // namespace perfetto::trace_processor
diff --git a/src/trace_processor/perfetto_sql/tokenizer/tokenize_internal.c b/src/trace_processor/perfetto_sql/tokenizer/tokenize_internal.c
new file mode 100644
index 0000000..be5eabf
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/tokenizer/tokenize_internal.c
@@ -0,0 +1,563 @@
+/*
+** 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.
+**
+*************************************************************************
+** An tokenizer for SQL
+**
+** This file contains C code that splits an SQL input string up into
+** individual tokens and sends those tokens one-by-one over to the
+** parser for analysis.
+*/
+#include "src/trace_processor/perfetto_sql/tokenizer/tokenize_internal_helper.h"
+#include <stdlib.h>
+
+/* Character classes for tokenizing
+**
+** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented
+** using a lookup table, whereas a switch() directly on c uses a binary search.
+** The lookup table is much faster.  To maximize speed, and to ensure that
+** a lookup table is used, all of the classes need to be small integers and
+** all of them need to be used within the switch.
+*/
+#define CC_X          0    /* The letter 'x', or start of BLOB literal */
+#define CC_KYWD0      1    /* First letter of a keyword */
+#define CC_KYWD       2    /* Alphabetics or '_'.  Usable in a keyword */
+#define CC_DIGIT      3    /* Digits */
+#define CC_DOLLAR     4    /* '$' */
+#define CC_VARALPHA   5    /* '@', '#', ':'.  Alphabetic SQL variables */
+#define CC_VARNUM     6    /* '?'.  Numeric SQL variables */
+#define CC_SPACE      7    /* Space characters */
+#define CC_QUOTE      8    /* '"', '\'', or '`'.  String literals, quoted ids */
+#define CC_QUOTE2     9    /* '['.   [...] style quoted ids */
+#define CC_PIPE      10    /* '|'.   Bitwise OR or concatenate */
+#define CC_MINUS     11    /* '-'.  Minus or SQL-style comment */
+#define CC_LT        12    /* '<'.  Part of < or <= or <> */
+#define CC_GT        13    /* '>'.  Part of > or >= */
+#define CC_EQ        14    /* '='.  Part of = or == */
+#define CC_BANG      15    /* '!'.  Part of != */
+#define CC_SLASH     16    /* '/'.  / or c-style comment */
+#define CC_LP        17    /* '(' */
+#define CC_RP        18    /* ')' */
+#define CC_SEMI      19    /* ';' */
+#define CC_PLUS      20    /* '+' */
+#define CC_STAR      21    /* '*' */
+#define CC_PERCENT   22    /* '%' */
+#define CC_COMMA     23    /* ',' */
+#define CC_AND       24    /* '&' */
+#define CC_TILDA     25    /* '~' */
+#define CC_DOT       26    /* '.' */
+#define CC_ID        27    /* unicode characters usable in IDs */
+#define CC_ILLEGAL   28    /* Illegal character */
+#define CC_NUL       29    /* 0x00 */
+#define CC_BOM       30    /* First byte of UTF8 BOM:  0xEF 0xBB 0xBF */
+
+static const unsigned char aiClass[] = {
+#ifdef SQLITE_ASCII
+/*         x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf */
+/* 0x */   29, 28, 28, 28, 28, 28, 28, 28, 28,  7,  7, 28,  7,  7, 28, 28,
+/* 1x */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 2x */    7, 15,  8,  5,  4, 22, 24,  8, 17, 18, 21, 20, 23, 11, 26, 16,
+/* 3x */    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  5, 19, 12, 14, 13,  6,
+/* 4x */    5,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+/* 5x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2,  9, 28, 28, 28,  2,
+/* 6x */    8,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+/* 7x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2, 28, 10, 28, 25, 28,
+/* 8x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* 9x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Ax */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Bx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Cx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Dx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Ex */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30,
+/* Fx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27
+#endif
+#ifdef SQLITE_EBCDIC
+/*         x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf */
+/* 0x */   29, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28,  7,  7, 28, 28,
+/* 1x */   28, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 2x */   28, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 3x */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 4x */    7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 12, 17, 20, 10,
+/* 5x */   24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 15,  4, 21, 18, 19, 28,
+/* 6x */   11, 16, 28, 28, 28, 28, 28, 28, 28, 28, 28, 23, 22,  2, 13,  6,
+/* 7x */   28, 28, 28, 28, 28, 28, 28, 28, 28,  8,  5,  5,  5,  8, 14,  8,
+/* 8x */   28,  1,  1,  1,  1,  1,  1,  1,  1,  1, 28, 28, 28, 28, 28, 28,
+/* 9x */   28,  1,  1,  1,  1,  1,  1,  1,  1,  1, 28, 28, 28, 28, 28, 28,
+/* Ax */   28, 25,  1,  1,  1,  1,  1,  0,  2,  2, 28, 28, 28, 28, 28, 28,
+/* Bx */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28,  9, 28, 28, 28, 28, 28,
+/* Cx */   28,  1,  1,  1,  1,  1,  1,  1,  1,  1, 28, 28, 28, 28, 28, 28,
+/* Dx */   28,  1,  1,  1,  1,  1,  1,  1,  1,  1, 28, 28, 28, 28, 28, 28,
+/* Ex */   28, 28,  1,  1,  1,  1,  1,  0,  2,  2, 28, 28, 28, 28, 28, 28,
+/* Fx */    3,  3,  3,  3,  3,  3,  3,  3,  3,  3, 28, 28, 28, 28, 28, 28,
+#endif
+};
+
+/*
+** The charMap() macro maps alphabetic characters (only) into their
+** lower-case ASCII equivalent.  On ASCII machines, this is just
+** an upper-to-lower case map.  On EBCDIC machines we also need
+** to adjust the encoding.  The mapping is only valid for alphabetics
+** which are the only characters for which this feature is used. 
+**
+** Used by keywordhash.h
+*/
+#ifdef SQLITE_ASCII
+# define charMap(X) sqlite3UpperToLower[(unsigned char)X]
+#endif
+#ifdef SQLITE_EBCDIC
+# define charMap(X) ebcdicToAscii[(unsigned char)X]
+const unsigned char ebcdicToAscii[] = {
+/* 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 0x */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 1x */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 2x */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 3x */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 4x */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 5x */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 95,  0,  0,  /* 6x */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 7x */
+   0, 97, 98, 99,100,101,102,103,104,105,  0,  0,  0,  0,  0,  0,  /* 8x */
+   0,106,107,108,109,110,111,112,113,114,  0,  0,  0,  0,  0,  0,  /* 9x */
+   0,  0,115,116,117,118,119,120,121,122,  0,  0,  0,  0,  0,  0,  /* Ax */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* Bx */
+   0, 97, 98, 99,100,101,102,103,104,105,  0,  0,  0,  0,  0,  0,  /* Cx */
+   0,106,107,108,109,110,111,112,113,114,  0,  0,  0,  0,  0,  0,  /* Dx */
+   0,  0,115,116,117,118,119,120,121,122,  0,  0,  0,  0,  0,  0,  /* Ex */
+   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* Fx */
+};
+#endif
+
+/*
+** The sqlite3KeywordCode function looks up an identifier to determine if
+** it is a keyword.  If it is a keyword, the token code of that keyword is 
+** returned.  If the input is not a keyword, TK_ID is returned.
+**
+** The implementation of this routine was generated by a program,
+** mkkeywordhash.c, located in the tool subdirectory of the distribution.
+** The output of the mkkeywordhash.c program is written into a file
+** named keywordhash.h and then included into this source file by
+** the #include below.
+*/
+
+
+/*
+** If X is a character that can be used in an identifier then
+** IdChar(X) will be true.  Otherwise it is false.
+**
+** For ASCII, any character with the high-order bit set is
+** allowed in an identifier.  For 7-bit characters, 
+** sqlite3IsIdChar[X] must be 1.
+**
+** For EBCDIC, the rules are more complex but have the same
+** end result.
+**
+** Ticket #1066.  the SQL standard does not allow '$' in the
+** middle of identifiers.  But many SQL implementations do. 
+** SQLite will allow '$' in identifiers for compatibility.
+** But the feature is undocumented.
+*/
+#ifdef SQLITE_ASCII
+#define IdChar(C)  ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0)
+#endif
+#ifdef SQLITE_EBCDIC
+const char sqlite3IsEbcdicIdChar[] = {
+/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 4x */
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0,  /* 5x */
+    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,  /* 6x */
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,  /* 7x */
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0,  /* 8x */
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0,  /* 9x */
+    1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,  /* Ax */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* Bx */
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,  /* Cx */
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,  /* Dx */
+    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,  /* Ex */
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0,  /* Fx */
+};
+#define IdChar(C)  (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
+#endif
+
+/* Make the IdChar function accessible from ctime.c and alter.c */
+int sqlite3IsIdChar(u8 c){ return IdChar(c); }
+
+#ifndef SQLITE_OMIT_WINDOWFUNC
+/*
+** Return the id of the next token in string (*pz). Before returning, set
+** (*pz) to point to the byte following the parsed token.
+*/
+static int getToken(const unsigned char **pz){
+  const unsigned char *z = *pz;
+  int t;                          /* Token type to return */
+  do {
+    z += sqlite3GetToken(z, &t);
+  }while( t==TK_SPACE );
+  if( t==TK_ID 
+   || t==TK_STRING 
+   || t==TK_JOIN_KW 
+   || t==TK_WINDOW 
+   || t==TK_OVER 
+   || sqlite3ParserFallback(t)==TK_ID 
+  ){
+    t = TK_ID;
+  }
+  *pz = z;
+  return t;
+}
+
+/*
+** The following three functions are called immediately after the tokenizer
+** reads the keywords WINDOW, OVER and FILTER, respectively, to determine
+** whether the token should be treated as a keyword or an SQL identifier.
+** This cannot be handled by the usual lemon %fallback method, due to
+** the ambiguity in some constructions. e.g.
+**
+**   SELECT sum(x) OVER ...
+**
+** In the above, "OVER" might be a keyword, or it might be an alias for the 
+** sum(x) expression. If a "%fallback ID OVER" directive were added to 
+** grammar, then SQLite would always treat "OVER" as an alias, making it
+** impossible to call a window-function without a FILTER clause.
+**
+** WINDOW is treated as a keyword if:
+**
+**   * the following token is an identifier, or a keyword that can fallback
+**     to being an identifier, and
+**   * the token after than one is TK_AS.
+**
+** OVER is a keyword if:
+**
+**   * the previous token was TK_RP, and
+**   * the next token is either TK_LP or an identifier.
+**
+** FILTER is a keyword if:
+**
+**   * the previous token was TK_RP, and
+**   * the next token is TK_LP.
+*/
+static int analyzeWindowKeyword(const unsigned char *z){
+  int t;
+  t = getToken(&z);
+  if( t!=TK_ID ) return TK_ID;
+  t = getToken(&z);
+  if( t!=TK_AS ) return TK_ID;
+  return TK_WINDOW;
+}
+static int analyzeOverKeyword(const unsigned char *z, int lastToken){
+  if( lastToken==TK_RP ){
+    int t = getToken(&z);
+    if( t==TK_LP || t==TK_ID ) return TK_OVER;
+  }
+  return TK_ID;
+}
+static int analyzeFilterKeyword(const unsigned char *z, int lastToken){
+  if( lastToken==TK_RP && getToken(&z)==TK_LP ){
+    return TK_FILTER;
+  }
+  return TK_ID;
+}
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+
+/*
+** Return the length (in bytes) of the token that begins at z[0]. 
+** Store the token type in *tokenType before returning.
+*/
+int sqlite3GetToken(const unsigned char *z, int *tokenType){
+  int i, c;
+  switch( aiClass[*z] ){  /* Switch on the character-class of the first byte
+                          ** of the token. See the comment on the CC_ defines
+                          ** above. */
+    case CC_SPACE: {
+      testcase( z[0]==' ' );
+      testcase( z[0]=='\t' );
+      testcase( z[0]=='\n' );
+      testcase( z[0]=='\f' );
+      testcase( z[0]=='\r' );
+      for(i=1; sqlite3Isspace(z[i]); i++){}
+      *tokenType = TK_SPACE;
+      return i;
+    }
+    case CC_MINUS: {
+      if( z[1]=='-' ){
+        for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
+        *tokenType = TK_SPACE;   /* IMP: R-22934-25134 */
+        return i;
+      }else if( z[1]=='>' ){
+        *tokenType = TK_PTR;
+        return 2 + (z[2]=='>');
+      }
+      *tokenType = TK_MINUS;
+      return 1;
+    }
+    case CC_LP: {
+      *tokenType = TK_LP;
+      return 1;
+    }
+    case CC_RP: {
+      *tokenType = TK_RP;
+      return 1;
+    }
+    case CC_SEMI: {
+      *tokenType = TK_SEMI;
+      return 1;
+    }
+    case CC_PLUS: {
+      *tokenType = TK_PLUS;
+      return 1;
+    }
+    case CC_STAR: {
+      *tokenType = TK_STAR;
+      return 1;
+    }
+    case CC_SLASH: {
+      if( z[1]!='*' || z[2]==0 ){
+        *tokenType = TK_SLASH;
+        return 1;
+      }
+      for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
+      if( c ) i++;
+      *tokenType = TK_SPACE;   /* IMP: R-22934-25134 */
+      return i;
+    }
+    case CC_PERCENT: {
+      *tokenType = TK_REM;
+      return 1;
+    }
+    case CC_EQ: {
+      *tokenType = TK_EQ;
+      return 1 + (z[1]=='=');
+    }
+    case CC_LT: {
+      if( (c=z[1])=='=' ){
+        *tokenType = TK_LE;
+        return 2;
+      }else if( c=='>' ){
+        *tokenType = TK_NE;
+        return 2;
+      }else if( c=='<' ){
+        *tokenType = TK_LSHIFT;
+        return 2;
+      }else{
+        *tokenType = TK_LT;
+        return 1;
+      }
+    }
+    case CC_GT: {
+      if( (c=z[1])=='=' ){
+        *tokenType = TK_GE;
+        return 2;
+      }else if( c=='>' ){
+        *tokenType = TK_RSHIFT;
+        return 2;
+      }else{
+        *tokenType = TK_GT;
+        return 1;
+      }
+    }
+    case CC_BANG: {
+      if( z[1]!='=' ){
+        *tokenType = TK_ILLEGAL;
+        return 1;
+      }else{
+        *tokenType = TK_NE;
+        return 2;
+      }
+    }
+    case CC_PIPE: {
+      if( z[1]!='|' ){
+        *tokenType = TK_BITOR;
+        return 1;
+      }else{
+        *tokenType = TK_CONCAT;
+        return 2;
+      }
+    }
+    case CC_COMMA: {
+      *tokenType = TK_COMMA;
+      return 1;
+    }
+    case CC_AND: {
+      *tokenType = TK_BITAND;
+      return 1;
+    }
+    case CC_TILDA: {
+      *tokenType = TK_BITNOT;
+      return 1;
+    }
+    case CC_QUOTE: {
+      int delim = z[0];
+      testcase( delim=='`' );
+      testcase( delim=='\'' );
+      testcase( delim=='"' );
+      for(i=1; (c=z[i])!=0; i++){
+        if( c==delim ){
+          if( z[i+1]==delim ){
+            i++;
+          }else{
+            break;
+          }
+        }
+      }
+      if( c=='\'' ){
+        *tokenType = TK_STRING;
+        return i+1;
+      }else if( c!=0 ){
+        *tokenType = TK_ID;
+        return i+1;
+      }else{
+        *tokenType = TK_ILLEGAL;
+        return i;
+      }
+    }
+    case CC_DOT: {
+#ifndef SQLITE_OMIT_FLOATING_POINT
+      if( !sqlite3Isdigit(z[1]) )
+#endif
+      {
+        *tokenType = TK_DOT;
+        return 1;
+      }
+      /* If the next character is a digit, this is a floating point
+      ** number that begins with ".".  Fall thru into the next case */
+      /* no break */ deliberate_fall_through
+    }
+    case CC_DIGIT: {
+      testcase( z[0]=='0' );  testcase( z[0]=='1' );  testcase( z[0]=='2' );
+      testcase( z[0]=='3' );  testcase( z[0]=='4' );  testcase( z[0]=='5' );
+      testcase( z[0]=='6' );  testcase( z[0]=='7' );  testcase( z[0]=='8' );
+      testcase( z[0]=='9' );  testcase( z[0]=='.' );
+      *tokenType = TK_INTEGER;
+#ifndef SQLITE_OMIT_HEX_INTEGER
+      if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
+        for(i=3; sqlite3Isxdigit(z[i]); i++){}
+        return i;
+      }
+#endif
+      for(i=0; sqlite3Isdigit(z[i]); i++){}
+#ifndef SQLITE_OMIT_FLOATING_POINT
+      if( z[i]=='.' ){
+        i++;
+        while( sqlite3Isdigit(z[i]) ){ i++; }
+        *tokenType = TK_FLOAT;
+      }
+      if( (z[i]=='e' || z[i]=='E') &&
+           ( sqlite3Isdigit(z[i+1]) 
+            || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
+           )
+      ){
+        i += 2;
+        while( sqlite3Isdigit(z[i]) ){ i++; }
+        *tokenType = TK_FLOAT;
+      }
+#endif
+      while( IdChar(z[i]) ){
+        *tokenType = TK_ILLEGAL;
+        i++;
+      }
+      return i;
+    }
+    case CC_QUOTE2: {
+      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
+      *tokenType = c==']' ? TK_ID : TK_ILLEGAL;
+      return i;
+    }
+    case CC_VARNUM: {
+      *tokenType = TK_VARIABLE;
+      for(i=1; sqlite3Isdigit(z[i]); i++){}
+      return i;
+    }
+    case CC_DOLLAR:
+    case CC_VARALPHA: {
+      int n = 0;
+      testcase( z[0]=='$' );  testcase( z[0]=='@' );
+      testcase( z[0]==':' );  testcase( z[0]=='#' );
+      *tokenType = TK_VARIABLE;
+      for(i=1; (c=z[i])!=0; i++){
+        if( IdChar(c) ){
+          n++;
+#ifndef SQLITE_OMIT_TCL_VARIABLE
+        }else if( c=='(' && n>0 ){
+          do{
+            i++;
+          }while( (c=z[i])!=0 && !sqlite3Isspace(c) && c!=')' );
+          if( c==')' ){
+            i++;
+          }else{
+            *tokenType = TK_ILLEGAL;
+          }
+          break;
+        }else if( c==':' && z[i+1]==':' ){
+          i++;
+#endif
+        }else{
+          break;
+        }
+      }
+      if( n==0 ) *tokenType = TK_ILLEGAL;
+      return i;
+    }
+    case CC_KYWD0: {
+      if( aiClass[z[1]]>CC_KYWD ){ i = 1;  break; }
+      for(i=2; aiClass[z[i]]<=CC_KYWD; i++){}
+      if( IdChar(z[i]) ){
+        /* This token started out using characters that can appear in keywords,
+        ** but z[i] is a character not allowed within keywords, so this must
+        ** be an identifier instead */
+        i++;
+        break;
+      }
+      *tokenType = TK_ID;
+      return keywordCode((char*)z, i, tokenType);
+    }
+    case CC_X: {
+#ifndef SQLITE_OMIT_BLOB_LITERAL
+      testcase( z[0]=='x' ); testcase( z[0]=='X' );
+      if( z[1]=='\'' ){
+        *tokenType = TK_BLOB;
+        for(i=2; sqlite3Isxdigit(z[i]); i++){}
+        if( z[i]!='\'' || i%2 ){
+          *tokenType = TK_ILLEGAL;
+          while( z[i] && z[i]!='\'' ){ i++; }
+        }
+        if( z[i] ) i++;
+        return i;
+      }
+#endif
+      /* If it is not a BLOB literal, then it must be an ID, since no
+      ** SQL keywords start with the letter 'x'.  Fall through */
+      /* no break */ deliberate_fall_through
+    }
+    case CC_KYWD:
+    case CC_ID: {
+      i = 1;
+      break;
+    }
+    case CC_BOM: {
+      if( z[1]==0xbb && z[2]==0xbf ){
+        *tokenType = TK_SPACE;
+        return 3;
+      }
+      i = 1;
+      break;
+    }
+    case CC_NUL: {
+      *tokenType = TK_ILLEGAL;
+      return 0;
+    }
+    default: {
+      *tokenType = TK_ILLEGAL;
+      return 1;
+    }
+  }
+  while( IdChar(z[i]) ){ i++; }
+  *tokenType = TK_ID;
+  return i;
+}
+
diff --git a/src/trace_processor/perfetto_sql/tokenizer/tokenize_internal_helper.h b/src/trace_processor/perfetto_sql/tokenizer/tokenize_internal_helper.h
new file mode 100644
index 0000000..08cbc75
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/tokenizer/tokenize_internal_helper.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_PERFETTO_SQL_TOKENIZER_TOKENIZE_INTERNAL_HELPER_H_
+#define SRC_TRACE_PROCESSOR_PERFETTO_SQL_TOKENIZER_TOKENIZE_INTERNAL_HELPER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+
+#include "src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.h"
+#include "src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash.h"
+
+#define SQLITE_ASCII 1
+
+const unsigned char sqlite3CtypeMap[256] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07    ........ */
+    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f    ........ */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17    ........ */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f    ........ */
+    0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27     !"#$%&' */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f    ()*+,-./ */
+    0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37    01234567 */
+    0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f    89:;<=>? */
+
+    0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47    @ABCDEFG */
+    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f    HIJKLMNO */
+    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57    PQRSTUVW */
+    0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f    XYZ[\]^_ */
+    0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67    `abcdefg */
+    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f    hijklmno */
+    0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77    pqrstuvw */
+    0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f    xyz{|}~. */
+
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf    ........ */
+
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7    ........ */
+    0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40  /* f8..ff    ........ */
+};
+
+static inline int sqlite3Isspace(char c) {
+  return isspace(c);
+}
+static inline int sqlite3Isdigit(char c) {
+  return isdigit(c);
+}
+static inline int sqlite3Isxdigit(char c) {
+  return isxdigit(c);
+}
+
+int sqlite3GetToken(const unsigned char* z, int* tokenType);
+
+static inline int sqlite3ParserFallback(int token) {
+  return 0;
+}
+
+#ifdef __cplusplus
+#define deliberate_fall_through [[fallthrough]];
+#else
+#define deliberate_fall_through
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // SRC_TRACE_PROCESSOR_PERFETTO_SQL_TOKENIZER_TOKENIZE_INTERNAL_HELPER_H_
diff --git a/tools/fix_include_guards b/tools/fix_include_guards
index f336b1a..8780ac9 100755
--- a/tools/fix_include_guards
+++ b/tools/fix_include_guards
@@ -24,6 +24,7 @@
 
 EXCLUDED_FILES = [
   'src/trace_processor/perfetto_sql/preprocessor/preprocessor_grammar.h',
+  'src/trace_processor/perfetto_sql/grammar/perfettosql_grammar.h',
 ]
 
 
diff --git a/tools/update_sql_parsers.py b/tools/update_sql_parsers.py
index 5c82e56..2dda99f 100755
--- a/tools/update_sql_parsers.py
+++ b/tools/update_sql_parsers.py
@@ -20,31 +20,80 @@
 import sys
 import tempfile
 
+GRAMMAR_FOOTER = '''
+%token SPACE ILLEGAL.
+'''
+
+KEYWORDHASH_HEADER = '''
+#include "src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash_helper.h"
+'''
+
+
+def copy_tokenizer(args: argparse.Namespace):
+  shutil.copy(args.sqlite_tokenize, args.sqlite_tokenize_out)
+
+  with open(args.sqlite_tokenize_out, 'r+', encoding='utf-8') as fp:
+    res: str = fp.read()
+    idx = res.find('/*\n** Run the parser on the given SQL string.')
+    assert idx != -1
+    res = res[0:idx]
+    res = res.replace(
+        '#include "sqliteInt.h"',
+        '#include "src/trace_processor/perfetto_sql/tokenizer/tokenize_internal_helper.h"',
+    )
+    res = res.replace('#include "keywordhash.h"\n', '')
+    fp.seek(0)
+    fp.write(res)
+    fp.truncate()
+
 
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument(
-      '--lemon',
-      default=os.path.join(
-          os.path.normpath('buildtools/sqlite_src/tool/lemon.c')))
+      '--lemon', default=os.path.normpath('buildtools/sqlite_src/tool/lemon.c'))
+  parser.add_argument(
+      '--mkkeywordhash',
+      default=os.path.normpath('buildtools/sqlite_src/tool/mkkeywordhash.c'))
   parser.add_argument(
       '--lemon-template',
-      default=os.path.join(
-          os.path.normpath('buildtools/sqlite_src/tool/lempar.c')))
+      default=os.path.normpath('buildtools/sqlite_src/tool/lempar.c'))
   parser.add_argument(
-      '--clang',
-      default=os.path.join(
-          os.path.normpath('buildtools/linux64/clang/bin/clang')))
+      '--clang', default=os.path.normpath('buildtools/linux64/clang/bin/clang'))
   parser.add_argument(
       '--preprocessor-grammar',
+      default=os.path.normpath(
+          'src/trace_processor/perfetto_sql/preprocessor/preprocessor_grammar.y'
+      ),
+  )
+  parser.add_argument(
+      '--sqlite-grammar',
+      default=os.path.normpath('buildtools/sqlite_src/src/parse.y'),
+  )
+  parser.add_argument(
+      '--perfettosql-grammar-include',
+      default=os.path.normpath(
+          'src/trace_processor/perfetto_sql/grammar/perfettosql_include.y'),
+  )
+  parser.add_argument(
+      '--grammar-out',
+      default=os.path.join(
+          os.path.normpath('src/trace_processor/perfetto_sql/grammar/')),
+  )
+  parser.add_argument(
+      '--sqlite-tokenize',
+      default=os.path.normpath('buildtools/sqlite_src/src/tokenize.c'),
+  )
+  parser.add_argument(
+      '--sqlite-tokenize-out',
       default=os.path.join(
           os.path.normpath(
-              'src/trace_processor/perfetto_sql/preprocessor/preprocessor_grammar.y'
-          )),
+              'src/trace_processor/perfetto_sql/tokenizer/tokenize_internal.c')
+      ),
   )
   args = parser.parse_args()
 
   with tempfile.TemporaryDirectory() as tmp:
+    # Preprocessor grammar
     subprocess.check_call([
         args.clang,
         os.path.join(args.lemon), '-o',
@@ -59,6 +108,46 @@
         '-s',
     ])
 
+    # PerfettoSQL keywords
+    keywordhash_tmp = os.path.join(tmp, 'mkkeywordhash.c')
+    shutil.copy(args.mkkeywordhash, keywordhash_tmp)
+    subprocess.check_call([
+        args.clang,
+        os.path.join(keywordhash_tmp), '-o',
+        os.path.join(tmp, 'mkkeywordhash')
+    ])
+    keywordhash_res = subprocess.check_output(
+        [os.path.join(tmp, 'mkkeywordhash')]).decode()
+    with open(os.path.join(args.grammar_out, "perfettosql_keywordhash.h"),
+              "w") as g:
+      idx = keywordhash_res.find('#define SQLITE_N_KEYWORD 147')
+      assert idx != -1
+      keywordhash_res = keywordhash_res[0:idx]
+      g.write(KEYWORDHASH_HEADER)
+      g.write(keywordhash_res)
+
+    # PerfettoSQL grammar
+    sqlite_grammar = subprocess.check_output([
+        os.path.join(tmp, 'lemon'),
+        args.sqlite_grammar,
+        '-g',
+    ]).decode()
+    with open(os.path.join(args.grammar_out, "perfettosql_grammar.y"),
+              "w") as g:
+      with open(args.perfettosql_grammar_include, 'r') as i:
+        g.write(i.read())
+      g.write(sqlite_grammar)
+      g.write(GRAMMAR_FOOTER)
+    subprocess.check_call([
+        os.path.join(tmp, 'lemon'),
+        os.path.join(args.grammar_out, "perfettosql_grammar.y"),
+        '-q',
+        '-l',
+        '-s',
+    ])
+
+  copy_tokenizer(args)
+
   return 0