public Evaluator(Instructions instructions, Tokens tokens = null)
 {
     Memory = new double[instructions.Count];
     Variables = new Dictionary<char, double>(30);
     Variables.Add('p', Math.PI);
     Variables.Add('e', Math.E);
     Instructions = instructions;
     IsConstantExpression = true;
     if (tokens == null)
     {
         foreach (var token in tokens) {
             if (token == TokenType.Variable)
             {
                 IsConstantExpression = false;
                 break;
             }
         }
         if (IsConstantExpression)
         {
             IsConstantExpression = false;
             Evaluate();
             IsConstantExpression = true;
         }
     }
     else
     {
         IsConstantExpression = false;
     }
 }
        public Tokens GenerateTokens()
        {
            int N = Expression.Length;
            Tokens tokens = new Tokens(N);
            StringBuilder tokenValue = new StringBuilder(N);
            State currentState = State.BEGIN;
            int position = 0;
            while (position <= N && !LexicalError)
            {
                char symbol = position < N ? Expression[position] : EndOfExpression;
                switch (currentState)
                {
                    case State.BEGIN:
                        if (Char.IsLetter(symbol))
                        {
                            tokenValue.Append(symbol);
                            currentState = State.VAR;
                        }
                        else if (Char.IsDigit(symbol))
                        {
                            tokenValue.Append(symbol);
                            currentState = State.NUM1;
                        }
                        else if ("+-*/^()".Contains(symbol))
                        {
                            tokenValue.Append(symbol);
                            currentState = State.OK;
                        }
                        else if (symbol != EndOfExpression)
                        {
                            if (position < N)
                            {
                                var error = String.Format("Invalid symbol {0}", symbol);
                                TokenError = new Token(TerminalSymbolType.UnRecognized, position, error);
                                tokens.Add(TokenError);
                                LexicalError = true;
                            }
                        }
                        position++;
                        break;
                    case State.VAR:
                        if (Char.IsLetter(symbol))
                        {
                            tokenValue.Append(symbol);
                            position++;
                            currentState = State.FUNC;
                        }
                        else
                        {
                            tokens.Add(new Token(TokenType.Variable, position, tokenValue.ToString()));
                            tokenValue.Clear();
                            currentState = State.BEGIN;
                        }
                        break;
                    case State.FUNC:
                        if (Char.IsLetter(symbol))
                        {
                            tokenValue.Append(symbol);
                            position++;
                        }
                        else
                        {
                            var str = tokenValue.ToString();
                            if (IsFunction(str))
                            {
                                tokens.Add(new Token(TokenType.Function, position, str));
                                tokenValue.Clear();
                                currentState = State.BEGIN;
                            }
                            else
                            {
                                var error = String.Format("Unrecognized {0}", str);
                                TokenError = new Token(TokenType.UnRecognized, position, error);
                                tokens.Add(TokenError);
                                LexicalError = true;
                            }
                        }
                        break;
                    case State.OK:
                        tokens.Add(makeOneCharToken(tokenValue.ToString(), position));
                        tokenValue.Clear();
                        currentState = State.BEGIN;
                        break;
                    case State.NUM1:
                        if (Char.IsDigit(symbol))
                        {
                            tokenValue.Append(symbol);
                            position++;
                        }
                        else if (symbol == '.')
                        {
                            tokenValue.Append(symbol);
                            position++;
                            currentState = State.TRANS;
                        }
                        else
                        {
                            tokens.Add(new Token(TokenType.Value, position, tokenValue.ToString()));
                            tokenValue.Clear();
                            currentState = State.BEGIN;
                        }
                        break;
                    case State.TRANS:
                        if (Char.IsDigit(symbol))
                        {
                            tokenValue.Append(symbol);
                            position++;
                            currentState = State.NUM2;
                        }
                        else
                        {
                            var error = String.Format("Invalid number format {0}", tokenValue.Append(symbol));
                            TokenError = new Token(TokenType.UnRecognized, position, error);
                            tokens.Add(TokenError);
                            LexicalError = true;
                        }
                        break;
                    case State.NUM2:
                        if (Char.IsDigit(symbol))
                        {
                            tokenValue.Append(symbol);
                            position++;
                        }
                        else
                        {
                            tokens.Add(new Token(TokenType.Value, position, tokenValue.ToString()));
                            tokenValue.Clear();
                            currentState = State.BEGIN;
                        }
                        break;
                }

            }
            return tokens;
        }