private void classes() {
   if (tokenAtual.getTipo() == TokenType.CLASSE) {
     classe();
     classes();
   } else if (tokenAtual.getTipo() != TokenType.EOF)
     throw new ErroSintaticoException("esperava declaração de classe: ");
 }
 private void declaracao_constantes() {
   if (primeiro(DECL_CONSTANTES_MESMO_TIPO).contains(tokenAtual.getTipo())) {
     decl_constantes_mesmo_tipo();
     declaracao_constantes();
   } else if (tokenAtual.getTipo() != TokenType.FECHACHAVE
       && tokenAtual.getTipo() != TokenType.EOF)
     throw new ErroSintaticoException("Esperava uma declaração de constante: ");
 }
 private void tipo_metodo_menos_vazio() {
   if (tokenAtual.getTipo() == TokenType.INTEIRO
       || tokenAtual.getTipo() == TokenType.REAL
       || tokenAtual.getTipo() == TokenType.LOGICO
       || tokenAtual.getTipo() == TokenType.CARACTERE
       || tokenAtual.getTipo() == TokenType.CADEIA) proxToken();
   else throw new ErroSintaticoException("esperava uma declaração de tipo: ");
 }
 private void outros_blocos_classe() {
   if (tokenAtual.getTipo() == TokenType.VARIAVEIS) {
     bloco_variaveis();
     bloco_metodos();
   } else if (tokenAtual.getTipo() == TokenType.METODOS) {
     bloco_metodos();
   }
 }
 private void declaracao_variaveis() {
   if (primeiro(DECL_VARIAVEIS_MESMO_TIPO).contains(tokenAtual.getTipo())) {
     decl_variaveis_mesmo_tipo();
     declaracao_variaveis();
   } else if (tokenAtual.getTipo() != TokenType.FECHACHAVE
       && tokenAtual.getTipo() != TokenType.EOF)
     throw new ErroSintaticoException("Esperava uma declaração de variavel: ");
 }
 private void tipo_variavel() {
   if (tokenAtual.getTipo() == TokenType.INTEIRO
       || tokenAtual.getTipo() == TokenType.REAL
       || tokenAtual.getTipo() == TokenType.LOGICO
       || tokenAtual.getTipo() == TokenType.CARACTERE
       || tokenAtual.getTipo() == TokenType.CADEIA) proxToken();
   else throw new ErroSintaticoException("Faltando declaraçao de tipo");
 }
 private void operador_relacional() {
   if (tokenAtual.getTipo() == TokenType.MAIOR
       || tokenAtual.getTipo() == TokenType.MENOR
       || tokenAtual.getTipo() == TokenType.MAIORIGUAL
       || tokenAtual.getTipo() == TokenType.MENORIGUAL
       || tokenAtual.getTipo() == TokenType.IGUAL
       || tokenAtual.getTipo() == TokenType.DIF) proxToken();
   else throw new ErroSintaticoException("operador relacional esperado: ");
 }
 private void complemento_referencia_variavel() {
   if (tokenAtual.getTipo() == TokenType.PONTO || tokenAtual.getTipo() == TokenType.ABREPAR) {
     acesso_objeto();
   } else if (tokenAtual.getTipo() == TokenType.ABRECOLCH) {
     match(TokenType.ABRECOLCH);
     expressao_aritmetica();
     match(TokenType.FECHACOLCH);
   }
 }
 private void loop_acesso_objeto() {
   if (tokenAtual.getTipo() == TokenType.PONTO) {
     acesso_objeto();
   } else if (tokenAtual.getTipo() == TokenType.ABREPAR) {
     match(TokenType.ABREPAR);
     parametros_reais();
     match(TokenType.FECHAPAR);
   }
 }
 private void parametro_real() {
   if (tokenAtual.getTipo() == TokenType.ID
       || tokenAtual.getTipo() == TokenType.NUM
       || tokenAtual.getTipo() == TokenType.LITERAL
       || tokenAtual.getTipo() == TokenType.CARACTER
       || tokenAtual.getTipo() == TokenType.VERDADEIRO
       || tokenAtual.getTipo() == TokenType.FALSO) proxToken();
   else throw new ErroSintaticoException("esperava uma variável ou valor como parâmetro: ");
 }
 private void outros_blocos_programa() {
   if (tokenAtual.getTipo() == TokenType.VARIAVEIS) {
     bloco_variaveis();
     classes();
   } else if (tokenAtual.getTipo() == TokenType.CLASSE) {
     classes();
   } else if (tokenAtual.getTipo() != TokenType.EOF)
     throw new ErroSintaticoException("esperava bloco de variaveis ou declaração de classe: ");
 }
 private void expressao() {
   if (primeiro(EXPRESSAO_ARITMETICA).contains(tokenAtual.getTipo())) {
     expressao_aritmetica();
     complemento_exp_aritmetica();
   } else if (tokenAtual.getTipo() == TokenType.VERDADEIRO
       || tokenAtual.getTipo() == TokenType.FALSO) {
     expressao_booleana();
     prox_trecho_expl();
   }
 }
 private void termo_aritm() {
   if (tokenAtual.getTipo() == TokenType.ID
       || tokenAtual.getTipo() == TokenType.NUM
       || tokenAtual.getTipo() == TokenType.ABREPAR) {
     fator();
     complemento_fator();
   } else
     throw new ErroSintaticoException(
         "esperava inicio de uma expressao aritmética - numero ou identificador: ");
 }
 private void condicao_comandos() {
   if (primeiro(EXPRESSAO_ARITMETICA).contains(tokenAtual.getTipo())) {
     expressao_relacional();
     prox_trecho_expl();
   } else if (tokenAtual.getTipo() == TokenType.VERDADEIRO
       || tokenAtual.getTipo() == TokenType.FALSO) {
     expressao_booleana();
     op_relacional_igualdade();
     match(TokenType.ID);
   } else throw new ErroSintaticoException("esperava uma expressão lógica ou relacional: ");
 }
  private void complemento_id_atribuicao() {
    if (tokenAtual.getTipo() == TokenType.PONTO
        || tokenAtual.getTipo() == TokenType.ATRIB
        || tokenAtual.getTipo() == TokenType.ABRECOLCH) {

      complemento_referencia_variavel_atrib();
    } else if (tokenAtual.getTipo() == TokenType.INCR || tokenAtual.getTipo() == TokenType.DECR) {

      incremento_decremento();
    }
  }
 private void atribuicao() {
   if (tokenAtual.getTipo() == TokenType.ID) {
     match(TokenType.ID);
     complemento_id_atribuicao();
   } else if (tokenAtual.getTipo() == TokenType.INCR || tokenAtual.getTipo() == TokenType.DECR) {
     incremento_decremento();
     match(TokenType.ID);
   } else
     throw new ErroSintaticoException(
         "Esperando início de atribuição ou operador de incremento/decremento: ");
 }
 private void termo_l() {
   if (primeiro(EXPRESSAO_ARITMETICA).contains(tokenAtual.getTipo())) {
     expressao_relacional();
     prox_trecho_expl();
   } else if (tokenAtual.getTipo() == TokenType.VERDADEIRO
       || tokenAtual.getTipo() == TokenType.FALSO) {
     expressao_booleana();
     prox_trecho_expl();
   } else
     throw new ErroSintaticoException("esperava uma expressão relacional ou um valor lógico: ");
 }
 private void acesso_objeto() {
   if (tokenAtual.getTipo() == TokenType.PONTO) {
     match(TokenType.PONTO);
     match(TokenType.ID);
     loop_acesso_objeto();
   } else if (tokenAtual.getTipo() == TokenType.ABREPAR) {
     match(TokenType.ABREPAR);
     parametros_reais();
     match(TokenType.FECHAPAR);
   } else throw new ErroSintaticoException("Esperando acesso a atributo ou chamada de método: ");
 }
 private void param_retorno() {
   if (tokenAtual.getTipo() == TokenType.ID
       || tokenAtual.getTipo() == TokenType.NUM
       || tokenAtual.getTipo() == TokenType.VERDADEIRO
       || tokenAtual.getTipo() == TokenType.FALSO
       || tokenAtual.getTipo() == TokenType.ABREPAR) {
     expressao();
   } else if (tokenAtual.getTipo() == TokenType.LITERAL
       || tokenAtual.getTipo() == TokenType.CARACTER) proxToken();
   else throw new ErroSintaticoException("esperava uma expressão ou valor como retorno: ");
 }
  private void param_escreva() {
    if (tokenAtual.getTipo() == TokenType.ABREPAR
        || tokenAtual.getTipo() == TokenType.VERDADEIRO
        || tokenAtual.getTipo() == TokenType.FALSO
        || tokenAtual.getTipo() == TokenType.ID
        || tokenAtual.getTipo() == TokenType.NUM) {

      expressao();
    } else if (tokenAtual.getTipo() == TokenType.LITERAL) {
      match(TokenType.LITERAL);
    } else throw new ErroSintaticoException("esperava um valor ou expressão como argumento: ");
  }
 private void fator() {
   if (tokenAtual.getTipo() == TokenType.ID) {
     match(TokenType.ID);
     complemento_referencia_variavel();
   } else if (tokenAtual.getTipo() == TokenType.NUM) {
     match(TokenType.NUM);
   } else if (tokenAtual.getTipo() == TokenType.ABREPAR) {
     match(TokenType.ABREPAR);
     expressao_aritmetica();
     match(TokenType.FECHAPAR);
   } else throw new ErroSintaticoException("esperava identificador ou numero: ");
 }
 private void complemento_exp_aritmetica() {
   if (tokenAtual.getTipo() == TokenType.MAIOR
       || tokenAtual.getTipo() == TokenType.MENOR
       || tokenAtual.getTipo() == TokenType.MAIORIGUAL
       || tokenAtual.getTipo() == TokenType.MENORIGUAL
       || tokenAtual.getTipo() == TokenType.IGUAL
       || tokenAtual.getTipo() == TokenType.DIF) {
     operador_relacional();
     expressao_aritmetica();
     prox_trecho_expl();
   }
 }
 private void loop_acesso_objeto_comando() {
   if (tokenAtual.getTipo() == TokenType.PONTO) {
     acesso_objeto_comando();
   } else if (tokenAtual.getTipo() == TokenType.ABREPAR) {
     match(TokenType.ABREPAR);
     parametros_reais();
     match(TokenType.FECHAPAR);
   } else if (tokenAtual.getTipo() == TokenType.ATRIB) {
     match(TokenType.ATRIB);
     segundo_membro_atribuicao();
   } else throw new ErroSintaticoException("Esperando chamada de método ou atribuição: ");
 }
  private void loop_parametros_mesmo_tipo() {
    if (tokenAtual.getTipo() == TokenType.INTEIRO
        || tokenAtual.getTipo() == TokenType.REAL
        || tokenAtual.getTipo() == TokenType.LOGICO
        || tokenAtual.getTipo() == TokenType.CARACTERE
        || tokenAtual.getTipo() == TokenType.VAZIO
        || tokenAtual.getTipo() == TokenType.CADEIA) {

      parametros_formais();
    } else
      throw new ErroSintaticoException(
          "esperava outra declaração de parametro formal após ponto e vírgula: ");
  }
  private List<Token> removerErrosEComentarios(ArrayList<Token> tokens) {
    List<Token> resultado = (List) tokens.clone();

    for (Iterator<Token> i = resultado.iterator(); i.hasNext(); ) {
      Token token = i.next();
      if (token.getTipo() == TokenType.ERRO
          || token.getTipo() == TokenType.COMENTBLOCO
          || token.getTipo() == TokenType.COMENTLINHA) {
        i.remove();
      }
    }

    return resultado;
  }
 private void complemento_decl_classe() {
   if (tokenAtual.getTipo() == TokenType.ABRECHAVE) {
     match(TokenType.ABRECHAVE);
     blocos_classe();
     match(TokenType.FECHACHAVE);
   } else if (tokenAtual.getTipo() == TokenType.HERDA_DE) {
     match(TokenType.HERDA_DE);
     match(TokenType.ID);
     match(TokenType.ABRECHAVE);
     blocos_classe();
     match(TokenType.FECHACHAVE);
   } else
     throw new ErroSintaticoException(
         "esperava a chave de abertura do corpo da classe ou a declaração de herança herda_de :");
 }
  private void declaracao_metodos() {
    if (tokenAtual.getTipo() == TokenType.INTEIRO
        || tokenAtual.getTipo() == TokenType.REAL
        || tokenAtual.getTipo() == TokenType.LOGICO
        || tokenAtual.getTipo() == TokenType.CARACTERE
        || tokenAtual.getTipo() == TokenType.CADEIA) {

      tipo_metodo_menos_vazio();
      declaracao_metodo();
      declaracao_metodos();
    } else if (tokenAtual.getTipo() == TokenType.VAZIO) {
      match(TokenType.VAZIO);
      declaracao_metodo_vazio();
    }
  }
  private void parametros_formais() {
    if (tokenAtual.getTipo() == TokenType.INTEIRO
        || tokenAtual.getTipo() == TokenType.REAL
        || tokenAtual.getTipo() == TokenType.LOGICO
        || tokenAtual.getTipo() == TokenType.CARACTERE
        || tokenAtual.getTipo() == TokenType.CADEIA) {

      parametros_mesmo_tipo();
      complemento_parametros_mesmo_tipo();
    } else if (tokenAtual.getTipo() == TokenType.VAZIO) {
      match(TokenType.VAZIO);
    } else
      throw new ErroSintaticoException(
          "esperava declaração de parametros formais ou palavra chave 'vazio': ");
  }
 private void comando_geral() {
   try {
     if (primeiro(COMANDO_LINHA).contains(tokenAtual.getTipo())) {
       comando_linha();
       match(TokenType.PONTOVIRGULA);
     } else if (primeiro(COMANDO_BLOCO).contains(tokenAtual.getTipo())) {
       comando_bloco();
     } else {
       throw new ErroSintaticoException(
           "esperava o início de um comando de linha ou comando de bloco: ");
     }
   } catch (ErroSintaticoException ex) {
     erroSintatico(ex);
     panico(conjuntoSequencia.getConjunto(COMANDO_GERAL));
   }
 }
 private void acesso_objeto_comando() {
   if (tokenAtual.getTipo() == TokenType.PONTO) {
     match(TokenType.PONTO);
     match(TokenType.ID);
     loop_acesso_objeto_comando();
   }
 }