Clase 8
Analisis Sintactico
Ejemplo de analizador
lexico-sintactico mini-dev
Objetivos
El analizador sintáctico
(ASN) comprueba que el orden en que el analizador léxico le va entregando los
tokens es válido. Si esto es así significará que la sucesión de símbolos que
representan dichos tokens puede ser generada por la gramática correspondiente
al lenguaje del código fuente.
La forma más habitual de
representar la sintaxis de un programa es el árbol de análisis sintáctico, y lo
que hacen los analizadores sintácticos es construir una derivación por la
izquierda o por la derecha del programa fuente, que en realidad son dos
recorridos determinados del árbol de análisis sintáctico.
Prototipo de un analizador léxico
|
Ejemplo1(prueba_lexico.txt):
M
{
R a;
R b;
C = a+ b;
W c;
}
|
|
Ejemplo2
(prueba_sintactico.txt):
M
{
R a;
R b;
c = a + b * 2;
W c;
}
|
Archivos
de Código Fuente
Analizador Léxico (Lexico.h)
#ifndef Lexico_H
#define
Lexico_H
#include<iostream>
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string>
#define
TAM_BUFFER 100
using
namespace std;
class
Lexico
{
char *nombreFichero;
FILE* entrada;
int
n1;
int
traza;
char
buffer[TAM_BUFFER];
int pBuffer;
public:
Lexico(char *unNombreFichero, int una_traza=0);
~Lexico(void);
char siguienteToken(void);
void
devuelveToken(char toke);
int
lineaActual(void){return n1; };
int
existeTraza(void){if(traza)return 1; else return 0;}
};
Lexico::Lexico(char *unNombreFichero, int
una_traza)
{
entrada=fopen(unNombreFichero, "rt");
if((entrada==NULL))
{
cout<<"No se puede abrir el archivo"<<endl;
system("pause");
exit(-2);
}
if(una_traza) traza=1;
else traza = 0;
n1=1;
pBuffer=0;
}
Lexico::~Lexico()
{
fclose(entrada);
}
char Lexico::siguienteToken(void)
{
char
car;
while((car=((pBuffer>0)
? buffer[--pBuffer]:getc(entrada)))!=EOF)
{
if(car==' ') continue;
if(car=='\n'){++n1; continue;}
break;
}
if(traza)
cout<<"ANALIZADOR LEXICO: Lee el token"<<car<<endl;
switch(car)
{
case'M':
case'R':
case'W':
case'=':
case'(':
case')':
case';':
case'}':
case'{':
case'.':
case'+':
case'*':
case'-':
case'/':
case'%':
return(car);
}
if(islower(car))return(car);
else
if(isdigit(car)) return(car);
else
{
cout<<"Error Lexico: Token Desconocido"<<endl;
system("pause");
exit(-4);
}
return(car);
}
void
Lexico::devuelveToken(char token)
{
if(pBuffer>TAM_BUFFER)
{
cout<<"ERROR: Desbordamiento de
buffer del analizador léxico"<<endl;
system("pause");
exit(-5);
}
else
{
buffer[pBuffer++]=token;
if(existeTraza())
cout<<"ANALIZADOR LEXICO: Recibe en
buffer el token"<<token<<endl;
system("pause");
}
}
#endif
Analizador Sintáctico (Sintactico.h)
#ifndef Sintactico_H
#define Sintactico_H
#include
"lexico.h"
#include
<stdlib.h>
using
namespace std;
class
Sintactico{
void
programa (void);
void
bloque (void);
void sentencia (void);
void otra_sentencia (void);
void
asignacion(void);
void
lectura (void);
void
escritura(void);
void
variable(void);
void
expresion(void);
void
termino(void);
void mas_terminos(void);
void factor(void);
void mas_factores(void);
void constante(void);
void errores (int codigo);
Lexico lexico; //objeto léxico miembro de la
clase
public:
Sintactico(char *fuente, int traza);
~Sintactico(void);
};
Sintactico::Sintactico(char *fuente, int traza):lexico(fuente,
traza)
//se inicializa el constructor de la clase
léxico
{
if (lexico.existeTraza())
cout<<"INICIO DE ANALISIS
SINTACTICO"<<endl;
programa();
}
/********************************************************************/
Sintactico::~Sintactico(void)
{
if (lexico.existeTraza())
{
cout<<"FIN DE ANALISIS
SINTACTICO"<<endl;
cout<<"FIN DE
COMPILACION"<<endl;
}
}
/********************************************************************/
void Sintactico::programa(void)
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<PROGRAMA>"<<endl;
token=lexico.siguienteToken();
if
(token=='M') cout <<"M";
else
errores(8);
token=lexico.siguienteToken();
if
(token!='{') errores(9);
bloque();
token=lexico.siguienteToken();
if
(token=='}')
{
cout<<"}";
}
else errores(2);
}
/************************************************************************/
void Sintactico::bloque(void)
{
char
token=' ';
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<BLOQUE>"<<endl;
sentencia();
otra_sentencia();
}
/**********************************************************************/
void Sintactico::otra_sentencia(void)
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<OTRA_SENTENCIA>"<<endl;
token=lexico.siguienteToken();
if
(token==';')
{
sentencia();
otra_sentencia();
}
else lexico.devuelveToken(token); //vacio
}
/*********************************************************************/
void Sintactico::sentencia(void)
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO: <SENTENCIA>"<<endl;
token=lexico.siguienteToken();
if
((token>='a') && (token<='z'))
{
lexico.devuelveToken(token);
asignacion();
}
else
if (token=='R') lectura();
else
if (token=='W') escritura();
else errores(6);
}
/**********************************************************************/
void Sintactico::asignacion()
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<ASIGNACION>"<<endl;
variable();
token=lexico.siguienteToken();
if (token!='=') errores(3);
expresion();
}
/*********************************************************************/
void Sintactico::variable(void)
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<VARIABLE>"<<endl;
token=lexico.siguienteToken();
if
((token>='a') && (token<='z')) cout<<token;
else errores(5);
}
/********************************************************************/
void Sintactico::expresion(void)
{
if (lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<EXPRESION>"<<endl;
termino();
mas_terminos();
}
/*********************************************************************/
void Sintactico::termino(void)
{
if (lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<TERMINO>"<<endl;
factor();
mas_factores();
}
/*********************************************************************/
void Sintactico::mas_terminos(void)
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<MAS_TERMINOS>"<<endl;
token=lexico.siguienteToken();
if
(token=='+')
{
termino();
mas_terminos();
}
else
if (token =='-')
{
termino();
mas_terminos();
}
else lexico.devuelveToken(token); //
<vacio>
}
/*********************************************************************/
void Sintactico::factor(void)
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS
SINTACTICO: <FACTOR>"<<endl;
token=lexico.siguienteToken();
if
((token>='0') && (token<='9'))
{
lexico.devuelveToken(token);
constante();
}
else
if (token=='(')
{
expresion();
token=lexico.siguienteToken();
if
(token!=')') errores(4);
}
else
{
lexico.devuelveToken(token);
variable();
}
}
/*********************************************************************/
void Sintactico::mas_factores(void)
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<MAS_FACTORES>"<<endl;
token=lexico.siguienteToken();
switch
(token)
{
case
'*':factor();
mas_factores();
break;
case
'/':factor();
mas_factores();
break;
case
'%':factor();
mas_factores();
break;
default: //<vacio>
lexico.devuelveToken(token);
}
}
/*********************************************************************/
void Sintactico::lectura(void)
{
char token;
token=lexico.siguienteToken();
if (lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<LECTURA> "<<token<<endl;
if((token<'a')||(token>'z')) errores(5);
}
/**********************************************************************/
void Sintactico::escritura(void)
{
char token;
token=lexico.siguienteToken();
if (lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<ESCRITURA> "<<token<<endl;
if
((token<'a') || (token>'z')) errores(5);
}
/************************************************/
void Sintactico::constante(void)
{
char
token;
if
(lexico.existeTraza())
cout<<"ANALISIS SINTACTICO:
<CONSTANTE>"<<endl;
token=lexico.siguienteToken();
if
((token>='0') && (token<='9')) cout<<token;
else errores(7);
}
/*******************************************************************/
void Sintactico::errores(int codigo)
{
int
x;
cout<<"LINEA
"<<lexico.lineaActual();
cout<<" ERROR SINTACTICO
"<<codigo;
switch (codigo)
{
case
1 :cout<<" :ESPERABA UN ;"<<endl;break;
case
2 :cout<<" :ESPERABA UNA }"<<endl;break;
case
3 :cout<<" :ESPERABA UN ="<<endl;break;
case
4 :cout<<" :ESPERABA UN )"<<endl;break;
case
5 :cout<<" :ESPERABA UN IDENTIFICADOR"<<endl;break;
case
6 :cout<<" :INSTRUCCION DESCONOCIDA"<<endl;break;
case
7 :cout<<" :ESPERABA UNA CONSTANTE"<<endl;break;
case
8 :cout<<" :ESPERABA UNA M DE MAIN"<<endl;break;
case
9 :cout<<" :ESPERABA UNA {"<<endl;break;
default:
cout<<" :NO
DOCUMENTADO"<<endl;
}
cin>>x;
exit(-(codigo+100));
}
#endif
Programa Principal (Lexico.cpp)
#include<iostream>
#include
"Lexico.h"
using
namespace std;
int
main()
{
Lexico lexico("prueba_lexico.txt",1);
return
0;
}
Programa Principal (Sintactico.cpp)
#include<iostream>
#include
"Sintactico.h"
using
namespace std;
int
main()
{
Sintactico
sintactico("prueba_sintactico.txt",1);
return 0;
}
Alumnos
|
|
|
|
Después de haber ejecutado con éxito el analizador sintáctico responda lo siguiente:
1.
Coloque
en el archivo prueba.txt algún carácter no reconocido por el lenguaje MINI-DEV.
Vuelva a ejecutar la aplicación generada en C++. ¿Qué observó en la ejecución?
¿Cuál es la razón del resultado? Realizar capturas de pantalla y anexar al
reporte
|
|
|
|
|
|
|
|
|
|
2.
Elimine
el carácter “;” de alguna de las instrucciones. Vuelva a ejecutar la
aplicación. ¿Qué observó en la ejecución? ¿Cuál es la razón del resultado?
Realizar capturas de pantalla y anexar al reporte
|
|
|
|
|
|
|
|
|
|
3.
Investigar
cuáles son los tipos de análisis sintáctico y sus características.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4.
Investigar
que es la notación LL(K) y LLR, notación
EBNF y BNF.
|
|
|
|
|
|
|
|
|
|
|
|
|
|




































No hay comentarios.:
Publicar un comentario