using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DotPrograms
{
    public class Expression
    {
        private string expression;
        private ParseTreeEvaluator tree;

        public ParseErrors Errors
        {
            get
            {
                if (tree != null)
                    return tree.Errors;
                else 
                    return null;
            }
        }

        public Expression(string exp)
            : this(exp, Context.Default)
        {
        }
        public Expression(string exp, Context context)
        {
            expression = exp;
            Scanner scanner = new Scanner();
            Parser parser = new Parser(scanner);
            tree = new ParseTreeEvaluator(context, scanner);
            tree = parser.Parse(expression, tree) as ParseTreeEvaluator;
        }

        public object Eval()
        {
            object result = tree.Eval(null);
            if (tree.Context.CurrentStackSize > 0)
                Errors.Add(new ParseError("Stacksize is not empty", 0, null));
            return result;
        }

        public static object Eval(string expression)
        {
            return Expression.Eval<object>(expression);
        }

        public static T Eval<T>(string expression) 
        {
            object result = null;
            try
            {
                Expression exp = new Expression(expression);
                
                if (exp.tree.Errors.Count > 0)
                    result = exp.tree.Errors[0].Message;
                else
                    result = exp.Eval();
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }

            return result != null ? ((T)(result)) : default(T);
        }
    }
}
