417 lines
12 KiB
BNF
417 lines
12 KiB
BNF
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// WQL Version 1.1 for WBEM M6 / SMS Opal.
|
||
|
//
|
||
|
// This file describes a validated LL(1) grammar for top-down
|
||
|
// or recursive descent parsing of WQL.
|
||
|
//
|
||
|
// raymcc 11-Sep-97 Created
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<parse> ::= WQL_TOK_SELECT <select_stmt>;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// SELECT statement
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<select_stmt> ::=
|
||
|
<select_type>
|
||
|
<col_ref_list>
|
||
|
<from_clause>
|
||
|
<where_clause>
|
||
|
;
|
||
|
|
||
|
<select_type> ::= WQL_TOK_ALL;
|
||
|
<select_type> ::= WQL_TOK_DISTINCT;
|
||
|
<select_type> ::= <>;
|
||
|
|
||
|
<subselect_stmt> ::=
|
||
|
WQL_TOK_SELECT
|
||
|
<select_type>
|
||
|
<col_ref_list> // Additionally, must be a single col & not an asterisk
|
||
|
<from_clause>
|
||
|
<where_clause>
|
||
|
;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Column reference list
|
||
|
//
|
||
|
// Supports either simple names, *, or qualified names of the form
|
||
|
// "table.col" where table could be a literal table name or an aliased
|
||
|
// table name. At this point in the parsing, we can't really tell
|
||
|
// which one is being used.
|
||
|
//
|
||
|
// Either * is required, or at least one column reference.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<col_ref_list> ::= <col_ref> <col_ref_rest>;
|
||
|
<col_ref_list> ::= WQL_TOK_ASTERISK;
|
||
|
<col_ref_list> ::= WQL_TOK_COUNT <count_clause>;
|
||
|
|
||
|
<col_ref_rest> ::= WQL_TOK_COMMA <col_ref_list>;
|
||
|
<col_ref_rest> ::= <>;
|
||
|
|
||
|
<count_clause> ::= WQL_TOK_OPEN_PAREN <count_col> WQL_TOK_CLOSE_PAREN;
|
||
|
<count_col> ::= WQL_TOK_ASTERISK;
|
||
|
<count_col> ::= <col_ref>;
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Column reference
|
||
|
//
|
||
|
// Used both in the WHERE clause and the COUNT clause
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<col_ref> ::= <qualified_name>;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// qualified names
|
||
|
//
|
||
|
// (dot-separated names with optional array references.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<qualified_name> ::= WQL_TOK_IDENT <qualified_name2>;
|
||
|
<qualified_name2> ::= WQL_TOK_DOT WQL_TOK_IDENT <qualified_name2>;
|
||
|
|
||
|
<qualified_name2> ::=
|
||
|
WQL_TOK_OPEN_BRACKET
|
||
|
WQL_TOK_INT
|
||
|
WQL_TOK_CLOSEBRACKET
|
||
|
<qname_becomes_array_ref>
|
||
|
<qualified_name2>;
|
||
|
|
||
|
<qname_becomes_array_ref> ::= <>; // Dummy to enforce array semantics
|
||
|
|
||
|
<qualified_name2> ::= <>;
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// "FROM" clause
|
||
|
//
|
||
|
// Both SQL-89 and SQL-92 join syntax supported.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<from_clause> ::= WQL_TOK_FROM <table_list>;
|
||
|
|
||
|
<table_list> ::= <single_table_decl> <optional_join>;
|
||
|
|
||
|
<optional_join> ::= <sql89_join_entry>;
|
||
|
<optional_join> ::= <sql92_join_entry>;
|
||
|
|
||
|
<optional_join> ::= <>; // Unary query
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Table reference
|
||
|
//
|
||
|
// This supports a single table reference in a FROM clause, whether
|
||
|
// an isolated name, or alias (with or without AS).
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<single_table_decl> ::= <unbound_table_ident> <table_decl_rest>;
|
||
|
|
||
|
<unbound_table_ident> ::= WQL_TOK_IDENT;
|
||
|
<table_decl_rest> ::= <redundant_as> <table_alias>;
|
||
|
<table_decl_rest> ::= <>;
|
||
|
<table_alias> ::= WQL_TOK_IDENT;
|
||
|
|
||
|
<redundant_as> ::= WQL_TOK_AS;
|
||
|
<redundant_as> ::= <>;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// SQL-89 Joins
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<sql89_join_entry> ::= WQL_TOK_COMMA <sql89_join_list>;
|
||
|
|
||
|
<sql89_join_list> ::= <single_table_decl> <sql89_join_rest>;
|
||
|
|
||
|
<sql89_join_rest> ::= WQL_TOK_COMMA <sql89_join_list>;
|
||
|
<sql89_join_rest> ::= <>;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// SQL-92 Joins.
|
||
|
//
|
||
|
// We support:
|
||
|
// 1. [INNER] JOIN
|
||
|
// 2. LEFT [OUTER] JOIN
|
||
|
// 3. RIGHT [OUTER] JOIN
|
||
|
// 4. FULL [OUTER] JOIN
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<sql92_join_entry> ::= <simple_join_clause>;
|
||
|
<sql92_join_entry> ::= WQL_TOK_INNER <simple_join_clause>;
|
||
|
<sql92_join_entry> ::= WQL_TOK_FULL <opt_outer> <simple_join_clause>;
|
||
|
<sql92_join_entry> ::= WQL_TOK_LEFT <opt_outer> <simple_join_clause>;
|
||
|
<sql92_join_entry> ::= WQL_TOK_RIGHT <opt_outer> <simple_join_clause>;
|
||
|
|
||
|
<opt_outer> ::= WQL_TOK_OUTER;
|
||
|
<opt_outer> ::= <>;
|
||
|
|
||
|
<simple_join_clause> ::=
|
||
|
WQL_TOK_JOIN
|
||
|
<single_table_decl>
|
||
|
<on_clause>
|
||
|
<sql92_join_continuator>
|
||
|
;
|
||
|
|
||
|
<on_clause> ::= WQL_TOK_ON <rel_expr>;
|
||
|
|
||
|
<sql92_join_continuator> ::= <sql92_join_entry>;
|
||
|
<sql92_join_continuator> ::= <>;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// "WHERE" clause
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<where_clause> ::= WQL_TOK_WHERE <rel_expr> <where_options>;
|
||
|
<where_clause> ::= <>; // 'where' is not required
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// WHERE OPTIONS
|
||
|
//
|
||
|
// We currently force the GROUP BY to precede ORDER BY if they are both
|
||
|
// present. If this causes a problem, we can fix it by using an
|
||
|
// iterative construct below and doing the checking in the parser itself
|
||
|
// as a semantic operation.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<where_options> ::=
|
||
|
<group_by_clause>
|
||
|
<order_by_clause>
|
||
|
;
|
||
|
|
||
|
<group_by_clause> ::= WQL_TOK_GROUP WQL_TOK_BY <col_list> <having_clause>;
|
||
|
<group_by_clause> ::= <>;
|
||
|
|
||
|
<having_clause> ::= WQL_TOK_HAVING <rel_expr>;
|
||
|
<having_clause> ::= <>;
|
||
|
|
||
|
<order_by_clause> ::= WQL_TOK_ORDER WQL_TOK_BY <col_list>;
|
||
|
<order_by_clause> ::= <>;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Simple column list with no asterisk
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<col_list> ::= <col_ref> <col_list_rest>;
|
||
|
<col_list_rest> ::= WQL_TOK_COMMA <col_ref> <col_list_rest>;
|
||
|
<col_list_rest> ::= <>;
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Relational expressions
|
||
|
//
|
||
|
// These set out the precedence of typed expressions relative to the
|
||
|
// NOT, AND, OR and parentheses operators.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<rel_expr> ::= <rel_term> <rel_expr2>;
|
||
|
<rel_expr2> ::= WQL_TOK_OR <rel_term> <rel_expr2>;
|
||
|
<rel_expr2> ::= <>;
|
||
|
|
||
|
<rel_term> ::= <rel_simple_expr> <rel_term2>;
|
||
|
<rel_term2> ::= WQL_TOK_AND <rel_simple_expr> <rel_term2>;
|
||
|
<rel_term2> ::= <>;
|
||
|
|
||
|
<rel_simple_expr> ::= WQL_TOK_NOT <rel_expr>;
|
||
|
<rel_simple_expr> ::= WQL_TOK_OPEN_PAREN <rel_expr> WQL_TOK_CLOSE_PAREN;
|
||
|
<rel_simple_expr> ::= <typed_expr>;
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Typed expression
|
||
|
//
|
||
|
// This is the lower level expression which requires a relational
|
||
|
// operator. Many of these combined constitute a relational expression.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<typed_expr> ::= <typed_subexpr> <rel_op> <typed_subexpr_rh>;
|
||
|
|
||
|
<typed_subexpr> ::= <function_call>;
|
||
|
<typed_subexpr> ::= <typed_const>;
|
||
|
<typed_subexpr> ::= <col_ref>;
|
||
|
|
||
|
<typed_subexpr_rh> ::= <function_call>;
|
||
|
<typed_subexpr_rh> ::= <typed_const>;
|
||
|
<typed_subexpr_rh> ::= <col_ref>;
|
||
|
|
||
|
<typed_subexpr_rh> ::= <in_clause>; // Operator must be _IN or _NOT_IN
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Function calls
|
||
|
//
|
||
|
// Each of the recognized functions is part of the grammar.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<function_call> ::= WQL_TOK_UPPER <function_call_parms>;
|
||
|
<function_call> ::= WQL_TOK_LOWER <function_call_parms>;
|
||
|
<function_call> ::= WQL_TOK_DATEPART <datepart_call>;
|
||
|
<function_call> ::= WQL_TOK_QUALIFIER <function_call_parms>;
|
||
|
<function_call> ::= WQL_TOK_ISNULL <function_call_parms>;
|
||
|
|
||
|
<function_call_parms> ::=
|
||
|
WQL_TOK_OPEN_PAREN
|
||
|
<func_args>
|
||
|
WQL_TOK_CLOSE_PAREN
|
||
|
;
|
||
|
|
||
|
<func_args> ::= <func_arg> <func_arg_list>;
|
||
|
<func_arg_list> ::= WQL_TOK_COMMA <func_arg> <func_arg_list>;
|
||
|
<func_arg_list> ::= <>;
|
||
|
|
||
|
<func_arg> ::= <typed_const>;
|
||
|
<func_arg> ::= <col_ref>;
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// IN clause
|
||
|
//
|
||
|
// We support three syntax branches:
|
||
|
// (a) IN with subselect
|
||
|
// (b) IN with const-list
|
||
|
// (c) IN with qualified name which is an array reference
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<in_clause> ::= WQL_TOK_OPEN_PAREN <in_type> WQL_TOK_CLOSE_PAREN;
|
||
|
<in_type> ::= <subselect_stmt>;
|
||
|
<in_type> ::= <const_list>;
|
||
|
<in_type> ::= <qualified_name>;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Comma-separated list of constants
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<const_list> ::= <typed_const> <const_list2>;
|
||
|
<const_list2> ::= WQL_TOK_COMMA <typed_const> <const_list2>;
|
||
|
<const_list2> ::= <>;
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Primary relational operator terminals
|
||
|
// Some branching with continuators occurs for IS, IN, and NOT.
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<rel_op> ::= WQL_TOK_LE;
|
||
|
<rel_op> ::= WQL_TOK_LT;
|
||
|
<rel_op> ::= WQL_TOK_GE;
|
||
|
<rel_op> ::= WQL_TOK_GT;
|
||
|
<rel_op> ::= WQL_TOK_EQ;
|
||
|
<rel_op> ::= WQL_TOK_NE;
|
||
|
<rel_op> ::= WQL_TOK_LIKE;
|
||
|
<rel_op> ::= WQL_TOK_BETWEEN;
|
||
|
<rel_op> ::= WQL_TOK_IS <is_continuator>;
|
||
|
<rel_op> ::= WQL_TOK_ISA;
|
||
|
<rel_op> ::= WQL_TOK_IN;
|
||
|
<rel_op> ::= WQL_TOK_NOT <not_continuator>;
|
||
|
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Tokens which can follow IS
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<is_continuator> ::= WQL_TOK_LIKE;
|
||
|
<is_continuator> ::= WQL_TOK_BEFORE;
|
||
|
<is_continuator> ::= WQL_TOK_AFTER;
|
||
|
<is_continuator> ::= WQL_TOK_BETWEEN;
|
||
|
<is_continuator> ::= WQL_TOK_NULL;
|
||
|
<is_continuator> ::= WQL_TOK_NOT <not_continuator>;
|
||
|
<is_continuator> ::= WQL_TOK_IN;
|
||
|
<is_continuator> ::= WQL_TOK_A;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Tokens which can follow NOT
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<not_continuator> ::= WQL_TOK_LIKE;
|
||
|
<not_continuator> ::= WQL_TOK_BEFORE;
|
||
|
<not_continuator> ::= WQL_TOK_AFTER;
|
||
|
<not_continuator> ::= WQL_TOK_BETWEEN;
|
||
|
<not_continuator> ::= WQL_TOK_NULL;
|
||
|
<not_continuator> ::= WQL_TOK_IN;
|
||
|
<not_continuator> ::= WQL_TOK_A;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Typed constants (literals)
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<typed_const> ::= WQL_TOK_QSTRING;
|
||
|
<typed_const> ::= WQL_TOK_INT;
|
||
|
<typed_const> ::= WQL_TOK_REAL;
|
||
|
<typed_const> ::= WQL_TOK_NULL;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Transact-SQL plagiarism: Datepart
|
||
|
//
|
||
|
// datepart(ident, col)
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
<datepart_call> ::=
|
||
|
WQL_TOK_OPEN_PAREN
|
||
|
WQL_TOK_IDENT // yy, mm,dd, hh, mm, ss, year, month, etc.
|
||
|
WQL_TOK_COMMA
|
||
|
<col_ref>
|
||
|
WQL_TOK_CLOSE_PAREN
|
||
|
;
|
||
|
|
||
|
// RAIX xxxx: Ensure that lexer returns single quoted strings as valid, and recognizes escapes
|
||
|
// RAID 3716: Syntax to reference a qualifier; promised to do this
|
||
|
// qualifier(prop, "MyQual") = 'xxx' qualifier("MyQual") = 'const'
|
||
|
// RAID xxxx : Hex constants
|
||
|
//
|
||
|
// Intrinsic function applied to columns in "select a, func(b), c from d where..."
|
||
|
// Use of qualified asterisks "select t1.*, t2.*, t3.x from ..."
|
||
|
//
|
||
|
// BETWEEN needs to be supported *correctly*
|
||
|
// Unexpected Features: (1) subselects in IN, (2) DatePart (required new approach to functions
|
||
|
// because of the keyword problem, (3) functionized col-refs, (4) COUNT(col-name) as opposed
|
||
|
// to COUNT(*), (5)
|
||
|
|
||
|
|