/// <summary>
        /// Faz a leitura do código e retorna um hash com as variáveis que existem no mesmo
        /// </summary>
        /// <param name="File"></param>
        /// <returns></returns>
        private Dictionary <string, Variable> GetVariables(string[] File)
        {
            Dictionary <string, Variable> variables = new Dictionary <string, Variable>();

            LexicAnalizer.Analize(File);

            Token token = null;

            do
            {
                token = LexicAnalizer.NextToken();
                if (token != null)
                {
                    if (token.Type == TokenType.VARIABLE)
                    {
                        string variableName = token.Value;
                        if (!variables.ContainsKey(variableName))
                        {
                            variables.Add(variableName, new Variable(variableName));
                        }
                    }
                }
            } while (token != null);

            return(variables);
        }
        /// <summary>
        /// Para calcular expressões sem parênteses e sem variáveis
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public int CalculateExpression(string expression)
        {
            LexicAnalizer lexic = new LexicAnalizer();

            lexic.Analize(new string[] { expression });

            int   result = 0;
            Token token  = null;

            //Primeiro deve vir um número
            token  = lexic.NextToken();
            result = int.Parse(token.Value);

            do
            {
                token = lexic.NextToken();

                if (token != null)
                {
                    string mathOperator = token.Value;

                    token = lexic.NextToken();
                    int nextValue = int.Parse(token.Value);

                    switch (mathOperator)
                    {
                    case "+":
                        result += nextValue;
                        break;

                    case "-":
                        result -= nextValue;
                        break;

                    case "*":
                        result *= nextValue;
                        break;

                    case "/":
                        result /= nextValue;
                        break;
                    }
                }
            } while (token != null);

            return(result);
        }
        public string[] CalculateExpressionVariable(string expression, Dictionary <string, Variable> variables)
        {
            //Não é aceitável ter RND com variável
            List <string> commands     = new List <string>();
            String        commandCache = null;

            bool hasParenthesis = expression.Contains('(');

            if (hasParenthesis)
            {
                //Remove todos os parênteses colocando a expressão na forma que deve acontecer
                expression = AdjustParenthesis(expression);
            }

            LexicAnalizer lexic = new LexicAnalizer();

            lexic.Analize(new string[] { expression });

            bool hasVariables = lexic.HasVariable();

            string hexValue;
            string hexValue2;

            if (hasVariables)
            {
                Token token = null;
                do
                {
                    token = lexic.NextToken();

                    if (token != null)
                    {
                        switch (token.Type)
                        {
                        case TokenType.VALUE:
                        {
                            IntToHexa(int.Parse(token.Value), out hexValue, out hexValue2);
                            commands.Add("LDI");
                            commands.Add(hexValue);
                            commands.Add(hexValue2);
                            if (commandCache != null)
                            {
                                commands.Add(commandCache);
                                commandCache = null;
                            }
                        }
                        break;

                        case TokenType.VARIABLE:
                        {
                            Variable variable = variables[token.Value];
                            IntToHexa(variable.CodePosition, out hexValue, out hexValue2);
                            commands.Add("LOD");
                            commands.Add(hexValue);
                            commands.Add(hexValue2);
                            if (commandCache != null)
                            {
                                commands.Add(commandCache);
                                commandCache = null;
                            }
                        }
                        break;

                        case TokenType.MATH_OPERATOR:
                        {
                            string command = "";
                            switch (token.Value)
                            {
                            case "+":
                                command = "ADD";
                                break;

                            case "-":
                                command = "MIN";
                                break;

                            case "*":
                                command = "TIM";
                                break;

                            case "/":
                                command = "DIV";
                                break;
                            }
                            commandCache = command;
                        }
                        break;
                        }
                    }
                } while (token != null);
            }
            else
            {
                int result = CalculateExpression(expression);
                IntToHexa(result, out hexValue, out hexValue2);
                commands.Add("LDI");
                commands.Add(hexValue);
                commands.Add(hexValue2);
            }

            return(commands.ToArray());
        }
        /// <summary>
        /// Busca as linhas que correspondem aos input do código
        /// </summary>
        /// <param name="variables"></param>
        /// <param name="File"></param>
        /// <returns></returns>
        private string[] GetInputs(Dictionary <string, Variable> variables, string[] File)
        {
            //Utiliza um analisador léxico próprio para a expressão, para não confundir os tokens
            LexicAnalizer lexic = new LexicAnalizer();

            lexic.Analize(File);

            List <string> inputList = new List <string>();

            Token    token     = null;
            Variable variable  = null;
            bool     nextToken = true;
            string   hexValue;
            string   hexValue2;

            do
            {
                if (nextToken)
                {
                    token     = lexic.NextToken();
                    nextToken = false;
                }
                if (token != null)
                {
                    if (token.Type == TokenType.RESERVED_WORD)
                    {
                        if (token.Value.Equals("INPUT"))
                        {
                            //Pega a primeira variável
                            token    = lexic.NextToken();
                            variable = variables[token.Value];

                            IntToHexa(variable.CodePosition, out hexValue, out hexValue2);
                            inputList.Add(hexValue);
                            inputList.Add(hexValue2);

                            token = lexic.NextToken();
                            //Procura por uma lista de inputs
                            if (token != null)
                            {
                                while (token != null && token.Type == TokenType.SEPARATOR)
                                {
                                    token    = lexic.NextToken();
                                    variable = variables[token.Value];

                                    IntToHexa(variable.CodePosition, out hexValue, out hexValue2);
                                    inputList.Add(hexValue);
                                    inputList.Add(hexValue2);

                                    token = lexic.NextToken();
                                }
                            }
                        }
                        else
                        {
                            nextToken = true;
                        }
                    }
                    else
                    {
                        nextToken = true;
                    }
                }
            } while (token != null);

            return(inputList.ToArray());
        }
        private string[] ReadLine(Dictionary <string, Variable> variables, Dictionary <int, int> lineNumber, string line, int offset)
        {
            //Importante: A leitura dos hexadecimais é feita da esquerda para a direita
            List <string> code = new List <string>();

            if (line == null || line.Equals(""))
            {
                return(new string[] { });
            }

            LexicAnalizer localLexic = new LexicAnalizer();

            localLexic.Analize(new string[] { line });

            Token  token = localLexic.NextToken();
            string hexValue;
            string hexValue2;

            //Expressão começou com um identificador de linha
            if (token.Type == TokenType.VALUE)
            {
                int number = int.Parse(token.Value);
                if (!lineNumber.ContainsKey(number))
                {
                    lineNumber[number] = offset;
                }

                token = localLexic.NextToken();
            }
            switch (token.Value)
            {
            case "GOTO":
            {
                string expression = line.Substring(line.IndexOf("GOTO") + 4);

                string[] commands = CalculateExpressionVariable(expression, variables);

                int jmpNumber = lineNumber[int.Parse(commands[1])] + 1;
                IntToHexa(jmpNumber, out hexValue, out hexValue2);

                code.Add("JMP");
                code.Add(hexValue);
                code.Add(hexValue2);
            }
            break;

            case "LET":
            {
                token = localLexic.NextToken();

                Variable variable = variables[token.Value];

                string expression = line.Substring(line.IndexOf("=") + 2);

                string[] commands = CalculateExpressionVariable(expression, variables);
                code.AddRange(commands);

                int address = variable.CodePosition;

                IntToHexa(address, out hexValue, out hexValue2);
                code.Add("STO");
                code.Add(hexValue);
                code.Add(hexValue2);
            }
            break;

            case "PRINT":
            {
                string[] printCode = null;

                do
                {
                    token = localLexic.NextToken();

                    if (token != null)
                    {
                        if (token.Type == TokenType.STRING)
                        {
                            printCode = PrintString(token.Value);
                        }
                        else
                        {
                            #region Print de Expressão
                            string expression = "";
                            do
                            {
                                expression = token.Value + " ";
                                token      = localLexic.NextToken();
                            } while (token != null && token.Type != TokenType.SEPARATOR && !token.Value.Equals(","));

                            printCode = CalculateExpressionVariable(expression, variables);
                            #endregion
                        }
                        code.AddRange(printCode);
                        code.Add("OUT");
                    }
                } while (token != null);
            }
            break;

            case "REM":
            {
                token = localLexic.NextToken();

                string[] printCode = PrintString(token.Value);
                code.AddRange(printCode);
            }
            break;

            case "RETURN":
            {
                code.Add("STOP");
            }
            break;

            case "IF":
            {
                string firstExp   = "";
                string compareExp = "";

                #region Carrega o valor da primeira expressão
                token = localLexic.NextToken();
                do
                {
                    firstExp += token.Value + " ";
                    token     = localLexic.NextToken();
                } while (token.Type != TokenType.RELATIONAL_OPERATOR);

                string[] firstCode = CalculateExpressionVariable(firstExp, variables);

                code.AddRange(firstCode);
                #endregion

                //Busca o comparador da expressão do IF
                string comparator = GetComparator(token);

                #region Carrega o valor da segunda expressão

                token = localLexic.NextToken();
                do
                {
                    compareExp += token.Value + " ";
                    token       = localLexic.NextToken();
                } while (token.Type != TokenType.RESERVED_WORD);

                string[] compareCode = CalculateExpressionVariable(compareExp, variables);

                code.AddRange(compareCode);
                #endregion

                code.Add(comparator);

                //Carrega o valor do THEN
                string thenExpression = line.Substring(line.IndexOf("THEN") + 5);

                string[] thenCode = ReadLine(variables, lineNumber, thenExpression, offset);

                int actualNumberOfAddresses = code.Count;

                int numberOfAddresses = thenCode.Length;

                //+1 para pular a linha do JF
                //+1 para a próxima expressão depois do IF
                int jumpTo = offset + actualNumberOfAddresses + numberOfAddresses + 4;

                IntToHexa(jumpTo, out hexValue, out hexValue2);
                code.Add("JF");
                code.Add(hexValue);
                code.Add(hexValue2);

                for (int i = 0; i < thenCode.Length; i++)
                {
                    /*Atualiza os endereços JF dos IF aninhados
                     * para o valor do JF relativo ao IF mais externo*/
                    if (thenCode[i].Contains("JF"))
                    {
                        thenCode[i]     = "JF";
                        thenCode[i + 1] = hexValue;
                        thenCode[i + 2] = hexValue2;
                        break;
                    }
                }

                code.AddRange(thenCode);
            }
            break;
            }

            return(code.ToArray());
        }