Interpreter

GOF Intent:
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

از Interpreter Pattern زماني استفاده مي‌شود که بخواهيم يک regular Expression يا يک Pattern رشته اي را تفسير نماييم.

اين Pattern بر خلاف ساير Pattern ها استفاده عمومي ندارد و فقط در موارد خاص (تفسير Expression) مورد استفاده قرار مي گيرد.

براي درک بهتر Interpreter Pattern مثالي را پي مي گيريم.

مثال:
عبارت هاي محاسباتي با دو عملگر جمع و تفريق را در نظر بگيريد:

(10 + 7) – (6 – 1) + 5

در اين مثال گرامر اينگونه خواهد بود:

Expression = NumberExpression | AddExpression | SubtractExpression
AddExpression = Expression + Expression
SubtractExpression = Expression – Expression

براي محاسبه عبارت مي توان آن را به حالت Postfix تبديل کرد و در قالب درخت سازماندهي نمود:

(10 + 7) – (6 – 1) + 5 —–> 10 7 + 6 1 – – 5 +

کارهايي که در اين مثال انجام شد مقدمات پياده سازي Interpreter Pattern است.

مراحل اعمال Interpreter Design Pattern :

  1. براي زبان گرامر تعريف کنيد.
  2. هر يک از بخش هاي گرامر را به يک کلاس map کنيد.
  3. کلاس ها را در ساختاري مشابه Composite Pattern سازماندهي نماييد.
  4. متد interpret(Context) را پياده سازي نماييد.

اجزاي Interpreter Design Pattern:
1- AbstractExpression : يک متد با نام Intepret تعريف مي کند
2- TerminalExpression : کلاس متناظر براي اجزاي با مقدار مشخص از جمله اعداد. در ساختار درختي Composite اين TerminalExpression ها برگ هاي درخت هستند.
3- NonterminalExpression : کلاس متناظر براي هر يک از عملگرها يا قواعد زبان. درساختار Composite Pattern، اين ها کلاس هاي Composite هستند.
4- Context : کلاسي است که درصورت لزوم عبارت اصلي و عبارت Interpret شده را در خود Encapsulate مي کند و بصورت Global در دسترس متد Interpret قرار دارد. در مثال ما يک String ساده است.
5- Client: دو وظيفه دارد

  • ساخت و سازماندهي درخت براي هر عبارت که بايد Interpret شود. اين درخت شامل کلاس هاي TerminalExpression و NonterminalExpression است.
  • فراخواني متد Interpret

نمونه کد:

public interface Expression {
   public int interpret();
}


public class NumberExpression implements Expression{
   int number;

   public NumberExpression(int number){
      this.number = number;
   }

   public int interpret() {
      return number;
   }
}


public class AddExpression implements Expression{

   Expression leftExpression;
   Expression rightExpression;

   public AddExpression(Expression left, Expression right){
      leftExpression = left;
      rightExpression = right;
   }

   public int interpret() {
      return leftExpression.interpret() + rightExpression.interpret();
   }
}


public class SubtractExpression implements Expression{

   Expression leftExpression;
   Expression rightExpression;

   public SubtractExpression(Expression left, Expression right){
      leftExpression = left;
      rightExpression = right;
   }

   public int interpret() {
      return leftExpression.interpret() – rightExpression.interpret();
   }
}


import java.util.Stack;
import java.util.ArrayList;

public class Evaluator {
   private Expression syntaxTree;

   public Evaluator(String expression){

      String[] tokens = expression.split(” “);
      Stack<Expression> expressionStack = new Stack<Expression>();

      for (String token : tokens){
         if (! (token.equals(“+”) || token.equals(“-”))){
            expressionStack.push(new NumberExpression(Integer.parseInt(token)));
         } else {

            Expression right = expressionStack.pop();
            Expression left = expressionStack.pop();

            if (token.equals(“+”))
               expressionStack.push(new AddExpression(left, right));
            else
               expressionStack.push(new SubtractExpression(left, right));
         }
      }
      syntaxTree = expressionStack.pop();
   }

   public int interpret(){
      return syntaxTree.interpret();
   }
}


public static void main(String[] args){
   // (10 + 6) – (7 – 2)
   String context = “10 6 + 7 2 – -”;
   Evaluator e1 = new Evaluator(context);
   System.out.println(e1.interpret());
}

نکته 1:
با استفاده از Interpreter Pattern تغيير و گسترش گرامر ساده است. زيرا هر قاعده گرامر در يک کلاس پياده شده است و با تغيير آنها يا Extend نمون آنها مي توان گرامر را تغيير داد.

نکته 2:
اما استفاده از Interpreter Pattern براي گرامر هاي پيچيده و حجيم، مديريت و Maintanance برنامه را دشوار مي کند.



منبع ها:

  1. Design Patterns – Elements of Reusable Object Oriented Software (GOF) By Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
  2. Interpreter in Devlake
  3. Interpreter in Wikipedia
  4. Interpreter in Sourcemaking

پست شده در Design Pattern

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

*


سه + = 6

شما می‌توانید از این دستورات HTML استفاده کنید: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

تماس با من: admin@paspars.com