private static IBoolable BuildExpression(List <Token> tokens) { // turn list of tokens into list of BoolExpressionElements // they are in usual infix notation // when this is done, their order is changed to Reverse Polish Notation // meanwhile check, if it all can be represented as simple one negated IBoolable // finally build BoolExpression List <IBoolExpressionElement> infixList = new List <IBoolExpressionElement>(); List <Token> currentTokens = new List <Token>(); bool readingFunction = false; Token previousToken = new Token(TokenType.Null); // first, merge many tokens into fewer number of IBoolables foreach (Token tok in tokens) { bool actionDone = false; if (TokenGroups.IsLogicSign(tok.GetTokenType())) { if (readingFunction) { if (Brackets.AllBracketsClosed(currentTokens)) { IBoolable ibo = BoolableBuilder.Build(currentTokens); if (!ibo.IsNull()) { infixList.Add(ibo); } else { return(null); } currentTokens.Clear(); readingFunction = false; infixList.Add(new BoolExpressionOperator(GetBEOT(tok.GetTokenType()))); } else { currentTokens.Add(tok); } } else { if (currentTokens.Count > 0) { IBoolable ibo = BoolableBuilder.Build(currentTokens); if (!ibo.IsNull()) { infixList.Add(ibo); } else { return(null); } currentTokens.Clear(); } infixList.Add(new BoolExpressionOperator(GetBEOT(tok.GetTokenType()))); } actionDone = true; } if (tok.GetTokenType().Equals(TokenType.BracketOn)) { if (readingFunction) { currentTokens.Add(tok); } else { if (currentTokens.Count == 1 && previousToken.GetTokenType().Equals(TokenType.Variable)) { currentTokens.Add(tok); readingFunction = true; } else { if (currentTokens.Count > 0) { IBoolable ibo = BoolableBuilder.Build(currentTokens); if (!ibo.IsNull()) { infixList.Add(ibo); } else { return(null); } currentTokens.Clear(); } infixList.Add(new BoolExpressionOperator(BoolExpressionOperatorType.BracketOn)); } } actionDone = true; } if (tok.GetTokenType().Equals(TokenType.BracketOff)) { if (readingFunction) { if (Brackets.AllBracketsClosed(currentTokens)) { IBoolable ibo = BoolableBuilder.Build(currentTokens); if (!ibo.IsNull()) { infixList.Add(ibo); } else { return(null); } currentTokens.Clear(); readingFunction = false; infixList.Add(new BoolExpressionOperator(BoolExpressionOperatorType.BracketOff)); } else { currentTokens.Add(tok); } } else { if (currentTokens.Count > 0) { IBoolable ibo = BoolableBuilder.Build(currentTokens); if (!ibo.IsNull()) { infixList.Add(ibo); } else { return(null); } currentTokens.Clear(); } infixList.Add(new BoolExpressionOperator(BoolExpressionOperatorType.BracketOff)); } actionDone = true; } if (!actionDone) { currentTokens.Add(tok); } previousToken = tok; } if (currentTokens.Count > 0) { IBoolable ibo = BoolableBuilder.Build(currentTokens); if (!ibo.IsNull()) { infixList.Add(ibo); } else { return(null); } } // try to build negation of one boolable if (infixList.Count == 2 && (infixList[0] is BoolExpressionOperator) && (infixList[1] is IBoolable) && (infixList[0] as BoolExpressionOperator).GetOperatorType().Equals(BoolExpressionOperatorType.Not)) { return(new NegatedBoolable(infixList[1] as IBoolable)); } // check if value of infixlist can be computed (check order of elements) if (!CheckExpressionComputability(infixList)) { throw new SyntaxErrorException("ERROR! Wrong syntax of logic expression."); } // if everything is right, finally build BoolExpression in RPN return(new BoolExpression(ReversePolishNotation(infixList))); }