Universidad de Costa Rica
|
|
|
|
|
yylex() para la calculadora
Modifique su solución de la
tarea anterior para que use
la clase Token cuyo bosquejo aparece en la
Figura 1.
// Token.h (c) adolfo@di-mare.com
class Extractor_yylex; // produce letras para yylex()
int yylex( Astring & lexema, char &estado, Extractor_yylex &extractor );
// token = yylex(lexema, ch, extractor);
// retorna: Un número que representa el token, de Token::Tipo
// lexema: atributo del token
// estado: recuerda el último valor obtenido de "extractor"
// extractor: produce el siguiente caracter a leer
void double_long( const char *s, double &d, long& i );
class Token {
public:
enum Tipo {
OP_SUM = 321, // podría ser otro, mientras no "choque"
OP_MUL, // con otros valores para tokens
NUM,
P_ABRE,
P_CIERRA, ERROR = 666, FIN = 999
};
const Astring& lexema() const { return _lexema; }
const int token () const { return _tipo; }
const char* Nombre() const { return Nombre(_tipo); }
static const char* Nombre(int);
private:
Tipo _tipo; // Token::Tipo
Astring _lexema;
}; // Token
class Extractor_yylex { /*
- Jerarquía para Extractor_yylex:
+-----------------+
| Extractor_yylex |
+-----------------+
|-------------------------+
| |
+-------------------+ +------------------+
| Extractor_istream | | Extractor_Vector |
+-------------------+ +------------------+
|
|
+----------------+
| Extractor_cin |
+----------------+ */
public:
virtual char Saque() = 0; // retorna el siguiente caracter
}; // Extractor_yylex
class Extractor_istream : public Extractor_yylex {
public:
Extractor_istream(istream &CIN) :_CIN(CIN) {}
virtual char Saque() { return _CIN.get(); }
private:
istream &_CIN;
}; // Extractor_istream
class Extractor_cin : public Extractor_istream {
public:
Extractor_cin() : Extractor_istream(cin) {}
}; // Extractor_cin
class Extractor_Vector : public Extractor_yylex {
public:
Extractor_Vector() : _vec(0), _end(0) { }
Extractor_Vector(const char* v) { _vec = v; _end = v+strlen(v); }
virtual char Saque() { return (_vec == _end ? '\n' : *_vec++ ); }
Extractor_Vector & operator = (const char *v)
{ _vec = v; _end = v+strlen(v); return *this; }
private:
const char *_vec; // principio del vector
const char *_end; // uno más allá del final del vector
}; // Extractor_Vector
|
Use la
implementación
de la clase Token que recibió en clase.
También cambie el programa
CLC.cpp para que ya no use el
campo Calcualdora::_infijo, por lo que debe
eliminarlo de la clase Calculadora. Además,
note que el campo Calcualdora::preAnalisis debe ser
de tipo "Token" y no un "char" como en
el programa original.
#include "Token.h"
// typedef char Token; // YA NO
class Calculadora {
// ...
private:
Token preAnalisis; // siguiente token
// Astring _prefijo; // ELIMINADO
list<Token> _posfijo; // Lista o vector de tokens
}; // Calculadora
void Calculadora::r2() {
// r2 ==> * factor r2
// r2 ==> / factor r2
// r2 ==> £
if (preAnalisis.token == Token::OP_MUL) { // r2 ==> * factor r2
aparea(Token::OP_MUL);
factor(); {{ _posfijo += etc....; }}
r2();
} else { } // r2 ==> £
} // Calculadora::r2()
void Calculadora::aparea(Token ch) {
/* resultado
Consume el terminal, y avanza al siguiente lexema.
- Si "ch" no coincide con el valor de "preAnalisis"
emite un error.
*/
if (preAnalisis.token() != ch.token()) {
error("Token inesperado");
}
// NO preAnalisis = _infijo[++_cursor];
... yylex(...); ...
// NO while (_infijo[_cursor] == ' ') { // ignora blancos
// NO preAnalisis = _infijo[++_cursor];
// NO }
} // Calculadora::aparea()
|
En la Figura 2 está un bosquejo de los cambios que debe hacerle al programa CLC.cpp. Note que el programa queda mucho más corto al usar los lexemas que contiene cada token.
Entregue su tarea por correo electrónico, como lo hizo anteriormente.
|
Adolfo Di Mare <adolfo@di-mare.com>.
|
|
|