Introducción

El patrón de diseño Interpreter es un patrón de comportamiento que proporciona una forma de evaluar o interpretar sentencias en un lenguaje. Este patrón es útil cuando se necesita interpretar un lenguaje específico, como un lenguaje de comandos, un lenguaje de programación o un lenguaje de consulta.

Objetivos del Módulo

  • Comprender el propósito y la estructura del patrón Interpreter.
  • Aprender a implementar el patrón Interpreter en un ejemplo práctico.
  • Identificar situaciones en las que el patrón Interpreter es útil.

¿Qué es el Patrón Interpreter?

El patrón Interpreter define una representación gramatical para un lenguaje y un intérprete que utiliza esta representación para interpretar sentencias en el lenguaje.

Componentes Clave

  1. Contexto: Contiene información global que el intérprete necesita.
  2. Expresión Abstracta: Declara una interfaz para interpretar el contexto.
  3. Expresión Terminal: Implementa una operación interpretativa para símbolos terminales en la gramática.
  4. Expresión No Terminal: Implementa una operación interpretativa para símbolos no terminales en la gramática.

Diagrama de Clases

+----------------+       +------------------+
|    Context     |<------| AbstractExpression|
+----------------+       +------------------+
                           /       \
                          /         \
                         /           \
            +----------------+  +----------------+
            | TerminalExpression |  | NonTerminalExpression |
            +----------------+  +----------------+

Ejemplo Práctico

Vamos a implementar un intérprete simple para una expresión matemática que solo maneja sumas y restas.

Paso 1: Definir el Contexto

El contexto contiene información que es global para el intérprete.

class Context:
    def __init__(self):
        self.variables = {}

    def get_value(self, variable):
        return self.variables.get(variable, 0)

    def set_value(self, variable, value):
        self.variables[variable] = value

Paso 2: Definir la Expresión Abstracta

La expresión abstracta declara una interfaz para interpretar el contexto.

from abc import ABC, abstractmethod

class Expression(ABC):
    @abstractmethod
    def interpret(self, context):
        pass

Paso 3: Definir Expresiones Terminales

Las expresiones terminales implementan operaciones interpretativas para símbolos terminales.

class Number(Expression):
    def __init__(self, number):
        self.number = number

    def interpret(self, context):
        return self.number

class Variable(Expression):
    def __init__(self, name):
        self.name = name

    def interpret(self, context):
        return context.get_value(self.name)

Paso 4: Definir Expresiones No Terminales

Las expresiones no terminales implementan operaciones interpretativas para símbolos no terminales.

class Add(Expression):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def interpret(self, context):
        return self.left.interpret(context) + self.right.interpret(context)

class Subtract(Expression):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def interpret(self, context):
        return self.left.interpret(context) - self.right.interpret(context)

Paso 5: Uso del Patrón Interpreter

Ahora podemos usar el patrón Interpreter para evaluar una expresión.

# Crear el contexto
context = Context()
context.set_value('x', 5)
context.set_value('y', 10)

# Crear la expresión: x + y - 3
expression = Subtract(Add(Variable('x'), Variable('y')), Number(3))

# Interpretar la expresión
result = expression.interpret(context)
print(f"Resultado: {result}")  # Resultado: 12

Ejercicio Práctico

Ejercicio

Implementa un intérprete para una expresión que incluya multiplicación y división.

  1. Define las clases Multiply y Divide que extiendan la clase Expression.
  2. Implementa el método interpret para cada una de estas clases.
  3. Crea una expresión que combine suma, resta, multiplicación y división y evalúala.

Solución

class Multiply(Expression):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def interpret(self, context):
        return self.left.interpret(context) * self.right.interpret(context)

class Divide(Expression):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def interpret(self, context):
        return self.left.interpret(context) / self.right.interpret(context)

# Crear el contexto
context = Context()
context.set_value('x', 6)
context.set_value('y', 3)

# Crear la expresión: (x * y) / 2 + 4 - 1
expression = Subtract(Add(Divide(Multiply(Variable('x'), Variable('y')), Number(2)), Number(4)), Number(1))

# Interpretar la expresión
result = expression.interpret(context)
print(f"Resultado: {result}")  # Resultado: 10.0

Conclusión

El patrón Interpreter es útil para definir una gramática y un intérprete para un lenguaje específico. Aunque no es uno de los patrones más comunes, es extremadamente útil en situaciones donde se necesita interpretar o evaluar sentencias en un lenguaje específico. En este módulo, hemos aprendido a implementar el patrón Interpreter y hemos visto un ejemplo práctico de su uso.

© Copyright 2024. Todos los derechos reservados