{}
{
{}
Henry Gálvez
22/09/2021
{
Patrón Intérprete con Jison
Agenda
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
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