Universidad de Costa Rica
Escuela de Ciencias de la
Computación e Informática
Profesor Adolfo Di Mare
CI-1322
II Semestre 2003
[<=] [home] [<>] [\/] [=>]
CI-1322 Autómatas y compiladores

Tarea #4 [solución]

El tokenizador 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
Figura 1

      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()
Figura 2

      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.

[mailto:] Entrega de Tareas

Tiempo de entrega: 1 semana
Modalidad: En parejas

Soluciones

[mailto:] Adolfo Di Mare <adolfo@di-mare.com>.
Copyright © 2003
Derechos de autor reservados © 2003
[home] <> [/\]