Értelmező programtervezési minta
A számítógép programozásban az értelmező minta egy tervezési minta, mely meghatározza, hogyan értékeljen ki mondatokat egy nyelv. Az alap ötlet az volt, hogy legyen egy osztály minden szimbólumra (terminális és nem terminális) egy erre specializált nyelvben. Egy nyelvben a mondat szintaxis fája egy példánya az összetétel mintának, és a mondat megértésére használja a kliens. Lásd még összetétel minta.

Értelmező mintát használók 
 Speciális adatbázis lekérdező nyelvek, mint például az SQL
 Speciális programozási nyelvek, amelyek általában kommunikációs protokollok leírására használnak.
 A legtöbb általános célú programozási nyelv valójában magába foglal néhány más speciális nyelvet.
 Virtuális gép Javához és szkript nyelvekhez.

Struktúra 
Az értelmező minta az alábbi struktúrával írható le:

Példák 

BNF, C# és JAVA nyelveken.

BNF 
A következő "Backus-Naur-Formula" (BNF) példa illusztrálja az interpreter mintát. A nyelvtan:

expression ::= plus | minus | variable | number
plus ::= expression expression '+'
minus ::= expression expression '-'
variable  ::= 'a' | 'b' | 'c' | ... | 'z'
digit = '0' | '1' | ... | '9'
number ::= digit | digit number

Definiál egy nyelvet, amellyel a fordított lengyel jelöléssel lehet kifejezéseket megadni. Például az alábbiakat:
a b +
a b c + -
a b + c a - -

C# 
Ez a strukturális kód bemutatja az értelmező mintát, amely egy definiált nyelvtant alkalmaz.

//IVSR: Interpreter design pattern
namespace IVSR.DesignPaterns.Interpreter
{
// "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()");
    }  
  }
  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();
    }
  }
}

Java 
A következő példa egy értelmező minta megvalósítását mutatja be, ahol minden nyelvtani szabályra van egy osztály.

import java.util.Map;
 
interface Expression {
    public int interpret(Map<String,Expression> variables);
}
 
class Number implements Expression {
    private int number;
    public Number(int number)       { this.number = number; }
    public int interpret(Map<String,Expression> variables)  { return number; }
}
 
class Plus implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Plus(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }
 
    public int interpret(Map<String,Expression> variables)  { 
        return leftOperand.interpret(variables) + rightOperand.interpret(variables);
    }
}
 
class Minus implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Minus(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }
 
    public int interpret(Map<String,Expression> variables)  { 
        return leftOperand.interpret(variables) - rightOperand.interpret(variables);
    }
}
 
class Variable implements Expression {
    private String name;
    public Variable(String name)       { this.name = name; }
    public int interpret(Map<String,Expression> variables)  { 
        if(null==variables.get(name)) return 0; //Either return new Number(0).
        return variables.get(name).interpret(variables); 
    }
}

import java.util.Map;
import java.util.Stack;
 
class Evaluator implements Expression {
    private Expression syntaxTree;
 
    public Evaluator(String expression) {
        Stack<Expression> expressionStack = new Stack<Expression>();
        for (String token : expression.split(" ")) {
            if  (token.equals("+")) {
                Expression subExpression = new Plus(expressionStack.pop(), expressionStack.pop());
                expressionStack.push( subExpression );
            }
            else if (token.equals("-")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new Minus(left, right);
                expressionStack.push( subExpression );
            }
            else                        
                expressionStack.push( new Variable(token) );
        }
        syntaxTree = expressionStack.pop();
    }
 
    public int interpret(Map<String,Expression> context) {
        return syntaxTree.interpret(context);
    }
}

Végül értékeli a kifejezést :   "w x z - +" with w = 5, x = 10, and z = 42.

import java.util.Map;
import java.util.HashMap;
 
public class InterpreterExample {
    public static void main(String[] args) {
        String expression = "w x z - +";
        Evaluator sentence = new Evaluator(expression);
        Map<String,Expression> variables = new HashMap<String,Expression>();
        variables.put("w", new Number(5));
        variables.put("x", new Number(10));
        variables.put("z", new Number(42));
        int result = sentence.interpret(variables);
        System.out.println(result);
    }
}

Kapcsolódó szócikkek
Értelmező
Backus–Naur-forma
Domain specifikus nyelvek
Programtervezési minták
Combinator#Combinatory logic in computing

Jegyzetek

További információk

interpreter megvalósítása Rubyban
Interpreter megvalósítása C++-ban
SourceMaking kézikönyv
Interpreter pattern description from the Portland Pattern Repository

Fordítás

Programtervezési minták
Java-kódpéldák
C Sharp-kódpéldák
A számítógép programozásban az értelmező minta egy tervezési minta , mely meghatározza , hogyan értékeljen ki mondatokat egy nyelv . Az alap ötlet az volt , hogy legyen egy osztály minden szimbólumra ( terminális és nem terminális ) egy erre specializált nyelvben . Egy nyelvben a mondat szintaxis fája egy példánya az összetétel mintának , és a mondat megértésére használja a kliens . Lásd még összetétel minta . Értelmező mintát használók Speciális adatbázis lekérdező nyelvek , mint például az SQL Speciális programozási nyelvek , amelyek általában kommunikációs protokollok leírására használnak . A legtöbb általános célú programozási nyelv valójában magába foglal néhány más speciális nyelvet . Virtuális gép Javához és szkript nyelvekhez . Struktúra Az értelmező minta az alábbi struktúrával írható le : Példák BNF , C # és JAVA nyelveken . BNF A következő " Backus-Naur-Formula " ( BNF ) példa illusztrálja az interpreter mintát . A nyelvtan : expression \ : := plus | minus | variable | number plus \: := expression expression '+' minus \: := expression expression '-' variable \ : := 'a' | 'b' | 'c' |\... | 'z' digit = '0' | '1' |\... | '9' number \ : := digit | digit number Definiál egy nyelvet , amellyel a fordított lengyel jelöléssel lehet kifejezéseket megadni . Például az alábbiakat : a b + a b c + - a b + c a - - C # Ez a strukturális kód bemutatja az értelmező mintát , amely egy definiált nyelvtant alkalmaz . //IVSR: Interpreter design pattern namespace IVSR.DesignPaterns.Interpreter { / / " 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 ( ) " ) ; } } 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 ( ) ; } } } Java A következő példa egy értelmező minta megvalósítását mutatja be , ahol minden nyelvtani szabályra van egy osztály. import java.util.Map ; interface Expression { public int interpret ( Map<String, Expression> variables ) ; } class Number implements Expression { private int number ; public Number( int number ) { this.number = number ; } public int interpret ( Map<String, Expression> variables ) { return number ; } } class Plus implements Expression { Expression leftOperand ; Expression rightOperand ; public Plus ( Expression left , Expression right ) { leftOperand = left ; rightOperand = right ; } public int interpret ( Map<String, Expression> variables ) { return leftOperand.interpret ( variables ) + rightOperand.interpret ( variables ) ; } } class Minus implements Expression { Expression leftOperand ; Expression rightOperand ; public Minus ( Expression left , Expression right ) { leftOperand = left ; rightOperand = right ; } public int interpret ( Map<String, Expression> variables ) { return leftOperand.interpret ( variables ) - rightOperand.interpret ( variables ) ; } } class Variable implements Expression { private String name ; public Variable( String name ) { this.name = name ; } public int interpret ( Map<String, Expression> variables ) { if( null==variables.get( name ) ) return //Either return new Number( 0 ) . return variables.get ( name) .interpret( variables ) ; } } import java.util.Map ; import java.util.Stack ; class Evaluator implements Expression { private Expression syntaxTree ; public Evaluator( String expression ) { Stack<Expression> expressionStack = new Stack<Expression> ( ) ; for ( String token \ : expression.split ( " " ) ) { if ( token.equals ( " + " ) ) { Expression subExpression = new Plus( expressionStack.pop ( ) , expressionStack.pop ( ) ) ; expressionStack.push ( subExpression ) ; } else if ( token.equals ( " - " ) ) { / / it's necessary remove first the right operand from the stack Expression right = expressionStack.pop ( ) ; / /\..and after the left one Expression left = expressionStack.pop ( ) ; Expression subExpression = new Minus( left , right ) ; expressionStack.push ( subExpression ) ; } else expressionStack.push ( new Variable( token ) ) ; } syntaxTree = expressionStack.pop ( ) ; } public int interpret ( Map<String, Expression> context ) { return syntaxTree.interpret ( context ) ; } } Végül értékeli a kifejezést \ : " w x z - + " with w = x = and z = import java.util.Map ; import java.util.HashMap ; public class InterpreterExample { public static void main( String [ ] args ) { String expression = " w x z - + " ; Evaluator sentence = new Evaluator( expression ) ; Map<String, Expression> variables = new HashMap<String, Expression> ( ) ; variables.put ( " w " , new Number ( 5 ) ) ; variables.put ( " x " , new Number( 10 ) ) ; variables.put ( " z " , new Number( 42 ) ) ; int result = sentence.interpret ( variables ) ; System.out.println ( result ) ; } } Kapcsolódó szócikkek Értelmező Backus–Naur-forma Domain specifikus nyelvek Programtervezési minták Combinator# Combinatory logic in computing Jegyzetek További információk interpreter megvalósítása Rubyban Interpreter megvalósítása C++-ban SourceMaking kézikönyv Interpreter pattern description from the Portland Pattern Repository Fordítás Programtervezési minták Java-kódpéldák C Sharp-kódpéldák