En programación informática , el patrón intérprete es un patrón de diseño que especifica cómo evaluar las oraciones en un lenguaje. La idea básica es tener una clase para cada símbolo ( terminal o no terminal ) en un lenguaje informático especializado . El árbol sintáctico de una oración en el lenguaje es una instancia del patrón compuesto y se utiliza para evaluar (interpretar) la oración para un cliente. [1] : 243 Véase también Patrón compuesto .
El patrón de diseño Interpreter [2] es uno de los veintitrés patrones de diseño GoF conocidos que describen cómo resolver problemas de diseño recurrentes para diseñar software orientado a objetos flexible y reutilizable, es decir, objetos que son más fáciles de implementar, cambiar, probar y reutilizar.
Fuente: [3]
Cuando un problema ocurre muy a menudo, se podría considerar representarlo como una oración en un lenguaje simple ( lenguajes específicos de dominio ) para que un intérprete pueda resolver el problema interpretando la oración.
Por ejemplo, cuando se deben especificar muchas expresiones de búsqueda diferentes o complejas, implementarlas (integrarlas) directamente en una clase es inflexible porque compromete la clase con expresiones particulares y hace imposible especificar nuevas expresiones o cambiar las existentes independientemente de la clase (sin tener que cambiarla).
Expression
jerarquía de clases e implementando una interpret()
operación.Expression
instancias.interpret()
al AST.Los objetos de expresión se componen recursivamente en una estructura compuesta/de árbol que se denomina árbol de sintaxis abstracta (consulte el patrón Compuesto ).
El patrón Intérprete no describe cómo construir un árbol de sintaxis abstracta. Esto puede hacerse manualmente por un cliente o automáticamente por un analizador .
Vea también el diagrama de clases y objetos UML a continuación.
En el diagrama de clases UML anterior , la clase hace referencia a la interfaz común para interpretar una expresión .
La clase no tiene hijos e interpreta una expresión directamente.
La clase mantiene un contenedor de expresiones secundarias ( ) y reenvía solicitudes de interpretación a estas .Client
AbstractExpression
interpret(context)
TerminalExpression
NonTerminalExpression
expressions
expressions
El diagrama de colaboración de objetos muestra las interacciones en tiempo de ejecución: el Client
objeto envía una solicitud de interpretación al árbol de sintaxis abstracta. La solicitud se reenvía a (se ejecuta en) todos los objetos hacia abajo en la estructura del árbol.
Los NonTerminalExpression
objetos ( ntExpr1,ntExpr2
) reenvían la solicitud a sus expresiones secundarias.
Los TerminalExpression
objetos ( tExpr1,tExpr2,…
) realizan la interpretación directamente.
Esta implementación de C++11 se basa en el código de muestra anterior a C++98 del libro.
#include <iostream> #include <mapa> #include <cstring> clase Contexto ; clase BooleanExp { público : BooleanExp () = predeterminado ; virtual ~ BooleanExp () = predeterminado ; virtual bool evaluar ( Contexto & ) = 0 ; virtual BooleanExp * reemplazar ( const char * , BooleanExp & ) = 0 ; virtual BooleanExp * copiar () const = 0 ; }; clase VariableExp ; clase Contexto { público : Contexto () : m () {} bool búsqueda ( const VariableExp * clave ) { return m.at ( clave ) ; } void asignar ( VariableExp * clave , bool valor ) { m [ clave ] = valor ; } privado : std :: map < const VariableExp * , bool > m ; } ; clase VariableExp : public BooleanExp { public : VariableExp ( const char * nombre_ ) : nombre ( nullptr ) { nombre = strdup ( nombre_ ); } virtual ~ VariableExp () = default ; virtual bool evaluating ( Context & aContext ) { return aContext.lookup ( this ); } virtual BooleanExp * replace ( const char * nombre_ , BooleanExp & exp ) { if ( 0 == strcmp ( nombre_ , nombre )) { return exp.copy ( ); } else { return new VariableExp ( nombre ) ; } } virtual BooleanExp * copy () const { return new VariableExp ( nombre ); } VariableExp ( const VariableExp & ) = delete ; // regla de tres VariableExp & operador = ( const VariableExp & ) = delete ; privado : char * nombre ; } ; clase AndExp : public BooleanExp { public : AndExp ( BooleanExp * op1 , BooleanExp * op2 ) : operando1 ( nullptr ), operando2 ( nullptr ) { operando1 = op1 ; operando2 = op2 ; } virtual ~ AndExp () = predeterminado ; virtual bool evaluar ( Contexto & unContexto ) { devuelve operando1 -> evaluar ( unContexto ) && operando2 -> evaluar ( unContexto ); } virtual BooleanExp * reemplazar ( const char * nombre_ , BooleanExp & exp ) { devuelve nuevo AndExp ( operando1 -> reemplazar ( nombre_ , exp ), operando2 -> reemplazar ( nombre_ , exp ) ); } virtual BooleanExp * copiar () const { devuelve nuevo AndExp ( operando1 -> copiar (), operando2 -> copiar ()); } AndExp ( const AndExp & ) = delete ; // regla de tres AndExp & operador = ( const AndExp & ) = delete ; privado : BooleanExp * operando1 ; BooleanExp * operando2 ; }; int main () { BooleanExp * expresión ; Contexto contexto ; VariableExp * x = new VariableExp ( "X" ); VariableExp * y = new VariableExp ( "Y" ); expresión = new AndExp ( x , y ); contexto . asignar ( x , falso ); contexto . asignar ( y , verdadero ); bool resultado = expresión -> evaluar ( contexto ); std :: cout << resultado << '\n' ; contexto . asignar ( x , verdadero ); contexto . asignar ( y , verdadero ); resultado = expresión -> evaluar ( contexto ); std :: cout << resultado << '\n' ; }
La salida del programa es:
0 1
{{cite book}}
: CS1 maint: multiple names: authors list (link)