Upload
hjambo
View
61
Download
1
Embed Size (px)
Citation preview
Compiladores Página 1
UNIVERSIDAD PRIVADA DEL NORTE
CARREA DE INGENIERIA DE SISTEMAS
NOMBRE:
Biffi Suropachin, Irbin [email protected]
Ocas Cerna, Segundo [email protected]
Vásquez Salazar, Herman [email protected]
Huaripata Sánchez Luis [email protected]
Villanueva Castrejon, Rafael [email protected]
Jambo Huayac, Hernán [email protected]
DOCENTE:
José Luis Peralta Lujan
TRABAJO:
Diseño e implementación de un Analizador Léxico-Sintáctico
CURSO:
Compiladores
FECHA:
Julio - 2011
Compiladores Página 2
INDICE:
INTRODUCCION ................................................................................................................................. 3
I. MARCO TEORICO .............................................................................................................................. 4
Lenguaje a utilizar: .......................................................................................................................... 4
Lexema: ........................................................................................................................................... 4
Token: .............................................................................................................................................. 4
Ejemplo entre un lexema y un token .............................................................................................. 5
Palabras reservadas: ....................................................................................................................... 5
Componente léxico (token) ............................................................................................................. 6
Atributos de los componentes léxicos ............................................................................................ 7
Reconocimiento de Componentes Léxicos ..................................................................................... 7
Función del análisis sintáctico ......................................................................................................... 9
Análisis sintáctico por precedencia de operadores ...................................................................... 10
II DESARROLLO DEL COMPILADOR .................................................................................................... 11
CONCLUSIONES ................................................................................................................................. 17
RECOMENDACIONES ......................................................................................................................... 18
Compiladores Página 3
INTRODUCCION
El siguiente trabajo que presentaremos daremos a conocer lo aprendido durante
todo el ciclo, es por eso que vamos a crear nuestro propio analizador léxico y
sintáctico, este trabajo será desarrollado en un lenguaje de programación
conocido por todos los alumnos que conformamos este curso, el lenguaje a utilizar
será el lenguaje C el cual es un lenguaje de programación muy conocido.
Compiladores Página 4
I. MARCO TEORICO
Lenguaje a utilizar:
Lenguaje C:
C es un lenguaje de programación creado en 1972 por Dennis M. Ritchie en los
Laboratorios Bell como evolución del anterior lenguaje B, a su vez basado en
BCPL.
Al igual que B, es un lenguaje orientado a la implementación de Sistemas
Operativos, concretamente Unix. C es apreciado por la eficiencia del código que
produce y es el lenguaje de programación más popular para crear software de
sistemas, aunque también se utiliza para crear aplicaciones.
Se trata de un lenguaje débilmente tipificado de medio nivel pero con muchas
características de bajo nivel.
Lexema:
La cadena original que se identifica como token
No hay correspondencia 1-1 entre token-lexema
Token:
o Elemento básico del lenguaje
o Unidad léxica indivisible
o Identifica una entidad lógica dentro del lenguaje
o Incluyen: Palabras Reservadas, Constantes, Operadores.
o Signos de Puntuación e Identificadores
Compiladores Página 5
Ejemplo entre un lexema y un token
Palabras reservadas:
Identificador es una palabra que inicia con una Letra, y es seguida por letras
o dígitos.
Las palabras clave cumplen con este mismo
Patrón de construcción Se hace necesario un mecanismo que permita
decidir cuando una cadena es una palabra clave o un identificador Solución
sencilla: Palabras Reservadas (que no pueden ser usadas como
Identificadores)
Compiladores Página 6
Componente léxico (token)
Son las unidades lógicas que genera el analizador léxico. Formar caracteres en
tokens es muy parecido a formar palabras en un lenguaje natural.
Es el conjunto de cadenas de entrada que produce como salida el mismo componente
léxico. Cada token es una secuencia de caracteres que representa una unidad de
información en el programa fuente.
Los componentes léxicos más comunes son los siguientes:
Palabras clave o reservadas
operadores aritméticos
operadores relacionales
operadores lógicos
operador de asignación
identificadores
constantes
cadenas
literales
signos de puntuación
librerías
Compiladores Página 7
Atributos de los componentes léxicos
El analizador léxico recoge información sobre los componentes léxicos en sus
atributos asociados. Los componentes léxicos influyen en las decisiones del
análisis sintáctico y los atributos en la traducción de los componentes léxicos:
Apuntador a la entrada de la Tabla de símbolos donde se guarda la
información sobre el componente léxico.
El lexema para un identificador.
El número de línea en que se encontró por primera vez.
Reconocimiento de Componentes Léxicos
Prop if expr prop
| if expr prop else prop
| €
expr termino op_rel termino
| termino
termino id | num
Compiladores Página 8
Con este ejemplo se puede decir que la sentencia if, else, opr_rel, id, num, generan
conjuntos de cadenas dadas por la siguiente definición regular:
If if
else else
op_rel < | <= | == | >= | > | < >
id letra (letra|digito)*
num digitos fraccion_optativa exponente_optativo
letra a|b|c|d| ... |z|A|B|C|...|Z
digito 0|1|2|3|...|9
digitos digito digito*
fraccion_optativa .digitos|€
exponente_optativo (E(+|-|€) digitos)|€
· El analizador léxico reconoce las palabras clave del lenguaje (if, else)
· op_rel, id, num, los representa por su expresión regular.
Compiladores Página 9
Función del análisis sintáctico
En el modelo del compilador, el analizador sintáctico obtiene una cadena de
componentes léxicos del analizador léxico, y comprueba si la cadena puede ser
generada por la gramática del programa fuente.
Esta iteración se esquematiza como sigue
Existen 2 tipos generales de analizadores sintácticos para gramáticas:
a) Análisis sintáctico descendente. Construye árboles de análisis sintáctico desde
arriba (raíz) hacia abajo (hojas). El análisis se realiza de lo general a lo particular.
b) Análisis sintáctico ascendente. Construyen árboles de análisis sintáctico
comenzando en las hojas y suben hacia la raíz. El análisis se realiza de lo particular a lo
general
Compiladores Página 10
Análisis sintáctico por precedencia de operadores
Para una pequeña clase de gramáticas se puede construir con facilidad a mano
eficientes analizadores sintácticos ascendentes.
Estas gramáticas, por precedencia de operadores, tienen la propiedad de que
ningún lado derecho de la producción es є ni tiene 2 terminales adyacentes.
Una gramática con esta última propiedad de denomina gramática de operadores.
Esta técnica, históricamente, se describió primero como una manipulación de
componentes léxicos sin hacer referencia a ninguna gramática subyacente.
Dada su sencillez, se han construido muchos compiladores que utilizan las
técnicas de análisis sintáctico por precedencia de operadores para expresiones
Compiladores Página 11
II DESARROLLO DEL COMPILADOR
Creando LEXICO.L
En el Léxico desarrollaremos lo siguiente.
%{
#include <stdio.h>
#include <conio.h>
#include "c:\practica\parser.h"
%}
%option noyywrap
%option yylineno
ignora " "|\t|\n
letra [[:alpha:]]
digito [0-9]
asigna ":="
especial "#"|"="|"+"|";"
%%
{ignora}* {;}
\"({letra}|{digito}|" ")+\" {return CADENA;}
{digito}+ { return ENTERO; }
{digito}+"."{digito}+ { return REAL; }
{asigna} { return ASIG;}
"PROGRAM" { return PROGRAM; }
"BEGIN" { return BEGIN; }
"END" { return END; }
"IF" { return IF; }
"THEN" { return THEN; }
"ELSE" { return ELSE; }
"FOR" { return FOR; }
"WHILE" { return WHILE; }
"WRITE" { return WRITE; }
"READ" { return READ; }
"INT" { return INT; }
"FLOAT" { return FLOAT; }
{letra}({letra}|{digito})* { return IDENT; }
"COUT" { return COUT;}
"PRINTF" { return PRINTF;}
"SCANF" { return SCANF;}
"CIN" { return CIN;}
"+" { return('+');}
"-" { return('-');}
"*" { return('*');}
"/" { return ('/');}
"<" { return('<');}
">" { return('>');}
"=" { return('=');}
"<=" { return('<=');}
">=" { return('<=');}
"==" { return('==');}
Compiladores Página 12
"!=" { return('!=');}
"<<" { return('<<');}
">>" { return('>>');}
"*=" { return('*=');}
"/=" { return('/=');}
"%" { return('%');}
"+=" { return('+=');}
"-=" { return('-=');}
"&=" { return('&=');}
"^=" { return('^=');}
"|=" { return('|=');}
"{" { return('{');}
"}" { return('}');}
"(" { return('(');}
")" { return(')');}
";" { return(';');}
"." { return('.');}
. { printf("ERROR EN LINEA %d: Caracter
Ilegal\n",yylineno); }
%%
void main()
{
char NomArch[30];
clrscr();
printf("Ingrese nombre de archivo: ");
gets(NomArch);
if ((yyin = fopen(NomArch, "rt")) == NULL) /*yyin:variable que apunta al archivo
fuente */
printf("\nNo se puede abrir el archivo: %s\n", NomArch);
else
yyparse();
fclose(yyin);
getch();
}
Creando parser.h donde se define los Tokens
#ifndef YYSTYPE
#define YYSTYPE int
#endif
#define PROGRAM 257
#define IDENT 258
#define BEGIN 259
#define END 260
#define IF 261
#define THEN 262
#define ELSE 263
#define FOR 264
#define WHILE 265
#define FLOAT 266
#define ASIG 267
#define READ 268
#define WRITE 269
#define ENTERO 270
#define REAL 271
#define CADENA 272
#define COUT 273
#define PRINTF 274
#define SCANF 275
#define CIN 276
#define INT 277
extern YYSTYPE yylval;
Compiladores Página 13
Configurando LEXICO.L con Flex
Y se genera lexico.c
lexico.c
Creando el analizador sintáctico PARSER.Y
En el analizador sintáctico definimos lo siguiente:
%{
int yystopparser=0;
%}
%token PROGRAM IDENT BEGIN END IF THEN ELSE FOR WHILE FLOAT
%token ASIG READ WRITE ENTERO REAL CADENA COUT PRINTF SCANF CIN INT
%start programa
%%
programa : encabezado cuerpo '.'
encabezado : PROGRAM CADENA';'
cuerpo : '{' lista_sent '}'
lista_sent : sent
| sent';' lista_sent
sent : sent_asig
| sent_B
| sent_read
| sent_write
Compiladores Página 14
| sent_tipodato
| /*vacio*/
sent_asig : IDENT ASIG expresion
| IDENT relacional expresion
sent_B : IF condicion sent
| ELSE sent
| WHILE condicion sent
sent_read : READ '(' IDENT ')'
| READ '(' CADENA ')'
sent_write : WRITE '(' expresion ')'
sent_tipodato : INT IDENT
| FLOAT IDENT
condicion : expresion relacional expresion
| expresion
relacional : '<'
| '>'
| '='
expresion : expresion '+' termino
| expresion '-' termino
| termino
termino : termino '*' factor
| termino '/' factor
| factor
factor : IDENT
| ENTERO
| REAL
Configurando PARSER.Y con Bison
Y se genera parser.c
parser.c
Compiladores Página 15
Se crea el archivo ERROR.C que contiene los siguiente:
void yyerror(char * msg){
printf("%s\n", msg);
}
Creando el Proyecto con C
Elegimos PARSER.C, LEXICO.C, ERROR.C para agregarlo al proyecto.
Compiladores Página 16
Luego se compila y se ingresa la dirección del archivo a procesar.
El archivo de este ejemplo contiene lo siguiente:
PROGRAM "Analizador Lexico y Sintactico";
{
a:=2;
b:=3;
suma:=a+b;
WRITE(suma);
}.
Una vez terminado de generar en la carpeta aparecerá el archivo .exe
Compiladores Página 17
CONCLUSIONES
El sistema de análisis léxico y sintáctico que presentamos, es un analizador que se
ejecutara en un lenguaje de programación tal como el C, el cual proporciona un programa
de alto nivel y sencillo de utilizar y comprender.
Compiladores Página 18
RECOMENDACIONES
Para desarrollar un analizador léxico debemos tener encuenta que el código fuente del
programa secundario este bien hecho para así recibir como entrada un código fuente
bueno y entendible, y así producir una salida compuesta de tokens.
Un analizador léxico crea tokens de una secuencia de caracteres de entrada y son estos
tokens los que son procesados por el analizador sintáctico para construir la estructura de
datos, por ejemplo un árbol de análisis o árboles de sintaxis abstracta.