public SqlGrammar()

in src/OrchardCore.Modules/OrchardCore.Queries/Sql/SqlGrammar.cs [7:160]


        public SqlGrammar() : base(false)
        {
            var comment = new CommentTerminal("comment", "/*", "*/");
            var lineComment = new CommentTerminal("line_comment", "--", "\n", "\r\n");
            NonGrammarTerminals.Add(comment);
            NonGrammarTerminals.Add(lineComment);
            var number = new NumberLiteral("number");
            var string_literal = new StringLiteral("string", "'", StringOptions.AllowsDoubledQuote);
            var Id_simple = TerminalFactory.CreateSqlExtIdentifier(this, "id_simple"); //covers normal identifiers (abc) and quoted id's ([abc d], "abc d")
            var comma = ToTerm(",");
            var dot = ToTerm(".");
            var CREATE = ToTerm("CREATE");
            var NULL = ToTerm("NULL");
            var NOT = ToTerm("NOT");
            var ON = ToTerm("ON");
            var SELECT = ToTerm("SELECT");
            var FROM = ToTerm("FROM");
            var AS = ToTerm("AS");
            var COUNT = ToTerm("COUNT");
            var JOIN = ToTerm("JOIN");
            var BY = ToTerm("BY");
            var TRUE = ToTerm("TRUE");
            var FALSE = ToTerm("FALSE");

            //Non-terminals
            var Id = new NonTerminal("Id");
            var statement = new NonTerminal("stmt");
            var selectStatement = new NonTerminal("selectStatement");
            var idlist = new NonTerminal("idlist");
            var aliaslist = new NonTerminal("aliaslist");
            var aliasItem = new NonTerminal("aliasItem");
            var orderList = new NonTerminal("orderList");
            var orderMember = new NonTerminal("orderMember");
            var orderDirOptional = new NonTerminal("orderDirOpt");
            var whereClauseOptional = new NonTerminal("whereClauseOpt");
            var expression = new NonTerminal("expression");
            var expressionList = new NonTerminal("exprList");
            var optionalSelectRestriction = new NonTerminal("optionalSelectRestriction");
            var selectorList = new NonTerminal("selList");
            var fromClauseOpt = new NonTerminal("fromClauseOpt");
            var groupClauseOpt = new NonTerminal("groupClauseOpt");
            var havingClauseOpt = new NonTerminal("havingClauseOpt");
            var orderClauseOpt = new NonTerminal("orderClauseOpt");
            var limitClauseOpt = new NonTerminal("limitClauseOpt");
            var offsetClauseOpt = new NonTerminal("offsetClauseOpt");
            var columnItemList = new NonTerminal("columnItemList");
            var columnItem = new NonTerminal("columnItem");
            var columnSource = new NonTerminal("columnSource");
            var asOpt = new NonTerminal("asOpt");
            var aliasOpt = new NonTerminal("aliasOpt");
            var tuple = new NonTerminal("tuple");
            var joinChainOpt = new NonTerminal("joinChainOpt");
            var joinStatement = new NonTerminal("joinStatement");
            var joinKindOpt = new NonTerminal("joinKindOpt");
            var term = new NonTerminal("term");
            var unExpr = new NonTerminal("unExpr");
            var unOp = new NonTerminal("unOp");
            var binExpr = new NonTerminal("binExpr");
            var binOp = new NonTerminal("binOp");
            var betweenExpr = new NonTerminal("betweenExpr");
            var inExpr = new NonTerminal("inExpr");
            var parSelectStatement = new NonTerminal("parSelectStmt");
            var notOpt = new NonTerminal("notOpt");
            var funCall = new NonTerminal("funCall");
            var parameter = new NonTerminal("parameter");
            var statementLine = new NonTerminal("stmtLine");
            var optionalSemicolon = new NonTerminal("semiOpt");
            var statementList = new NonTerminal("stmtList");
            var functionArguments = new NonTerminal("funArgs");
            var boolean = new NonTerminal("boolean");

            //BNF Rules
            this.Root = statementList;
            statementLine.Rule = statement + optionalSemicolon;
            optionalSemicolon.Rule = Empty | ";";
            statementList.Rule = MakePlusRule(statementList, statementLine);

            statement.Rule = selectStatement;

            Id.Rule = MakePlusRule(Id, dot, Id_simple);

            aliasOpt.Rule = Empty | asOpt + Id;
            asOpt.Rule = Empty | AS;

            idlist.Rule = MakePlusRule(idlist, comma, columnSource);

            aliaslist.Rule = MakePlusRule(aliaslist, comma, aliasItem);
            aliasItem.Rule = Id + aliasOpt;

            //Create Index
            orderList.Rule = MakePlusRule(orderList, comma, orderMember);
            orderMember.Rule = Id + orderDirOptional;
            orderDirOptional.Rule = Empty | "ASC" | "DESC";

            //Select stmt
            selectStatement.Rule = SELECT + optionalSelectRestriction + selectorList + fromClauseOpt + whereClauseOptional +
                              groupClauseOpt + havingClauseOpt + orderClauseOpt + limitClauseOpt + offsetClauseOpt;
            optionalSelectRestriction.Rule = Empty | "ALL" | "DISTINCT";
            selectorList.Rule = columnItemList | "*";
            columnItemList.Rule = MakePlusRule(columnItemList, comma, columnItem);
            columnItem.Rule = columnSource + aliasOpt;

            columnSource.Rule = funCall | Id;
            fromClauseOpt.Rule = Empty | FROM + aliaslist + joinChainOpt;
            joinChainOpt.Rule = MakeStarRule(joinChainOpt, joinStatement);
            joinStatement.Rule = joinKindOpt + JOIN + aliaslist + ON + Id + "=" + Id;
            joinKindOpt.Rule = Empty | "INNER" | "LEFT" | "RIGHT";
            whereClauseOptional.Rule = Empty | "WHERE" + expression;
            groupClauseOpt.Rule = Empty | "GROUP" + BY + idlist;
            havingClauseOpt.Rule = Empty | "HAVING" + expression;
            orderClauseOpt.Rule = Empty | "ORDER" + BY + orderList;
            limitClauseOpt.Rule = Empty | "LIMIT" + expression;
            offsetClauseOpt.Rule = Empty | "OFFSET" + expression;

            //Expression
            expressionList.Rule = MakePlusRule(expressionList, comma, expression);
            expression.Rule = term | unExpr | binExpr | betweenExpr | inExpr | parameter;
            term.Rule = Id | boolean | string_literal | number | funCall | tuple | parSelectStatement ;
            boolean.Rule = TRUE | FALSE;
            tuple.Rule = "(" + expressionList + ")";
            parSelectStatement.Rule = "(" + selectStatement + ")";
            unExpr.Rule = unOp + term;
            unOp.Rule = NOT | "+" | "-" | "~";
            binExpr.Rule = expression + binOp + expression;
            binOp.Rule = ToTerm("+") | "-" | "*" | "/" | "%" //arithmetic
                       | "&" | "|" | "^"                     //bit
                       | "=" | ">" | "<" | ">=" | "<=" | "<>" | "!=" | "!<" | "!>"
                       | "AND" | "OR" | "LIKE" | "NOT LIKE" ;
            betweenExpr.Rule = expression + notOpt + "BETWEEN" + expression + "AND" + expression;
            inExpr.Rule = expression + notOpt + "IN" + "(" + functionArguments + ")";
            notOpt.Rule = Empty | NOT;
            //funCall covers some pseudo-operators and special forms like ANY(...), SOME(...), ALL(...), EXISTS(...), IN(...)
            funCall.Rule = Id + "(" + functionArguments + ")";
            functionArguments.Rule = selectStatement | expressionList | "*";
            parameter.Rule = "@" + Id | "@" + Id + ":" + term;

            //Operators
            RegisterOperators(10, "*", "/", "%");
            RegisterOperators(9, "+", "-");
            RegisterOperators(8, "=", ">", "<", ">=", "<=", "<>", "!=", "!<", "!>", "LIKE", "IN");
            RegisterOperators(7, "^", "&", "|");
            RegisterOperators(6, NOT);
            RegisterOperators(5, "AND");
            RegisterOperators(4, "OR");

            MarkPunctuation(",", "(", ")");
            MarkPunctuation(asOpt, optionalSemicolon);
            //Note: we cannot declare binOp as transient because it includes operators "NOT LIKE", "NOT IN" consisting of two tokens.
            // Transient non-terminals cannot have more than one non-punctuation child nodes.
            // Instead, we set flag InheritPrecedence on binOp , so that it inherits precedence value from it's children, and this precedence is used
            // in conflict resolution when binOp node is sitting on the stack
            base.MarkTransient(statement, term, asOpt, aliasOpt, statementLine, expression, unOp, tuple);
            binOp.SetFlag(TermFlags.InheritPrecedence);
        }