1 /* 2 * Copyright (C) 2025 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 %name PerfettoSqlParse 18 %token_prefix TK_ 19 %start_symbol input 20 21 %include { 22 #include <stdio.h> 23 #include <stddef.h> 24 #include "src/trace_processor/perfetto_sql/grammar/perfettosql_grammar_interface.h" 25 26 #define YYNOERRORRECOVERY 1 27 #define YYPARSEFREENEVERNULL 1 28 } 29 30 %token CREATE REPLACE PERFETTO MACRO INCLUDE MODULE RETURNS FUNCTION. 31 32 %left OR. 33 %left AND. 34 %right NOT. 35 %left IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ. 36 %left GT LE LT GE. 37 %right ESCAPE. 38 %left BITAND BITOR LSHIFT RSHIFT. 39 %left PLUS MINUS. 40 %left STAR SLASH REM. 41 %left CONCAT PTR. 42 %left COLLATE. 43 %right BITNOT. 44 %nonassoc ON. 45 46 %fallback 47 // Taken from SQLite 48 ID 49 ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW 50 CONFLICT DATABASE DEFERRED DESC DETACH DO 51 EACH END EXCLUSIVE EXPLAIN FAIL FOR 52 IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN 53 QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS 54 ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT 55 NULLS FIRST LAST 56 CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED 57 EXCLUDE GROUPS OTHERS TIES 58 GENERATED ALWAYS 59 MATERIALIZED 60 REINDEX RENAME CTIME_KW IF 61 // Our additions. 62 FUNCTION MODULE PERFETTO 63 . 64 %wildcard ANY. 65 66 %token_type {struct PerfettoSqlToken} 67 68 %extra_context {struct PerfettoSqlParserState* state} 69 %syntax_error { 70 OnPerfettoSqlSyntaxError(state, &yyminor); 71 } 72 73 // Helper function like scantok but usable by us. 74 pscantok(A) ::= . { 75 assert( yyLookahead!=YYNOCODE ); 76 A = yyLookaheadToken; 77 } 78 79 // Shared rules 80 %type sql_argument_list { struct PerfettoSqlArgumentList* } 81 %destructor sql_argument_list { OnPerfettoSqlFreeArgumentList(state, $$); } 82 sql_argument_list(A) ::=. { A = 0; } 83 sql_argument_list(A) ::= sql_argument_list_nonempty(X). { A = X; } 84 85 sql_argument_type(A) ::= ID(B). { A = B; } 86 sql_argument_type(A) ::= ID(B) LP ID DOT ID RP. { A = B; } 87 88 %type sql_argument_list_nonempty { struct PerfettoSqlArgumentList* } 89 %destructor sql_argument_list_nonempty { OnPerfettoSqlFreeArgumentList(state, $$); } 90 sql_argument_list_nonempty(A) ::= sql_argument_list_nonempty(B) COMMA ID(C) sql_argument_type(D). { 91 A = OnPerfettoSqlCreateOrAppendArgument(state, B, &C, &D); 92 } 93 sql_argument_list_nonempty(A) ::= ID(B) sql_argument_type(C). { 94 A = OnPerfettoSqlCreateOrAppendArgument(state, 0, &B, &C); 95 } 96 97 %type table_schema { struct PerfettoSqlArgumentList* } 98 %destructor table_schema { OnPerfettoSqlFreeArgumentList(state, $$); } 99 table_schema(A) ::=. { A = 0; } 100 table_schema(A) ::= LP sql_argument_list_nonempty(B) RP. { A = B; } 101 102 // CREATE statements 103 %type or_replace {int} 104 or_replace(A) ::=. { A = 0; } 105 or_replace(A) ::= OR REPLACE. { A = 1; } 106 107 // CREATE PERFETTO FUNCTION 108 cmd ::= CREATE or_replace(R) PERFETTO FUNCTION ID(N) LP sql_argument_list(A) RP RETURNS return_type(T) AS select(E) pscantok(S). { 109 OnPerfettoSqlCreateFunction(state, R, &N, A, T, &E, &S); 110 } 111 112 %type return_type { struct PerfettoSqlFnReturnType* } 113 %destructor return_type { OnPerfettoSqlFnFreeReturnType(state, $$); } 114 return_type(Y) ::= ID(X). { 115 Y = OnPerfettoSqlCreateScalarReturnType(&X); 116 } 117 return_type(Y) ::= TABLE LP sql_argument_list_nonempty(A) RP. { 118 Y = OnPerfettoSqlCreateTableReturnType(A); 119 } 120 121 // CREATE PERFETTO TABLE 122 cmd ::= CREATE or_replace(R) PERFETTO TABLE ID(N) table_schema(S) AS select(A) pscantok(Q). { 123 OnPerfettoSqlCreateTable(state, R, &N, S, &A, &Q); 124 } 125 126 // CREATE PERFETTO VIEW 127 cmd ::= CREATE(C) or_replace(R) PERFETTO VIEW ID(N) table_schema(S) AS select(A) pscantok(Q). { 128 OnPerfettoSqlCreateView(state, R, &C, &N, S, &A, &Q); 129 } 130 131 // CREATE PERFETTO INDEX 132 cmd ::= CREATE(C) or_replace(R) PERFETTO INDEX ID(N) ON ID(T) LP indexed_column_list(L) RP. { 133 OnPerfettoSqlCreateIndex(state, R, &C, &N, &T, L); 134 } 135 136 %type indexed_column_list { struct PerfettoSqlIndexedColumnList* } 137 %destructor indexed_column_list { OnPerfettoSqlFreeIndexedColumnList(state, $$); } 138 indexed_column_list(A) ::= indexed_column_list(B) COMMA ID(C). { 139 A = OnPerfettoSqlCreateOrAppendIndexedColumn(B, &C); 140 } 141 indexed_column_list(A) ::= ID(B). { 142 A = OnPerfettoSqlCreateOrAppendIndexedColumn(0, &B); 143 } 144 145 // CREATE PERFETTO MACRO 146 cmd ::= CREATE or_replace(R) PERFETTO MACRO ID(N) LP macro_argument_list(A) RP RETURNS ID(T) AS macro_body(S) pscantok(B). { 147 OnPerfettoSqlCreateMacro(state, R, &N, A, &T, &S, &B); 148 } 149 macro_body ::= ANY. 150 macro_body ::= macro_body ANY. 151 152 %type macro_argument_list_nonempty { struct PerfettoSqlMacroArgumentList* } 153 %destructor macro_argument_list_nonempty { OnPerfettoSqlFreeMacroArgumentList(state, $$); } 154 macro_argument_list_nonempty(A) ::= macro_argument_list_nonempty(D) COMMA ID(B) ID(C). { 155 A = OnPerfettoSqlCreateOrAppendMacroArgument(state, D, &B, &C); 156 } 157 macro_argument_list_nonempty(A) ::= ID(B) ID(C). { 158 A = OnPerfettoSqlCreateOrAppendMacroArgument(state, 0, &B, &C); 159 } 160 161 %type macro_argument_list { struct PerfettoSqlMacroArgumentList* } 162 %destructor macro_argument_list { OnPerfettoSqlFreeMacroArgumentList(state, $$); } 163 macro_argument_list(A) ::=. { A = 0; } 164 macro_argument_list(A) ::= macro_argument_list_nonempty(B). { A = B; } 165 166 // INCLUDE statement 167 cmd ::= INCLUDE PERFETTO MODULE module_name(M). { 168 OnPerfettoSqlInclude(state, &M); 169 } 170 module_name(A) ::= ID|STAR|INTERSECT(B). { 171 A = B; 172 } 173 module_name(A) ::= module_name(B) DOT ID|STAR|INTERSECT(C). { 174 A = (struct PerfettoSqlToken) {B.ptr, C.ptr + C.n - B.ptr}; 175 } 176 177 // DROP statement 178 cmd ::= DROP PERFETTO INDEX ID(N) ON ID(T). { 179 OnPerfettoSqlDropIndex(state, &N, &T); 180 } 181