<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Interpreter_%28Entwurfsmuster%29</id>
	<title>Interpreter (Entwurfsmuster) - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Interpreter_%28Entwurfsmuster%29"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Interpreter_(Entwurfsmuster)&amp;action=history"/>
	<updated>2026-06-12T00:43:36Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Wikipedia (Deutsch) – Lokale Kopie</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki-de.moshellshocker.dns64.de/index.php?title=Interpreter_(Entwurfsmuster)&amp;diff=782016&amp;oldid=prev</id>
		<title>imported&gt;AndreAdrian: /* Nachteile */ recursive decent parser dazu</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Interpreter_(Entwurfsmuster)&amp;diff=782016&amp;oldid=prev"/>
		<updated>2023-05-09T11:20:19Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Nachteile: &lt;/span&gt; recursive decent parser dazu&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Der &amp;#039;&amp;#039;&amp;#039;Interpreter&amp;#039;&amp;#039;&amp;#039; (englisch {{lang|en|&amp;#039;&amp;#039;interpreter pattern&amp;#039;&amp;#039;}}) ist ein [[Entwurfsmuster]] aus dem Bereich der [[Softwareentwicklung]] und gehört zu der Kategorie der [[Verhaltensmuster (Software)|Verhaltensmuster]] (englisch {{lang|en|&amp;#039;&amp;#039;behavioural patterns&amp;#039;&amp;#039;}}). Das Muster ist eines der sogenannten [[Viererbande (Softwareentwicklung)|GoF-Muster]].&lt;br /&gt;
&lt;br /&gt;
Das Interpretermuster definiert eine Repräsentation für die Grammatik einer Sprache und die Möglichkeit, Sätze dieser Sprache zu interpretieren.&amp;lt;ref&amp;gt;{{Literatur |Autor=[[Erich Gamma]], [[Richard Helm]], [[Ralph Johnson]], [[John Vlissides]] |Titel=Entwurfsmuster |Auflage=5 |Verlag=[[Addison-Wesley]] |Ort= |Datum=1996 |ISBN=3-8273-1862-9 |Seiten=319}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verwendung ==&lt;br /&gt;
Wenn ähnliche Probleme oft genug gelöst werden müssen, ist es häufig sinnvoll, das Problem mit einer einfachen Sprache zu beschreiben. Beispiele für ein solches Problem sind das Auswerten von regulären Ausdrücken und die Berechnung von logischen oder [[Mathematische Formel|mathematischen Formeln]].&lt;br /&gt;
&lt;br /&gt;
== UML-Diagramm ==&lt;br /&gt;
[[Datei:Interpreter UML class diagram de.svg|ohne|UML-Klassendiagramm]]&lt;br /&gt;
&lt;br /&gt;
== Bestandteile ==&lt;br /&gt;
Die abstrakte Klasse &amp;lt;code&amp;gt;AbstrakterAusdruck&amp;lt;/code&amp;gt; schreibt eine Methode &amp;lt;code&amp;gt;Interpretiere()&amp;lt;/code&amp;gt; vor, die von allen abgeleiteten, konkreten Klassen implementiert werden muss und den entsprechenden Ausdruck auswertet.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;lt;code&amp;gt;TerminalerAusdruck&amp;lt;/code&amp;gt; steht für einen Ausdruck, der keinen Unterausdruck hat, d.&amp;amp;nbsp;h. für einen festen Wert innerhalb eines gemäß der Grammatik geformten Satzes. Z.&amp;amp;nbsp;B. steht &amp;#039;&amp;#039;Zahl&amp;#039;&amp;#039; für einen Zahlenwert innerhalb einer mathematischen Formel.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;lt;code&amp;gt;NonterminalerAusdruck&amp;lt;/code&amp;gt; steht für einen Ausdruck, der aus Unterausdrücken besteht, zum Beispiel &amp;#039;&amp;#039;Addition&amp;#039;&amp;#039; oder &amp;#039;&amp;#039;Multiplikation&amp;#039;&amp;#039;, die beide zwei Operanden als Unterausdrücke benötigen. Ein Unterausdruck kann sowohl ein &amp;lt;code&amp;gt;TerminalerAusdruck&amp;lt;/code&amp;gt; als auch ein NichtterminalAusdruck sein.&lt;br /&gt;
&lt;br /&gt;
Für den zu interpretierenden Satz wird gemäß der Grammatik ein [[Syntaxbaum]] aus Nichtterminal- und Terminalausdrücken aufgebaut. Dies kann durch einen externen [[Parser]] oder den &amp;#039;&amp;#039;Klienten&amp;#039;&amp;#039; selbst geschehen. Der Klient wertet diesen Syntaxbaum aus, indem er für den obersten Ausdruck die Methode &amp;lt;code&amp;gt;Interpretiere()&amp;lt;/code&amp;gt; aufruft.&lt;br /&gt;
&lt;br /&gt;
Im &amp;#039;&amp;#039;Kontext&amp;#039;&amp;#039; werden die konkreten Werte der Terminalausdrücke gekapselt, mit denen der Satz interpretiert werden soll, z.&amp;amp;nbsp;B. die Belegung von Variablen.&lt;br /&gt;
&lt;br /&gt;
== Vorteile ==&lt;br /&gt;
Die Grammatik kann durch dieses Entwurfsmuster leicht geändert oder erweitert, derselbe Satz oder Ausdruck durch Ändern des Kontextes immer wieder auf neue Art und Weise interpretiert werden.&lt;br /&gt;
&lt;br /&gt;
== Nachteile ==&lt;br /&gt;
Für komplexe Grammatiken und sehr große Sätze ist das Interpretermuster ungeeignet, da die Klassenhierarchie zu groß wird und die Effizienz bei großen Syntaxbäumen leidet. Sollen komplexe Grammatiken verarbeitet werden, eignet sich [[Rekursiver Abstieg]] oder [[Parsergenerator]] besser. Große Syntaxbäume werden üblicherweise in andere Strukturen konvertiert und zum Beispiel mit Hilfe von [[Zustandsautomat]]en bearbeitet.&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
Diese C++11 Implementierung basiert auf dem vor C++98 Beispielcode im Buch Entwurfsmuster.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;lt;map&amp;gt;&lt;br /&gt;
#include &amp;lt;cstring&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Kontext;&lt;br /&gt;
&lt;br /&gt;
class BoolscherAusdruck {&lt;br /&gt;
public:&lt;br /&gt;
  BoolscherAusdruck() = default;&lt;br /&gt;
  virtual ~BoolscherAusdruck() = default;&lt;br /&gt;
  virtual bool werteAus(Kontext&amp;amp;) = 0;&lt;br /&gt;
  virtual BoolscherAusdruck* ersetze(const char*, BoolscherAusdruck&amp;amp;) = 0;&lt;br /&gt;
  virtual BoolscherAusdruck* kopiere() const = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class VariablenAusdruck;&lt;br /&gt;
&lt;br /&gt;
class Kontext {&lt;br /&gt;
public:&lt;br /&gt;
  Kontext() :m() {}&lt;br /&gt;
  bool lookup(const VariablenAusdruck* key) { return m.at(key); }&lt;br /&gt;
  void weiseZu(const VariablenAusdruck* key, bool value) { m[key] = value; }&lt;br /&gt;
private:&lt;br /&gt;
  std::map&amp;lt;const VariablenAusdruck*, bool&amp;gt; m;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class VariablenAusdruck : public BoolscherAusdruck {&lt;br /&gt;
public:&lt;br /&gt;
  VariablenAusdruck(const char* name_) :name(nullptr) {&lt;br /&gt;
    name = strdup(name_);&lt;br /&gt;
  }&lt;br /&gt;
  virtual ~VariablenAusdruck() = default;&lt;br /&gt;
  virtual bool werteAus(Kontext&amp;amp; einKontext) {&lt;br /&gt;
    return einKontext.lookup(this);&lt;br /&gt;
  }&lt;br /&gt;
  virtual BoolscherAusdruck* ersetze(const char* name_, BoolscherAusdruck&amp;amp; ausdruck) {&lt;br /&gt;
    if (0 == strcmp(name_, name)) {&lt;br /&gt;
      return ausdruck.kopiere();&lt;br /&gt;
    } else {&lt;br /&gt;
      return new VariablenAusdruck(name);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  virtual BoolscherAusdruck* kopiere() const {&lt;br /&gt;
    return new VariablenAusdruck(name);&lt;br /&gt;
  }&lt;br /&gt;
  VariablenAusdruck(const VariablenAusdruck&amp;amp;) = delete; // Dreierregel&lt;br /&gt;
  VariablenAusdruck&amp;amp; operator=(const VariablenAusdruck&amp;amp;) = delete;&lt;br /&gt;
private:&lt;br /&gt;
  char* name;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class UndAusdruck : public BoolscherAusdruck {&lt;br /&gt;
public:&lt;br /&gt;
  UndAusdruck(BoolscherAusdruck* op1, BoolscherAusdruck* op2)&lt;br /&gt;
    :operand1(nullptr), operand2(nullptr) {&lt;br /&gt;
    operand1 = op1;&lt;br /&gt;
    operand2 = op2;&lt;br /&gt;
  }&lt;br /&gt;
  virtual ~UndAusdruck() = default;&lt;br /&gt;
  virtual bool werteAus(Kontext&amp;amp; einKontext) {&lt;br /&gt;
    return operand1-&amp;gt;werteAus(einKontext) &amp;amp;&amp;amp; operand2-&amp;gt;werteAus(einKontext);&lt;br /&gt;
  }&lt;br /&gt;
  virtual BoolscherAusdruck* ersetze(const char* name_, BoolscherAusdruck&amp;amp; ausdruck) {&lt;br /&gt;
    return new UndAusdruck(operand1-&amp;gt;ersetze(name_, ausdruck),&lt;br /&gt;
      operand2-&amp;gt;ersetze(name_, ausdruck));&lt;br /&gt;
  }&lt;br /&gt;
  virtual BoolscherAusdruck* kopiere() const {&lt;br /&gt;
    return new UndAusdruck(operand1-&amp;gt;kopiere(), operand2-&amp;gt;kopiere());&lt;br /&gt;
  }&lt;br /&gt;
  UndAusdruck(const UndAusdruck&amp;amp;) = delete; // Dreierregel&lt;br /&gt;
  UndAusdruck&amp;amp; operator=(const UndAusdruck&amp;amp;) = delete;&lt;br /&gt;
private:&lt;br /&gt;
  BoolscherAusdruck* operand1;&lt;br /&gt;
  BoolscherAusdruck* operand2;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
  BoolscherAusdruck* ausdruck;&lt;br /&gt;
  Kontext kontext;&lt;br /&gt;
  VariablenAusdruck* x = new VariablenAusdruck(&amp;quot;X&amp;quot;);&lt;br /&gt;
  VariablenAusdruck* y = new VariablenAusdruck(&amp;quot;Y&amp;quot;);&lt;br /&gt;
  ausdruck = new UndAusdruck(x, y);&lt;br /&gt;
&lt;br /&gt;
  kontext.weiseZu(x, false);&lt;br /&gt;
  kontext.weiseZu(y, true);&lt;br /&gt;
  bool resultat = ausdruck-&amp;gt;werteAus(kontext);&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; resultat &amp;lt;&amp;lt; &amp;#039;\n&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
  kontext.weiseZu(x, true);&lt;br /&gt;
  kontext.weiseZu(y, true);&lt;br /&gt;
  resultat = ausdruck-&amp;gt;werteAus(kontext);&lt;br /&gt;
  std::cout &amp;lt;&amp;lt; resultat &amp;lt;&amp;lt; &amp;#039;\n&amp;#039;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Programmausgabe ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
0&lt;br /&gt;
1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In der [[Umgekehrte polnische Notation|umgekehrten polnischen Notation (UPN)]] sind Ausdrücke gemäß folgender Grammatik gegeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
expression ::= plus | minus | variable | number&lt;br /&gt;
plus ::= expression expression &amp;#039;+&amp;#039;&lt;br /&gt;
minus ::= expression expression &amp;#039;-&amp;#039;&lt;br /&gt;
variable ::= &amp;#039;a&amp;#039; | &amp;#039;b&amp;#039; | &amp;#039;c&amp;#039; | ... | &amp;#039;z&amp;#039;&lt;br /&gt;
number ::= &amp;#039;-&amp;#039;? (&amp;#039;0&amp;#039; | &amp;#039;1&amp;#039; | &amp;#039;2&amp;#039; | ... | &amp;#039;9&amp;#039;)+&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiele für Ausdrücke, die dieser Grammatik entsprechen, sind&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 1 +&lt;br /&gt;
a 2 + 3 -&lt;br /&gt;
5 4 - a b + +&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Interpreter sieht für jeden Terminal-Ausdruck und für jeden Nichtterminal-Ausdruck eine konkrete Klasse vor, die eine gemeinsame Schnittstelle implementiert. Diese Schnittstelle schreibt vor, dass die jeweilige Klasse einen zu ihr passenden Ausdruck in einem Kontext interpretieren können muss. Der Kontext ist hier die Belegung der Variablen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import java.util.*;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Interface for all expression types&lt;br /&gt;
 */&lt;br /&gt;
interface IExpressable {&lt;br /&gt;
    /**&lt;br /&gt;
     * Interprets the passed variables&lt;br /&gt;
     * @param variables&lt;br /&gt;
     * @return Result&lt;br /&gt;
     */&lt;br /&gt;
    int interpret(final HashMap&amp;lt;String, Integer&amp;gt; variables);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Class for a non-terminal expression&lt;br /&gt;
 */&lt;br /&gt;
class Plus implements IExpressable {&lt;br /&gt;
    /** Left operation */&lt;br /&gt;
    private IExpressable leftOperand = null;&lt;br /&gt;
    /** Right operation */&lt;br /&gt;
    private IExpressable rightOperand = null;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor&lt;br /&gt;
     * @param left Left expression&lt;br /&gt;
     * @param right Right expression&lt;br /&gt;
     */&lt;br /&gt;
    public Plus(final IExpressable left, final IExpressable right) {&lt;br /&gt;
        leftOperand  = left;&lt;br /&gt;
        rightOperand = right;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* (non-Javadoc)&lt;br /&gt;
     * @see interpreter.IExpressable#interpret(java.util.HashMap)&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public int interpret(final HashMap&amp;lt;String, Integer&amp;gt; variables) {&lt;br /&gt;
        return leftOperand.interpret(variables)&lt;br /&gt;
                + rightOperand.interpret(variables);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Converts the content to a readable string by overloading the Object&lt;br /&gt;
     * method.&lt;br /&gt;
     * @return String representation&lt;br /&gt;
     */&lt;br /&gt;
    public String toString() {&lt;br /&gt;
        return leftOperand.toString() + &amp;quot; + &amp;quot;&lt;br /&gt;
                + rightOperand.toString();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Class for a non-terminal expression&lt;br /&gt;
 */&lt;br /&gt;
class Minus implements IExpressable {&lt;br /&gt;
    /** Left operation */&lt;br /&gt;
    private IExpressable leftOperand = null;&lt;br /&gt;
    /** Right operation */&lt;br /&gt;
    private IExpressable rightOperand = null;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor&lt;br /&gt;
     * @param left Left expression&lt;br /&gt;
     * @param right Right expression&lt;br /&gt;
     */&lt;br /&gt;
    public Minus(final IExpressable left,&lt;br /&gt;
            final IExpressable right) {&lt;br /&gt;
        leftOperand  = left;&lt;br /&gt;
        rightOperand = right;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* (non-Javadoc)&lt;br /&gt;
     * @see interpreter.IExpressable#interpret(java.util.HashMap)&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public int interpret(final HashMap&amp;lt;String, Integer&amp;gt; variables) {&lt;br /&gt;
        return leftOperand.interpret(variables)&lt;br /&gt;
                - rightOperand.interpret(variables);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Class for a terminal expression&lt;br /&gt;
 */&lt;br /&gt;
class Variable implements IExpressable {&lt;br /&gt;
    /** Variable name */&lt;br /&gt;
    private String name = null;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor&lt;br /&gt;
     * @param name&lt;br /&gt;
     */&lt;br /&gt;
    public Variable(final String name) {&lt;br /&gt;
        this.name = name;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* (non-Javadoc)&lt;br /&gt;
     * @see interpreter.IExpressable#interpret(java.util.HashMap)&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public int interpret(final HashMap&amp;lt;String, Integer&amp;gt; variables) {&lt;br /&gt;
        return variables.get(name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Class for a terminal expression&lt;br /&gt;
 */&lt;br /&gt;
class Number implements IExpressable {&lt;br /&gt;
    /** Number object */&lt;br /&gt;
    private int number = 0;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor&lt;br /&gt;
     * @param number&lt;br /&gt;
     */&lt;br /&gt;
    public Number(final int number) {&lt;br /&gt;
        this.number = number;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* (non-Javadoc)&lt;br /&gt;
     * @see interpreter.IExpressable#interpret(java.util.HashMap)&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public int interpret(final HashMap&amp;lt;String, Integer&amp;gt; variables) {&lt;br /&gt;
        return number;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Interpreter beschäftigt sich nicht mit dem Parsen des ursprünglichen Ausdrucks und dem Erzeugen des Syntax-Baumes, der dem Ausdruck entspricht.&amp;lt;ref&amp;gt;[[Erich Gamma]], [[Richard Helm]], [[Ralph Johnson]], [[John Vlissides]]: &amp;#039;&amp;#039;Design Patterns: Elements of Reusable Object-Oriented Software&amp;#039;&amp;#039;. Addison-Wesley, 1995, ISBN 0-201-63361-2, S. 247&amp;lt;/ref&amp;gt; Der Vollständigkeit halber hier die Implementierung eines einfachen Parsers. Er ist unvollständig in dem Sinne, dass er manche nicht-gültige Ausdrücke &amp;#039;&amp;#039;nicht&amp;#039;&amp;#039; verwirft! (Aber alle gültigen Ausdrücke parst er korrekt und erzeugt den Syntax-Baum dafür.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Java&amp;quot;&amp;gt;&lt;br /&gt;
class Parser {&lt;br /&gt;
    /**&lt;br /&gt;
     * Parser method&lt;br /&gt;
     * @param expression&lt;br /&gt;
     * @return Parsed result&lt;br /&gt;
     */&lt;br /&gt;
    static public IExpressable parseExpression(final String expression) {&lt;br /&gt;
        IExpressable syntaxTree = null;&lt;br /&gt;
        Pattern numberPattern = Pattern.compile(&amp;quot;[+-]?\\d+&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        Stack&amp;lt;IExpressable&amp;gt; expressionStack = new Stack&amp;lt;IExpressable&amp;gt;();&lt;br /&gt;
        for (String token : expression.split(&amp;quot; &amp;quot;)) {&lt;br /&gt;
            if  (token.equals(&amp;quot;+&amp;quot;)) {&lt;br /&gt;
                IExpressable subExpression = new Plus(expressionStack.pop(),&lt;br /&gt;
                        expressionStack.pop());&lt;br /&gt;
                expressionStack.push(subExpression);&lt;br /&gt;
            } else if (token.equals(&amp;quot;-&amp;quot;)) {&lt;br /&gt;
                IExpressable subExpression = new Minus(expressionStack.pop(),&lt;br /&gt;
                        expressionStack.pop());&lt;br /&gt;
                expressionStack.push(subExpression);&lt;br /&gt;
            } else if(numberPattern.matcher(token).matches()) {&lt;br /&gt;
                expressionStack.push(new Number(Integer.parseInt(token.trim())));&lt;br /&gt;
            } else expressionStack.push(new Variable(token));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        syntaxTree = expressionStack.pop();&lt;br /&gt;
&lt;br /&gt;
        return syntaxTree;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Test class&lt;br /&gt;
 */&lt;br /&gt;
public class InterpreterExample {&lt;br /&gt;
    /**&lt;br /&gt;
     * Test method for the interpreter&lt;br /&gt;
     * @param arguments&lt;br /&gt;
     */&lt;br /&gt;
    public static void main(final String[] arguments) {&lt;br /&gt;
        final String expression = &amp;quot;w x z - + -2 +&amp;quot;;&lt;br /&gt;
        final HashMap&amp;lt;String, Integer&amp;gt; variables =&lt;br /&gt;
                new HashMap&amp;lt;String, Integer&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
        variables.put(&amp;quot;w&amp;quot;, 5);&lt;br /&gt;
        variables.put(&amp;quot;x&amp;quot;, 33);&lt;br /&gt;
        variables.put(&amp;quot;z&amp;quot;, 10);&lt;br /&gt;
&lt;br /&gt;
        final IExpressable tree = Parser.parseExpression(expression);&lt;br /&gt;
&lt;br /&gt;
        System.out.println(tree.interpret(variables));&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist nun recht einfach, die Grammatik zu erweitern und die erweiterten Ausdrücke zu interpretieren. Um eine Quadrier-Funktion &amp;lt;code&amp;gt;sqr&amp;lt;/code&amp;gt; einzubauen (einen unären Operator), muss nur eine neue Klasse eingeführt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Java&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Class for a non-terminal expression&lt;br /&gt;
 */&lt;br /&gt;
class SqrFunction implements IExpressable {&lt;br /&gt;
    /** Operand */&lt;br /&gt;
    IExpressable operand = null;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor&lt;br /&gt;
     * @param operand&lt;br /&gt;
     */&lt;br /&gt;
    public SqrFunction(final IExpressable operand)  {&lt;br /&gt;
        this.operand = operand;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* (non-Javadoc)&lt;br /&gt;
     * @see interpreter.IExpressable#interpret(java.util.HashMap)&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public int interpret(final HashMap&amp;lt;String,Integer&amp;gt; variables) {&lt;br /&gt;
        int tmp = operand.interpret(variables);&lt;br /&gt;
        return tmp*tmp;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der (unvollständige) Parser kann folgendermaßen erweitert werden, um auch &amp;lt;code&amp;gt;sqr&amp;lt;/code&amp;gt;-Ausdrücke zu parsen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Java&amp;quot;&amp;gt;&lt;br /&gt;
     else if(token.equals(&amp;quot;sqr&amp;quot;)) {&lt;br /&gt;
        IExpressable subExpression = new SqrFunction(expressionStack.pop());&lt;br /&gt;
                expressionStack.push( subExpression );&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Verwandte Entwurfsmuster ==&lt;br /&gt;
Der Syntaxbaum wird durch ein [[Kompositum (Entwurfsmuster)|Kompositum]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Ein [[Besucher (Entwurfsmuster)|Visitor]] kann das Verhalten aller Nichtterminalsymbole in sich kapseln, um die Anzahl der Klassen zu verringern und/oder das Verhalten dieser austauschbar zu gestalten.&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe des [[Fliegengewicht (Entwurfsmuster)|Flyweight]] können Terminalsymbole gemeinsam genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Ein [[Iterator (Entwurfsmuster)|Iterator]] kann verwendet werden, um den Syntaxbaum zu traversieren.&lt;br /&gt;
&lt;br /&gt;
== Einzelnachweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Navigationsleiste Entwurfsmuster}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Verhaltensmuster (Software)]]&lt;br /&gt;
[[Kategorie:Viererbande-Entwurfsmuster]]&lt;/div&gt;</summary>
		<author><name>imported&gt;AndreAdrian</name></author>
	</entry>
</feed>