Exemplo n.º 1
0
        private static void ValidateArgumentList(ParseTreeNode args, params string[] validArgs)
        {
            if (args != null)
            {
                var dups = args.ChildNodes
                           .GroupBy(a => a.FindToken().ValueString.ToLower())
                           .Select(a => new { Name = a.Key, Count = a.Count() })
                           .Where(a => a.Count > 1)
                           .FirstOrDefault();

                if (dups != null)
                {
                    throw args.GetException($"Argument {dups.Name} was specified more than once in function {args.FindToken().ValueString}");
                }

                var invalidArgs = args.ChildNodes
                                  .Select(a => a.FindToken())
                                  .Where(a => !a.ValueString.ToLower().IsIn(validArgs));

                if (invalidArgs.Any())
                {
                    var badArg = invalidArgs.First();
                    throw badArg.GetException($"Invalid argument '{badArg.ValueString}'");
                }
            }
        }
Exemplo n.º 2
0
        private static bool GetSwitchValue(this ParseTreeNode switchArgNode, string argumentName, bool defaultValue = false)
        {
            if (switchArgNode.ChildNodes.Any() && switchArgNode.ChildNodes[0].FindToken().ValueString.ToLower() != argumentName.ToLower())
            {
                throw switchArgNode.GetException("Invalid argument");
            }

            switch (switchArgNode.ChildNodes.Count)
            {
            case 0:
                return(defaultValue);

            case 1:
                return(true);

            case 2:
                return(switchArgNode.ChildNodes[1].FindToken().ValueString.As <bool>());

            default:
                throw switchArgNode.GetException("Invalid switch argument");
            }
        }
Exemplo n.º 3
0
        private static bool TryGetNamedArgumentValue <T>(ParseTreeNode argsListNode, string argName, out T value, bool required)
        {
            value = default;
            bool found = false;

            if (argsListNode.ChildNodes.Any())
            {
                var arg = argsListNode.ChildNodes.FirstOrDefault(a => a.ChildNodes[0].FindToken().ValueString.ToLower() == argName);
                if (arg != null)
                {
                    var actualArgName = arg.ChildNodes[0].FindToken().ValueString;

                    if (typeof(T) == typeof(Regex))
                    {
                        value = (T)(object)GetTokenAsRegex(arg.ChildNodes[1].FindToken());
                        found = true;
                    }
                    else if (arg.ChildNodes.Count > 1)
                    {
                        var actualArgValue = arg.ChildNodes[1].FindToken().ValueString;

                        try
                        {
                            value = arg.ChildNodes[1].FindToken().ValueString.As <T>();
                            found = true;
                        }
                        catch (Exception e) when(e is InvalidCastException || e is FormatException)
                        {
                            throw arg.GetException($"Invalid value '{actualArgValue}' for argument '{actualArgName}'. Expected a {typeof(T)} type");
                        }
                    }
                    else if (typeof(T) == typeof(bool))
                    {
                        value = (T)(object)true;
                        found = true;
                    }
                    else
                    {
                        throw arg.GetException($"Expected a value of type {typeof(T)} for argument '{actualArgName}'");
                    }
                }
            }

            if (required && !found)
            {
                throw argsListNode.GetException($"Missing required argument {argName}");
            }
            return(found);
        }
Exemplo n.º 4
0
        private static ExpTreeNode GetAsExpressionTree(this ParseTreeNode parsedNode, ExpTreeNode parentExpNode)
        {
            //The current node is a variable / value token. Create a value node and return it back
            if (!parsedNode.ChildNodes.Any())
            {
                switch (parsedNode.Term.Name)
                {
                case "variable":
                {
                    var varName = parsedNode.FindTokenAndGetValue <string>();
                    return(new VariableValue(varName, parentExpNode));
                }

                case "boolean":
                    return(new LiteralValue(parsedNode.FindTokenAndGetValue <bool>(), parentExpNode));

                case "integer":
                case "decimal":
                    return(new LiteralValue(parsedNode.FindTokenAndGetValue <double>(), parentExpNode));

                case "SingleQuoteString":
                case "DoubleQuoteString":
                    return(new LiteralValue(parsedNode.FindTokenAndGetValue <string>(), parentExpNode));

                default:
                    throw parsedNode.GetException($"Invalid token type '{parsedNode.Term.Name}' in expression");
                }
            }

            // Look on the next node down
            else if (parsedNode.ChildNodes.Count == 1)
            {
                return(GetAsExpressionTree(parsedNode.ChildNodes[0], parentExpNode));
            }

            //Ignore parenthesis, the middle non-terminal is what we want
            // Look on the next node down
            else if (parsedNode.ChildNodes.Count == 3 && parsedNode.ChildNodes[0]?.Token?.Text == "(")
            {
                return(GetAsExpressionTree(parsedNode.ChildNodes[1], parentExpNode));
            }

            //Binary operator
            else if (parsedNode.ChildNodes.Count == 3)
            {
                BinaryOperatorBase binaryOp;
                var opStr = parsedNode.ChildNodes[1].FindToken().ValueString;
                switch (opStr)
                {
                // Math
                case "+":
                    binaryOp = new AdditionOperator(parentExpNode);
                    break;

                case "-":
                    binaryOp = new SubtractionOperator(parentExpNode);
                    break;

                case "*":
                    binaryOp = new MultiplacationOperator(parentExpNode);
                    break;

                case "/":
                    binaryOp = new DivisionOperator(parentExpNode);
                    break;

                case "%":
                    binaryOp = new ModulusOperator(parentExpNode);
                    break;

                case "^":
                    binaryOp = new PowerOperator(parentExpNode);
                    break;

                // Bool
                case "~==":
                    binaryOp = new LooseEqualsOperator(parentExpNode);
                    break;

                case "~!=":
                    binaryOp = new LooseNotEqualsOperator(parentExpNode);
                    break;

                case "==":
                    binaryOp = new EqualsOperator(parentExpNode);
                    break;

                case "!=":
                    binaryOp = new NotEqualsOperator(parentExpNode);
                    break;

                case "like":
                    binaryOp = new LikeOperator(parentExpNode);
                    break;

                case "match":
                    binaryOp = new MatchOperator(parentExpNode);
                    break;

                case ">":
                    binaryOp = new GreaterThanOperator(parentExpNode);
                    break;

                case ">=":
                    binaryOp = new GreaterThanOrEqualOperator(parentExpNode);
                    break;

                case "<":
                    binaryOp = new LessThanOperator(parentExpNode);
                    break;

                case "<=":
                    binaryOp = new LessThanOrEqualOperator(parentExpNode);
                    break;

                case "&&":
                    binaryOp = new AndOperator(parentExpNode);
                    break;

                case "||":
                    binaryOp = new OrOperator(parentExpNode);
                    break;

                default:
                    throw parsedNode.ChildNodes[1].GetException($"Unrecognized operator '{opStr}'");
                }

                binaryOp.LeftOperand  = GetAsExpressionTree(parsedNode.ChildNodes[0], binaryOp);
                binaryOp.RightOperand = GetAsExpressionTree(parsedNode.ChildNodes[2], binaryOp);

                //Optimize
                if (binaryOp.LeftOperand is LiteralValue && binaryOp.RightOperand is LiteralValue)
                {
                    return(new LiteralValue(binaryOp.Eval(), parentExpNode));
                }

                return(binaryOp);
            }

            // Unary operator
            else if (parsedNode.ChildNodes.Count == 2)
            {
                var opVal = parsedNode.ChildNodes[0].FindToken().Value;
                UnaryOperatorBase unaryOp;
                if (parsedNode.ChildNodes[0].FindToken().Value is TypeCode convertType)
                {
                    unaryOp = new TypeConversionOperator(convertType, parentExpNode);
                }
                else
                {
                    var opStr = opVal.ToString();
                    switch (opStr)
                    {
                    case "!":
                        unaryOp = new NotOperator(parentExpNode);
                        break;

                    //Property Checking
                    case "lengthof":
                        unaryOp = new LengthOperator(parentExpNode);
                        break;

                    case "typeof":
                        unaryOp = new TypeOperator(parentExpNode);
                        break;

                    default:
                        unaryOp = new GenericUnaryMathFunctionOperator(opStr, parentExpNode);
                        break;
                    }
                }

                unaryOp.Operand = GetAsExpressionTree(parsedNode.ChildNodes[1], unaryOp);

                //Optimize
                if (unaryOp.Operand is LiteralValue)
                {
                    return(new LiteralValue(unaryOp.Eval(), parentExpNode));
                }

                return(unaryOp);
            }

            else
            {
                throw parsedNode.GetException($"Invalid number of tokens ({parsedNode.ChildNodes.Count})");
            }
        }
Exemplo n.º 5
0
 private static T FindTokenAndGetValue <T>(this ParseTreeNode node)
 {
     try { return(node.FindToken().ValueString.As <T>()); }
     catch { throw node.GetException($"Invalid token '{node.FindTokenAndGetText()}'. Expected a token of type {typeof(T)}"); }
 }