static private ParseTree Parse(string expression, IResolver resolver) { if (expression == null) { throw new ArgumentNullException("expression"); } ParseTree tokenTree = new ParseTree(); StringBuilder literal = new StringBuilder(); CharReader reader = new CharReader(expression); Token last = Token.Null; while (reader.Next()) { Debug.Assert(literal.Length == 0); char c = reader.Read(); switch (c) { case '(': { switch (last.Type) { case TokenType.Prefix: case TokenType.Operation: case TokenType.Expression: case TokenType.None: last = Token.Create(TokenType.Expression, null); tokenTree.Append(last); break; default: throw ThrowSyntaxError(reader.Position); } } break; case ')': { switch (last.Type) { case TokenType.Boolean: case TokenType.Number: case TokenType.String: case TokenType.Variable: case TokenType.Function: case TokenType.EndExpression: last = Token.Create(TokenType.EndExpression, null); tokenTree.Append(last); break; default: throw ThrowSyntaxError(reader.Position); } } break; case '?': switch (last.Type) { case TokenType.Boolean: case TokenType.Number: case TokenType.String: case TokenType.Variable: case TokenType.Function: case TokenType.EndExpression: last = Token.CreateOperator(c.ToString()); tokenTree.Append(last); break; default: throw ThrowSyntaxError(reader.Position); } break; case '|': case '&': switch (last.Type) { case TokenType.Boolean: case TokenType.Number: case TokenType.String: case TokenType.Variable: case TokenType.Function: case TokenType.Expression: literal.Append(c); if (!reader.Next()) { throw ThrowSyntaxError(reader.Position); } if (reader.Current != c) { throw ThrowSyntaxError(reader.Position); } literal.Append(reader.Read()); last = Token.CreateOperator(literal.ToString()); tokenTree.Append(last); literal.Length = 0; break; default: throw ThrowSyntaxError(reader.Position); } break; case '!': switch (last.Type) { case TokenType.Operation: case TokenType.Expression: case TokenType.None: // prefix last = Token.CreatePrefix(c.ToString()); tokenTree.Append(last); break; case TokenType.Boolean: case TokenType.Number: case TokenType.String: case TokenType.Variable: case TokenType.Function: case TokenType.EndExpression: // operator literal.Append(c); if (!reader.Next()) { throw ThrowSyntaxError(reader.Position); } if (reader.Current != '=') { throw ThrowSyntaxError(reader.Position); } literal.Append(reader.Read()); last = Token.CreateOperator(literal.ToString()); tokenTree.Append(last); literal.Length = 0; break; default: throw ThrowSyntaxError(reader.Position); } break; case '-': switch (last.Type) { case TokenType.Operation: case TokenType.Expression: case TokenType.None: // prefix last = Token.CreatePrefix(c.ToString()); tokenTree.Append(last); break; case TokenType.Boolean: case TokenType.Number: case TokenType.String: case TokenType.Variable: case TokenType.Function: case TokenType.EndExpression: // operator last = Token.CreateOperator(c.ToString()); tokenTree.Append(last); break; default: throw ThrowSyntaxError(reader.Position); } break; case '+': case '*': case '/': case '%': switch (last.Type) { case TokenType.Boolean: case TokenType.Number: case TokenType.String: case TokenType.Variable: case TokenType.Function: case TokenType.EndExpression: last = Token.CreateOperator(c.ToString()); tokenTree.Append(last); break; default: throw ThrowSyntaxError(reader.Position); } break; case '>': case '<': switch (last.Type) { case TokenType.Boolean: case TokenType.Number: case TokenType.String: case TokenType.Variable: case TokenType.Function: case TokenType.EndExpression: literal.Append(c); if (!reader.Next()) { throw ThrowSyntaxError(reader.Position); } if (reader.Current == '=') { literal.Append(reader.Read()); } last = Token.CreateOperator(literal.ToString()); tokenTree.Append(last); literal.Length = 0; break; default: throw ThrowSyntaxError(reader.Position); } break; case '=': switch (last.Type) { case TokenType.Boolean: case TokenType.Number: case TokenType.String: case TokenType.Variable: case TokenType.Function: case TokenType.EndExpression: literal.Append(c); if (!reader.Next()) { throw ThrowSyntaxError(reader.Position); } if (reader.Current != '=') { throw ThrowSyntaxError(reader.Position); } literal.Append(reader.Read()); last = Token.CreateOperator(literal.ToString()); tokenTree.Append(last); literal.Length = 0; break; default: throw ThrowSyntaxError(reader.Position); } break; case '\'': switch (last.Type) { case TokenType.Operation: case TokenType.Expression: case TokenType.None: last = ExpandString(reader, literal); tokenTree.Append(last); literal.Length = 0; break; default: throw ThrowSyntaxError(reader.Position); } break; default: if (char.IsLetter(c)) { switch (last.Type) { case TokenType.Prefix: case TokenType.Operation: case TokenType.Expression: case TokenType.None: literal.Append(c); last = ExpandVariable(reader, literal, resolver); tokenTree.Append(last); literal.Length = 0; break; default: throw ThrowSyntaxError(reader.Position); } } else if (char.IsDigit(c)) { switch (last.Type) { case TokenType.Prefix: case TokenType.Operation: case TokenType.Expression: case TokenType.None: literal.Append(c); last = ExpandNumber(reader, literal); tokenTree.Append(last); literal.Length = 0; break; default: throw ThrowSyntaxError(reader.Position); } } else { // it is whitespace or newline, to do nothing... } break; } } return(tokenTree); }