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}'"); } } }
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"); } }
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); }
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})"); } }
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)}"); } }