public void TestConditionParserInvalidConditions() { var conditionTests = new string[] { "$123", // Property names cannot start with a number "$_123", // Property names cannot start with an underscore "$1.23", // Property names cannot contain special characters "horizontal||$Prop[gt]1000",// OR is '|', not '||' "$Prop==1||$Prop==2" // OR is '|', not '||' }; var parseContext = new ParseContext(); ConditionParser parser = new ConditionParser(new ConditionFormat() { StatesUnderscored = false }); foreach (var test in conditionTests) { try { parser.Parse(test, parseContext); Assert.Fail("Parsing {0} succeeded", test); } catch { } } }
public IConditionTreeItem Parse(string input, ParseContext context) { var andList = new Stack<ConditionTreeLeaf>(); string[] conditions = input.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string condition in conditions) andList.Push(ParseLeaf(condition, context)); return LegacyConditionParser.AndListToTree(andList); }
public void TestConditionParserValidConditions() { var horizontal = new ConditionTreeLeaf(ConditionType.State, "horizontal", ConditionComparison.Equal, new PropertyUnion(true)); var propertyEq1 = new ConditionTreeLeaf(ConditionType.Property, "Property", ConditionComparison.Equal, new PropertyUnion(1)); var conditionTests = new Dictionary<string, IConditionTreeItem>() { { "horizontal", horizontal}, { "$Property==1", propertyEq1}, { "horizontal|$Property==1", new ConditionTree(ConditionTree.ConditionOperator.OR, horizontal, propertyEq1)}, { "horizontal,$Property==1", new ConditionTree(ConditionTree.ConditionOperator.AND, horizontal, propertyEq1)} }; var parseContext = new ParseContext(); parseContext.PropertyTypes.Add(new KeyValuePair<string,PropertyUnionType>("Property", PropertyUnionType.Double)); ConditionParser parser = new ConditionParser(new ConditionFormat() { StatesUnderscored = false }); foreach(var test in conditionTests) { var parsed = parser.Parse(test.Key, parseContext); Assert.AreEqual(test.Value, parsed); } }
public LoadContext() { Errors = new List<LoadError>(); ParseContext = new ParseContext(); }
public IConditionTreeItem Parse(string input, ParseContext context) { // Tokenize var output = new Queue<ConditionToken>(); var operators = new Stack<ConditionToken>(); var reader = new PositioningReader(new StringReader(input)); ConditionToken? token = ReadToken(reader); while (token.HasValue) { ConditionToken t = token.Value; if (t.Type == ConditionToken.TokenType.Symbol) output.Enqueue(t); else if (t.Type == ConditionToken.TokenType.LeftBracket) operators.Push(t); else if (t.Type == ConditionToken.TokenType.RightBracket) { ConditionToken n = operators.Pop(); while (n.Type != ConditionToken.TokenType.LeftBracket) { if (operators.Count == 0) { // Not enough operators throw new ConditionFormatException("Syntax error", 0, 0); } output.Enqueue(n); n = operators.Pop(); } if (operators.Count > 0 && operators.Peek() == ConditionToken.AND) output.Enqueue(operators.Pop()); } else if (t == ConditionToken.AND) { while (operators.Count > 0 && (operators.Peek() == ConditionToken.AND || operators.Peek() == ConditionToken.OR)) { output.Enqueue(operators.Pop()); } operators.Push(t); } else if (t == ConditionToken.OR) { while (operators.Count > 0 && (operators.Peek().Type == ConditionToken.TokenType.Operator && operators.Peek().Operator == ConditionToken.OperatorType.OR)) { output.Enqueue(operators.Pop()); } operators.Push(t); } token = ReadToken(reader); } while (operators.Count > 0) output.Enqueue(operators.Pop()); // Convert to tree Queue<ConditionToken> reversed = new Queue<ConditionToken>(output.Reverse()); return (ParseToken(reversed, context) as IConditionTreeItem); }
private IConditionTreeItem ParseToken(Queue<ConditionToken> r, ParseContext context) { if (r.Count == 0) throw new ConditionFormatException("Invalid condition", 0, 0); ConditionToken t = r.Dequeue(); if (t.Type == ConditionToken.TokenType.Symbol) return ParseLeaf(t, context); else if (t.Type == ConditionToken.TokenType.Operator && t.Operator == ConditionToken.OperatorType.AND) { IConditionTreeItem right = ParseToken(r, context); IConditionTreeItem left = ParseToken(r, context); return new ConditionTree( ConditionTree.ConditionOperator.AND, left, right); } else if (t.Type == ConditionToken.TokenType.Operator && t.Operator == ConditionToken.OperatorType.OR) { IConditionTreeItem right = ParseToken(r, context); IConditionTreeItem left = ParseToken(r, context); return new ConditionTree( ConditionTree.ConditionOperator.OR, left, right); } else throw new ArgumentException("Invalid queue.", "r"); }
private ConditionTreeLeaf ParseLeaf(ConditionToken token, ParseContext context) { bool isNegated; bool isState; string property; string comparisonStr; string compareToStr; SplitLeaf(token, out isNegated, out isState, out property, out comparisonStr, out compareToStr); if (compareToStr == String.Empty) compareToStr = "true"; // Implicit true ConditionComparison comparison; switch(comparisonStr) { case "==": comparison = ConditionComparison.Equal; break; case "!=": comparison = ConditionComparison.NotEqual; break; case "[gt]": comparison = ConditionComparison.Greater; break; case "[lt]": comparison = ConditionComparison.Less; break; case "[gteq]": comparison = ConditionComparison.GreaterOrEqual; break; case "[lteq]": comparison = ConditionComparison.LessOrEqual; break; default: comparison = ConditionComparison.Equal; break; } if (isNegated && comparison == ConditionComparison.Equal) comparison = ConditionComparison.NotEqual; else if (isNegated) { // Operator cannot be negated throw new ConditionFormatException("Comparison cannot be negated (illegal '!')", token.Position, token.Symbol.Length); } if (isState) { if (!legalStateNames.Contains(property)) throw new ConditionFormatException(String.Format("Unknown component state '{0}'", property), token.Position, token.Symbol.Length); return new ConditionTreeLeaf(ConditionType.State, property, comparison, new PropertyUnion(compareToStr, PropertyUnionType.Boolean)); } else { PropertyUnionType propertyType; if (!context.PropertyTypes.TryGetValue(property, out propertyType)) throw new ConditionFormatException(String.Format("Unknown property '{0}'", property), token.Position, token.Symbol.Length); return new ConditionTreeLeaf(ConditionType.Property, property, comparison, new PropertyUnion(compareToStr, propertyType)); } }
private ConditionTreeLeaf ParseLeaf(string value, ParseContext context) { ConditionType type; if (value.IndexOf("_") <= 1 && value.IndexOf("_") != -1) type = ConditionType.State; else type = ConditionType.Property; ConditionComparison comparisonType = ConditionComparison.Equal; Regex ltCheck = new Regex("\\(lt_[0-9.]+\\)"); Match ltMatch = ltCheck.Match(value); Regex gtCheck = new Regex("\\(gt_[0-9.]+\\)"); Match gtMatch = gtCheck.Match(value); Regex eqCheck = new Regex("\\(eq_[a-zA-Z0-9.]+\\)"); Match eqMatch = eqCheck.Match(value); Regex lteqCheck = new Regex("\\(lteq_[0-9.]+\\)"); Match lteqMatch = lteqCheck.Match(value); Regex gteqCheck = new Regex("\\(gteq_[0-9.]+\\)"); Match gteqMatch = gteqCheck.Match(value); Regex emptyCheck = new Regex("\\(empty\\)"); Match emptyMatch = emptyCheck.Match(value); string compareTo = "true"; if (ltMatch.Success) { comparisonType = ConditionComparison.Less; compareTo = ltMatch.Value.Replace("(lt_", "").Replace(")", ""); } else if (gtMatch.Success) { comparisonType = ConditionComparison.Greater; compareTo = gtMatch.Value.Replace("(gt_", "").Replace(")", ""); } else if (eqMatch.Success) { compareTo = eqMatch.Value.Replace("(eq_", "").Replace(")", ""); } else if (lteqMatch.Success) { comparisonType = ConditionComparison.LessOrEqual; compareTo = lteqMatch.Value.Replace("(lteq_", "").Replace(")", ""); } else if (gteqMatch.Success) { comparisonType = ConditionComparison.GreaterOrEqual; compareTo = gteqMatch.Value.Replace("(gteq_", "").Replace(")", ""); } else if (emptyMatch.Success) { comparisonType = ConditionComparison.Empty; compareTo = ""; } if (value.StartsWith("!")) { if (comparisonType == ConditionComparison.Equal) comparisonType = ConditionComparison.NotEqual; else if (comparisonType == ConditionComparison.NotEqual) comparisonType = ConditionComparison.Equal; else if (comparisonType == ConditionComparison.Empty) comparisonType = ConditionComparison.NotEmpty; } string variableName = Regex.Match(value, "\\$[a-zA-Z]+").Value.Replace("$", "").Replace("!", ""); if (type == ConditionType.State) variableName = value.Replace("_", "").Replace("!", "").ToLowerInvariant(); var propertyType = PropertyUnionType.Boolean; if (type == ConditionType.Property && !context.PropertyTypes.TryGetValue(variableName, out propertyType)) throw new ConditionFormatException(String.Format("Unknown property '{0}'", variableName), 0, 0); return new ConditionTreeLeaf(type, variableName, comparisonType, new PropertyUnion(compareTo, propertyType)); }