private SaidaRotina Eol(Evento evento)
        {
            if (Acumulador.Any())
            {
                return(new SaidaRotina(
                           new List <Evento>(),
                           new List <Evento>()
                {
                    new Evento(evento.InstanteProgramado + 1, TipoEvento.RESET, evento.Tarefa, null)
                },
                           new List <Evento>()
                {
                    new Evento(evento.InstanteProgramado + 1, TipoEvento.TOKEN_LEXICO, evento.Tarefa, GetTokenLexicoFromEstadoAtual()), new Evento(evento.InstanteProgramado + 2, TipoEvento.EOL, evento.Tarefa, null)
                }
                           ));
            }

            else
            {
                return(new SaidaRotina(
                           new List <Evento>(),
                           new List <Evento>()
                {
                    new Evento(evento.InstanteProgramado + 1, TipoEvento.RESET, evento.Tarefa, null)
                },
                           new List <Evento>()
                {
                    new Evento(evento.InstanteProgramado + 1, TipoEvento.EOL, evento.Tarefa, null)
                }
                           ));
            }
        }
        /// <summary>
        /// Recebe um Evento contendo um Token Lexico
        /// </summary>
        /// <param name="evento">Tipo: TOKEN_LEXICO, Conteudo: TokenLexico </param>
        /// <returns></returns>
        public SaidaRotina ReceberToken(Evento evento)
        {
            TokenLexico tokenLexico = (TokenLexico)evento.Conteudo;

            Transicao transicao = AutomatoFinito.BuscaTransicao(Cabecote.EstadoAtual, tokenLexico.Categoria);

            if (transicao != null)
            {
                Transicao(transicao);
                Acumulador.Add(tokenLexico);
                return(new SaidaRotina(
                           new List <Evento>(),
                           new List <Evento>(),
                           new List <Evento>()
                           ));
            }
            else
            {
                if (Cabecote.Aceito)
                {
                    return(new SaidaRotina(
                               new List <Evento>(),
                               new List <Evento>()
                    {
                        new Evento(evento.InstanteProgramado + 1, TipoEvento.RESET, evento.Tarefa, null), new Evento(evento.InstanteProgramado + 2, TipoEvento.TOKEN_LEXICO, evento.Tarefa, evento.Conteudo)
                    },
                               new List <Evento>()
                    {
                        new Evento(evento.InstanteProgramado + 1, TipoEvento.TOKEN_LEXICO, evento.Tarefa, GetTokenLexicoFromEstadoAtual())
                    }
                               ));
                }
                else
                {
                    List <Evento> eventosSaida = new List <Evento>();
                    eventosSaida.AddRange(Acumulador.Select(t => new Evento(evento.InstanteProgramado + 1, TipoEvento.TOKEN_LEXICO, evento.Tarefa, t)));
                    eventosSaida.Add(new Evento(evento.InstanteProgramado + 2, TipoEvento.TOKEN_LEXICO, evento.Tarefa, evento.Conteudo));

                    return(new SaidaRotina(
                               new List <Evento>(),
                               new List <Evento>()
                    {
                        new Evento(evento.InstanteProgramado + 1, TipoEvento.RESET, evento.Tarefa, null)
                    },
                               eventosSaida
                               ));
                }
            }
        }
        TokenLexico GetTokenLexicoFromEstadoAtual()
        {
            string               valor     = string.Concat(Acumulador.Select(cc => cc.Caracter));
            TipoTokenLexico      tipo      = TipoTokenLexico.NA;
            CategoriaTokenLexico categoria = CategoriaTokenLexico.NA;

            switch (Cabecote.EstadoAtual)
            {
            case "ESPECIAL":
                tipo      = TipoTokenLexico.ESPECIAL;
                categoria = TokenLexico.CategorizarEspecial(valor);
                break;

            case "IDENTIFICADOR":
                tipo      = TipoTokenLexico.IDENTIFICADOR;
                categoria = TokenLexico.CategorizarIdentificador(valor);
                break;

            case "INTEIRO":
                tipo      = TipoTokenLexico.NUMERO;
                categoria = CategoriaTokenLexico.NUMERO_INTEIRO;
                break;

            case "ESPECIAL_2":
                tipo      = TipoTokenLexico.ESPECIAL;
                categoria = TokenLexico.CategorizarEspecial(valor);
                break;

            case "DECIMAL":
                tipo      = TipoTokenLexico.NUMERO;
                categoria = CategoriaTokenLexico.NUMERO_DECIMAL;
                break;

            case "CIENTIFICO":
                tipo      = TipoTokenLexico.NUMERO;
                categoria = CategoriaTokenLexico.NUMERO_CIENTIFICO;
                break;

            case "TEXTO":
                tipo      = TipoTokenLexico.TEXTO;
                categoria = CategoriaTokenLexico.TEXTO;
                break;
            }

            return(new TokenLexico()
            {
                Valor = valor, Tipo = tipo, Categoria = categoria
            });
        }
        TokenLexico GetTokenLexicoFromEstadoAtual()
        {
            string               valor     = string.Concat(Acumulador.Select(t => t.Valor));
            TipoTokenLexico      tipo      = TipoTokenLexico.NA;
            CategoriaTokenLexico categoria = CategoriaTokenLexico.NA;

            switch (Cabecote.EstadoAtual)
            {
            case "GOTO":
                tipo      = TipoTokenLexico.IDENTIFICADOR;
                categoria = CategoriaTokenLexico.RESERVADA_GOTO;
                break;

            case "DEF_FN":
                tipo      = TipoTokenLexico.IDENTIFICADOR;
                categoria = CategoriaTokenLexico.RESERVADA_DEF_FN;
                break;

            case "MAIOR_IGUAL":
                tipo      = TipoTokenLexico.ESPECIAL;
                categoria = CategoriaTokenLexico.ESPECIAL_MAIOR_IGUAL;
                break;

            case "MENOR_IGUAL":
                tipo      = TipoTokenLexico.ESPECIAL;
                categoria = CategoriaTokenLexico.ESPECIAL_MENOR_IGUAL;
                break;

            case "DIFERENTE":
                tipo      = TipoTokenLexico.ESPECIAL;
                categoria = CategoriaTokenLexico.ESPECIAL_DIFERENTE;
                break;

            case "REMARK":
                tipo      = TipoTokenLexico.TEXTO;
                categoria = CategoriaTokenLexico.COMENTARIO;
                break;
            }

            return(new TokenLexico()
            {
                Valor = valor, Tipo = tipo, Categoria = categoria
            });
        }
        /// <summary>
        /// Recebe um Evento contendo uma CaracterCaracterizado
        /// </summary>
        /// <param name="evento">Tipo: ASCII, Conteudo: CaracterClassificado </param>
        /// <returns></returns>
        //  Token possui Tipo (Identificador, Número, Especial) e Valor
        public SaidaRotina ReceberCaracter(Evento evento)
        {
            CaracterClassificado caracterClassificado = (CaracterClassificado)evento.Conteudo;

            Transicao transicao = AutomatoFinito.BuscaTransicao(Cabecote.EstadoAtual, caracterClassificado.Caracter);

            if (transicao != null)
            {
                Transicao(transicao);
                if (caracterClassificado.Funcao != FuncaoCaracter.DESCARTAVEL)
                {
                    Acumulador.Add(caracterClassificado);
                }
                return(new SaidaRotina(
                           new List <Evento>(),
                           new List <Evento>(),
                           new List <Evento>()
                           ));
            }
            else if (caracterClassificado.Tipo == TipoCaracter.DELIMITADOR || Cabecote.Aceito)
            {
                return(new SaidaRotina(
                           new List <Evento>(),
                           new List <Evento>()
                {
                    new Evento(evento.InstanteProgramado + 1, TipoEvento.RESET, evento.Tarefa, null), new Evento(evento.InstanteProgramado + 2, TipoEvento.ASCII, evento.Tarefa, evento.Conteudo)
                },
                           new List <Evento>()
                {
                    new Evento(evento.InstanteProgramado + 1, TipoEvento.TOKEN_LEXICO, evento.Tarefa, GetTokenLexicoFromEstadoAtual())
                }
                           ));
            }
            else
            {
                TransicaoNA();
                Acumulador.Add(caracterClassificado);
                return(new SaidaRotina(
                           new List <Evento>(),
                           new List <Evento>(),
                           new List <Evento>()
                           ));
            }
        }