%{ {{{ GRAMMAR_HEADER }}} %} #line 5 "third_party/libpg_query/grammar/grammar.y" %pure-parser %expect 0 %name-prefix="base_yy" %locations %parse-param {core_yyscan_t yyscanner} %lex-param {core_yyscan_t yyscanner} %union { core_YYSTYPE core_yystype; /* these fields must match core_YYSTYPE: */ int ival; char *str; const char *keyword; const char *conststr; char chr; bool boolean; PGJoinType jtype; PGDropBehavior dbehavior; PGOnCommitAction oncommit; PGOnCreateConflict oncreateconflict; PGList *list; PGNode *node; PGValue *value; PGObjectType objtype; PGTypeName *typnam; PGObjectWithArgs *objwithargs; PGDefElem *defelt; PGSortBy *sortby; PGWindowDef *windef; PGJoinExpr *jexpr; PGIndexElem *ielem; PGAlias *alias; PGRangeVar *range; PGIntoClause *into; PGCTEMaterialize ctematerialize; PGWithClause *with; PGInferClause *infer; PGOnConflictClause *onconflict; PGOnConflictActionAlias onconflictshorthand; PGAIndices *aind; PGResTarget *target; PGInsertStmt *istmt; PGVariableSetStmt *vsetstmt; PGOverridingKind override; PGSortByDir sortorder; PGSortByNulls nullorder; PGIgnoreNulls ignorenulls; PGConstrType constr; PGLockClauseStrength lockstrength; PGLockWaitPolicy lockwaitpolicy; PGSubLinkType subquerytype; PGViewCheckOption viewcheckoption; PGInsertColumnOrder bynameorposition; PGLoadInstallType loadinstalltype; PGTransactionStmtType transactiontype; PGMergeAction mergeaction; } %type stmt %type stmtblock %type stmtmulti {{{ TYPES }}} /* * Non-keyword token types. These are hard-wired into the "flex" lexer. * They must be listed first so that their numeric codes do not depend on * the set of keywords. PL/pgSQL depends on this so that it can share the * same lexer. If you add/change tokens here, fix PL/pgSQL to match! * * DOT_DOT is unused in the core SQL grammar, and so will always provoke * parse errors. It is needed by PL/pgSQL. */ %token IDENT FCONST SCONST BCONST XCONST Op %token ICONST PARAM %token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER INTEGER_DIVISION POWER_OF SINGLE_ARROW DOUBLE_ARROW SINGLE_COLON %token LESS_EQUALS GREATER_EQUALS NOT_EQUALS /* * If you want to make any keyword changes, update the keyword table in * src/include/parser/kwlist.h and add new keywords to the appropriate one * of the reserved-or-not-so-reserved keyword lists, below; search * this file for "Keyword category lists". */ /* ordinary key words in alphabetical order */ {{{ KEYWORDS }}} /* * The grammar thinks these are keywords, but they are not in the kwlist.h * list and so can never be entered directly. The filter in parser.c * creates these tokens when required (based on looking one token ahead). * * NOT_LA exists so that productions such as NOT LIKE can be given the same * precedence as LIKE; otherwise they'd effectively have the same precedence * as NOT, at least with respect to their left-hand subexpression. * NULLS_LA and WITH_LA are needed to make the grammar LALR(1). */ %token NOT_LA NULLS_LA WITH_LA /* Precedence: lowest to highest */ %left SINGLE_COLON %nonassoc SET /* see */ %left UNION EXCEPT %left INTERSECT %left SINGLE_ARROW DOUBLE_ARROW %left OR %left AND %right NOT %nonassoc IS ISNULL NOTNULL /* IS sets precedence for IS NULL, etc */ %nonassoc '<' '>' '=' LESS_EQUALS GREATER_EQUALS NOT_EQUALS %nonassoc BETWEEN IN_P GLOB LIKE ILIKE SIMILAR NOT_LA %nonassoc ESCAPE /* ESCAPE must be just above LIKE/ILIKE/SIMILAR */ %left POSTFIXOP /* dummy for postfix Op rules */ /* * To support target_el without AS, we must give IDENT an explicit priority * between POSTFIXOP and Op. We can safely assign the same priority to * various unreserved keywords as needed to resolve ambiguities (this can't * have any bad effects since obviously the keywords will still behave the * same as if they weren't keywords). We need to do this for PARTITION, * RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS * so that they can follow a_expr without creating postfix-operator problems; * for GENERATED so that it can follow b_expr; * and for NULL so that it can follow b_expr in without creating * postfix-operator problems. * * To support CUBE and ROLLUP in GROUP BY without reserving them, we give them * an explicit priority lower than '(', so that a rule with CUBE '(' will shift * rather than reducing a conflicting rule that takes CUBE as a function name. * Using the same precedence as IDENT seems right for the reasons given above. * * The frame_bound productions UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING * are even messier: since UNBOUNDED is an unreserved keyword (per spec!), * there is no principled way to distinguish these from the productions * a_expr PRECEDING/FOLLOWING. We hack this up by giving UNBOUNDED slightly * lower precedence than PRECEDING and FOLLOWING. At present this doesn't * appear to cause UNBOUNDED to be treated differently from other unreserved * keywords anywhere else in the grammar, but it's definitely risky. We can * blame any funny behavior of UNBOUNDED on the SQL standard, though. */ %nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */ %nonassoc IDENT GENERATED NULL_P PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE ROLLUP ENUM_P %left Op OPERATOR /* multi-character ops and user-defined operators */ %left '+' '-' %left '*' '/' '%' INTEGER_DIVISION %left '^' POWER_OF /* Unary Operators */ %left AT /* sets precedence for AT TIME ZONE */ %left COLLATE %right UMINUS %left '[' ']' %left '(' ')' %left TYPECAST %left '.' /* * These might seem to be low-precedence, but actually they are not part * of the arithmetic hierarchy at all in their use as JOIN operators. * We make them high-precedence to support their use as function names. * They wouldn't be given a precedence at all, were it not that we need * left-associativity among the JOIN rules themselves. */ %left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL POSITIONAL PIVOT UNPIVOT ANTI SEMI ASOF /* kluge to keep from causing shift/reduce conflicts */ %right PRESERVE STRIP_P IGNORE_P RESPECT_P %% /* * The target production for the whole parse. */ stmtblock: stmtmulti { pg_yyget_extra(yyscanner)->parsetree = $1; } ; /* * At top level, we wrap each stmt with a PGRawStmt node carrying start location * and length of the stmt's text. Notice that the start loc/len are driven * entirely from semicolon locations (@2). It would seem natural to use * @1 or @3 to get the true start location of a stmt, but that doesn't work * for statements that can start with empty nonterminals (opt_with_clause is * the main offender here); as noted in the comments for YYLLOC_DEFAULT, * we'd get -1 for the location in such cases. * We also take care to discard empty statements entirely. */ stmtmulti: stmtmulti ';' stmt { if ($1 != NIL) { /* update length of previous stmt */ updateRawStmtEnd(llast_node(PGRawStmt, $1), @2); } if ($3 != NULL) $$ = lappend($1, makeRawStmt($3, @2 + 1)); else $$ = $1; } | stmt { if ($1 != NULL) $$ = list_make1(makeRawStmt($1, 0)); else $$ = NIL; } ; {{{ STATEMENTS }}} {{{ GRAMMAR RULES }}} {{{ KEYWORD_DEFINITIONS }}} %% {{{ GRAMMAR_SOURCE }}}