// 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
|