private static Expression ParseTernary(ExpressionLexer lexer)
        {
            var expr = ParseCondCombo(lexer);

            if (lexer.PeekNextToken() == ExprTokenType.QuestionMark)
            {
                lexer.GetNextToken(ExprTokenType.QuestionMark);
                var trueValue = ParseTernary(lexer);
                lexer.GetNextToken(ExprTokenType.Colon);
                var falseValue = ParseTernary(lexer);
                return(new TernaryExpression(expr, trueValue, falseValue));
            }
            return(expr);
        }
        public static Expression Parse(string source)
        {
            var lexer = new ExpressionLexer(source);

            Expression result = ParseTernary(lexer);

            lexer.GetNextToken(ExprTokenType.EOF);
            result.Source = source;
            return(result);
        }
        private static Expression ParseFactor(ExpressionLexer lexer)
        {
            ExprTokenType tokenType = lexer.PeekNextToken();

            if (tokenType == ExprTokenType.Number)
            {
                return(new PrimitiveExpression((int)lexer.GetNextToken(ExprTokenType.Number)));
            }
            if (tokenType == ExprTokenType.String)
            {
                return(new PrimitiveExpression((string)lexer.GetNextToken(ExprTokenType.String)));
            }
            if (tokenType == ExprTokenType.Symbol)
            {
                string symbol = (string)lexer.GetNextToken(ExprTokenType.Symbol);
                if (lexer.PeekNextToken() == ExprTokenType.Dot)
                {
                    lexer.GetNextToken(ExprTokenType.Dot);
                    Expression exprInContext = ParseFactor(lexer);
                    return(new ContextExpression(symbol, exprInContext, new Expression[0]));
                }

                if (lexer.PeekNextToken() == ExprTokenType.Open)
                {
                    lexer.GetNextToken(ExprTokenType.Open);
                    var parameters = new List <Expression>();
                    while (lexer.PeekNextToken() != ExprTokenType.Close)
                    {
                        if (parameters.Count > 0)
                        {
                            lexer.GetNextToken(ExprTokenType.Comma);
                        }
                        parameters.Add(ParseCondCombo(lexer));
                    }
                    lexer.GetNextToken(ExprTokenType.Close);
                    if (lexer.PeekNextToken() == ExprTokenType.Dot)
                    {
                        lexer.GetNextToken(ExprTokenType.Dot);
                        Expression exprInContext = ParseFactor(lexer);
                        return(new ContextExpression(symbol, exprInContext, parameters.ToArray()));
                    }
                    return(new FunctionExpression(symbol, parameters.ToArray()));
                }
                return(new SymbolExpression(symbol));
            }
            if (tokenType == ExprTokenType.Open)
            {
                lexer.GetNextToken(ExprTokenType.Open);
                Expression result = ParseCondCombo(lexer);
                lexer.GetNextToken(ExprTokenType.Close);
                return(result);
            }
            if (tokenType == ExprTokenType.Minus || tokenType == ExprTokenType.NOT)
            {
                lexer.GetNextToken(tokenType);
                return(new UnaryExpression(ParseFactor(lexer), tokenType));
            }
            throw new ParseException("Unexpected token " + tokenType, lexer.CurrentPosition);
        }