An in-depth analysis of the application of interpreter pattern in C + + design pattern programming _c language

Source: Internet
Author: User
Tags extend

The interpreter pattern (interpreter), given a language, defines a representation of its grammar, and defines an interpreter that uses the representation to interpret a sentence in a language.

The interpreter pattern needs to address that if a particular type of problem occurs at a high frequency, it may be worthwhile to express each instance of the problem as a sentence in a simple language. This allows you to build an interpreter that interprets the sentences to solve the problem. Interpreter mode is used when there is a language that needs to be interpreted, and you can represent a sentence in that language as an abstract syntax tree. Using the interpreter pattern means that you can easily change and extend the grammar, because the pattern uses classes to represent the grammar rules, and you can use inheritance to change or extend the grammar. It is also easier to implement grammars because classes that define the nodes in the abstract syntax tree are generally similar, and these classes are easy to write directly.

Structure Chart:

Instance:

Music Interpreter

PlayContext.h

/************************************************************************ 
 * Description: Performance Content 
 * Remark:    
************************************************************************/ 
#ifndef _play_context_h_ 
#define _play_context_h_ 
#include <string> 
#include <iostream> 
using namespace std; 
Class Playcontext 
{public 
: 
  string Getplaytext () 
  {return 
    m_strtext; 
  } 
  void Setplaytext (const string& strText) 
  { 
    m_strtext = strText; 
  } 
Private: 
  string m_strtext; 
}; 
#endif//_play_context_h_ 

Expression.h

/************************************************************************ * Description: Expression class * Remark: ********* /#ifndef _expression_h_ #define _expression_h_ 
    Include "playContext.h" class Expression {public://interpreter void interpret (playcontext& playcontext) { 
    if (Playcontext.getplaytext (). empty ()) {return; 
      else {string strplaykey = Playcontext.getplaytext (). substr (0, 1); 
      String strtemp = Playcontext.getplaytext (). substr (2); 
       
      Playcontext.setplaytext (strtemp); 
      size_t NPOs = Playcontext.getplaytext (). Find (""); 
      String strplayvalue = Playcontext.getplaytext (). substr (0, NPOs); 
      int nplayvalue = atoi (Strplayvalue.c_str ()); 
      NPOs = Playcontext.getplaytext (). Find (""); 
      Playcontext.setplaytext (Playcontext.getplaytext (). substr (NPOs + 1)); 
    Excute (Strplaykey, Nplayvalue); }//Execute Virtual void Excute (string& strkey, const int Nvalue) = 0; 
Private:}; 
 

 #endif//_expression_h_

Note.h

/************************************************************************ * Description: Note class * Remark: ************************************************************************/#ifndef _NOTE_H_ #define _ Note_h_ #include "expression.h" class Note:public expression {public:virtual void Excute (string& strkey, CO 
    NST int nvalue) {char szkey[2]; 
    strncpy (Szkey, Strkey.c_str (), strkey.length ()); 
    String Strnote; 
      Switch (szkey[0]) {case ' C ': strnote = ' 1 '; 
    Break 
      Case ' D ': Strnote = "2"; 
    Break 
      Case ' E ': Strnote = "3"; 
    Break 
      Case ' F ': strnote = "4"; 
    Break 
      Case ' G ': strnote = "5"; 
    Break 
      Case ' A ': strnote = "6"; 
    Break 
      Case ' B ': strnote = "7"; 
    Break 
      Default:strnote = "Error"; 
    Break 
  } cout << strnote << ""; 
} 
}; #endif//_note_h_ 

Scale.h

/************************************************************************ 
 * Description: Scale class 
 * remark:    
************************************************************************/ 
#ifndef _scale_h_ 
# Define _scale_h_ 
#include "expression.h" 
class Scale:public expression 
{public 
: 
  virtual void Excute (string& strkey, const int nvalue) 
  { 
    string strscale; 
    Switch (nvalue) 
    {case 
    1: 
      Strscale = "Bass"; 
      break; 
    Case 2: 
      strscale = "Alto"; 
      break; 
    Case 3: 
      Strscale = "Treble"; 
      break; 
    Default: 
      Strscale = "error"; 
      break; 
    cout << strscale << ""; 
  } 
Private: 
}; 
#endif//_scale_h_ 


Speed.h

#ifndef _speed_h_ 
#define _speed_h_ 
#include "expression.h" 
class Speed:public expression 
{ 
Public: 
  virtual void Excute (string& strkey, const int nvalue) 
  { 
    string strspeed; 
    if (Nvalue < 3) 
    { 
      strspeed = "Fast"; 
    } 
    else if (nvalue >= 6) 
    { 
      strspeed = "slow"; 
    } 
    else 
    { 
      strspeed = "Medium speed"; 
    } 
    cout << strspeed << ""; 
  } 
}; 
#endif//_speed_h_  

Client: InterpreterApp.cpp

InterpreterApp.cpp: Defines the entry point for a console application. #include "stdafx.h" #include "note.h" #include "scale.h" #include "speed.h" #include "playContext.h" int _tmain (i 
  NT ARGC, _tchar* argv[]) {Playcontext context; 
   
  cout << "Music:"; 
  Context.setplaytext ("T 2 O 2 E 3 G 5 G 5"); 
   
  expression* expressobj = NULL; 
    while (!context.getplaytext (). empty ()) {string strsep = Context.getplaytext (). substr (0, 1); 
    Char szkey[2]; 
    strncpy (Szkey, Strsep.c_str (), strsep.length ()); 
      Switch (szkey[0]) {case ' O ': expressobj = new scale (); 
    Break 
      Case ' T ': expressobj = new speed (); 
    Break 
      Case ' C ': Case ' D ': Case ' E ': Case ' F ': Case ' G ': Case ' A ': Case ' B ': Case ' P ': 
      Expressobj = new Note (); 
    Break 
    Default:break; 
    } if (NULL!= expressobj) {Expressobj->interpret (context); 
  } system ("Pause"); 
return 0; 

 }

The inadequacy of the place
The interpreter mode is not sufficient, the interpreter pattern defines at least one class for each rule in the grammar, so a grammar containing many rules may be difficult to manage and maintain. It is recommended that when the grammar is very complex, it is handled using other techniques such as a parser or compiler builder.

Applicable scenarios

    • Interpreter mode is used when there is a language that needs to be interpreted, and you can represent a sentence in that language as an abstract syntax tree. This pattern works best when the following conditions are present:
    • The grammar is simple for complex grammars, and the class level of the grammar becomes too large to be managed. This is a better choice for a tool like parser builder. They do not need to construct an abstract syntax tree to interpret an expression, which saves space and may also save time.
    • Efficiency is not a key problem the most efficient interpreters are not usually implemented by directly interpreting the parsing tree, but by first converting them into another form. For example, regular expressions are usually converted to state machines. However, even in this case, the converter can still be implemented in the interpreter mode, and the pattern is still useful.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.