{}
{
{}
Henry Gálvez
22/09/2021
{
Patrón Intérprete con Jison
Agenda
- Método del Árbol
-
Patrón intérprete
-
Que es Jison
-
Estructura de Jison
-
Ejemplo
Método del Árbol
Es una técnica que consiste en crear una estructura de dato abstracto en el cual debemos recorrer cada uno de los nodos de la estructura y según la metadata que almacenen, interpretamos una acción u otra.
Método del Árbol
Var a = 1 + 2 * 3;
Var b = 4;
…
...
recorrerArbol(raiz){
//...
for(hijo in raiz.hijos){
recorrerArbol(hijos);
}
}INIT
Método del Árbol
Var a = 1 + 2 * 3;
Var b = 4;
…
...
recorrerArbol(raiz){
//...
for(hijo in raiz.hijos){
recorrerArbol(hijos);
}
}INIT
INSTRUCCIONES
Método del Árbol
Var a = 1 + 2 * 3;
Var b = 4;
…
...
INIT
recorrerArbol(raiz){
//...
for(hijo in raiz.hijos){
recorrerArbol(hijos);
}
}INSTRUCCIONES
INSTRUCCION
Método del Árbol
Var a = 1 + 2 * 3;
Var b = 4;
…
...
INIT
recorrerArbol(raiz){
if(raiz.valor === 'DECLARACION'){
ejecutarDeclaracion(raiz);
}else if(raiz.valor === 'ASIGNACION'){
ejecutarAsignacion(raiz);
}else if ...
for(hijo in raiz.hijos){
recorrerArbol(hijos);
}
}INSTRUCCIONES
INSTRUCCION
DECLARACION
Método del Árbol
Var a = 1 + 2 * 3;
ejecutarDeclaracion(raiz){
//verificar raiz.hijos[0]
//verificar raiz.hijos[1]
ejecutarExp(raiz.hijos[2]);
/* Acciones necesarias
*
* return alguna respuesta
* */
}DECLARACION
Var
a
EXPRESION
Método del Árbol
Var a = 1 + 2 * 3;
ejecutarDeclaracion(raiz){
//verificar raiz.hijos[0]
//verificar raiz.hijos[1]
ejecutarExp(raiz.hijos[2]);
/* Acciones necesarias
*
* return alguna respuesta
* */
}DECLARACION
Var
a
EXPRESION
+
Método del Árbol
Var a = 1 + 2 * 3;
ejecutarDeclaracion(raiz){
//verificar raiz.hijos[0]
//verificar raiz.hijos[1]
ejecutarExp(raiz.hijos[2]);
/* Acciones necesarias
*
* return alguna respuesta
* */
}DECLARACION
Var
a
EXPRESION
+
*
Método del Árbol
Var a = 1 + 2 * 3;
ejecutarDeclaracion(raiz){
//verificar raiz.hijos[0]
//verificar raiz.hijos[1]
ejecutarExp(raiz.hijos[2]);
/* Acciones necesarias
*
* return alguna respuesta
* */
}DECLARACION
Var
a
EXPRESION
+
*
VALOR
Método del Árbol
Var a = 1 + 2 * 3;
ejecutarDeclaracion(raiz){
//verificar raiz.hijos[0]
//verificar raiz.hijos[1]
ejecutarExp(raiz.hijos[2]);
/* Acciones necesarias
*
* return alguna respuesta
* */
}DECLARACION
Var
a
EXPRESION
+
*
VALOR
2
Método del Árbol
Var a = 1 + 2 * 3;
ejecutarDeclaracion(raiz){
//verificar raiz.hijos[0]
//verificar raiz.hijos[1]
ejecutarExp(raiz.hijos[2]);
/* Acciones necesarias
*
* return alguna respuesta
* */
}DECLARACION
Var
a
EXPRESION
+
*
VALOR
2
VALOR
3
Método del Árbol
Var a = 1 + 2 * 3;
ejecutarDeclaracion(raiz){
//verificar raiz.hijos[0]
//verificar raiz.hijos[1]
ejecutarExp(raiz.hijos[2]);
/* Acciones necesarias
*
* return alguna respuesta
* */
}DECLARACION
Var
a
EXPRESION
+
*
VALOR
2
VALOR
3
VALOR
1
Método del Árbol
Var a = 1 + 2 * 3;
Var b = 4;
…
...
recorrerArbol(raiz){
if(raiz.valor === 'DECLARACION'){
ejecutarDeclaracion(raiz);
}else if(raiz.valor === 'ASIGNACION'){
ejecutarAsignacion(raiz);
}else if ...
for(hijo in raiz.hijos){
recorrerArbol(hijos);
}
}INIT
INSTRUCCIONES
INSTRUCCION
DECLARACION
INSTRUCCIONES
INSTRUCCIONES
...
Método - Patrón Intérprete
Es una técnica que consiste en el manejo de múltiples clases las cuales albergan lo necesario para ejecutar las instrucciones o expresiones dentro de nuestro código, por ejemplo, cuando queremos ejecutar una instrucción If, While, For, etc.
Patrón Intérprete - Ventajas
- Código más ordenado.
- Es más fácil encontrar y corregir errores.
- Más simple la reutilización de código.
Patrón Intérprete - Estructura
En esta forma de trabajar se utilizan 2 principales clases.
- Clase Instrucción
- Clase Expresión
En esta clase se ejecutan las acciones y no se espera ningún valor de retorno
Estructura - Clase Instrucción
| INSTRUCCION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int |
| + ejecutar(TablaSimbolo): void |
| INSTRUCCION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int |
| + ejecutar(TablaSimbolo): void |
En esta clase se ejecutan las acciones y no se espera ningún valor de retorno
Estructura - Clase Instrucción
| INSTRUCCION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int |
| + ejecutar(TablaSimbolo): void |
| WHILE |
|---|
| + Tipo: ENUM + Fila: int + Columna: int .... |
| + ejecutar(TablaSimbolo): void |
| FOR |
|---|
| + Tipo: ENUM + Fila: int + Columna: int .... |
| + ejecutar(TablaSimbolo): void |
| DECLARACION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int .... |
| + ejecutar(TablaSimbolo): void |
Estructura - Clase Instrucción
| INSTRUCCION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int |
| + ejecutar(TablaSimbolo): void |
| WHILE |
|---|
| + Tipo: ENUM + Fila: int + Columna: int .... |
| + ejecutar(TablaSimbolo): void |
| DECLARACION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int .... |
| + ejecutar(TablaSimbolo): void |
List<Declaracion> instrucciones = new Lista<Declaracion>();
instrucciones.push(new Declaracion(...));
instrucciones.push(new While(...));Estructura - Clase Instrucción
| INSTRUCCION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int |
| + ejecutar(TablaSimbolo): void |
| WHILE |
|---|
| + Tipo: ENUM + Fila: int + Columna: int .... |
| + ejecutar(TablaSimbolo): void |
| DECLARACION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int .... |
| + ejecutar(TablaSimbolo): void |
/*
* List<Declaracion> instrucciones = new Lista<Declaracion>();
*
* instrucciones.push(new Declaracion(...));
*
* instrucciones.push(new While(...));
* */
List<Instruccion> instrucciones = new Lista<Instruccion>();
instrucciones.push(new Declaracion(...));
instrucciones.push(new While(...));Estructura - Clase Instrucción
List<Instrucciones> instrucciones = new List<Instrucciones>();
SymbolTable tabla = new SymbolTable();
instrucciones.forEach((instruccion) => {
instruccion.ejecutar(tabla);
});Estructura - Clase Expresión
En esta clase se ejecutan las acciones y se espera un valor de retorno
| INSTRUCCION |
|---|
| + Tipo: ENUM + Fila: int + Columna: int |
| + ejecutar(TablaSimbolo): void |
| EXPRESION |
|---|
| + nodo_izquierdo: Expresion + nodo_derecho: Expresion + Tipo: ENUM + Fila: int + Columna: int |
| + operar(TablaSimbolo): Valor |
Estructura - Clase Expresión
En esta clase se ejecutan las acciones y se espera un valor de retorno
| EXPRESION |
|---|
| + nodo_izquierdo: Expresion + nodo_derecho: Expresion + Tipo: ENUM + Fila: int + Columna: int |
| + operar(TablaSimbolo): Valor |
| ARITMETICA |
|---|
| + nodo_izquierdo: Expresion + nodo_derecho: Expresion + Tipo: ENUM + Fila: int + Columna: int .... |
| + operar(TablaSimbolo): Valor |
| LOGICA |
|---|
| + nodo_izquierdo: Expresion + nodo_derecho: Expresion + Tipo: ENUM + Fila: int + Columna: int .... |
| + operar(TablaSimbolo): Valor |
| VALOR |
|---|
| + nodo_izquierdo: Expresion + nodo_derecho: Expresion + Tipo: ENUM + Fila: int + Columna: int .... |
| + operar(TablaSimbolo): Valor |
Método
Patrón Interprete
1 + 2 * 3
class Aritmetica extends Expresion {
constructor(...)
{...}
operar(TableSymbol tb){
// 1 - Operar los atributos
let op1 = nodo_izquierdo.operar(tb);
let op2 = nodo_derecho.operar(tb);
// 2 - Validar los atributos
// 3 - Ejecutar la logica
if(Tipo === Tipos.SUMA){
return new Valor(op1.valor + op2.valor);
}
else if(Tipo === Tipos.MULTIPLICACION){
return new Valor(op1.valor * op2.valor);
}
else if(Tipo === Tipos.RESTA){
return new Valor(op1.valor - op2.valor);
}
else if(Tipo === Tipos.DIVISION){
return new Valor(op1.valor / op2.valor);
}
else {
//Generar el ERROR
return new Valor(null);
}
// 4 - retornar la respuesta
}
}| Aritmetica |
|---|
| Tipo = SUMA |
| Aritmetica |
|---|
| Tipo = MULTI |
| VALOR |
|---|
| valor = 2 |
| VALOR |
|---|
| valor = 3 |
| VALOR |
|---|
| valor = 1 |
Tabla de Símbolos
| TablaSimbolo |
|---|
| + simbolos: Lista<Simbolo> + ts_super: TablaSimbolo |
| + addSimbol(Simbolo): bool + rmSimbol(Simbolo): bool ... |
Tabla de Símbolos -Ejemplo
int num1 = 12;
int num2 = 4;
suma();
suma (){
int num3 = 30;
print(num1+num2+num3);
int num4 = 34;
while(num4 > 0) {
num4--;
}
int numextra = 0;
}
int num5 = 5;Tabla de Símbolos -Ejemplo
int num1 = 12;
int num2 = 4;
suma();
suma (){
int num3 = 30;
print(num1+num2+num3);
int num4 = 34;
while(num4 > 0) {
num4--;
}
int numextra = 0;
}
int num5 = 5;| Simbolo | Valor |
|---|---|
| num1 | 12 |
| num2 | 4 |
Tabla de Símbolos -Ejemplo
int num1 = 12;
int num2 = 4;
suma();
suma (){
int num3 = 30;
print(num1+num2+num3);
int num4 = 34;
while(num4 > 0) {
num4--;
}
int numextra = 0;
}
int num5 = 5;| Simbolo | Valor |
|---|---|
| num1 | 12 |
| num2 | 4 |
| Simbolo | Valor |
|---|---|
Tabla de Símbolos -Ejemplo
int num1 = 12;
int num2 = 4;
suma();
suma (){
int num3 = 30;
print(num1+num2+num3);
int num4 = 34;
while(num4 > 0) {
num4--;
}
int numextra = 0;
}
int num5 = 5;| Simbolo | Valor |
|---|---|
| num1 | 12 |
| num2 | 4 |
| Simbolo | Valor |
|---|---|
| num3 | 30 |
Tabla de Símbolos -Ejemplo
int num1 = 12;
int num2 = 4;
suma();
suma (){
int num3 = 30;
print(num1+num2+num3);
int num4 = 34;
while(num4 > 0) {
num4--;
}
int numextra = 0;
}
int num5 = 5;| Simbolo | Valor |
|---|---|
| num1 | 12 |
| num2 | 4 |
| Simbolo | Valor |
|---|---|
| num3 | 30 |
Tabla de Símbolos -Ejemplo
int num1 = 12;
int num2 = 4;
suma();
suma (){
int num3 = 30;
print(num1+num2+num3);
int num4 = 34;
while(num4 > 0) {
num4--;
}
int numextra = 0;
}
int num5 = 5;| Simbolo | Valor |
|---|---|
| num1 | 12 |
| num2 | 4 |
| Simbolo | Valor |
|---|---|
| num3 | 30 |
| num4 | 34 |
Tabla de Símbolos -Ejemplo
int num1 = 12;
int num2 = 4;
suma();
suma (){
int num3 = 30;
print(num1+num2+num3);
int num4 = 34;
while(num4 > 0) {
num4--;
}
int numextra = 0;
}
int num5 = 5;| Simbolo | Valor |
|---|---|
| num1 | 12 |
| num2 | 4 |
| Simbolo | Valor |
|---|---|
| num3 | 30 |
| num4 | 34 |
| Simbolo | Valor |
|---|---|
Tabla de Símbolos -Ejemplo
int num1 = 12;
int num2 = 4;
suma();
suma (){
int num3 = 30;
print(num1+num2+num3);
int num4 = 34;
while(num4 > 0) {
num4--;
}
int numextra = 0;
}
int num5 = 5;| Simbolo | Valor |
|---|---|
| num1 | 12 |
| num2 | 4 |
| Simbolo | Valor |
|---|---|
| num3 | 30 |
| num4 | 34 |
| numextra | 0 |
¿Qué es Jison?
Es una herramienta para generar analizadores sintácticos que trabaja a partir de gramáticas libres de contexto como entrada y genera archivos de tipo javascript con lo necesario para reconocer los patrones plasmados en la gramática, su sintaxis es similar a Bison y Yacc.
Estructura de Jison
Para poder compilar correctamente el archivo de entrada de Jison es necesario cumplir con una estructura específica, la cual consiste en.
-
Código Javascript personalizado
-
Definición de analizador Léxico
-
Definición de analizador Sintáctico
Código JavaScript personalizado
%{
const Arithmetical = require('./clases/Arithmetical');
const SymbolTable = require('./clases/SymbolTable');
global_var = [];
var symbolt = new SymbolTable(null);
%}%lex
%options case-insensitive
%%
"//".* // comentario simple línea
[/][*][^*]*[*]+([^/*][^*]*[*]+)*[/] // comentario multiple líneas
"+" return 'suma';
"-" return 'resta';
"*" return 'multiplicacion';
"integer" return 'resinteger';
/lexDefinición de analizador Léxico
%right igual
%right interrogacion
%left incremento
%left decremento
%left xor
%left or
%left and
%left identico, diferente, referencias
%left mayor, menor, mayorigual, menorigual
%left suma, resta
%left multiplicacion, slash,modulo
%right potencia
%right not
%left parenta,parentc,llavea,llavecDefinición de precedencia
%% /* Definición de la gramática */
ini
: INSTRUCTIONS EOF {}
| EOF
;
TYPE
: resinteger {$$ = Type.ENTERO}
| resdouble {$$ = Type.DECIMAL}
| resboolean {$$ = Type.BOOL}
| reschar {$$ = Type.CARACTER}
| resstring {$$ = Type.CADENA}
;Definición de analizador Sintáctico
Ejemplo en Código
https://github.com/HenryGalvez/Interprete-basico-con-Jison
Dudas
Intérprete con Jison
By henrygalvez
Intérprete con Jison
- 66