Está en la página 1de 12

UNIVERSIDAD AUTONOMA

DEL ESTADO DE HIDALGO


Instituto de Ciencias Básicas e Ingeniería

Videos (Autómatas y Compiladores)

Nombre: Bautista Bautista Pedro Jhonatan


Materia: Autómatas y Compiladores
Grupo: 1 // Semestre: 6

2022
Video 1
Compiladores
Análisis léxico

- Detecta entradas con tokens ilegales

Analizando

- Detecta entradas de árboles con análisis mal formados.

Análisis semántico

- Utiliza la fase de "front end"


- Captura todos los errores restantes

El análisis léxico, analizador y análisis semántico como filtros que progresivamente


rechazar más y más cadenas de entrada hasta que finalmente te quedes después
de las tres fases se han ejecutado con solo programas válidos para compilar, bueno,
el análisis semántico es la última línea de defensa. Es el último en esa tubería y su
trabajo es atrapar todos posibles errores restantes en un programa.

¿Por qué incluso se necesita una fase separada de análisis semántico?

Hay algunas características de los lenguajes de programación, algunos tipos de


errores que puede cometer que los análisis simplemente no pueden detectar. El a
análisis que se utilizara en contexto a las gramáticas libres no son lo
suficientemente expresivas para describir todo lo que nos interesa en una definición
de lenguaje. Entonces, algunas de estas construcciones del lenguaje no son
contextuales.

Gramática libre de contexto

Se utilizan para describir características adicionales de nuestros lenguajes de


programación por sí mismos tampoco son suficientes, y hay algunas características
adicionales más aquellos que no se pueden expresar fácilmente usando
construcciones libres de contexto.
¿Que hace el análisis semántico?

En un caso de Cool C, hace comprobaciones de muchos diferentes tipos, y eso es


bastante típico. Así que aquí hay una lista de seis clases de comprobaciones
realizadas por Cool C

Primero

Se verificar que todos los identificadores estén declarados, y también que se


observe cualquier restricción de alcance en esos identificadores

Segundo

Se verificarán las relaciones de herencia entre las clases para ver si tienen sentido

No queremos que se redefinan las clases; solo queremos una clase definición por
clase. De manera similar, los métodos solo deben definirse una vez dentro de una
clase

Cool tiene una serie de identificadores reservados y se tiene que tener cuidado de
como usarlos.

El mensaje principal es que el analizador médico necesita hacer bastantes cosas,


diferentes clases de cheques. Estas comprobaciones variarán según el idioma. Los
tipos de cheques que hace C es bastante típico en la orientación a objetos marcada
estáticamente idiomas, Pero otras familias de idiomas tendrán diferentes tipos de
controles.
Video 2

En este video se habla sobre un tema que es las tablas simples una estructura de
datos importante en muchos compiladores antes de hablar de lo que es una tabla
simple quiero hablar de un algoritmo genérico que vamos a ver una y otra vez
durante el resto del curso. Por lo tanto, una gran cantidad de análisis semántico y
de hecho, una gran cantidad de generación de código puede expresarse como un
descenso recursivo de un árbol sintáctico abstracta. Y la idea básica es que en cada
paso hacemos las siguientes tres cosas. siempre estamos procesando un nodo
particular en el árbol, así que si hago un dibujo del árbol de sintaxis abstracta árbol
de sintaxis abstracta puede tener un nodo y algunos sub-árboles que cuelgan de él.
Y podemos hacer algún procesamiento del nodo antes de hacer cualquier otra cosa.
Llegamos al nodo al nodo digamos desde los padres, venimos aquí por el padre,
hacemos algún procesamiento en el nodo y sólo estoy indicando que por el color
azul para indicar que hicimos algo aquí. Y luego salimos y procesamos los hijos.
Bien. Y después procesamos los hijos, después de volver al nodo, hacemos algo
más

Esto se llama un recursivo de un árbol. Hay algunos casos en los que sólo
procesaremos cada nota antes de procesar los hijos. Otros en los que sólo
procesamos cada nota después de procesar todos los hijos. Algunos en los que
hacemos ambas cosas como se ilustra aquí en este pequeño Y volviendo al tema
principal de este video en particular. Cuando estamos realizando un análisis
semántico en una porción del árbol de sintaxis abstracta necesitamos saber qué
identificadores están definidos. ¿Qué identificadores están en alcance? Un ejemplo
de este tipo de estrategia de descenso recursivo es cómo podemos procesar los
enlaces let para rastrear el conjunto de variables que están en el ámbito. Así,
tenemos nuestro nodo let en el árbol de sintaxis fx y en un subárbol tenemos la
inicialización, y en el otro subárbol tenemos e, el cuerpo del let, y luego es un let
para alguna variable en particular, y vamos a escribir esa dentro del nodo padre.

Entonces vamos a recurrir vamos a procesar todas. del árbol de sintaxis abstracta
no des en el cuerpo de la inaudible dentro de E, y después de terminar de procesar
E, vamos a eliminar la definición de X y restaurar la antigua definición de X que
teníamos. Y una tabla de símbolos es sólo una estructura de datos que logra estas
cosas. Rastrea los enlaces actuales de los identificadores en cada punto del árbol
sintáctico abstracto. Para una tabla muy simple, simple tabla, podríamos usar una
pila, y tendría sólo digamos la después de tres operaciones, podríamos añadir un
símbolo a la tabla de símbolos y eso simplemente empuja el símbolo, empuja la
variable a la pila y cualquier otra información que queramos, como su tipo.

Cuando salimos de un ámbito podemos eliminar un símbolo simplemente abriendo


la pila. Simplemente la variable actual de esta pila. Esto eliminará la definición más
definición más reciente. Y, y dejar la pila, dejar el conjunto de definiciones en el
mismo estado que tenía antes de entrar en el nodo. Así que, en este ejemplo, si
dejamos el ámbito en el que se define la Y y que fue saltado de la pila, por lo que
fuese ha ido. Ahora, cuando busquemos Y encontraremos la definición exterior. La
que fue definida fuera de ese ámbito interno, Así que esta simple tabla de símbolos
funciona bien para let, porque los símbolos se clasifican de uno en uno, y porque
las declaraciones están perfectamente anidadas. Y de hecho, el hecho de que las
declaraciones estén perfectamente anidadas es realmente la razón por la que
podemos usar una pila/ Así que, echa un vistazo a este pequeño ejemplo, digamos
que tenemos tres lets anidados, y aquí no estoy mostrando los inicializadores en los
subárboles menos, y ellos, no importan, para lo que quiero ilustrar. Así que si usted
piensa en ello a medida que caminamos desde la raíz aquí hacia abajo a la estamos
empujando cosas en la pila, empujaremos cosas en la pila en el orden X, Y, y luego
Z. Y luego al salir, después de haber procesado este sub árbol, y lo estamos
dejando, caminando de nuevo, vamos a encontrar estos ámbitos de la izquierda
ámbitos exactamente en el orden inverso. Y sacarlos de la pila es exactamente el
es exactamente el orden en el que queremos eliminarlos, y es por eso que una pila
funciona bien. Así que La estructura funciona bien para lets, pero para algunas otras
construcciones no es tan cómo podría ser, así que, por ejemplo, considera el
siguiente trozo de código.
Un trozo de código ilegal, debo añadir. Digamos que estamos declarando un
método, y tiene dos argumentos llamados X. Ahora, eso no es legal pero para
detectar que no es legal tú. ¿Por qué no es legal? No es legal porque ambos están
definidos en el mismo ámbito. Entonces, las funciones, o los métodos, tienen la
propiedad de introducir múltiples nombres a la vez en el mismo ámbito.

El mayor cambio es que ahora tenemos funciones explícitas de entrada y salida


explícitas de entrada y salida, por lo que estas funciones comienzan en el ámbito
anidado y salen del ámbito actual. ámbito actual. Y la forma de pensar en esto es
que nuestra nueva estructura es una pila de ámbitos, así que [inaudible] es todo el
ámbito y el ámbito interno. Es, son todas las variables que se definen en el mismo
nivel, dentro de ese único ámbito. Así que, al igual que como antes, tenemos una
operación de búsqueda de símbolos que buscará un nombre de variable nombre de
una variable, y devolverá la definición actual, o null si no hay definición en ningún
ámbito que esté disponible actualmente. Tendremos una operación de añadir
símbolo que añade un nuevo símbolo a la tabla, y lo añade en el ámbito actual, así
que lo que sea, el ámbito está en la parte superior de nuestra pila de ámbito. Y luego
una nueva operación, check scope. Devolverá true si X ya está definido en el ámbito
actual.
Video 3

Compiladores

En este video fue una introducción a los tipos.

¿Qué es un tipo?

Lo que es un tipo, varía de lenguaje de programación a lenguaje de programación.

Ahora, en términos generales, el consenso es que un tipo es un conjunto de valores,


y también, quizás más importante, un conjunto de operaciones que son único a esos
valores, un conjunto de operaciones que se definen en esos valores.

Diferencia entre clases y tipos

Entonces, en la modernidad los tipos de lenguajes de programación se expresan de


diferentes maneras. en objeto lenguas orientales. A menudo vemos que las clases
son la noción de tipo. Entonces, en general, los nombres de las clases son los tipos,
todos son, con una excepción, llamado tipo propio. Los nombres de clase son
exactamente los tipos. Y solo quería señalar que este no tiene por qué ser el caso.
Sucede que a menudo es conveniente en Idiomas victorianos para equiparar clases
y tipos. Y en algunos idiomas, donde no hay noción de clase, los tipos son cosas
completamente diferentes. Entonces, las clases y los tipos son realmente dos cosas
diferentes que suceden, para ser identificadas en una gran cantidad de orientación
a objetos diseños Y solo quiero que sepas que esa no es necesariamente la única
manera para hacerlo.

Así que considere el fragmento de lenguaje ensamblador agregar R1 R2 R3 y qué


hace esto realmente. Bueno, toma el contenido del registro R2 y el contenido del
registro R3 los suma, y pone los resultados en el registro R1. Y la pregunta es,
¿cuáles son los tipos de R1, R2 y R3? Y es de esperar que sean números enteros,
pero de hecho esta es una, esta es una pregunta capciosa Porque en la asamblea
nivel de idioma que no puedo decir. No hay nada que impida que R1, R2 y R3 tener
tipos arbitrarios. Entonces, para acer esto un poco claro, tal vez sea útil pensar en
ciertas operaciones que son legales para valores de cada tipo.
Sistema de tipos de idiomas

Un sistema de tipos de idiomas especifica qué operaciones son válidas para qué
tipos.

Entonces el objetivo de la verificación de tipos es garantizar que las operaciones se


usen solo, solo con los tipos correctos. Y al hacer esto, la verificación de tipos hace
cumplir la intención interpretación de los valores porque nada más se va a
comprobar. Una vez que lleguemos al nivel de código de máquina, todo es solo un
montón de 0 y 1, y la máquina estará feliz para hacer cualquier operación que le
indiquemos en esos 0 y 1, sean o no esos las operaciones tienen sentido. Entonces,
el propósito de los sistemas de tipos es hacer cumplir las interpretaciones de esos
patrones de bits y asegurarme de que si tengo un patrón de bits para enteros que
no hago ninguna operación no entera en eso y obtengo algunas cosas que no tiene
sentido.

Categorías

Hoy en día, los lenguajes de programación se dividen en tres diferentes categorías


con respecto a cómo tratan los tipos.

Tipos estáticos lenguajes, donde toda, o casi toda, la comprobación de tipos se


realiza como parte de compilación, y Cool es uno de estos y otros lenguajes que
probablemente hayas visto, como C y Java.

lenguajes tipeados, donde casi toda la verificación de tipos se realiza como parte de
ejecución del programa. Y la familia de lenguajes Lisp, como Scheme y Lisp, están
en esta categoría, al igual que lenguajes como Python y Pearl.

Lenguajes no tipificados en los que no se realiza ninguna verificación de tipo, ya


sea en tiempo de compilación o en tiempo de ejecución.

Escritura estática vs dinámica

Durante décadas se ha debatido sobre los méritos relativos de la estática frente a


la escritura dinámica y sin tomar partido, permítanme explicarles cuáles son los
diversos proponentes de cada lado. Entonces, las personas que creen en la
escritura estática dicen: que la verificación estática detecta muchos errores de
programación en tiempo de compilación y también evita la sobrecarga de las
comprobaciones de tipos en tiempo de ejecución. Estas son las dos grandes
ventajas de la estática. Comprobación, en primer lugar, demuestra que algunos
errores nunca pueden ocurrir, esos son detectados en tiempo de compilación para
que nunca tenga que preocuparme por esos errores en tiempo de ejecución, y los
defensores de la tipificación dinámica más rápida responden que los sistemas de
tipografía estética son restrictivos.

Entonces, esencialmente, el sistema de tipo estético tiene que probar que el


programa está bien tipificado, que todos los tipos tienen sentido y lo hace
restringiendo lo que tipos de programas que puede escribir. Hay algunos programas
que son más difíciles de escribir en un lenguaje de tipo estético porque el compilador
tiene dificultades demostrando que son correctos. Y también existe la creencia de
que la creación rápida de prototipos es más difícil con el sistema de tipo extático.

Creo que la idea aquí está que, si estás creando prototipos de algo, si estás
explorando alguna idea es posible que en realidad no sepa exactamente cuáles son
todos los tipos en ese momento y tener que comprometerse con algo que va a
funcionar en todos los casos. ya sabes, a tener un programa de tipo correcto cuando
solo estás tratando de juguetear y descifrar qué es lo que estás tratando de hacer.
Eso es muy restrictivo y hace que el trabajo funcione bastante más lento.

Ahora en el sitio de escritura dinámica, las personas que programan lenguajes


dinámicos, siempre terminaron o parecían terminar ajustando el registro de escritura
estática a estos escritos dinámicamente idiomas. Por lo general, si un lenguaje
escrito dinámicamente es lo suficientemente popular como para personas que
intentan escribir compiladores de optimización para ellos y lo primero que la gente
quiere tener en un compilador de optimización.

Now Cool es un lenguaje tipificado estáticamente y los tipos que están disponibles
en Cool son los nombres de las clases, por lo que cada vez que defines una clase,
definesun nuevo tipo, y el símbolo de reserva especial.
Y la forma en que funciona genial es que el usuario declara los tipos para
identificadores.

Para cada identificador tiene que decir cuál es su tipo, pero, entonces el compilador
hace el resto del trabajo. El compilador hace referencia al tipo de las expresiones.
Y en particular, el compilador asigna un tipo a cada expresión en el programa. Por
lo tanto, recorrerá toda la cadena de sintaxis abstracta y usará el tipo declarado para
identificar, calcular un tipo para cada expresión y subexpresión.

En realidad, hay muchos idiomas que en realidad son muy, muy diferentes, pero la
gente a menudo usa los términos indistintamente, y no tendré especial cuidado en
mis videos sobre qué término estoy usando tampoco.

Video 4

Entonces, las reglas if-else son enunciados de implicación que alguna hipótesis
implica alguna conclusión Y en el caso particular de verificación de tipos ejemplo o
tipo típico de razonamiento que vemos en la verificación de tipos es que, si un un
par de expresiones tienen ciertos tipos, entonces se garantiza alguna otra expresión
tener un cierto tipo. Y tan claramente que la declaración de verificación de tipo aquí
es un ejemplo de una regla de inferencia. Una notación de regla de inferencia es
solo una compacta forma de codificar este tipo de declaraciones if then.

Así que ahora considere la siguiente regla de tipo muy simple. Y fíjate que, esa
declaración que acabamos de escribir out es un caso especial de una regla de
inferencia. Es un montón de hipótesis unidas juntos e implica alguna conclusión.
Estas son todas las hipótesis, luego lo de abajo.

Este es el torniquete que se utilizan para las hipótesis y la conclusión. Que algo es
demostrable en el sistema de reglas que estamos definiendo Entonces, la forma en
que leerías esto es que si es demostrable que todos estos las hipótesis son
verdaderas. Entonces, si es demostrable que la primera hipótesis es cierta, todas
las hipótesis intermedias, y si es mejorable, si es demostrable la última hipótesis es
verdadera. Los siguientes tipos de hipótesis y conclusiones que vamos a probar,
dentro del sistema, que alguna expresión tiene un tipo particular.

Así que con esas definiciones fuera del camino, en realidad tenemos suficiente para
escribir al menos unas pocas reglas de tipos simples. Y aquí está la regla para
agregar escrita ahora en la notación de la regla de inferencia. La regla para
constantes enteras solo usa un genérico entero i. No dio una regla separada para
cada número entero posible, y la regla para más expresiones usadas e uno y e dos.

Y entonces podemos conectar cualquier expresión que queramos que satisfacen


las hipótesis, y luego podemos producir una tipificación completa para expresiones
Entonces, como un ejemplo concreto, mostremos que uno más dos tiene tipo int.
Así que queremos escribir la expresión uno más dos, y como conocemos la regla
para sumar eso significa que necesitamos construir una prueba del tipo del número
uno, y una prueba del tipo del número dos. Y tenemos una regla para tratar con
clases enteras, principalmente podemos probar porque uno es una clase entera que
tiene tipo int, y nosotros podemos probar que dos es de tipo int, y ahora tenemos
las dos hipótesis que necesitamos para la expresión suma y podemos probar que
uno más dos tiene tipo int. Lo que queremos es lo que sea que el sistema de tipos
pueda probar que alguna expresión tiene el tipo system tiene un tipo particular T. Si
tomo E y lo ejecuto en la computadora el valor que devuelve, el valor que viene
después de ejecutar E de hecho tiene el tipo predicho por el sistema de tipos.

Entonces, si el sistema de tipos es capaz de dar tipos de cosas que realmente


reflejan qué tipo de valor obtienes cuando ejecutas el programa, entonces decimos
que el sistema de tipos es sólido. si tengo un literal entero Y quiero darle un tipo,
mientras nosotros, nosotros, te mostré lo mejor posible regla anterior donde dijimos
que tiene tipo, Pero también sería correcto, pero no muy preciso decir que tiene tipo
de objeto. Ciertamente, si evalúo un número entero, obtendré un objeto porque cada
entero en, también es un objeto, Pero esto no es tan útil porque ahora no puede
hacer ninguna de las operaciones con enteros Y entonces hay muchos sonidos
diferentes reglas, no hay una sola regla única para cualquier expresión dada que
serán sólidos, pero algunos de ellos son mejores que otros, y en el caso de números
enteros literales el que realmente queremos.

También podría gustarte