Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Compiladores
Autores:
Profesora:
Noviembre de 2022
Índice
1. Introdución 2
1.1. Objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2. Introducción teórica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.1. Compiladores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.2. Modelo de análisis y síntesis de la compilación . . . . . . . . . . . . . . . 2
1.2.3. Análisis léxico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3. Yacc (Yet Another Compiler-Compiler) . . . . . . . . . . . . . . . . . . . . . . . 3
1.4. Especicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.5. Requerimientos de entrega de práctica . . . . . . . . . . . . . . . . . . . . . . . 4
2. Desarrollo Experimental 5
2.1. Programas a analizar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.1. Palindromo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.2. Reconocimiento de grámatica . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.3. Binario a decimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2. Programas a realizar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.1. Numero par . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.2. Binario a Hexadecimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.3. Números Capícuos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3. Código 13
3.1. Código a analizar (geeksforgeeks) . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2. Código Realizado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4. Conclusiones 22
4.1. Conclusiones Eduardo Hernández Vergara . . . . . . . . . . . . . . . . . . . . . 22
4.2. Conclusiones José Ángel Rojas Cruz . . . . . . . . . . . . . . . . . . . . . . . . 22
5. Referencias 23
1
1. Introdución
1.1. Objetivo
El alumno utilizará la biblioteca YACC (yet another compiler-compiler) para el proceso de
análisis sintáctico de un compilador.
Figura 2: Un compilador
En la compilación hay 2 partes: análisis y síntesis. La parte del analisis divide al programa
fuente en sus elementos componentes y crea una representación intermedia del programa fuente.
La parte de la síntesis construye el programa objeto deseado a partir de la representación
intermedia. Durante el análisis, se determinan las operaciones que implica el programa fuente
y se registran en una estructura jerárquica llamada árbol.
2
1. El identicador posición.
2. El símbolo de asignación :=.
3. El identicador inicial
4. El signo de suma
5. El identicador velocidad
6. El signo de multiplicacion
7. El número 60
Los espacios en blanco que separan los caracteres de estos componentes léxicos normalmente
se eliminan durante el análisis léxico.
1.4. Especicaciones
Ingresar al siguiente enlace para conocer el uso y aplicación de la biblioteca YACC en lenguaje
C.
https://www.geeksforgeeks.org/introduction-to-yacc/?ref=rp
3
b ) YACC program to recognize string with grammar (anbn >= 0): https://www.geeksforgeeks.org/y
program-to-recognize-string-with-grammar-anbn-n0/?ref=rp
c ) YACC program for Binary to Decimal Conversion: https://www.geeksforgeeks.org/yacc-
program-for-binary-to-decimal-conversion/?ref=rp
2. Programe lo siguiente:
a ) Reconocer cadenas binarias y aceptar aquellas que contengan un número par de 0's
o 1's
b ) Programar la conversión de binario a hexadecimal
4
2. Desarrollo Experimental
2.1.1. Palindromo
En este código tenemos que ingresar una cadena y decir si es palindromo o no.
5
2.1.2. Reconocimiento de grámatica
En este código tenemos que ingresar una cadena y tenemos que encontrar que la cadena dada
cumpla con la gramatica de
an bn |n ≥ 0
.
6
2.1.3. Binario a decimal
En este código por medio de las reglas de produccion hacemos una conversión de una cadena
binaria a un número entero decimal:
7
2.2. Programas a realizar
En esta sección pondremos el código que se nos realizar:
En este código tenemos que ingresar una cadena binaria y decir si la cadena tiene numero
par de ceros o numero par de unos, en caso de que sea verdadero se imprime en pantalla.
8
2.2.2. Binario a Hexadecimal
En este código por medio de las reglas de produccion hacemos una conversión de una cadena
binaria a una cadena Hexadecimal:
9
2.2.3. Números Capícuos
10
Figura 9: Mostramos los capicuos Pt1
11
Figura 10: Mostramos los capicuos Pt2
12
3. Código
1 %{
2 /* Definition section aqui ponemos las librerias que vamos a incluir
para que funcione nuestro c \ ' odigo , en este caso es la
3 entrada y salida de datos estandar y la libreria estandar , asi como
una libreria que se obtiene al compilar el archivo yacc
4 */
5 # include < stdio .h >
6 # include < stdlib .h >
7 # include " y . tab . h "
8 %}
9
10 /* %option noyywrap */
11
12 /* Rule Section Aqui definimos nuesto lenguaje , algo asi como el rejex
estandar */
13 %%
14
15 [a - zA - Z ]+ { yylval . f = yytext ; return STR ;}
16 [ -+() */] { return yytext [0];}
17 [ \ t ];
18 \ n { return 0; }
19 %%
20 // Aqui se pone la funcion yywrap para que jale
21 int yywrap ()
22 {
23 return -1;
24 }
1 %{
2 /* Definition section aqui ponemos las librerias que vamos a incluir
para que funcione nuestro c \ ' odigo y los prototipos asi como
inicializamos algunas variables */
3 # include < stdio .h >
4 # include < string .h >
5 # include < stdlib .h >
6 extern int yylex () ;
7
8 void yyerror ( char * msg ) ;
9 int flag ;
10
11 int i ;
12 int k =0;
13 %}
14 // Realizamos una union de chars para los strings
15 %union {
16 char * f ;
17 }
18 // Obtenemos el token STR del archivo lex
19 %token <f > STR
20 // Es el tipo E , para esto sirve la union de arriba
13
21 %type <f > E
22
23 /* Rule Section aqui es donde vamos a realizar las reglas de producci \ ' on
en este caso tenemos que una de nuestras de produccion es c \ ' odigo en
C */
24 %%
25
26 S : E {
27 flag = 0;
28 k = strlen ( $1 ) - 1;
29 for ( i = 0; i <= k /2; i ++) {
30 if ( $1 [ i ] != $1 [k - i ]) flag = 1;
31 }
32 if ( flag == 1) printf ( " Not palindrome \ n " ) ;
33 else printf ( " palindrome \ n " ) ;
34 printf ( " %s \ n " , $1 ) ;
35 }; // Aqui termina la regla de producci \ ' on que en este c \ ' odigo en C lo
que hace b \ ' asicamente ah \ ' i es recorrer un caracter de izquierda a
derecha
36 // y de derecha a izquierda y los compara , si son iguales simplemente
obtendriamos el palindromo , sino no es palindromo
37
38 E : STR { $$ = $1 ;}
39 // Esta regla de produccion obtiene el valor por el yyparcer
40 ;
41
42 %%
43 // Aqui nos devuelve si hay un error
44 void yyerror ( char * msg )
45 {
46 fprintf ( stderr , " %s \ n " , msg ) ;
47 exit (1) ;
48 }
49
50 // driver code aqui simplemente llamamos a la funci \ ' on yyparse
51 int main ()
52 {
53 yyparse () ;
54 return 0;
55 }
1 %{
2 /* Definition section donde solamente incluimos la generada por el yacc */
3 # include " y . tab . h "
4 %}
5
6 /* Rule Section definimos nuestro lenguaje , donde tenemos q obtener a y b
*/
7 %%
8 [ aA ] { return A ;}
9 [ bB ] { return B ;}
10 \ n { return NL ;}
11 . { return yytext [0];}
12 %%
13 // El yywrap para que funcione
14 int yywrap ()
15 {
16 return 1;
14
17 }
1 %{
2 /* Definition section donde incluimos la libreria de datos estandar y la
de entrada salida */
3 # include < stdio .h >
4 # include < stdlib .h >
5 %}
6 // obtenemos nuestros tokens del lex , estos son A , B , NL
7 %token A B NL
8
9 /* Rule Section en estas reglas de produccion podemos ver que ahora no es
c \ ' odigo c tal cual por lo que */
10 %%
11 // Primero stmt puede tiene que ser S y NL o sea que tiene que irse a S
dar un salto de linea e imprimir valid string
12 stmt : S NL { printf ( " valid string \ n " ) ;
13 exit (0) ; }
14 ;
15 // Despues S tiene que ser A = A o a , B = B o b , y tiene que llamarse a si
mismo las veces que sea necesario por eso se llama S , o sea por eso
16 // Esta A S B , tambien acepta cadenas vacias
17 S: A S B |
18 ;
19 %%
20 // Es para los errores
21 int yyerror ( char * msg )
22 {
23 printf ( " invalid string \ n " ) ;
24 exit (0) ;
25 }
26
27 // driver code donde simplemente imprimimos una cadena y mandamos a llamar
al yyparse
28 main ()
29 {
30 printf ( " enter the string \ n " ) ;
31 yyparse () ;
32 }
1 %{
2 /* Definition section donde importamos las librerias necesarias para el
desarrollo del proyecto */
3 # include < stdio .h >
4 # include < stdlib .h >
5 # include " y . tab . h "
6 extern int yylval ;
7 %}
8
9 /* Rule Section aqui tenemos lo que seria nuestros valores de nuestro
lenguaje */
10 %%
11 0 { yylval =0; return ZERO ;}
12 1 { yylval =1; return ONE ;}
13
15
14 [ \ t ] {;}
15 \ n return 0;
16 . return yytext [0];
17 %%
18
19 // El yywrap owo
20 int yywrap ()
21 {
22 return 1;
23 }
1 %{
2 /* Definition section donde ponemos prototipos y librerias */
3 # include < stdio .h >
4 # include < stdlib .h >
5 void yyerror ( char * s ) ;
6 %}
7 // Obtenemos nuestros tokens
8 %token ZERO ONE
9
10 /* Rule Section , estas reglas de produccion nos dicen si un numero es cero
o uno , ademas de que hace operaciones para convertir en binario
11 de manera q sea ' recursivo ', ya que primero se llama L a si mismo y
despues decide si simplemente obtener el valor del char pues , o
12 obtiene valor *2+ valor anterior , siendo que sea por ejemplo : 0011; B : ONE
, y despues se hace L : B , para tener el 1 y ahora seria nuestro
valor $2 , despues vuelve a ser llamado y ahora B : ONE , L : L B
es 2*1+1. y asi b \ ' asicamente ah \ ' i
13 */
14 %%
15 N : L { printf ( " \ n %d \ n " , $$ ) ;}
16 L : L B { $$ = $1 *2+ $2 ;}
17 | B { $$ = $1 ;}
18 B : ZERO { $$ = $1 ;}
19 | ONE { $$ = $1 ;};
20 %%
21
22 // driver code es llamado el yyparse de manera que solo se ejecute mientras
no se complete el programa .
23 int main ()
24 {
25 while ( yyparse () ) ;
26 }
27
28 yyerror ( char * s )
29 {
30 fprintf ( stdout , " \ n %s " , s ) ;
31 }
1 %{
2 // Realmente no hay mucho que explicar que no se haya explicado antes
16
3 /* Definition section */
4 # include < stdio .h >
5 # include < stdlib .h >
6 # include " y . tab . h "
7 %}
8
9 /* Rule Section */
10 %%
11
12 [0 -1]+ { yylval . f = yytext ; return STR ;}
13 [ \ t ];
14 \ n { return 0; }
15
16 %%
17
18
19 int yywrap ()
20 {
21 return 1;
22 }
1 %{
2 // Aqui lo unico que explicar es el c \ ' odigo en las reglas de producci \ '
on
3 /* Definition section */
4 # include < stdio .h >
5 # include < string .h >
6 # include < stdlib .h >
7 extern int yylex () ;
8
9 void yyerror ( char * msg ) ;
10 int flagC = 0 , flagU = 0;
11
12 int i ;
13 int k =0;
14 %}
15
16 %union {
17 char * f ;
18 }
19
20 %token <f > STR
21 %type <f > E
22
23 /* Rule Section */
24 %%
25 // Aqui obtenemos una cadena la recorremos y con ayuda de 2 contadores
obtenemos el numero total de ceros y de unos que hay , despues
simplemente se manda una estructura
26 // de control llamada if para comparar valores y decimos que si el modulo
2 de cualquiera de los 2 es cero se acepta la cadena
27 S : E {
28 k = strlen ( $1 ) - 1;
29 for ( i = 0; i <= k ; i ++) {
30 if ( $1 [ i ] == '0 ') flagC ++;
31 else flagU ++;
32 }
33 if (( flagC %2 ==0) || ( flagU %2 == 0) ) printf ( " Cadena Aceptada \ n " ) ;
17
34 else printf ( " No aceptada \ n " ) ;
35 printf ( " %s \ n " , $1 ) ;
36 }
37 ;
38
39 E : STR { $$ = $1 ;}
40 ;
41
42 %%
43
44 void yyerror ( char * msg )
45 {
46 fprintf ( stderr , " %s \ n " , msg ) ;
47 exit (1) ;
48 }
49
50 // driver code
51 int main ()
52 {
53 printf ( " Seleccione la cadena \ n " ) ;
54 yyparse () ;
55 printf ( " Fin del programa \ n " ) ;
56 return 0;
57 }
1 %{
2 /* Definition section donde importamos las librerias necesarias para el
desarrollo del proyecto */
3 # include < stdio .h >
4 # include < stdlib .h >
5 # include " y . tab . h "
6 extern int yylval ;
7 %}
8
9 /* Rule Section aqui tenemos lo que seria nuestros valores de nuestro
lenguaje */
10 %%
11 0 { yylval =0; return ZERO ;}
12 1 { yylval =1; return ONE ;}
13
14 [ \ t ] {;}
15 \ n return 0;
16 . return yytext [0];
17 %%
18
19 // El yywrap owo
20 int yywrap ()
21 {
22 return 1;
23 }
1 %{
2 /* Definition section donde ponemos prototipos y librerias */
3 # include < stdio .h >
4 # include < stdlib .h >
18
5 void yyerror ( char * s ) ;
6 %}
7 // Obtenemos nuestros tokens
8 %token ZERO ONE
9
10 /* Rule Section , estas reglas de producci \ ' on son las mismas que las de
binario a decimal la unica diferencia es que imprimimos el tipo de
dato a Hexadecimal
11 */
12 %%
13 N : L { printf ( " \ n %X \ n " , $$ ) ;}
14 L : L B { $$ = $1 *2+ $2 ;}
15 | B { $$ = $1 ;}
16 B : ZERO { $$ = $1 ;}
17 | ONE { $$ = $1 ;};
18 %%
19
20 // driver code es llamado el yyparse de manera que solo se ejecute mientras
no se complete el programa .
21 int main ()
22 {
23 while ( yyparse () ) ;
24 }
25
26 yyerror ( char * s )
27 {
28 fprintf ( stdout , " \ n %s " , s ) ;
29 }
1 %{
2 // Es el mismo que el de los palindromos solo que ahora es 0 -9 en vez de a
- zA - Z
3 /* Definition section */
4 # include < stdio .h >
5 # include < stdlib .h >
6 # include " y . tab . h "
7 %}
8
9 /* %option noyywrap */
10
11 /* Rule Section */
12 %%
13
14 [0 -9]+ { yylval . f = yytext ; return STR ;}
15 [ -+() */] { return yytext [0];}
16 [ \ t ];
17 \ n { return 0; }
18
19 %%
20
21 int yywrap ()
22 {
23 return -1;
24 }
1 %{
19
2 /* Definition section */
3 # include < stdio .h >
4 # include < string .h >
5 # include < stdlib .h >
6 extern int yylex () ;
7
8 void yyerror ( char * msg ) ;
9 int flag = 1;
10
11 int i ;
12 int n = 0 , k = 0;
13 %}
14
15 %union {
16 char * f ;
17 }
18
19 %token <f > STR
20 %type <f > E
21
22 /* Rule Section */
23 %%
24
25 S : E {
26 n = strlen ( $1 ) ;
27 k = n - 1;
28 for ( i = 0; i < n /2; i ++) {
29 if ( $1 [ i ] != $1 [k - i ])
30 flag = 0;
31 }
32 if ( flag )
33 printf ( " %s Es capicua \ n " , $1 ) ;
34 }
35 ;
36
37 E : STR { $$ = $1 ;}
38 ;
39
40 %%
41
42 void yyerror ( char * msg )
43 {
44 fprintf ( stderr , " %s \ n " , msg ) ;
45 exit (1) ;
46 }
47
48 // driver code
49 int main ()
50 {
51 // printf (" Seleccione el numero maximo que desea que sea el maximo de la
cadena : \ n ") ;
52 yyparse () ;
53 // printf (" Fin del programa \ n ") ;
54 return 0;
55 }
1 # !/ bin / bash
2 # Primero borramos si es que hay un archivo para no sobreescribir
20
3 rm num_capicua . txt
4 # Despues enviamos el texto a un archivo num_capicua
5 echo " En numeros de uno al 1000 , estos son los numeros capicua : " >
num_capicua . txt
6 # corremos el programa 1000 veces y los resultados se almacenan en el
archivo num_capicua . txt
7 for i in {0..1000}
8 do
9 ./ capicua <<< $i >> num_capicua . txt
10 done
21
4. Conclusiones
22
5. Referencias
Referencias
[1] Aho, A. (2008). Compiladores principios, técnicas y herramientas . Pearson Education In-
ternational.
23