Universidad de Costa Rica
|
|
yylex()
Modifique el programa de la
segunda tarea 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>.
|