Está en la página 1de 22

Instituto Tecnológico de Ciudad Guzmán

Ingeniería en Sistemas Computacionales


Lenguajes y autómatas II
Generación de código objeto

Alumnos: Carlos Alejandro Villa Mendoza y Ángel Iván


Álvarez Castillo.
Profesor: Marco Antonio Guzmán Solano.
Lugar y fecha: Ciudad Guzmán, Jalisco a 8 de diciembre de
2023.
índice
Introducción..............................................................................................................3
Análisis semántico................................................................................................ 3
Generación de código intermedio.........................................................................3
Optimización de código.........................................................................................3
Generación de código objeto................................................................................3
Módulo 1...................................................................................................................4
Módulo 2...................................................................................................................6
Módulo 3.................................................................................................................11
Módulo 4.................................................................................................................14
Conclusión..............................................................................................................20
Referencias............................................................................................................ 21

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.

La tarea principal del análisis semántico es la inferencia y la verificación de tipos.


Generación de código intermedio
Se puede considerar esta representación intermedia como un programa para una
máquina abstracta. Esta representación intermedia debe tener dos propiedades
importantes; debe ser fácil de producir y fácil de traducir al programa objeto.
Optimización de código
Su objetivo es que código que se ejecuta más eficientemente según los criterios
• Tiempo de ejecución (optimización temporal)
• Espacio de memoria utilizado (optimización espacial).

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

return columna (Aquí se regresa los valores de la columna)


si todo se escribió correctamente va así

Y si no marca error

5
Módulo 2

El siguiente código analiza expresiones aritméticas


def analizarExpresionMatematica(self, cadena):
Aquí declara una pila y un arreglo con la gramática:
pila = [0]

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()

Aquí hay una expresión regular

7
regex = r'([A-Za-z_][A-Za-z0-9_]*|\d+|[-+*/()])'

tokens = re.findall(regex, cadena)


tokens.append("$")

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")

while True and len(tokens) > 0:


estado_actual = pila[len(pila) - 1]
accion_actual = accion[estado_actual][self.obtener_columna(token_actual)]

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)]))

elif accion_actual == "ACCEPT":


return(True)
break
else:
print("ERROR: CADENA MATEMATICA ERRONEA")
return(False)
break
Si todo va bien saldrá una captura de pantalla como la del modulo uno donde solo
imprime la tabla, por el contrario imprimirá un mensaje de error.

9
Este es el código sin errores:

Este es el código con error en la primera línea:

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

for line in r_file:


find = False
aux = line.strip().split()
validar = vil(line)
if validar != "ninguna":

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

if find == False and validar == "imprimir":


match = re.search(r'"([^"]+)"', line)
if match:
texto_entre_comillas = match.group(1)

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"
)

En caso de que no se encuentre el archivo marcará este error.


except EnvironmentError:
print("No se encontró el archivo")
Primero mencionaremos que el código en assembler incluye una macro externa
Macro de impresión
IMPRIMIR MACRO VAR, EMPTY
lea dx, VAR+2
mov ah, 9
int 21h
lea dx, EMPTY
mov ah, 9
int 21h

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.

La importancia de este proceso radica en la detección temprana de errores en el


código fuente. Identificar problemas de estructura o sintaxis antes de la ejecución
del programa ayuda a los desarrolladores a corregirlos fácilmente, mejorando la
confiabilidad y robustez del software final. Además, entender y diseñar
analizadores sintácticos es esencial para la comprensión profunda de la teoría de
compiladores y lenguajes formales, conocimientos fundamentales en informática.

Lo aprendido al trabajar con este tipo de código incluye comprensión de


gramáticas formales, manejo de tablas de análisis sintáctico y aplicación de
algoritmos de análisis ascendente. Además, proporciona una visión más clara de
cómo los programas pueden interpretar y validar la estructura de un lenguaje de
programación, lo que es esencial en el diseño e implementación de lenguajes de
programación propios o en el desarrollo de compiladores.

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

También podría gustarte