Documentos de Académico
Documentos de Profesional
Documentos de Cultura
2
Introducción
Durante la materia de leguajes y autómatas II se realizan varias mejoras al
compilador que se hizo en la materia anterior como agregar un analizador
sintáctico, que valide expresiones matemáticas, optimización de código y por
último que genere una tabla de símbolos en ensamblador (MASM). A
continuación, se abarcará el trabajo hecho de esta materia mostrando como
funciona cada programa elaborado y dando una breve introducción de lo que trata
cada tema.
Análisis semántico
El análisis semántico es la fase que se encarga de validar el código fuente
Además de que el código debe ser sintácticamente correcto, debe ser coherente
con su contexto
Por ejemplo:
La suma sólo se puede efectuar entre datos que son numéricos.
Una variable debe ser declarada antes de usarse.
3
Generación de código objeto
La fase final de un compilador es la generación de código objeto, que por lo
general consiste en código de máquina relocalizable o código ensamblador. Las
posiciones de memoria se seleccionan para cada una de las variables usadas por
el programa. Después, cada una de las instrucciones intermedias se traduce a una
secuencia de instrucciones de máquina que ejecuta la misma tarea. Un aspecto
decisivo es la asignación de variables a registros.
Módulo 1
El siguiente código almacena los tokens y hace el análisis sintáctico ascendente
del código que se lee
import re
Nota: aquí se declaran los tokens.
class AnalizadorSintacticoAscendente():
def obtener_columna(self, token):
columna = -1
if token == "ID":
columna = 0
elif token == "+":
columna = 1
elif token == "-":
columna = 2
elif token == "*":
columna = 3
elif token == "/":
columna = 4
elif token == "(":
columna = 5
elif token == ")":
columna = 6
elif token == "$":
4
columna = 7
elif token == "E":
columna = 8
elif token == "T":
columna = 9
elif token == "F":
columna = 10
Y si no marca error
5
Módulo 2
gramatica = [
{"E+T": "E"},
{"E-T": "E"},
{"T": "E"},
{"T*F": "T"},
{"T/F": "T"},
{"F": "T"},
{"(E)": "F"},
6
{"ID": "F"},
]
Aquí usa un árbol para analizar la expresión aritmética:
accion = [
["D5", " ", " ", " ", " ", "D4", " ", " ", "1", "2", "3"],
[" ", "D6", "D7", " ", " ", " ", " ", "ACCEPT", " ", " ", " "],
[" ", "R3", "R3", "D8", "D9", " ", "R3", "R3", " ", " ", " "],
[" ", "R6", "R6", "R6", "R6", " ", "R6", "R6", " ", " ", " "],
["D5", " ", " ", " ", " ", "D4", " ", " ", "10", "2", "3"],
[" ", "R8", "R8", "R8", "R8", " ", "R8", "R8", " ", " ", " "],
["D5", " ", " ", " ", " ", "D4", " ", " ", " ", "11", "3"],
["D5", " ", " ", " ", " ", "D4", " ", " ", " ", "12", "3"],
["D5", " ", " ", " ", " ", "D4", " ", " ", " ", " ", "13"],
["D5", " ", " ", " ", " ", "D4", " ", " ", " ", " ", "14"],
[" ", "D6", "D7", " ", " ", " ", "D15", " ", " ", " ", " "],
[" ", "R1", "R1", "D8", "D9", " ", "R1", "R1", " ", " ", " "],
[" ", "R2", "R2", "D8", "D9", " ", "R2", "R2", " ", " ", " "],
[" ", "R4", "R4", "R4", "R4", " ", "R4", "R4", " ", " ", " "],
[" ", "R5", "R5", "R5", "R5", " ", "R5", "R5", " ", " ", " "],
[" ", "R7", "R7", "R7", "R7", " ", "R7", "R7", " ", " ", " "]
]
n=0
cadena = cadena.upper()
7
regex = r'([A-Za-z_][A-Za-z0-9_]*|\d+|[-+*/()])'
En este if empieza a analizar los tokens si hay algún error en los caracteres
escritos lo indica al usuario.
for i in range(len(tokens)):
if re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', tokens[i]) or tokens[i].isdigit():
tokens[i] = "ID"
if len(tokens) > 0:
token_actual = tokens[n]
n += 1
else:
print("INGRESO UNA CADENA VACIA")
if accion_actual[0] == "D":
pila.append(int(accion_actual[1:]))
token_actual = tokens[n]
n += 1
elif accion_actual[0] == "R":
indice_regla = int(accion_actual[1:]) - 1
8
regla = list(gramatica[indice_regla].keys())[0]
if regla == "ID":
pila.pop()
else:
for _ in range(len(regla)):
pila.pop()
nuevo_estado = pila[len(pila) - 1]
simbolo = gramatica[indice_regla].get(regla)
pila.append(int(accion[nuevo_estado][self.obtener_columna(simbolo)]))
9
Este es el código sin errores:
10
Aquí muestra primero el error y después la tabla:
Módulo 3
Aquí se validan los bucles: for, if y while.
El siguiente fragmento de código se analizará la sintaxis de los bucles y si se
escribieron correctamente:
def vcc(line, count, type):
if type == "for":
if re.match(r'^for\s+[a-zA-Z_][a-zA-Z0-9_]*\s+in\s+.+:$', line):
print("LINEA {} OK - Estructura de bucle for válida".format(count))
else:
print("LINEA {} ERROR - Estructura de bucle for inválida".format(count))
if type == "while":
if re.match(r'^while\s+.+:$', line):
print("LINEA {} OK - Estructura de bucle while válida".format(count))
else:
print("LINEA {} ERROR - Estructura de bucle while inválida".format(count))
11
if type == "if":
if re.match(r'^if\s+\(.+?\)\s*:$', line):
print("LINEA {} OK - Estructura de condición if válida".format(count))
else:
print("LINEA {} ERROR - Estructura de condición if inválida".format(count))
Ejemplo de un código con estructuras correcto
12
Como se ve funciona.
Ejemplo de un código mal:
13
Cómo se ve marca error.
Módulo 4
En el siguiente programa tiene cuatro partes:
1. El código en Python que contiene las expresiones del lenguaje inventado
(expresiones.py).
2. El código en el lenguaje inventado (code.ivn)
3. EL código que manda los datos del código en el lenguaje Iván s
ensamblador (lenguaje.py)
4. El código en ensamblador que recibe las cadenas (CODE.ASM).
Tenemos el código en lenguaje Iván
Pasa a los programas que leen las expresiones y sintaxis y luego lo convierte en
código en ensamblador:
count = 0
14
operacionesOrden = []
for i in range(len(nameAsignation)):
impEnable.append(False)
for i in range(len(nameAsignation)):
readEnable.append(False)
try:
with open(name + ".dep", "r") as r_file:
with open(name + ".ASM", "w") as write_file:
write_file.write("include MACROS.INC\n"
"pila segment para stack 'stack'\n"
" dw 500 dup(?)\n"
"pila ends\n"
"\n"
"datos segment para public 'data'\n"
" lv db 13, 10, '$'\n")
content_count = 1
15
for index, i in enumerate(nameAsignation):
if i in line and validar == "imprimir" and impEnable[index] == False:
write_file.write(f" p_{i} db ' {valueAsignation[index]}$'\n")
impEnable[index] = True
operacionesOrden.append(f"IMPRIMIR p_{i}, lv")
find = True
elif i in line and validar == "imprimir" and readEnable[index] ==
False:
operacionesOrden.append(f"IMPRIMIR p_{i}, lv")
find = True
elif i in line and validar == "leer" and readEnable[index] == False:
write_file.write(f" r_{i} db 254,?,254 dup('$')\n")
readEnable[index] = True
operacionesOrden.append(f"LEER r_{i}, lv")
impEnable[index] = True
find = True
elif i in line and validar == "imprimir" and impEnable[index] == True
and readEnable[index] == True:
operacionesOrden.append(f"IMPRIMIR r_{i}, lv")
find = True
elif i in line and validar == "leer" and readEnable[index] == True:
operacionesOrden.append(f"LEER r_{i}, lv")
find = True
16
write_file.write(f" t_{content_count} db ' {texto_entre_comillas}$'\
n")
operacionesOrden.append(f"IMPRIMIR t_{content_count}, lv")
content_count+=1
else:
print("ERROR no se encontro ninguna cadena para ASM")
Aquí se escribe el código en ensamblador
write_file.write(
"datos ends \n"
"extra segment para public 'data'\n"
"extra ends\n\n"
"public pp\n"
"assume cs:codigo,ds:datos,es:extra,ss:pila\n\n"
"codigo segment para public 'code'\n"
"pp proc far\n"
" push ds\n"
" mov ax,0\n"
" push ax\n"
" mov ax,datos\n"
" mov ds,ax\n"
" mov ax,extra\n"
" mov es,ax\n")
for i in range(len(operacionesOrden)):
write_file.write(" "+operacionesOrden[i] + "\n")
write_file.write(
" ret \n"
"pp endp \n"
"codigo ends \n"
17
" end pp \n"
)
ENDM
Macro de leer
LEER MACRO DIR, EMPTY
lea dx, DIR
mov ah, 0ah
int 21h
lea dx, EMPTY
mov ah, 9
int 21h
ENDM
18
Macro de borrar
CLEAR MACRO
mov ah, 0fh
int 10h
mov ah, 0
int 10h
ENDM
Código en ensamblador:
include MACROS.INC
Segmento de pila
pila segment para stack 'stack'
dw 500 dup(?)
pila ends
Segmento de datos
datos segment para public 'data'
lv db 13, 10, '$'
p_cadena db ' hola soy la primer cadena en una variable$'
r_cadena db 254,?,254 dup('$')
p_third db ' 25$'
p_first db ' 0$'
datos ends
Segmento extra
extra segment para public 'data'
extra ends
public pp
assume cs:codigo,ds:datos,es:extra,ss:pila
19
Segmento de código
codigo segment para public 'code'
pp proc far
push ds
mov ax,0
push ax
mov ax,datos
mov ds,ax
mov ax,extra
mov es,ax
IMPRIMIR p_cadena, lv
LEER r_cadena, lv
IMPRIMIR r_cadena, lv
IMPRIMIR p_third, lv
IMPRIMIR p_first, lv
ret
pp endp
codigo ends
end pp
Conclusión
Carlos Alejandro Villa Mendoza
Durante estas dos materias he aprendido como funciona desde adentro un
compilador como las expresiones que ingresamos para hacer un programa se van
traduciendo a un lenguaje que la máquina puede entender, como le hace para que
verifique los errores de las expresiones que escribimos como cuando nos falta
punto y coma o cualquier falta a la gramática o semántica que hayamos escrito.
También cómo mejorar nuestro código a través de la optimización, generar un
código intermedio y finalmente hacer un programa que mande los valores e
20
información de las variables a ensamblador. La verdad este proceso demandó
mucho de nuestra lógica adquirida en lo que va de la carrera.
Ángel Iván Álvarez Castillo.
Este código implementa un analizador sintáctico, una parte esencial en la
construcción de compiladores y lenguajes de programación. La finalidad de un
analizador sintáctico es verificar si una cadena de tokens (como una expresión
matemática) sigue la gramática definida por el lenguaje. Esto es crucial para
garantizar que las expresiones ingresadas por los usuarios sean sintácticamente
correctas antes de su ejecución.
Referencias
1.3.5. Generador de código intermedio. (s. f.).
http://cidecame.uaeh.edu.mx/lcc/mapa/proyecto/libro32/135_generador_de_cdigo_
intermedio.html
1.3.7. Generador de código objeto. (s. f.-a).
http://cidecame.uaeh.edu.mx/lcc/mapa/proyecto/libro32/137_generador_de__cdigo
_objeto.html
1.3.7. Generador de código objeto. (s. f.-b).
http://cidecame.uaeh.edu.mx/lcc/mapa/proyecto/libro32/137_generador_de__cdigo
_objeto.html
Universidad de Guanajuato. (2022, 16 julio). Clase digital 12. Análisis semántico y
estrategias de implementación. https://blogs.ugto.mx/rea/clase-digital-12-analisis-
semantico-y-estrategias-de-implementacion/
21
22