Professional Documents
Culture Documents
Apndice 3
20-01-2010
La produccin: ASB::=AsB define que S puede ser reemplazado por s, siempre que ocurra
entre A y B; por lo cual es sensible al contexto.
El uso de la recursin al definir producciones, permite generar un infinito nmero de sentencias
a partir de un nmero finito de producciones.
S::=aA
A::=b|cA
La categora A, est definida en trminos de s misma. En el ejemplo, los smbolos terminales se
representan con minsculas, los no terminales con maysculas.
A partir de S, se generan: ab, acb, accb, acccb, ..
20-01-2010
Inicio. Se lee a
Se reemplaza S. Se reconoce a.
Se acepta a. Se lee c
Se reemplaza A. Se reconoce c.
Se acepta c. Se lee c.
Se reemplaza A. Se reconoce c.
Se acepta c. Se lee b.
Se reemplaza A. Se reconoce b.
Se acepta la frase como correcta.
20-01-2010
intentar leer el prximo, como no quedan smbolos no terminales que leer y queda pendiente un
x que derivar, se concluye que el anlisis fall. Lo que se debi realizar era reemplazar A por
nula.
Para evitar la vuelta atrs en el reconocimiento, se impone una regla adicional para las
producciones que generen la secuencia nula:
Para una secuencia A que genera la secuencia nula, los smbolos iniciales que genera A deben
se disjuntos con los smbolos que siguen a cualquier secuencia generada por A.
En el ejemplo anterior, S dice que la sentencia A tiene a x como smbolo siguiente. Y la
produccin que define A, indica que el primer smbolo que puede generar A es tambin x.
Como los iniciales generados por A son iguales a los siguientes a A, se viola la regla anterior.
La repeticin de construcciones, que tambin es muy frecuente en los lenguajes, suele definirse
empleando recursin.
Por ejemplo la repeticin de una o ms veces del elemento B, puede anotarse:
A::= B|AB
Pero el primero de B y el primero de AB no es el vaco, y no cumple la primera de las reglas.
Si se cambia la definicin de A por:
A::=nula|AB
A genera: nula, B, BB, BBB, y se tendr que el primero de A y el siguiente a A sern B,
violando la segunda regla.
Lo cual permite visualizar que no puede emplearse recursin por la izquierda.
La recursin por la derecha, cumple las reglas anteriores:
A::=nula|BA
Esta ltima produccin tambin genera la repeticin de cero, una o ms veces del elemento B.
La frecuencia de construcciones repetitivas que generen la secuencia nula lleva a definir los
siguiente metasmbolos:
A::={B}
Que genera: nula, B, BB, BBB,
Esta definicin slo simplifica la notacin, pero an es preciso revisar que se cumpla la segunda
regla, para emplear algoritmos basados en leer un smbolo por adelantado y sin volver atrs.
20-01-2010
Smbolo terminal.
x
20-01-2010
B1
A
B2
Bn
b1
B1
b2
B2
bn
Bn
20-01-2010
A
B1
B2
Bn
20-01-2010
Resumen.
Para una gramtica dada, pueden construirse grafos sintcticos a partir de las producciones
descritas en BNF, y viceversa.
Y de stas derivar el cdigo del reconocedor.
Los grafos deben cumplir las siguientes dos reglas, para que se puedan recorrer leyendo un
smbolo por adelantado y sin volver atrs.
Los primeros smbolos en las alternativas deben ser diferentes. De tal forma que la
bifurcacin solo pueda escogerse observando el siguiente smbolo de esa rama.
Si un grafo reconocedor de una sentencia A, puede generar la secuencia nula, debe
rotularse con todos los smbolos que puedan seguir a A. Ya que ingresar al lazo puede
afectar el reconocimiento de lo que viene a continuacin.
Una vez definido el lenguaje a reconocer, mediante sus grafos, debe verificarse el cumplimiento
de las dos reglas anteriores. Un sistema de grafos que cumplan las reglas anteriores se denomina
determinista y puede ser recorrido sin volver atrs y solo leyendo un smbolo por adelantado.
Esta restriccin no es una limitante en los casos prcticos.
)
A
20-01-2010
La produccin que genera la secuencia nula tiene interseccin vaca del primer elemento de la
repeticin y del smbolo que sigue a esa repeticin:
{ + } { ) } =
El siguiente programa implementa un reconocedor, para sentencias que cumplan la sintaxis
descrita por el grafo. Lo ms importante es notar que el cdigo para el reconocedor de
sentencias A, puede ser escrito a partir del diagrama anterior. Cada conjunto de reglas da origen
a un programa determinado. Se han agregado las funciones que abren y leen el archivo con el
texto que ser analizado, para ilustrar los detalles del entorno. Se da trmino a las sentencias del
archivo con un asterisco, en la primera posicin de una lnea. Cada vez que termina el anlisis
de una sentencia avisa si la encontr correcta.
Se emplea una variable global ch, para disminuir el nmero de argumentos. Se destaca que debe
leerse un smbolo por adelantado, antes de invocar al reconocedor.
Si el descriptor del archivo se deja como variable global, pueden disminuirse an ms los
argumentos de las funciones, simplificndolas.
#include <stdio.h>
void error(int e)
{ printf("Error %d\n", e);}
char lee(FILE *stream)
{ return( fgetc(stream)); }
char ch='\0';
void A(FILE *stream)
{
if (ch=='x') ch=lee(stream);
else
if (ch=='(' )
{ ch=lee(stream); A(stream);
while(ch=='+') {ch=lee(stream); A(stream);}
if ( ch==')' ) ch=lee(stream); else error(1);
}
else
error(2);
}
/* Analiza archivo de texto */
int parser(void)
{
FILE *stream;
if ((stream = fopen("inparser.txt", "r")) == NULL) {
fprintf(stderr, "No pudo abrir archivo de entrada.\n");
return 1;
Profesor Leopoldo Silva Bijit
20-01-2010
10
}
int main(void)
{
parser();
return 0;
}
20-01-2010
11
char simbolo='\0';
int nl=1; //contador de lneas
int nc=0; //contador de caracteres en la lnea.
FILE *stream;
void error(int tipo)
{
putchar('\n');printf("(%d,%d): ",nl, nc+1);
switch (tipo)
{
case 1: printf("%s\n", "Esperaba smbolo no terminal");break;
case 2: printf("%s\n", "Esperaba signo igual"); break;
case 3: printf("%s\n", "Esperaba cierre parntesis"); break;
case 4: printf("%s\n", "Esperaba abre parntesis"); break;
case 5: printf("%s\n", "Esperaba punto"); break;
}
}
void getch(void)
{
if(!feof(stream))
{ simbolo = fgetc(stream); nc++;
if(smbolo == '\n') {nl++; nc=0;}
putchar(simbolo); //eco en salida estndard
}
}
void getsimbolo(void)
{
getch();
while(isspace(simbolo)) getch(); //descarta blancos
}
//factor ::= <smbolo terminal> | <smbolo no terminal> | ( <expresin> )
void factor(void)
{
if (isalpha(simbolo) ) getsimbolo();
else
if (simbolo == '(' )
{ getsimbolo(); expresion();
if(smbolo == ')' ) getsimbolo(); else error(3);
}
else error(4);
}
20-01-2010
12
20-01-2010
13
int main(void)
{
bnfparser();
return 0;
}
Para el siguiente archivo de entrada:
A = C.
B=x,A.
B=x,A,B,CC=x(B,D.
D=(A).
*
Se genera la siguiente salida:
A = C.
B=x,A.
B=x,A,B,C(3,10): Esperaba punto
C=x(B,D.
(4,8): Esperaba cierre parntesis
D=(A).
*fin de archivo nmero de lneas =5
20-01-2010
14
letra; luego se siguen almacenado los caracteres del identificador (crculo 1) hasta que llegue un
carcter no alfanumrico, en que se vuelve a esperar identificadores.
Si lo nico que se desea es extraer los identificadores, si no llega una letra cuando se espera una,
puede descartrsela y continuar el anlisis.
Si es letra
Si es espacio
Si es alfanumrico
No es letra
Si no es alfanumrico
20-01-2010
15
break;
case Almacenando_id:
if (isalnum(buffer[i]))
{id[j]=buffer[i]; j++;} //forma id
else
if(!isalnum(buffer[i]))
{ estado = Esperando_letra;
id[j]='\0'; //termina string
j=0; //reset posicin
//printf("%s %d\n", id, nl); //muestra los identificadores y la lnea
// Aqu debera hacerse algo con el identificador
root=insert(id, root, nl); //Ejemplo: lo inserta en rbol
}
break;
}
}
}
20-01-2010
16
alfanum
6
isspace
!alfanum
alfanum
!alfanum
id ==define
es alfanumrico
Es #
alfanum
id != define
Si es espacio
Si es letra
Si es alfanumrico
Si es espacio
0
alfanum
No es letra ni #
Si no es alfanumrico
20-01-2010
17
20-01-2010
18
}
El siguiente segmento, abre los archivos de entrada y salida.
int procesa_archivos(void)
{
/* Abre stream para lectura, en modo texto. */
if ((streami = fopen("input6.c", "r")) == NULL) {
fprintf(stderr, "No pudo abrir archivo de entrada.\n");
return 1;
}
/* Abre stream para escritura, en modo texto. */
if ((streamo = fopen("output6.c", "w")) == NULL) {
fprintf(stderr, "No pudo abrir archivo de salida.\n");
return 1;
}
/* lee hasta encontrar el final del stream */
while(!feof(streami))
{
g(); //lee uno por adelantado
if(!feof(streami))
{
parser();
//putchar(ch);
}
else break;
}
fclose(streami); /* close stream */
fclose(streamo);
return 0;
}
int main(void)
{ makenull();
procesa_archivos();
return 0;
}
20-01-2010
19
20-01-2010
20
FILE *stream;
Se suele proteger la apertura, en caso de falla, mediante:
if ((stream = fopen("testwr.txt", "w")) == NULL)
{
fprintf(stderr, "No puede abrir archivo de salida.\n");
return 1;
}
El stream o flujo de salida stderr suele ser la pantalla.
La siguiente instruccin escribe en el stream 4 caracteres por lnea, ms el terminador de lnea,
eol; que suele ser uno o dos caracteres. La estructura de la lnea: dd<sp>c<eol>.
fprintf(stream, "%2d %c\n", s.i, s.ch);
Una vez completada la escritura de todas las lneas, se cierra el archivo, mediante:
fclose(stream);
Lectura de archivos de texto con estructura de lneas.
Se incluye un programa para leer el archivo, ya sea generado con un editor o por un programa,
mediante la funcin fscanf. Se ha usado la funcin feof, para determinar si se lleg al final del
archivo. La accin que se realiza con los datos es simplemente desplegar en la pantalla, los
datos formateados.
/* Ejemplo con streams. Lectura de archivo de texto formateado */
#include <stdio.h>
//El archivo testwr.txt debe estar estructurado en lneas.
//Cada lnea debe estar formateada segn: <sep>entero<sep>char<eol>
//Donde <sep> pueden ser espacios o tabs.
//El entero debe ser de dos dgitos, si en el string de formato del fscanf figura como %2d.
FILE *stream;
int main(void)
{
int jj; char cc;
/* Abre stream para lectura, en modo texto. */
if ((stream = fopen("testwr.txt", "r")) == NULL){
fprintf(stderr, "No pudo abrir archivo de entrada.\n");
return 1;
}
/* lee hasta encontrar el final del stream */
Profesor Leopoldo Silva Bijit
20-01-2010
21
for(;;)
{
fscanf(stream, "%d %c", &jj, &cc); //lee variables segn su tipo y estructura de lnea.
if(feof(stream)) break;
printf("%d %c\n", jj, cc); //slo muestra las lneas del archivo
}
fclose(stream); /* close stream */
return 0;
}
Si se intenta leer ms all del fin de archivo la funcin feof, retorna verdadero.
Llenar un arreglo a partir de un archivo.
El siguiente ejemplo llena un arreglo de estructuras.
/* Ejemplo con streams. Con datos de archivo se escribe un arreglo */
#include <stdio.h>
//El archivo testwr.txt debe estar estructurado en lineas.
//Cada linea debe estar formateada segn: <sep>entero<sep>char<eol>
//Donde <sep> pueden ser espacios o tabs.
//El entero debe ser de dos dgitos, si en el string de formato del fscanf figura como %2d.
struct mystruct
{
int i;
char ch;
};
#define ITEMS 20
struct mystruct arr[ITEMS];
FILE *stream;
int main(void)
{
int i, jj; char cc;
/* Abre stream para lectura, en modo texto. */
if ((stream = fopen("testwr.txt", "r")) == NULL)
{
fprintf(stderr, "No pudo abrir archivo de entrada.\n");
return 1;
}
for(i=0; i< ITEMS; i++)
{
fscanf(stream, "%d %c", &jj, &cc); //lee variables segn tipo.
if(feof(stream)) break;
arr[i].i=jj; arr[i].ch=cc; //llena items del arreglo
}
Profesor Leopoldo Silva Bijit
20-01-2010
22
}
Escritura y lectura de archivos binarios.
El siguiente ejemplo, ilustra la escritura y lectura de archivos binarios, no de texto. Se emplean
ahora las funciones: fwrite, fseek y fread.
* Ejemplo con streams. Escritura y luego lectura de archivo binario */
#include <stdio.h>
struct mystruct
{
int i;
char ch;
};
int main(void)
{
FILE *stream;
struct mystruct s;
int j;
/* sobreescribe y lo abre para escritura o lectura en modo binario */
if ((stream = fopen("TEST.bin", "w+b")) == NULL)
{
fprintf(stderr, "No se puede crear archivo de salida.\n");
return 1;
}
for(j=0;j<20;j++)
{
s.i = j;
s.ch = 'A'+j;
fwrite(&s, sizeof(s), 1, stream); /* write struct s to file */
}
/* seek to the beginning of the file */
fseek(stream, SEEK_SET, 0);
/* lee y despliega los datos */
Profesor Leopoldo Silva Bijit
20-01-2010
23
for(j=0; j<20;j++)
{
fread(&s, sizeof(s), 1, stream);
printf("%d %c\n", s.i, s.ch);
}
fclose(stream); /* close file */
return 0;
}
El archivo TEST.bin, no puede ser visualizado con un editor de texto. Para su interpretacin
debe usarse un editor binario.
Compilacin y ejecucin en ambiente UNIX.
Para programas sencillos, como los ilustrados, puede generarse el ejecutable en ambiente UNIX,
mediante el comando: make <nombre de archivo c, sin extensin>
Esto crea un ejecutable de igual nombre al programa en C.
Para su ejecucin basta escribir su nombre.
Escritura y lectura de archivos por lneas.
#define LARGOLINEA 80 //mximo largo de lnea igual a 80 caracteres
char buffer[LARGOLINEA];
int lee_archivo(void)
{
FILE *stream;
/* Abre stream para lectura, en modo texto. */
if ((stream = fopen("input.txt", "r")) == NULL) {
fprintf(stderr, "No pudo abrir archivo de entrada.\n");
return 1;
}
while(!feof(stream)) /* lee hasta encontrar el final del stream */
{
fgets(buffer, LARGOLINEA, stream); //carga buffer
if(!feof(stream))
{
// Aqu debera procesarse la lnea
//printf("%s ", buffer); //muestra las lneas del archivo de entrada
}
else break;
}
fclose(stream); /* close stream */
return 0;
Profesor Leopoldo Silva Bijit
20-01-2010
24
}
int escribe_archivo(void)
{
FILE *stream;
/* Abre stream para escritura, en modo texto. */
if ((stream = fopen("output.txt", "w")) == NULL) {
fprintf(stderr, "No pudo crear archivo de salida.\n");
return 1;
}
// Aqu debera escribirse el el archivo..
//fputs(buffer, stream);
imprime lnea
//fprintf(stream, "%d\t", 5); salida formateada
// fputc('\n', stream);
salida caracteres
fclose(stream); /* close stream */
return 0;
}
Referencias.
Niklaus Wirth, Algorithms + Data Structures = Programs, Prentice-Hall 1975.
20-01-2010
25
ndice general.
APNDICE 3 .............................................................................................................................................. 1
INTRODUCCIN A LA ESTRUCTURA Y OPERACIN DE ANALIZADORES LXICOS. ...... 1
A3.1. ESTRUCTURA DE UN LENGUAJE DE PROGRAMACIN. ...................................................................... 1
A3.2. ANALIZADOR LXICO. (PARSER) ..................................................................................................... 2
A3.3. REGLAS DE ANLISIS. ..................................................................................................................... 4
Smbolo terminal. ................................................................................................................................ 5
Smbolo no terminal. ........................................................................................................................... 5
Alternativa. .......................................................................................................................................... 5
Concatenacin..................................................................................................................................... 6
Repeticin. ........................................................................................................................................... 7
Resumen. ............................................................................................................................................. 8
EJEMPLO A3.1. RECONOCEDOR SIMPLE. ................................................................................................... 8
EJEMPLO A3.2. PARSER BNF. ............................................................................................................... 10
EJEMPLO A3.3. RECONOCEDOR DE IDENTIFICADOR. .............................................................................. 13
EJEMPLO A3.4. RECONOCEDOR DE UNA DEFINICIN. ............................................................................ 15
A3.4. MANIPULACIN DE ARCHIVOS EN C. ............................................................................................. 18
Escritura de archivos de texto, con estructura de lneas. .................................................................. 19
Escritura de archivo, desde un programa. ........................................................................................ 19
Lectura de archivos de texto con estructura de lneas. ..................................................................... 20
Llenar un arreglo a partir de un archivo. ......................................................................................... 21
Escritura y lectura de archivos binarios. .......................................................................................... 22
Compilacin y ejecucin en ambiente UNIX. .................................................................................... 23
Escritura y lectura de archivos por lneas. ....................................................................................... 23
REFERENCIAS. ........................................................................................................................................ 24
NDICE GENERAL. ................................................................................................................................... 25
NDICE DE FIGURAS................................................................................................................................. 25
ndice de figuras.
FIGURA A3.1. ANLISIS SIN VOLVER ATRS. ................................................................................................ 3
FIGURA A3.2. SMBOLO TERMINAL. .............................................................................................................. 5
FIGURA A3.3. SMBOLO NO TERMINAL. ........................................................................................................ 5
FIGURA A3.4. ALTERNATIVA. ....................................................................................................................... 6
FIGURA A3.5. ALTERNATIVA, CON PRIMER SMBOLO EXPLCITO. ................................................................. 6
FIGURA A3.6. CONCATENACIN. .................................................................................................................. 7
FIGURA A3.7. REPETICIN............................................................................................................................ 7
FIGURA A3.8. REPETICIN, CON PRIMER SMBOLO EXPLCITO. ..................................................................... 7
FIGURA A3.9. GRAFO DEL RECONOCEDOR. ................................................................................................... 8
FIGURA A3.10. ESTADOS DE RECONOCEDOR DE IDENTIFICADOR. ............................................................... 14
FIGURA A3.11. ESTADOS DE RECONOCEDOR DE DEFINICIONES................................................................... 16
20-01-2010