Patrones de diseño de comportamiento: Interpreter

Intención del patrón


  • Dado un lenguaje, define una representación para su gramática junto con un intérprete que usa la representación para interpretar sentencias en el lenguaje.
  • Asignar un dominio al lenguaje, el lenguaje a una gramática y la gramática a un diseño orientado a objeto jerárquico.


Ejemplo de problema

Una clase de problemas que ocurre repetidamente en un dominio bien definido y bien entendido. Si el dominio fue caracterizado con un lenguaje, entonces los problemas podrían ser fácilmente resueltos con un motor de "interpretación".


Discusión

El patrón Interpreter discute: la definición de un lenguaje de dominio (es decir, la caracterización del problema) como la gramática de un lenguaje simple, en representación de las reglas de dominio como sentencias del lenguaje y la interpretación de éstas sentencias para resolver el problema. El patrón utiliza una clase para representar cada una de las reglas gramáticas y puesto que las reglas gramáticas son estructuras usualmente jerárquicas, una jerarquía de herencia de reglas calzaría muy bien.
Una clase base abstracta especifica el método Interpretar(). Cada subclase concreta implementa el método Interpretar() y acepta como argumento el estado actual del lenguaje del stream, y aportando su contribución al proceso de resolución del problema.

Estructura

El patrón Interpreter sugiere modelar el dominio con una gramática recursiva. Cada regla gramática puede ser compuesta (una regla que referencia a otras reglas) o terminal (una hoja en una estructura de tipo árbol).
Este patrón se basa en el recorrido recursivo del patrón Composite para interpretar las sentencias que se le solicita procesar.


Ejemplo

El patrón Interpreter define una representación gramatical para un lenguaje y un interprete para comprender esa gramática. Los músicos son ejemplos de Interpreter. El tono de un sonido y su duración puede ser representado en la notación musical de un pentagrama. Esta notación proporciona el lenguaje de la música. Los músicos tocan la música de la partitura son capaces de reproducir el tono original y la duración de cada sonido representado.


Check list


  1. Decidir si un "pequeño lenguaje" justifica el tiempo que se le invertirá.
  2. Definir una grmática para el lenguaje.
  3. Asignar cada producción en la gramática a una clase.
  4. Organizar el conjunto de clases en la estructura del patrón Composite.
  5. Defiinr un método Interpretar( Context ) en la jerarquía del patrón Composite.
  6. El objeto Context encapsula el estado actual de la entrada y la salida de como, primero es analizada y luego es acumulada. Este es manipulado por cada clase gramática como el proceso de "interpretación" convierte la entrada en la salida.


Reglas de oro

Considerado en su forma más general (por ejemplor, una operación distribuida en una jerarquía de clases basada en el patrón Composite), casi todos los usos del patrón Composite, contendrán también el patrón Interpreter. Pero el patrón Interpreter debería ser reservado para aquellos casos en los cuales se desea pensar en la jerarquía de clases como la definición de un lenguaje.
Interpreter puede usar State para definir análisis de contexto.
El árbol de sintaxis abstracta de Interpreter es un Composite (por lo tanto, Iterator y Visitor también son aplicables).
Los símbolos terminales en el árbol de sintaxis abstracta de Interpreter puede ser compartido con Flyweight.
El patrón no se ocupa de analizar. Cuando la gramática es muy compleja, otras técnicas (por ejemplo, un analizador), son más apropiadas.

Ejemplo de código en C#

using System;
using System.Collections;

class MainApp
{
  static void Main()
  {
    Context context = new Context();

    // Usually a tree 
    ArrayList list = new ArrayList(); 

    // Populate 'abstract syntax tree' 
    list.Add(new TerminalExpression());
    list.Add(new NonterminalExpression());
    list.Add(new TerminalExpression());
    list.Add(new TerminalExpression());

    // Interpret 
    foreach (AbstractExpression exp in list)
    {
      exp.Interpret(context);
    }

    // Wait for user 
    Console.Read();
  }
}

// "Context" 
class Context 
{
}

// "AbstractExpression" 
abstract class AbstractExpression 
{
  public abstract void Interpret(Context context);
}

// "TerminalExpression" 
class TerminalExpression : AbstractExpression
{
  public override void Interpret(Context context)  
  {
    Console.WriteLine("Called Terminal.Interpret()");
  }
}

// "NonterminalExpression" 
class NonterminalExpression : AbstractExpression
{
  public override void Interpret(Context context)  
  {
    Console.WriteLine("Called Nonterminal.Interpret()");
  }  
}

2 comentarios:

daveG dijo...

Se podría usar este patrón para una gramática que tiene ciclos como el WHILE y condicionales como el IF ? de antemano muchas gracias

Juan Barrionuevo dijo...

Hola daveG, muchas gracias por tu comentario.
De antemano debo pedirte que des más datos al respecto del problema, ya que con la información que das no puedo darte una respuesta concreta.

Publicar un comentario

Muchas gracias por leer el post y comentarlo.

 
Copyright 2009 Programación SOLIDa
BloggerTheme by BloggerThemes | Design by 9thsphere