/// <summary> /// Recupera o container condicional. /// </summary> /// <param name="enumerator"></param> /// <param name="configuration"></param> /// <returns></returns> private static ConditionalTerm GetContainer(ref IEnumerator <Text.InterpreterExpression.Expression> enumerator, Text.InterpreterExpression.ILexerConfiguration configuration) { if (enumerator.MoveNext()) { return(GetTerm(ref enumerator, configuration)); } return(null); }
/// <summary> /// Recupera a chamada de função. /// </summary> /// <param name="enumerator"></param> /// <param name="configuration"></param> /// <param name="containerStop"></param> /// <param name="callName"></param> /// <returns></returns> private static ConditionalTerm GetFunctionCall(ref IEnumerator <Text.InterpreterExpression.Expression> enumerator, Text.InterpreterExpression.ILexerConfiguration configuration, char?containerStop, Column callName) { var call = callName; var pars = new List <ConditionalTerm>(); var commaExpression = _conditionalLexer.TokenParser.GetTerm((int)Colosoft.Text.InterpreterExpression.TokenID.Comma); var token = enumerator.Current; var distinctFlag = false; while (!token.ToString().Equals(")")) { if (!enumerator.MoveNext()) { break; } token = enumerator.Current; if (token.ToString().Equals(")")) { enumerator.MoveNext(); break; } var termText = enumerator.Current.Text; ConditionalTerm term = null; while (true) { term = GetTerm(ref enumerator, configuration); if (term is Column && StringComparer.InvariantCultureIgnoreCase.Equals(((Column)term).Name, "DISTINCT")) { enumerator.MoveNext(); distinctFlag = true; } else { break; } } if (StringComparer.InvariantCultureIgnoreCase.Equals(call.Name, "CAST") && pars.Count == 1 && term is Column) { term = new Constant(((Column)term).Name); } if (!enumerator.MoveNext()) { pars.Add(term); break; } if (Conditional.IsConditionalOperator(enumerator.Current)) { var left = term; var oper = new Operator(enumerator.Current.Text); var right = GetTerm(ref enumerator); term = new Conditional(left, oper, right); if (!enumerator.MoveNext()) { pars.Add(term); break; } } if (Formula.IsArithmeticOperator(enumerator.Current)) { term = GetFormula(ref enumerator, configuration, term); } if ((token.Token == (int)Colosoft.Text.InterpreterExpression.TokenID.Identifier || Colosoft.Query.Parser.SqlTokenParser.IsSqlAnsiFunction(token.Token)) && enumerator.Current.Token == (int)Colosoft.Text.InterpreterExpression.TokenID.LParen) { var columnExpression = ParserColumnExpression(termText); term = GetFunctionCall(ref enumerator, configuration, ')', (columnExpression as Column) ?? new Column(termText)); if (Formula.IsArithmeticOperator(enumerator.Current)) { term = GetFormula(ref enumerator, configuration, term); } pars.Add(term); token = enumerator.Current; } else { pars.Add(term); token = enumerator.Current; } if (token.ToString().Equals(")")) { enumerator.MoveNext(); break; } if (!token.ToString().Equals(commaExpression)) { throw new ConditionalParserException(string.Format("Expected comma after '{0}'", pars.Last().ToString())); } } return(new FunctionCall() { Call = call, Parameters = pars.ToArray(), Options = distinctFlag ? FunctionCallOptions.Distinct : FunctionCallOptions.None }); }
/// <summary> /// Recupera container condicional. /// </summary> /// <param name="enumerator">Enumerador dos items que serão analizados.</param> /// <param name="configuration"></param> /// <param name="containerInfo"></param> /// <returns></returns> private static ConditionalTerm GetContainer(ref IEnumerator <Text.InterpreterExpression.Expression> enumerator, Text.InterpreterExpression.ILexerConfiguration configuration, Text.InterpreterExpression.ContainerChars containerInfo) { ConditionalContainer container = null; var logical = Text.InterpreterExpression.TokenID.And; while (containerInfo == null || (string.IsNullOrEmpty(enumerator.Current.Text) || enumerator.Current.Text[0] != containerInfo.Stop)) { var conditional = GetConditional(ref enumerator, configuration, containerInfo != null ? (char?)containerInfo.Stop : null); if (((conditional is ValuesArray) || (conditional is FunctionCall)) && container == null) { return(conditional); } else if (container == null) { container = new ConditionalContainer(conditional); } else if (logical == Text.InterpreterExpression.TokenID.And) { container.And(conditional); } else if (logical == Text.InterpreterExpression.TokenID.Plus || logical == Text.InterpreterExpression.TokenID.Minus || logical == Text.InterpreterExpression.TokenID.Star || logical == Text.InterpreterExpression.TokenID.Slash) { Operator oper = null; switch (logical) { case Text.InterpreterExpression.TokenID.Plus: oper = new Operator("+"); break; case Text.InterpreterExpression.TokenID.Minus: oper = new Operator("-"); break; case Text.InterpreterExpression.TokenID.Star: oper = new Operator("*"); break; case Text.InterpreterExpression.TokenID.Slash: oper = new Operator("/"); break; } ConditionalTerm left = container; if (container.ConditionalsCount == 1) { left = container.Conditionals.First(); } container = new ConditionalContainer(new Conditional(left, oper, conditional)); } else { container.Or(conditional); } if (enumerator.Current == null || (containerInfo != null && enumerator.Current.Text[0] == containerInfo.Stop)) { return(container); } else if (enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.And || enumerator.Current.Token == (int)Query.Parser.SqlTokenID.kAnd) { logical = Text.InterpreterExpression.TokenID.And; } else if (enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.Or || enumerator.Current.Token == (int)Query.Parser.SqlTokenID.kOr) { logical = Text.InterpreterExpression.TokenID.Or; } else if (enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.Plus || enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.Minus || enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.Star || enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.Slash) { logical = (Text.InterpreterExpression.TokenID)enumerator.Current.Token; } if (!enumerator.MoveNext()) { break; } } return(container); }
/// <summary> /// Recupera o vetor de valores. /// </summary> /// <param name="enumerator"></param> /// <param name="configuration"></param> /// <param name="containerStop"></param> /// <param name="firstConstants"></param> /// <returns></returns> private static ConditionalTerm GetValuesArray(ref IEnumerator <Text.InterpreterExpression.Expression> enumerator, Text.InterpreterExpression.ILexerConfiguration configuration, char?containerStop, params ConditionalTerm[] firstConstants) { var values = new List <ConditionalTerm>(firstConstants); var commaExpression = _conditionalLexer.TokenParser.GetTerm((int)Colosoft.Text.InterpreterExpression.TokenID.Comma); while (containerStop == null || enumerator.Current.Text[0] != containerStop) { if (enumerator.Current.Text != commaExpression) { throw new ConditionalParserException(string.Format("Expected comma after '{0}'", values.Last().ToString())); } if (!enumerator.MoveNext()) { break; } var term = GetTerm(ref enumerator, configuration); values.Add(term); if (!enumerator.MoveNext()) { break; } } return(new ValuesArray() { Values = values.ToArray() }); }
/// <summary> /// Recupera uma condição. /// </summary> /// <param name="enumerator"></param> /// <param name="configuration"></param> /// <param name="containerStop">Caracter que identifica o fim da condicional.</param> /// <returns></returns> private static ConditionalTerm GetConditional(ref IEnumerator <Text.InterpreterExpression.Expression> enumerator, Text.InterpreterExpression.ILexerConfiguration configuration, char?containerStop) { var left = GetTerm(ref enumerator, configuration); var isLeftNotToken = enumerator.Current != null && (enumerator.Current.Token == (int)Parser.SqlTokenID.kNot); int leftToken = enumerator.Current != null ? (int)enumerator.Current.Token : -1; if (!enumerator.MoveNext() || enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.And || enumerator.Current.Token == (int)Parser.SqlTokenID.kAnd || enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.Or || enumerator.Current.Token == (int)Parser.SqlTokenID.kOr) { return(left); } if (containerStop != null && enumerator.Current.Text[0] == containerStop) { return(left); } var oper = enumerator.Current; if (Formula.IsArithmeticOperator(oper)) { left = GetFormula(ref enumerator, configuration, left); oper = enumerator.Current; if (enumerator.Current == null || (containerStop != null && enumerator.Current.Text[0] == containerStop)) { return(left); } } var operToken = _conditionalLexer.TokenParser.Parse(oper.Text); if (left is Constant && operToken == (int)Text.InterpreterExpression.TokenID.LParen && (leftToken == (int)Parser.SqlTokenID.kDay || leftToken == (int)Parser.SqlTokenID.kMonth || leftToken == (int)Parser.SqlTokenID.kYear || leftToken == (int)Parser.SqlTokenID.kHour || leftToken == (int)Parser.SqlTokenID.kMinute || leftToken == (int)Parser.SqlTokenID.kSecond)) { left = new Column(((Constant)left).Text); } if (isLeftNotToken && operToken == (int)Parser.SqlTokenID.kExists) { enumerator.MoveNext(); left = GetFunctionCall(ref enumerator, configuration, containerStop, new Column("NOT EXISTS")); return(new Conditional(left, new Operator("NOT EXISTS"), null)); } else if ((operToken == (int)Text.InterpreterExpression.TokenID.LParen) && (left is Column)) { left = GetFunctionCall(ref enumerator, configuration, containerStop, (Column)left); var function = (FunctionCall)left; if (StringComparer.InvariantCultureIgnoreCase.Equals(((Column)function.Call).Name, "exists")) { function.Call = new Constant("EXISTS"); return(new Conditional(left, new Operator("EXISTS"), null)); } oper = enumerator.Current; if (oper == null) { return(function); } operToken = _conditionalLexer.TokenParser.Parse(oper.Text); } else if (operToken == (int)Colosoft.Text.InterpreterExpression.TokenID.Comma) { return(GetValuesArray(ref enumerator, configuration, containerStop, left)); } if (!enumerator.MoveNext()) { if (left is FunctionCall) { return(left); } throw new ConditionalParserException("Right conditional not found"); } if (left is FunctionCall && enumerator.Current.Token == (int)Colosoft.Query.Parser.SqlTokenID.kEnd) { return(left); } var optOper = enumerator.Current; var optOperToken = _conditionalLexer.TokenParser.Parse(optOper.Text); bool isOptOper = (optOperToken == (int)Colosoft.Query.Parser.SqlTokenID.kNot) || (operToken == (int)Colosoft.Query.Parser.SqlTokenID.kNot); if (isOptOper) { if (!enumerator.MoveNext()) { throw new ConditionalParserException("Right conditional not found"); } } var right = GetTerm(ref enumerator, configuration); enumerator.MoveNext(); if ((enumerator.Current != null) && (enumerator.Current.Text[0] == '(') && (right is Column)) { right = GetFunctionCall(ref enumerator, configuration, containerStop, (Column)right); } else if (operToken == (int)Colosoft.Query.Parser.SqlTokenID.kIn || optOperToken == (int)Colosoft.Query.Parser.SqlTokenID.kIn) { if (!(right is ValuesArray)) { var rcc = right as ConditionalContainer; if (rcc != null) { right = new ValuesArray() { Values = rcc.Conditionals.ToArray() }; } else { right = new ValuesArray { Values = new ConditionalTerm[] { right } } }; } } return(new Conditional(left, new Operator((isOptOper) ? oper.Text + ' ' + optOper.Text : oper.Text), right)); }
/// <summary> /// Recupera o termo da condicional CASE. /// </summary> /// <param name="enumerator"></param> /// <param name="configuration"></param> /// <returns></returns> private static CaseConditional GetCaseConditional(ref IEnumerator <Text.InterpreterExpression.Expression> enumerator, Text.InterpreterExpression.ILexerConfiguration configuration) { if (!enumerator.MoveNext()) { throw new ConditionalParserException("Expected input expression or WHEN keyword after CASE"); } ConditionalTerm inputExpression = null; var whenExpressions = new List <CaseWhenExpression>(); if (enumerator.Current.Token != (int)Parser.SqlTokenID.kWhen) { inputExpression = GetTerm(ref enumerator, configuration); if (!enumerator.MoveNext()) { throw new ConditionalParserException("Expected expression WHEN"); } } if (enumerator.Current.Token == (int)Parser.SqlTokenID.kWhen) { while (enumerator.Current.Token == (int)Parser.SqlTokenID.kWhen) { if (!enumerator.MoveNext()) { throw new ConditionalParserException("Expected expression after WHEN"); } IEnumerator <Text.InterpreterExpression.Expression> enumerator2 = new StopControlEnumerator(enumerator, new StopControlEnumerator.ContainerStartStop[] { new StopControlEnumerator.ContainerStartStop("CASE", "END") }, new string[] { "THEN" }, StringComparer.InvariantCultureIgnoreCase); var expression = GetTerm(ref enumerator2, configuration); if (!enumerator.MoveNext() || enumerator.Current.Token != (int)Parser.SqlTokenID.kThen) { throw new ConditionalParserException(string.Format("Expected THEN after {0}", expression.ToString())); } if (!enumerator2.MoveNext()) { throw new ConditionalParserException("Expected expression after THEN"); } enumerator2 = new StopControlEnumerator(enumerator, new StopControlEnumerator.ContainerStartStop[] { new StopControlEnumerator.ContainerStartStop("CASE", "END") }, new string[] { "THEN", "ELSE", "END" }, StringComparer.InvariantCultureIgnoreCase); var resultExpression = GetTerm(ref enumerator2, configuration); whenExpressions.Add(new CaseWhenExpression(expression, resultExpression)); if (!enumerator2.MoveNext()) { break; } } } else { throw new ConditionalParserException("Expected expression WHEN"); } ConditionalTerm elseExpression = null; if (enumerator.Current.Token == (int)Parser.SqlTokenID.kElse) { if (enumerator.MoveNext()) { IEnumerator <Text.InterpreterExpression.Expression> enumerator2 = new StopControlEnumerator(enumerator, new StopControlEnumerator.ContainerStartStop[] { new StopControlEnumerator.ContainerStartStop("CASE", "END") }, new string[] { "END" }, StringComparer.InvariantCultureIgnoreCase); elseExpression = GetTerm(ref enumerator2, configuration); } if (elseExpression is FunctionCall && enumerator.Current.Token == (int)Parser.SqlTokenID.kEnd) { } else if (!enumerator.MoveNext()) { throw new ConditionalParserException("Expected expression END"); } } if (enumerator.Current.Token == (int)Parser.SqlTokenID.kEnd) { return(new CaseConditional(inputExpression, whenExpressions, elseExpression)); } throw new ConditionalParserException("Expected expression END"); }
/// <summary> /// Recupera a formula contida nas expressões. /// </summary> /// <param name="enumerator"></param> /// <param name="configuration"></param> /// <param name="firstPart"></param> /// <returns></returns> private static Formula GetFormula(ref IEnumerator <Text.InterpreterExpression.Expression> enumerator, Text.InterpreterExpression.ILexerConfiguration configuration, ConditionalTerm firstPart) { var formula = new Formula(); formula.Parts.Add(firstPart); formula.Operators.Add(Formula.GetMathematicalOperator(enumerator.Current)); while (true) { if (!enumerator.MoveNext()) { throw new ConditionalParserException(string.Format("Expected expression after mathematical operator {0}", formula.Operators.First().ToString())); } var part = GetTerm(ref enumerator, configuration); if (!enumerator.MoveNext()) { formula.Parts.Add(part); break; } if (part is Column && (enumerator.Current.Token == (int)Text.InterpreterExpression.TokenID.LParen)) { part = GetFunctionCall(ref enumerator, configuration, ')', (Column)part); } formula.Parts.Add(part); if (Formula.IsArithmeticOperator(enumerator.Current)) { formula.Operators.Add(Formula.GetMathematicalOperator(enumerator.Current)); } else { break; } } return(formula); }
/// <summary> /// Recupera o valor do termo condicional. /// </summary> /// <param name="enumerator"></param> /// <param name="configuration"></param> /// <returns></returns> private static ConditionalTerm GetTerm(ref IEnumerator <Text.InterpreterExpression.Expression> enumerator, Text.InterpreterExpression.ILexerConfiguration configuration) { var item = enumerator.Current; if (item.Token == (int)Text.InterpreterExpression.TokenID.Minus) { if (!enumerator.MoveNext()) { throw new ConditionalParserException("Expected expression after minus"); } return(new MinusTerm(GetTerm(ref enumerator, configuration))); } else if (item.Token == (int)Parser.SqlTokenID.kCase) { return(GetCaseConditional(ref enumerator, configuration)); } var container = item.Text.Length > 0 && item.Token != (int)Colosoft.Text.InterpreterExpression.TokenID.StringLiteral ? Array.Find(configuration.Containers, f => f.Start == item.Text[0]) : null; if (container != null) { enumerator.MoveNext(); return(GetContainer(ref enumerator, configuration, container)); } var expression = new Parser.SqlExpression(item); if (expression.Type == Parser.SqlExpressionType.Column) { return(new Column(expression)); } else if (expression.Type == Parser.SqlExpressionType.Variable) { return(new Variable(expression.Value.Text)); } return(new Constant(item.ToString())); }