printПаттерны поведения

printИнтерпретатор

Interpreter

Назначение
Для заданного языка определяет представление его грамматики, а также интерпретатор предложений этого языка.

Результаты
1. Грамматику легко изменять и расширять.
2. Реализации классов, описывающих узлы абстрактного синтаксического дерева, достаточно тривиальна, их может автоматически создавать генератор синтаксических анализаторов.
3. Сложные грамматики трудно сопровождать, так как определяется по меньшей мере один класс для каждого правила грамматики.
4. Паттерн интерпретатор позволяет легко изменить способ вычисления выражений. При частом добавлении новых способов интерпретации выражений можно использовать паттерн посетитель.

Реализация
// Контекст
class Context {
public:
  int curr(); // текущий символ
  void next(); // переход к следующему символу
  int getpos(); // запомнить позицию
  void setpos(int); // восстановить позицию
};
// Исключительная ситуация для ошибки разбора
class SyntaxError {};
// Абстрактное выражение
class Expression {
public:
  virtual void Interpret(Context&)=0;
};
// Терминальное выражение - один символ
class Terminal : public Expression {
  int ch;
public:
  Terminal(int ch):ch(ch) {}
  void Interpret(Context &c) 
  { if(c.curr()!=ch) throw SintaxError();
    c.next();
  }
};
// Нетерминальное выражение для правила грамматики R::=R1 R2 ... Rn
class Nonterminal : public Expression {
  vector <Expression *> rule;
public:
  void Add(Expression *e) { rule.push_back(e); }
  void Interpret(Context &c) 
  { for(size_t i=0; i<rule.size(); ++i)
      rule[i]->Interpret(c);
  }
};
// Нетерминальное выражение для правила грамматики R::=R1 | R2 | ... | Rn
class Select : public Expression {
  vector <Expression *> rule;
public:
  void Add(Expression *e) { rule.push_back(e); }
  void Interpret(Context &c)
  { int p=c.getpos();
    for(size_t i=0; i<rule.size(); ++i)
    {
      try {
        rule[i]->Interpret(c);
        return;
      }
      catch(SyntaxError &e)
      { c.setpos(p); }
    }
    throw SyntaxError();
  }
};
loading