コード例 #1
0
        public sealed override PrecedenceKind GetPrecedenceKind(OperatorPrecedence precedence)
        {
            switch (precedence)
            {
            case OperatorPrecedence.NullCoalescing:
                return(PrecedenceKind.Coalesce);

            case OperatorPrecedence.ConditionalOr:
            case OperatorPrecedence.ConditionalAnd:
                return(PrecedenceKind.Logical);

            case OperatorPrecedence.LogicalOr:
            case OperatorPrecedence.LogicalXor:
            case OperatorPrecedence.LogicalAnd:
                return(PrecedenceKind.Bitwise);

            case OperatorPrecedence.Equality:
                return(PrecedenceKind.Equality);

            case OperatorPrecedence.RelationalAndTypeTesting:
                return(PrecedenceKind.Relational);

            case OperatorPrecedence.Shift:
                return(PrecedenceKind.Shift);

            case OperatorPrecedence.Additive:
            case OperatorPrecedence.Multiplicative:
                return(PrecedenceKind.Arithmetic);

            default:
                return(PrecedenceKind.Other);
            }
        }
コード例 #2
0
 public void Stringify(
     StringBuilder builder,
     OperatorPrecedence caller,
     Dictionary <string, IExpression> variables
     )
 {
     builder.Append("\"" + Value + "\"");
 }
コード例 #3
0
 public void Stringify(
     StringBuilder builder,
     OperatorPrecedence caller,
     Dictionary <string, IExpression> variables
     )
 {
     builder.Append(Value.ToString("0.####"));
     //builder.Append(" ");
     builder.Append(Units.PrettyPrint());
 }
コード例 #4
0
ファイル: ExprNodeLtr.cs プロジェクト: MoJoActive/MiniME
        public override OperatorPrecedence GetPrecedence()
        {
            OperatorPrecedence precedence = PrecedenceOfToken(Terms[0].Op);

            // Check all terms have the same precedence
            foreach (var t in Terms)
            {
                System.Diagnostics.Debug.Assert(PrecedenceOfToken(t.Op) == precedence);
            }

            return(precedence);
        }
コード例 #5
0
        private static bool IsFixable(SyntaxNode node, SyntaxKind parentKind)
        {
            if (node != null)
            {
                int groupNumber = GetGroupNumber(parentKind);

                return(groupNumber != 0 &&
                       groupNumber == GetGroupNumber(node) &&
                       OperatorPrecedence.GetPrecedence(node) < OperatorPrecedence.GetPrecedence(parentKind));
            }

            return(false);
        }
コード例 #6
0
 public void Stringify(
     StringBuilder builder,
     OperatorPrecedence caller,
     Dictionary <string, IExpression> variables
     )
 {
     if (variables.ContainsKey(Name))
     {
         variables[Name].Stringify(builder, caller, variables);
     }
     else
     {
         builder.Append(Name);
     }
 }
コード例 #7
0
ファイル: BoundNodePrinter.cs プロジェクト: kthompson/panther
 private void WriteNestedExpression(BoundExpression node, OperatorPrecedence parentPrecedence)
 {
     if (node is BoundBinaryExpression binaryExpression)
     {
         WriteNestedExpression(
             binaryExpression,
             parentPrecedence,
             binaryExpression.Operator.SyntaxKind.GetBinaryOperatorPrecedence()
             ?? throw new Exception("Invalid operator")
             );
     }
     else
     {
         node.Accept(this);
     }
 }
コード例 #8
0
ファイル: BoundNodePrinter.cs プロジェクト: kthompson/panther
 private void WriteNestedExpression(
     BoundNode node,
     OperatorPrecedence parent,
     OperatorPrecedence current
     )
 {
     if (parent >= current)
     {
         _writer.WritePunctuation("(");
         node.Accept(this);
         _writer.WritePunctuation(")");
     }
     else
     {
         node.Accept(this);
     }
 }
コード例 #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OperatorToken"/> struct.
        /// </summary>
        /// <param name="operatorType">Type of the operator.</param>
        public OperatorToken(OperatorType operatorType)
        {
            if (operatorType != OperatorType.Add &&
                operatorType != OperatorType.Divide &&
                operatorType != OperatorType.Multiply &&
                operatorType != OperatorType.Subtract &&
                operatorType != OperatorType.RaiseTo &&
                operatorType != OperatorType.Modulo &&
                operatorType != OperatorType.UnaryMinus)
            {
                throw new ArgumentException("The operator type is not of a valid type.", "operatorType");
            }

            this._operatorType = operatorType;
            this._precedence = operatorType.GetOperatorPrecedence();
            this._associativity = operatorType.GetAssociativity();
            this._argumentCount = operatorType.GetArgumentCount();
        }
コード例 #10
0
        public static void AnalyzeAwaitExpression(SyntaxNodeAnalysisContext context)
        {
            var awaitExpression = (AwaitExpressionSyntax)context.Node;

            ExpressionSyntax expression = awaitExpression.Expression;

            if (expression?.IsKind(SyntaxKind.ParenthesizedExpression) == true)
            {
                var parenthesizedExpression = (ParenthesizedExpressionSyntax)expression;

                ExpressionSyntax innerExpression = parenthesizedExpression.Expression;

                if (innerExpression != null
                    && OperatorPrecedence.GetPrecedence(innerExpression.Kind()) <= OperatorPrecedence.GetPrecedence(SyntaxKind.AwaitExpression))
                {
                    AnalyzeParenthesizedExpression(context, parenthesizedExpression);
                }
            }
        }
コード例 #11
0
        public void Stringify(
            StringBuilder builder,
            OperatorPrecedence caller,
            Dictionary <string, IExpression> variables
            )
        {
            if (caller < OperatorPrecedence.AdditionSubtraction)
            {
                builder.Append("(");
            }

            Left.Stringify(builder, OperatorPrecedence.AdditionSubtraction, variables);
            builder.Append(" + ");
            Right.Stringify(builder, OperatorPrecedence.AdditionSubtraction, variables);

            if (caller < OperatorPrecedence.AdditionSubtraction)
            {
                builder.Append(")");
            }
        }
コード例 #12
0
        public void Stringify(
            StringBuilder builder,
            OperatorPrecedence caller,
            Dictionary <string, IExpression> variables
            )
        {
            if (caller < OperatorPrecedence.MultiplicationDivision)
            {
                builder.Append("(");
            }

            Left.Stringify(builder, OperatorPrecedence.MultiplicationDivision, variables);
            builder.Append(" ÷ ");
            Right.Stringify(builder, OperatorPrecedence.MultiplicationDivision, variables);

            if (caller < OperatorPrecedence.MultiplicationDivision)
            {
                builder.Append(")");
            }
        }
コード例 #13
0
    private TreeNode parseBinaryOperator(OperatorPrecedence minPrecedence = OperatorPrecedence.Min)
    {
        TreeNode result = parseUnaryOperator();

        while (isBinaryOperator())
        {
            string             op          = peek();
            OperatorPrecedence precendence = operatorPrecedence[op];

            if (precendence >= minPrecedence)
            {
                advance();
                result = new BinaryOperator(op, result, this.parseBinaryOperator(minPrecedence + 1));
            }
            else
            {
                break;
            }
        }

        return(result);
    }
コード例 #14
0
        public static void AnalyzeAwaitExpression(SyntaxNodeAnalysisContext context)
        {
            var awaitExpression = (AwaitExpressionSyntax)context.Node;

            if (!(awaitExpression.Expression is ParenthesizedExpressionSyntax parenthesizedExpression))
            {
                return;
            }

            ExpressionSyntax expression = parenthesizedExpression.Expression;

            if (expression?.IsMissing != false)
            {
                return;
            }

            if (OperatorPrecedence.GetPrecedence(expression.Kind()) > OperatorPrecedence.GetPrecedence(SyntaxKind.AwaitExpression))
            {
                return;
            }

            AnalyzeParenthesizedExpression(context, parenthesizedExpression);
        }
コード例 #15
0
 /**
  * <summary>
  *  Constructor for the Operator class.
  * </summary>
  * <param name="Character">
  *  Which operator it is.
  * </param>
  * <param name="Precedence">
  *  What the precedence is.
  * </param>
  */
 public Operator(char Character, OperatorPrecedence Precedence)
 {
     this.Character  = Character;
     this.Precedence = Precedence;
     return;
 }
コード例 #16
0
 public Operator(OperatorType type, OperatorPrecedence precedence)
 {
     Type       = type;
     Precedence = precedence;
 }
コード例 #17
0
 public string ToGroupedString(OperatorPrecedence surroundingPrecedence)
 {
     return(surroundingPrecedence > ExpressionPrecedence ? $"({this})" : ToString());
 }
コード例 #18
0
 public ParametrizedCode Build(OperatorPrecedence operatorPrecedence) =>
 new ParametrizedCode(stringParts.ToArray(), parameters.ToArray(), operatorPrecedence);
コード例 #19
0
        private IExpression CompileExpression(Queue <Token> tokens, OperatorPrecedence minimumPrecedence, IList <string> variables, bool isWithinFunction)
        {
            if (tokens == null)
            {
                throw new ArgumentNullException(nameof(tokens), "You must call Tokenise before compiling");
            }

            IExpression leftHandSide  = null;
            var         currentToken  = tokens.PeekOrDefault();
            Token       previousToken = null;

            while (currentToken != null)
            {
                if (this.registeredOperators.TryGetValue(currentToken.CurrentToken, out var op)) // Are we an IOperator?
                {
                    var precedence = op.GetPrecedence(previousToken);

                    if (precedence > minimumPrecedence)
                    {
                        tokens.Dequeue();

                        if (!op.CanGetCaptiveTokens(previousToken, currentToken, tokens))
                        {
                            // Do it anyway to update the list of tokens
                            op.GetCaptiveTokens(previousToken, currentToken, tokens);
                            break;
                        }
                        else
                        {
                            IExpression rightHandSide = null;

                            var captiveTokens = op.GetCaptiveTokens(previousToken, currentToken, tokens);

                            if (captiveTokens.Length > 1)
                            {
                                var innerTokens = op.GetInnerCaptiveTokens(captiveTokens);
                                rightHandSide = this.CompileExpression(new Queue <Token>(innerTokens), OperatorPrecedence.Minimum, variables, isWithinFunction);

                                currentToken = captiveTokens[captiveTokens.Length - 1];
                            }
                            else
                            {
                                rightHandSide = this.CompileExpression(tokens, precedence, variables, isWithinFunction);
                                // We are at the end of an expression so fake it up.
                                currentToken = new Token(")", -1);
                            }

                            leftHandSide = op.BuildExpression(previousToken, new[] { leftHandSide, rightHandSide }, this.options);
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                else if (this.registeredFunctions.TryGetValue(currentToken.CurrentToken, out var function)) // or an IFunction?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    var expressions   = new List <IExpression>();
                    var captiveTokens = new Queue <Token>();
                    var parenCount    = 0;
                    tokens.Dequeue();

                    // Loop through the list of tokens and split by ParameterSeparator character
                    while (tokens.Count > 0)
                    {
                        var nextToken = tokens.Dequeue();

                        if (string.Equals(nextToken.CurrentToken, "(", StringComparison.Ordinal))
                        {
                            parenCount++;
                        }
                        else if (string.Equals(nextToken.CurrentToken, ")", StringComparison.Ordinal))
                        {
                            parenCount--;
                        }

                        if (!(parenCount == 1 && nextToken.CurrentToken == "(") &&
                            !(parenCount == 0 && nextToken.CurrentToken == ")"))
                        {
                            captiveTokens.Enqueue(nextToken);
                        }

                        if (parenCount == 0 &&
                            captiveTokens.Any())
                        {
                            expressions.Add(this.CompileExpression(captiveTokens, minimumPrecedence: OperatorPrecedence.Minimum, variables: variables, isWithinFunction: true));
                            captiveTokens.Clear();
                        }
                        else if (string.Equals(nextToken.CurrentToken, ParameterSeparator.ToString(), StringComparison.Ordinal) && parenCount == 1)
                        {
                            // TODO: Should we expect expressions to be null???
                            expressions.Add(this.CompileExpression(captiveTokens, minimumPrecedence: 0, variables: variables, isWithinFunction: true));
                            captiveTokens.Clear();
                        }

                        if (parenCount <= 0)
                        {
                            break;
                        }
                    }

                    leftHandSide = new FunctionExpression(currentToken.CurrentToken, function, expressions.ToArray());
                }
                else if (currentToken.CurrentToken.IsNumeric(this.currentCulture)) // Or a number
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();

                    if (int.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.currentCulture, out var intValue))
                    {
                        leftHandSide = new ConstantValueExpression(intValue);
                    }
                    else if (decimal.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.currentCulture, out var decimalValue))
                    {
                        leftHandSide = new ConstantValueExpression(decimalValue);
                    }
                    else if (double.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.currentCulture, out var doubleValue))
                    {
                        leftHandSide = new ConstantValueExpression(doubleValue);
                    }
                    else if (float.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.currentCulture, out var floatValue))
                    {
                        leftHandSide = new ConstantValueExpression(floatValue);
                    }
                    else if (long.TryParse(currentToken.CurrentToken, NumberStyles.Any, this.currentCulture, out var longValue))
                    {
                        leftHandSide = new ConstantValueExpression(longValue);
                    }
                }
                else if (currentToken.CurrentToken.StartsWith("[") && currentToken.CurrentToken.EndsWith("]")) // or a variable?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    var variableName = currentToken.CurrentToken.Replace("[", "").Replace("]", "");
                    leftHandSide = new VariableExpression(variableName);

                    if (!variables.Contains(variableName, this.stringComparer))
                    {
                        variables.Add(variableName);
                    }
                }
                else if (string.Equals(currentToken.CurrentToken, "true", StringComparison.OrdinalIgnoreCase)) // or a boolean?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    leftHandSide = new ConstantValueExpression(true);
                }
                else if (string.Equals(currentToken.CurrentToken, "false", StringComparison.OrdinalIgnoreCase))
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    leftHandSide = new ConstantValueExpression(false);
                }
                else if (string.Equals(currentToken.CurrentToken, "null", StringComparison.OrdinalIgnoreCase)) // or a null?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    leftHandSide = new ConstantValueExpression(null);
                }
                else if (currentToken.CurrentToken.StartsWith(DateSeparator.ToString()) && currentToken.CurrentToken.EndsWith(DateSeparator.ToString())) // or a date?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();

                    var dateToken = currentToken.CurrentToken.Replace(DateSeparator.ToString(), "");

                    // If we can't parse the date let's check for some known tags.
                    if (!DateTime.TryParse(dateToken, out var date))
                    {
                        if (string.Equals("TODAY", dateToken, StringComparison.OrdinalIgnoreCase))
                        {
                            date = DateTime.Today;
                        }
                        else if (string.Equals("NOW", dateToken, StringComparison.OrdinalIgnoreCase))
                        {
                            date = DateTime.Now;
                        }
                        else
                        {
                            throw new UnrecognisedTokenException(dateToken);
                        }
                    }

                    leftHandSide = new ConstantValueExpression(date);
                }
                else if ((currentToken.CurrentToken.StartsWith("'") && currentToken.CurrentToken.EndsWith("'")) ||
                         (currentToken.CurrentToken.StartsWith("\"") && currentToken.CurrentToken.EndsWith("\"")))
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    leftHandSide = new ConstantValueExpression(CleanString(currentToken.CurrentToken.Substring(1, currentToken.Length - 2)));
                }
                else if (string.Equals(currentToken.CurrentToken, ParameterSeparator.ToString(), StringComparison.Ordinal)) // Make sure we ignore the parameter separator
                {
                    if (!isWithinFunction)
                    {
                        throw new ExpressiveException($"Unexpected token '{currentToken.CurrentToken}' at position {currentToken.StartIndex}");
                    }
                    tokens.Dequeue();
                }
                else
                {
                    tokens.Dequeue();

                    if (options.HasFlag(ExpressiveOptions.UnknownTokensAsVariables))
                    {
                        this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                        var variableName = currentToken.CurrentToken;
                        leftHandSide = new VariableExpression(variableName);

                        if (!variables.Contains(variableName, this.stringComparer))
                        {
                            variables.Add(variableName);
                        }
                    }
                    else
                    {
                        throw new UnrecognisedTokenException(currentToken.CurrentToken);
                    }
                }

                previousToken = currentToken;
                currentToken  = tokens.PeekOrDefault();
            }

            return(leftHandSide);
        }
コード例 #20
0
        private IExpression CompileExpression(Queue <Token> tokens, OperatorPrecedence minimumPrecedence, IList <string> variables, bool isWithinFunction)
        {
            if (tokens == null)
            {
                throw new ArgumentNullException("tokens", "You must call Tokenise before compiling");
            }

            IExpression leftHandSide  = null;
            var         currentToken  = tokens.PeekOrDefault();
            Token       previousToken = null;

            while (currentToken != null)
            {
                Func <IExpression[], IDictionary <string, object>, object> function = null;
                IOperator op = null;

                if (_registeredOperators.TryGetValue(currentToken.CurrentToken, out op)) // Are we an IOperator?
                {
                    var precedence = op.GetPrecedence(previousToken);

                    if (precedence > minimumPrecedence)
                    {
                        tokens.Dequeue();

                        if (!op.CanGetCaptiveTokens(previousToken, currentToken, tokens))
                        {
                            // Do it anyway to update the list of tokens
                            op.GetCaptiveTokens(previousToken, currentToken, tokens);
                            break;
                        }
                        else
                        {
                            IExpression rightHandSide = null;

                            var captiveTokens = op.GetCaptiveTokens(previousToken, currentToken, tokens);

                            if (captiveTokens.Length > 1)
                            {
                                var innerTokens = op.GetInnerCaptiveTokens(captiveTokens);
                                rightHandSide = CompileExpression(new Queue <Token>(innerTokens), OperatorPrecedence.Minimum, variables, isWithinFunction);

                                currentToken = captiveTokens[captiveTokens.Length - 1];
                            }
                            else
                            {
                                rightHandSide = CompileExpression(tokens, precedence, variables, isWithinFunction);
                                // We are at the end of an expression so fake it up.
                                currentToken = new Token(")", -1);
                            }

                            leftHandSide = op.BuildExpression(previousToken, new[] { leftHandSide, rightHandSide }, _options);
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                else if (_registeredFunctions.TryGetValue(currentToken.CurrentToken, out function)) // or an IFunction?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    var expressions   = new List <IExpression>();
                    var captiveTokens = new Queue <Token>();
                    var parenCount    = 0;
                    tokens.Dequeue();

                    // Loop through the list of tokens and split by ParameterSeparator character
                    while (tokens.Count > 0)
                    {
                        var nextToken = tokens.Dequeue();

                        if (string.Equals(nextToken.CurrentToken, "(", StringComparison.Ordinal))
                        {
                            parenCount++;
                        }
                        else if (string.Equals(nextToken.CurrentToken, ")", StringComparison.Ordinal))
                        {
                            parenCount--;
                        }

                        if (!(parenCount == 1 && nextToken.CurrentToken == "(") &&
                            !(parenCount == 0 && nextToken.CurrentToken == ")"))
                        {
                            captiveTokens.Enqueue(nextToken);
                        }

                        if (parenCount == 0 &&
                            captiveTokens.Any())
                        {
                            expressions.Add(CompileExpression(captiveTokens, minimumPrecedence: OperatorPrecedence.Minimum, variables: variables, isWithinFunction: true));
                            captiveTokens.Clear();
                        }
                        else if (string.Equals(nextToken.CurrentToken, ParameterSeparator.ToString(), StringComparison.Ordinal) && parenCount == 1)
                        {
                            // TODO: Should we expect expressions to be null???
                            expressions.Add(CompileExpression(captiveTokens, minimumPrecedence: 0, variables: variables, isWithinFunction: true));
                            captiveTokens.Clear();
                        }

                        if (parenCount <= 0)
                        {
                            break;
                        }
                    }

                    leftHandSide = new FunctionExpression(currentToken.CurrentToken, function, expressions.ToArray());
                }
                else if (currentToken.CurrentToken.IsNumeric()) // Or a number
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    int     intValue     = 0;
                    decimal decimalValue = 0.0M;
                    double  doubleValue  = 0.0;
                    float   floatValue   = 0.0f;
                    long    longValue    = 0;

                    if (int.TryParse(currentToken.CurrentToken, out intValue))
                    {
                        leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Integer, intValue);
                    }
                    else if (decimal.TryParse(currentToken.CurrentToken, out decimalValue))
                    {
                        leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Decimal, decimalValue);
                    }
                    else if (double.TryParse(currentToken.CurrentToken, out doubleValue))
                    {
                        leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Double, doubleValue);
                    }
                    else if (float.TryParse(currentToken.CurrentToken, out floatValue))
                    {
                        leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Float, floatValue);
                    }
                    else if (long.TryParse(currentToken.CurrentToken, out longValue))
                    {
                        leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Long, longValue);
                    }
                }
                else if (currentToken.CurrentToken.StartsWith("[") && currentToken.CurrentToken.EndsWith("]")) // or a variable?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    string variableName = currentToken.CurrentToken.Replace("[", "").Replace("]", "");
                    leftHandSide = new VariableExpression(variableName);

                    if (!variables.Contains(variableName, _stringComparer))
                    {
                        variables.Add(variableName);
                    }
                }
                else if (string.Equals(currentToken.CurrentToken, "true", StringComparison.OrdinalIgnoreCase)) // or a boolean?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Boolean, true);
                }
                else if (string.Equals(currentToken.CurrentToken, "false", StringComparison.OrdinalIgnoreCase))
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Boolean, false);
                }
                else if (string.Equals(currentToken.CurrentToken, "null", StringComparison.OrdinalIgnoreCase)) // or a null?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Null, null);
                }
                else if (currentToken.CurrentToken.StartsWith(DateSeparator.ToString()) && currentToken.CurrentToken.EndsWith(DateSeparator.ToString())) // or a date?
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();

                    string   dateToken = currentToken.CurrentToken.Replace(DateSeparator.ToString(), "");
                    DateTime date      = DateTime.MinValue;

                    // If we can't parse the date let's check for some known tags.
                    if (!DateTime.TryParse(dateToken, out date))
                    {
                        if (string.Equals("TODAY", dateToken, StringComparison.OrdinalIgnoreCase))
                        {
                            date = DateTime.Today;
                        }
                        else if (string.Equals("NOW", dateToken, StringComparison.OrdinalIgnoreCase))
                        {
                            date = DateTime.Now;
                        }
                        else
                        {
                            throw new UnrecognisedTokenException(dateToken);
                        }
                    }

                    leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.DateTime, date);
                }
                else if ((currentToken.CurrentToken.StartsWith("'") && currentToken.CurrentToken.EndsWith("'")) ||
                         (currentToken.CurrentToken.StartsWith("\"") && currentToken.CurrentToken.EndsWith("\"")))
                {
                    this.CheckForExistingParticipant(leftHandSide, currentToken, isWithinFunction);

                    tokens.Dequeue();
                    leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.String, CleanString(currentToken.CurrentToken.Substring(1, currentToken.Length - 2)));
                }
                else if (string.Equals(currentToken.CurrentToken, ParameterSeparator.ToString(), StringComparison.Ordinal)) // Make sure we ignore the parameter separator
                {
                    // TODO should we throw an exception if we are not within a function?
                    if (!isWithinFunction)
                    {
                        throw new ExpressiveException($"Unexpected token '{currentToken}'");
                    }
                    tokens.Dequeue();

                    //throw new InvalidOperationException("Unrecognised token '" + currentToken + "'");

                    //if (!string.Equals(currentToken, ParameterSeparator.ToString(), StringComparison.Ordinal)) // Make sure we ignore the parameter separator
                    //{
                    //    currentToken = CleanString(currentToken);

                    //    leftHandSide = new ConstantValueExpression(ConstantValueExpressionType.Unknown, currentToken);
                    //}
                }
                else
                {
                    tokens.Dequeue();

                    throw new UnrecognisedTokenException(currentToken.CurrentToken);
                }

                previousToken = currentToken;
                currentToken  = tokens.PeekOrDefault();
            }

            return(leftHandSide);
        }
コード例 #21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OperatorPrecedenceAttribute"/> class.
 /// </summary>
 /// <param name="precedence">The precedence.</param>
 public OperatorPrecedenceAttribute(OperatorPrecedence precedence)
     : base()
 {
     this.Precedence = precedence;
 }
コード例 #22
0
ファイル: MathParser.cs プロジェクト: gratianlup/MathParser
 public OperatorStackItem(OperatorPrecedence precedence)
     : this(null, precedence)
 {
 }
コード例 #23
0
ファイル: MathParser.cs プロジェクト: gratianlup/MathParser
 public OperatorStackItem(IMathExpression expression, OperatorPrecedence precedence)
 {
     Expression = expression;
     Precedence = precedence;
 }
コード例 #24
0
        /// <summary>
        /// For expressions, we switch to a precedence climbing parser.
        /// </summary>
        public IExpressionSyntax ParseExpression(OperatorPrecedence minPrecedence)
        {
            var expression = ParseAtom();

            for (; ;)
            {
                IBinaryOperatorToken? @operator  = null;
                OperatorPrecedence?   precedence = null;
                var leftAssociative = true;
                switch (Tokens.Current)
                {
                case IEqualsToken _:
                case IPlusEqualsToken _:
                case IMinusEqualsToken _:
                case IAsteriskEqualsToken _:
                case ISlashEqualsToken _:
                    if (minPrecedence <= OperatorPrecedence.Assignment)
                    {
                        var assignmentOperator = BuildAssignmentOperator(Tokens.RequiredToken <IAssignmentToken>());
                        var rightOperand       = ParseExpression();
                        if (expression is IAssignableExpressionSyntax assignableExpression)
                        {
                            expression = new AssignmentExpressionSyntax(assignableExpression, assignmentOperator, rightOperand);
                        }
                        else
                        {
                            // Don't assign expression, so it is just the right hand side of the assignment
                            Add(ParseError.CantAssignIntoExpression(File, expression.Span));
                        }
                        continue;
                    }
                    break;

                case IQuestionQuestionToken _:
                    if (minPrecedence <= OperatorPrecedence.Coalesce)
                    {
                        precedence = OperatorPrecedence.Coalesce;
                        @operator  = Tokens.RequiredToken <IBinaryOperatorToken>();
                    }
                    break;

                case IOrKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.LogicalOr)
                    {
                        precedence = OperatorPrecedence.LogicalOr;
                        @operator  = Tokens.RequiredToken <IBinaryOperatorToken>();
                    }
                    break;

                case IAndKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.LogicalAnd)
                    {
                        precedence = OperatorPrecedence.LogicalAnd;
                        @operator  = Tokens.RequiredToken <IBinaryOperatorToken>();
                    }
                    break;

                case IEqualsEqualsToken _:
                case INotEqualToken _:
                    if (minPrecedence <= OperatorPrecedence.Equality)
                    {
                        precedence = OperatorPrecedence.Equality;
                        @operator  = Tokens.RequiredToken <IBinaryOperatorToken>();
                    }
                    break;

                case ILessThanToken _:
                case ILessThanOrEqualToken _:
                case IGreaterThanToken _:
                case IGreaterThanOrEqualToken _:
                case ILessThanColonToken _:     // Subtype operator
                case IAsKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.Relational)
                    {
                        precedence = OperatorPrecedence.Relational;
                        @operator  = Tokens.RequiredToken <IBinaryOperatorToken>();
                    }
                    break;

                case IDotDotToken _:
                case ILessThanDotDotToken _:
                case IDotDotLessThanToken _:
                case ILessThanDotDotLessThanToken _:
                    if (minPrecedence <= OperatorPrecedence.Range)
                    {
                        precedence = OperatorPrecedence.Range;
                        @operator  = Tokens.RequiredToken <IBinaryOperatorToken>();
                    }
                    break;

                case IPlusToken _:
                case IMinusToken _:
                    if (minPrecedence <= OperatorPrecedence.Additive)
                    {
                        precedence = OperatorPrecedence.Additive;
                        @operator  = Tokens.RequiredToken <IBinaryOperatorToken>();
                    }
                    break;

                case IAsteriskToken _:
                case ISlashToken _:
                    if (minPrecedence <= OperatorPrecedence.Multiplicative)
                    {
                        precedence = OperatorPrecedence.Multiplicative;
                        @operator  = Tokens.RequiredToken <IBinaryOperatorToken>();
                    }
                    break;

                case IDotToken _:
                case IQuestionDotToken _:
                    if (minPrecedence <= OperatorPrecedence.Primary)
                    {
                        // Member Access
                        var accessOperator = BuildAccessOperator(Tokens.RequiredToken <IAccessOperatorToken>());
                        var nameSyntax     = ParseName();
                        if (!(Tokens.Current is IOpenParenToken))
                        {
                            var memberAccessSpan = TextSpan.Covering(expression.Span, nameSyntax.Span);
                            expression = new QualifiedNameExpressionSyntax(memberAccessSpan, expression, accessOperator, nameSyntax.ToExpression());
                        }
                        else
                        {
                            Tokens.RequiredToken <IOpenParenToken>();
                            var arguments      = ParseArguments();
                            var closeParenSpan = Tokens.Expect <ICloseParenToken>();
                            var invocationSpan = TextSpan.Covering(expression.Span, closeParenSpan);
                            expression = new QualifiedInvocationExpressionSyntax(invocationSpan, expression, nameSyntax.Name, nameSyntax.Span, arguments);
                        }
                        continue;
                    }
                    break;

                default:
                    return(expression);
                }

                if (!(@operator is null) &&
                    precedence is OperatorPrecedence operatorPrecedence)
                {
                    if (leftAssociative)
                    {
                        operatorPrecedence += 1;
                    }

                    var rightOperand = ParseExpression(operatorPrecedence);
                    expression = BuildBinaryOperatorExpression(expression, @operator, rightOperand);
                }
コード例 #25
0
 public static JsSymbolicParameter CreateCodePlaceholder(string code, OperatorPrecedence operatorPrecedence) =>
 new JsSymbolicParameter(
     new CodeSymbolicParameter("AdHoc placeholder"),
     new CodeParameterAssignment(code, operatorPrecedence)
     );
コード例 #26
0
        /// <summary>
        /// For expressions, we switch to a precedence climbing parser.
        /// </summary>
        public ExpressionSyntax ParseExpression(OperatorPrecedence minPrecedence)
        {
            var expression = ParseAtom();

            for (; ;)
            {
                IOperatorToken     @operator  = null;
                OperatorPrecedence?precedence = null;
                var leftAssociative           = true;
                switch (Tokens.Current)
                {
                case IEqualsToken _:
                case IPlusEqualsToken _:
                case IMinusEqualsToken _:
                case IAsteriskEqualsToken _:
                case ISlashEqualsToken _:
                    if (minPrecedence <= OperatorPrecedence.Assignment)
                    {
                        precedence      = OperatorPrecedence.Assignment;
                        leftAssociative = false;
                        @operator       = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IQuestionQuestionToken _:
                    if (minPrecedence <= OperatorPrecedence.Coalesce)
                    {
                        precedence = OperatorPrecedence.Coalesce;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IOrKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.LogicalOr)
                    {
                        precedence = OperatorPrecedence.LogicalOr;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IAndKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.LogicalAnd)
                    {
                        precedence = OperatorPrecedence.LogicalAnd;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IEqualsEqualsToken _:
                case INotEqualToken _:
                    if (minPrecedence <= OperatorPrecedence.Equality)
                    {
                        precedence = OperatorPrecedence.Equality;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case ILessThanToken _:
                case ILessThanOrEqualToken _:
                case IGreaterThanToken _:
                case IGreaterThanOrEqualToken _:
                case ILessThanColonToken _:     // Subtype operator
                case IAsKeywordToken _:
                    if (minPrecedence <= OperatorPrecedence.Relational)
                    {
                        precedence = OperatorPrecedence.Relational;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IColonToken _:     // type kind
                    if (minPrecedence <= OperatorPrecedence.Relational)
                    {
                        var      colon = Tokens.Expect <IColonToken>();
                        TypeKind typeKind;
                        switch (Tokens.Current)
                        {
                        case IClassKeywordToken _:
                            typeKind = TypeKind.Class;
                            break;

                        case IStructKeywordToken _:
                            typeKind = TypeKind.Struct;
                            break;

                        default:
                            Tokens.Expect <ITypeKindKeywordToken>();
                            // We saw a colon without what we expected after, just assume it is missing
                            continue;
                        }
                        var typeKindSpan = Tokens.Expect <ITypeKindKeywordToken>();
                        var span         = TextSpan.Covering(colon, typeKindSpan);
                        expression = new TypeKindExpressionSyntax(span, typeKind);
                        continue;
                    }
                    break;

                case IDotDotToken _:
                case ILessThanDotDotToken _:
                case IDotDotLessThanToken _:
                case ILessThanDotDotLessThanToken _:
                    if (minPrecedence <= OperatorPrecedence.Range)
                    {
                        precedence = OperatorPrecedence.Range;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IPlusToken _:
                case IMinusToken _:
                    if (minPrecedence <= OperatorPrecedence.Additive)
                    {
                        precedence = OperatorPrecedence.Additive;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IAsteriskToken _:
                case ISlashToken _:
                    if (minPrecedence <= OperatorPrecedence.Multiplicative)
                    {
                        precedence = OperatorPrecedence.Multiplicative;
                        @operator  = Tokens.RequiredToken <IOperatorToken>();
                    }
                    break;

                case IDollarToken _:
                    if (minPrecedence <= OperatorPrecedence.Lifetime)
                    {
                        Tokens.Expect <IDollarToken>();
                        var(nameSpan, lifetime) = ParseLifetimeName();
                        expression = new ReferenceLifetimeSyntax(expression, nameSpan, lifetime);
                        continue;
                    }
                    break;

                case IQuestionToken _:
                    if (minPrecedence <= OperatorPrecedence.Unary)
                    {
                        var question = Tokens.Required <IQuestionToken>();
                        var span     = TextSpan.Covering(expression.Span, question);
                        expression = new UnaryExpressionSyntax(span, UnaryOperatorFixity.Postfix, UnaryOperator.Question, expression);
                        continue;
                    }
                    break;

                case IOpenParenToken _:
                    if (minPrecedence <= OperatorPrecedence.Primary)
                    {
                        var callee = expression;
                        Tokens.Expect <IOpenParenToken>();
                        var arguments      = ParseArguments();
                        var closeParenSpan = Tokens.Expect <ICloseParenToken>();
                        var span           = TextSpan.Covering(callee.Span, closeParenSpan);
                        expression = new InvocationSyntax(span, callee, arguments);
                        continue;
                    }
                    break;

                case IDotToken _:
                case ICaretDotToken _:
                case IQuestionDotToken _:
                    if (minPrecedence <= OperatorPrecedence.Primary)
                    {
                        // Member Access
                        var accessOperator = BuildAccessOperator(Tokens.RequiredToken <IAccessOperatorToken>());
                        var member         = ParseSimpleName();
                        var span           = TextSpan.Covering(expression.Span, member.Span);
                        expression = new MemberAccessExpressionSyntax(span, expression, accessOperator, member);
                        continue;
                    }
                    break;

                default:
                    return(expression);
                }

                if (@operator is IOperatorToken operatorToken &&
                    precedence is OperatorPrecedence operatorPrecedence)
                {
                    if (leftAssociative)
                    {
                        operatorPrecedence += 1;
                    }

                    var rightOperand = ParseExpression(operatorPrecedence);
                    expression = BuildOperatorExpression(expression, operatorToken, rightOperand);
                }