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

Tarea #3 [solución]

Analizadores léxico y sintáctico simples con Lex

      Tome el anlizador léxico y el sintáctico que le fueron entregados en clase y modifíquelos de manera que el programa completo use Lex/Flex para hacer el análisis léxico.

// ASU24.cpp  (C) 2007 adolfo@di-mare.com

/** \file  ASU24.cpp
    \brief Programa que muestra el reconocimiento sintáctico ASU24.cpp
    Este es el ejemplo de la sección 2.4 del libro del Dragón:
    - Título: "Compilers - Principles, Techniques, and Tools".
    - Autores: Aho, Sethi, Ullman.
    - A±ó: 1986.

    \author Adolfo Di Mare <adolfo@di-mare.com>
    \date   2007
*/

typedef int Token; ///< Los "tokens" se representan como números enteros.

// Estas son constantes globales para simplificar el programa.
enum { ID=260, ARRAY, OF, INTEGER, CHAR, NUM, DOTDOT }; ///< Tokens del lenguaje.
enum { NO_ERROR = -1 };

/** Reconocedor sintáctico para la gramática \c "ASU24.cpp".
    \code
    type ==> simple
           | ^ ID
           | ARRAY [ simple ] OF type

    simple ==> INTEGER
           | CHAR
           | NUM DOTDOT NUM
    \endcode
*/
class Analizador_Sintactico {
public:
    /// Constructor.
    Analizador_Sintactico(const Token* h=0)  : m_hilera (h) { }
    /// Reinicializa el analizador con la hilera \c "h".
    void operator =      (const Token* h  ) { m_hilera = h;   }
    void trabaje();
    int  error() { return m_error; } ///< Código de error actual.
private:
    void type();
    void simple();
    void aparea( int );
    void error( const char * msg );

private:
    int   m_preAnalisis;   /// Siguiente \c Token a procesar.
    int   m_cursor;        ///< Posición actual en \c m_hilera.
    int   m_error;         ///< Recuerda la posición del Token que causó el último error.
    const Token* m_hilera; ///< Hilera a analizar.
};  // Analizador_Sintactico

///  Hace el análisis sintáctico de la hilera asociada a \* "*this".
void Analizador_Sintactico::trabaje() {
    if (m_hilera == 0) {  // Hilera vacía, termina
        return;
    }
    m_cursor = 0;         // comienza en  m_hilera[0]
    m_error  = NO_ERROR;  // todavía no hay errores

    m_preAnalisis = m_hilera[m_cursor]; // inicializa m_preAnalisis
    type();      // reconoce la expresión m_hilera
} // Analizador_Sintactico::trabaje()

/// Recuerda la última posición de error en la hilera analizada.
void Analizador_Sintactico::error(const char * msg) {
    m_error = m_cursor;
    msg = msg; // quita warning
    #if 0
        cout << "ERROR(" << 1+m_cursor << ")";
        if (msg != 0) {  // +1 porque m_cursor comienza en 0
            if (msg[0] != 0) {
                cout << ": " << msg;
            }
        }
        cout << endl;
    #endif
} // Analizador_Sintactico::error()

/** Método para reconocer las producciones del no terminal \c "type".
    \code
    type ==> simple
           | ^ ID
           | ARRAY [ simple ] OF type
    \endcode
*/
void Analizador_Sintactico::type() {
    if ( ( m_preAnalisis == INTEGER ) ||
         ( m_preAnalisis == CHAR )    ||
         ( m_preAnalisis == NUM )
       ) {
        simple();
    }
    else if ( m_preAnalisis == ARRAY ) {
        aparea( ARRAY );
        aparea( '[' );
        simple();
        aparea( ']' );
        aparea( OF );
        type();
    }
    else if ( m_preAnalisis == '^' ) {
        aparea( '^' );
        aparea( ID );
    }
    else {
        error("type");
    }
} // Analizador_Sintactico::type()

/** Método para reconocer las producciones del no terminal \c "simple".
    \code
    simple ==> INTEGER
           | CHAR
           | NUM DOTDOT NUM
    \endcode
*/
void Analizador_Sintactico::simple() {
    if ( m_preAnalisis == INTEGER ) {
        aparea( INTEGER );
    }
    else if ( m_preAnalisis == CHAR ) {
        aparea( CHAR );
    }
    else if ( m_preAnalisis == NUM ) {
        aparea( NUM );
        aparea( DOTDOT );
        aparea( NUM );
    }
    else {
        error("simple");
    }
} // Analizador_Sintactico::simple()

/// Consume el terminal, y avanza al siguiente lexema.
/// - Emite un error si \c "token" no coincide con el valor de \c "m_preAnalisis".
void Analizador_Sintactico::aparea( int token ) {
    if (m_preAnalisis != token) {
        error("Token inesperado");
    }

    ++m_cursor;
    m_preAnalisis = m_hilera[m_cursor];
} // Analizador_Sintactico::aparea()

#include <cassert>

/// Programa principal.
int main() {
    {   Analizador_Sintactico C;
        Token H[] = { '^',  ID };
        C = H; // asocia la hilera al analizador sintáctico.
        C.trabaje(); // ejecuta el analizador sintáctico.
        assert( C.error() == NO_ERROR );
    }

    {   Analizador_Sintactico C;
        Token H[] = { ARRAY, '[', INTEGER, ']', OF, INTEGER };
        C = H; // asocia la hilera al analizador sintáctico.
        C.trabaje(); // ejecuta el analizador sintáctico.
        assert( C.error() == NO_ERROR );
    }

    {   Analizador_Sintactico C;
        Token H[] = { ARRAY, '[', NUM, DOTDOT, NUM, ']', OF, INTEGER };
        C = H; // asocia la hilera al analizador sintáctico.
        C.trabaje(); // ejecuta el analizador sintáctico.
        assert( C.error() == NO_ERROR );
    }

    return 0;
} // main()

// EOF: ASU24.cpp

      Entregue su tarea por correo electrónico, como lo hizo anteriormente.

[mailto:] Entrega de Tareas

Tiempo de entrega: 7 días
Modalidad: En parejas

Soluciones

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