private void ValidarTiposAtribuicao()
        {
            TipoItemTs tipoVar;

            var indexAtribuicao = IndexAtual;

            while (Tokens[indexAtribuicao].Tipo != TipoToken.SimboloAtribuicao)
            {
                indexAtribuicao--;
            }

            indexAtribuicao--;

            switch (Tokens[indexAtribuicao].Tipo)
            {
            case TipoToken.Identificador:
                tipoVar = TabelaDeSimbolos.Find(Tokens[indexAtribuicao].Cadeia, EscopoStack.Peek()).Tipo;
                break;

            case TipoToken.NumeroReal:
                tipoVar = TipoItemTs.NumeroReal;
                break;

            default:
                tipoVar = TipoItemTs.NumeroInteiro;
                break;
            }

            if (TipoItensExpressao.Any(x => x != tipoVar))
            {
                throw new CompiladorException(
                          $"Atribuição inválida, era esperado um valor do tipo {tipoVar.ToString()}\nLinha: {Tokens[indexAtribuicao].Linha}");
            }
        }
        private void ValidarTiposExpressao()
        {
            var firstTipoExpressao = TipoItensExpressao.FirstOrDefault();

            if (IsOpDivisao.HasValue && IsOpDivisao.Value)
            {
                if (TipoItensExpressao.Any(x => x == TipoItemTs.NumeroInteiro))
                {
                    throw new CompiladorException(
                              $"Não é possível realizar divisão de números inteiros\nLinha: {Tokens[IndexAtual].Linha}");
                }
            }

            if (TipoItensExpressao.Any(x => x != firstTipoExpressao))
            {
                throw new CompiladorException(
                          $"Não é possível ter  tipos diferentes em uma expressão\nLinha: {Tokens[IndexAtual].Linha}");
            }
        }
        private void Condicao()
        {
            CallStack.Push(nameof(Condicao));

            Expressao();
            var tipoExpressao1 = TipoItensExpressao.FirstOrDefault();

            Relacao();
            Expressao();
            var tipoExpressao2 = TipoItensExpressao.FirstOrDefault();

            if (tipoExpressao1 != tipoExpressao2)
            {
                throw new CompiladorException(
                          $"Não é possível comparar expressões de tipos diferentes\nLinha: {Tokens[IndexAtual].Linha}\nOu outro erro em linha proxixa");
            }

            CallStack.Pop();
        }
        private void Fator()
        {
            CallStack.Push(nameof(Fator));

            switch (Tokens[IndexAtual].Tipo)
            {
            case TipoToken.Identificador:
                ValidarVariavel();
                var simboloTs = TabelaDeSimbolos.Find(Tokens[IndexAtual].Cadeia, EscopoStack.Peek());
                TipoItensExpressao.Add(simboloTs.Tipo);
                IndexAtual++;
                break;

            case TipoToken.NumeroInteiro:
                IndexAtual++;
                TipoItensExpressao.Add(TipoItemTs.NumeroInteiro);
                break;

            case TipoToken.NumeroReal:
                IndexAtual++;
                TipoItensExpressao.Add(TipoItemTs.NumeroReal);
                break;

            case TipoToken.SimboloAbreParenteses:
                IndexAtual++;

                Expressao();

                if (Tokens[IndexAtual].Tipo == TipoToken.SimboloFechaParenteses)
                {
                    IndexAtual++;
                }
                else
                {
                    ThrowCompiladorException(Tokens[IndexAtual]);
                }
                break;
            }

            CallStack.Pop();
        }