00001 #include "simbolo.H"
00002
00003 #include <sstream>
00004
00005 using namespace std;
00006
00007 Calculo::Simbolo::Simbolo(istream& entrada)
00008 {
00009 char c;
00010 if(entrada >> c)
00011 switch(c) {
00012 case '?':
00013 tipo_ = teste_de_condicao;
00014 break;
00015 case ':':
00016 tipo_ = separador_de_condicao;
00017 break;
00018 case '|':
00019 tipo_ = ou;
00020 break;
00021 case '&':
00022 tipo_ = e;
00023 break;
00024 case '=':
00025 c = ' ';
00026 if(not entrada.get(c) or c != '=')
00027 throw ErroDeAnalise(string("símbolo '=' desconhecido: '=") +
00028 c + '\'');
00029 tipo_ = igual;
00030 break;
00031 case '!':
00032 if(entrada.peek() == '=') {
00033 tipo_ = diferente;
00034 entrada.get();
00035 } else
00036 tipo_ = negacao;
00037 break;
00038 case '<':
00039 if(entrada.peek() == '=') {
00040 tipo_ = menor_ou_igual;
00041 entrada.get();
00042 } else
00043 tipo_ = menor;
00044 break;
00045 case '>':
00046 if(entrada.peek() == '=') {
00047 tipo_ = maior_ou_igual;
00048 entrada.get();
00049 } else
00050 tipo_ = maior;
00051 break;
00052 case '+':
00053 tipo_ = adicao;
00054 break;
00055 case '-':
00056 tipo_ = subtraccao;
00057 break;
00058 case '*':
00059 tipo_ = produto;
00060 break;
00061 case '/':
00062 tipo_ = divisao;
00063 break;
00064 case '^':
00065 tipo_ = potencia;
00066 break;
00067 case '(':
00068 tipo_ = parenteses_esquerdo;
00069 break;
00070 case ')':
00071 tipo_ = parenteses_direito;
00072 break;
00073 case ',':
00074 tipo_ = virgula;
00075 break;
00076 case '%':
00077 leValorTextual(entrada);
00078 tipo_ = constante;
00079 break;
00080 default:
00081 entrada.putback(c);
00082 if(isdigit(c) or c == '.')
00083 leValorNumerico(entrada);
00084 else if(isalpha(c)) {
00085 leValorTextual(entrada);
00086 tipo_ = identificador;
00087 } else
00088 throw ErroDeAnalise(string("caractere '") + c + "' inválido");
00089 break;
00090 }
00091 else
00092 tipo_ = fim;
00093
00094 assert(cumpreInvariante());
00095 }
00096
00097 string Calculo::Simbolo::descricao() const
00098 {
00099 assert(cumpreInvariante());
00100
00101 ostringstream descricao;
00102
00103 descricao << nomeCompleto();
00104
00105 if(tipo_ == identificador or tipo_ == constante)
00106 descricao << " [valor = " << valorTextual() << ']';
00107 else if(tipo_ == numero)
00108 descricao << " [valor = " << valorNumerico() << ']';
00109
00110 return descricao.str();
00111 }
00112
00113 void Calculo::Simbolo::leValorTextual(istream& entrada)
00114 {
00115 valor_textual = "";
00116 char c;
00117
00118 while(entrada.get(c) and (isalpha(c) or isdigit(c) or
00119 c == '_'))
00120 valor_textual += c;
00121 if(entrada)
00122 entrada.putback(c);
00123 }
00124
00125 bool Calculo::Simbolo::eIdentificador(std::string const& nome)
00126 {
00127 if(nome == "" or not isalpha(nome[0]))
00128 return false;
00129 for(string::size_type i = 0; i != nome.length(); ++i)
00130 if(not isalpha(nome[i]) and not isdigit(nome[i]) and nome[i] != '_')
00131 return false;
00132 return true;
00133 }
00134
00135 string const Calculo::Simbolo::nomes_curtos_dos_tipos[fim + 1] =
00136 {
00137 "?", ":",
00138 "|", "&", "!",
00139 "==", "!=",
00140 "<", "<=",
00141 ">", ">=",
00142 "+", "-",
00143 "*", "/",
00144 "^",
00145 "(", ")",
00146 ",",
00147 "id", "num", "const",
00148 "fim"
00149 };
00150
00151 string const Calculo::Simbolo::nomes_longos_dos_tipos[fim + 1] =
00152 {
00153 "teste de condição", "separador de condição",
00154 "ou", "e", "negação",
00155 "igual", "diferente",
00156 "menor", "menor ou igual",
00157 "maior", "maior ou igual",
00158 "adição", "subtraccao",
00159 "produto", "divisão",
00160 "potência",
00161 "parênteses esquerdo", "parênteses direito",
00162 "vírgula",
00163 "identificador", "número", "constante",
00164 "fim da entrada"
00165 };