{}

{

{}

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';

/lex

Definició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,llavec

Definició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