private static IBooleanExpression BuildTree(List <BooleanExpressionToken> tokens) { BooleanExpressionGroup defaultGroup = new BooleanExpressionGroup(); bool not = false; for (int i = 0; i < tokens.Count; i++) { var token = tokens[i]; if (token.Type == BooleanExpressionTokenType.GroupClose || (defaultGroup.Operands.Count == 0 && (token.Type == BooleanExpressionTokenType.And || token.Type == BooleanExpressionTokenType.Or)) || (i == tokens.Count - 1 && (token.Type == BooleanExpressionTokenType.And || token.Type == BooleanExpressionTokenType.Or))) { throw new ArgumentException("Unexpected token '" + token.Value + "'"); } if (token.Type == BooleanExpressionTokenType.GroupOpen) { int numOpen = 1; List <BooleanExpressionToken> groupedExpression = new List <BooleanExpressionToken>(); for (int j = i + 1; j < tokens.Count; j++) { var innerToken = tokens[j]; if (innerToken.Type == BooleanExpressionTokenType.GroupClose && numOpen == 1) { numOpen = 0; i = j; break; } else if (innerToken.Type == BooleanExpressionTokenType.GroupClose) { numOpen--; } else if (innerToken.Type == BooleanExpressionTokenType.GroupOpen) { numOpen++; } groupedExpression.Add(innerToken); } if (numOpen > 0) { throw new ArgumentException("You are missing at least 1 closing parenthesis"); } if (groupedExpression.Count == 0) { throw new ArgumentException("You have an empty set of parenthesis"); } var group = BuildTree(groupedExpression); group.Not = not; defaultGroup.Operands.Add(group); not = false; } else if (token.Type == BooleanExpressionTokenType.Variable) { if (defaultGroup.Operands.Count != defaultGroup.Operators.Count) { throw new ArgumentException("Expected an operator, got variable: " + token.Value); } defaultGroup.Operands.Add(new BooleanVariable() { VariableName = token.Value, Not = not }); not = false; } else if (token.Type == BooleanExpressionTokenType.And || token.Type == BooleanExpressionTokenType.Or) { if (not) { throw new ArgumentException("You cannot have an operator '&' or '|' after a '!'"); } if (defaultGroup.Operators.Count >= defaultGroup.Operands.Count) { throw new ArgumentException("You cannot have two consecutive operators '&&' or '||', use '&' or '|'"); } defaultGroup.Operators.Add((BooleanOperator)token.Type); } else if (token.Type == BooleanExpressionTokenType.Not) { if (not) { throw new ArgumentException("You cannot have two consecutive '!' operators"); } else { not = true; } } else { throw new ArgumentException("Unexpected token '" + token.Value + "'"); } } if (not == true) { throw new ArgumentException("Unexpected token '!' at end of expression"); } if (defaultGroup.Operands.Count == 1) { return(defaultGroup.Operands[0]); } else { return(defaultGroup); } }
private static IBooleanExpression BuildTree(List<BooleanExpressionToken> tokens) { BooleanExpressionGroup defaultGroup = new BooleanExpressionGroup(); bool not = false; for (int i = 0; i < tokens.Count; i++) { var token = tokens[i]; if (token.Type == BooleanExpressionTokenType.GroupClose || (defaultGroup.Operands.Count == 0 && (token.Type == BooleanExpressionTokenType.And || token.Type == BooleanExpressionTokenType.Or)) || (i == tokens.Count - 1 && (token.Type == BooleanExpressionTokenType.And || token.Type == BooleanExpressionTokenType.Or))) { throw new ArgumentException("Unexpected token '" + token.Value + "'"); } if (token.Type == BooleanExpressionTokenType.GroupOpen) { int numOpen = 1; List<BooleanExpressionToken> groupedExpression = new List<BooleanExpressionToken>(); for (int j = i + 1; j < tokens.Count; j++) { var innerToken = tokens[j]; if (innerToken.Type == BooleanExpressionTokenType.GroupClose && numOpen == 1) { numOpen = 0; i = j; break; } else if (innerToken.Type == BooleanExpressionTokenType.GroupClose) { numOpen--; } else if (innerToken.Type == BooleanExpressionTokenType.GroupOpen) { numOpen++; } groupedExpression.Add(innerToken); } if (numOpen > 0) { throw new ArgumentException("You are missing at least 1 closing parenthesis"); } if (groupedExpression.Count == 0) { throw new ArgumentException("You have an empty set of parenthesis"); } var group = BuildTree(groupedExpression); group.Not = not; defaultGroup.Operands.Add(group); not = false; } else if (token.Type == BooleanExpressionTokenType.Variable) { if(defaultGroup.Operands.Count != defaultGroup.Operators.Count) { throw new ArgumentException("Expected an operator, got variable: "+token.Value); } defaultGroup.Operands.Add(new BooleanVariable() { VariableName = token.Value, Not = not }); not = false; } else if (token.Type == BooleanExpressionTokenType.And || token.Type == BooleanExpressionTokenType.Or) { if(not) { throw new ArgumentException("You cannot have an operator '&' or '|' after a '!'"); } if (defaultGroup.Operators.Count >= defaultGroup.Operands.Count) { throw new ArgumentException("You cannot have two consecutive operators '&&' or '||', use '&' or '|'"); } defaultGroup.Operators.Add((BooleanOperator)token.Type); } else if(token.Type == BooleanExpressionTokenType.Not) { if (not) { throw new ArgumentException("You cannot have two consecutive '!' operators"); } else { not = true; } } else { throw new ArgumentException("Unexpected token '" + token.Value + "'"); } } if(not == true) { throw new ArgumentException("Unexpected token '!' at end of expression"); } if (defaultGroup.Operands.Count == 1) { return defaultGroup.Operands[0]; } else { return defaultGroup; } }