Интерпретатор (Interpreter) :: Cетевой уголок Majestio

Интерпретатор (Interpreter)


Интерпретатор — это поведенческий паттерн проектирования, который, решает часто встречающуюся, но подверженную изменениям, задачу. Также известен как Little (Small) Language. Он определяет представление грамматики для заданного языка и интерпретатор предложений этого языка.

Применимость

На refactoring.guru данный раздел, увы, отсутствует

UML-диаграмма

Пример реализации

Очень примитивный пример парсинга числа "234", заданного строкой, и вывод его в словесное представление.

#include <iostream>
#include <sstream>
#include <unordered_map>

// Абстрактное выражение

class AbstractExpression {
 public:
  virtual void interpret(std::stringstream& context) = 0;
};

// Конкретная реализация терминального выражения для цифры

class DigitExpression : public AbstractExpression {
 private:
  std::unordered_map<char, std::string> digitMap = {
      {'0', "ноль"},   {'1', "один"},  {'2', "два"},   {'3', "три"},
      {'4', "четыре"}, {'5', "пять"},  {'6', "шесть"}, {'7', "семь"},
      {'8', "восемь"}, {'9', "девять"}};

 public:
  void interpret(std::stringstream& context) override {
    char digit;
    context >> digit;
    std::cout << digitMap[digit] << " ";
  }
};

// Конкретная реализация терминального выражения для сотен

class HundredExpression : public AbstractExpression {
 private:
  std::unordered_map<char, std::string> hundredMap = {
      {'1', "сто"},       {'2', "двести"},    {'3', "триста"},
      {'4', "четыреста"}, {'5', "пятьсот"},   {'6', "шестьсот"},
      {'7', "семьсот"},   {'8', "восемьсот"}, {'9', "девятьсот"}};

 public:
  void interpret(std::stringstream& context) override {
    char hundred;
    context >> hundred;
    std::cout << hundredMap[hundred] << " ";
  }
};

// Конкретная реализация терминального выражения для десятков

class TenExpression : public AbstractExpression {
 private:
  std::unordered_map<char, std::string> tenMap = {
      {'1', "десять"},    {'2', "двадцать"},    {'3', "тридцать"},
      {'4', "сорок"},     {'5', "пятьдесят"},   {'6', "шестьдесят"},
      {'7', "семьдесят"}, {'8', "восемьдесят"}, {'9', "девяносто"}};

 public:
  void interpret(std::stringstream& context) override {
    char ten;
    context >> ten;
    std::cout << tenMap[ten] << " ";
  }
};

// Конкретная реализация нетерминального выражения для числа

class NumberExpression : public AbstractExpression {
 private:
  AbstractExpression* hundredExpression;
  AbstractExpression* tenExpression;
  AbstractExpression* digitExpression;

 public:
  NumberExpression() {
    hundredExpression = new HundredExpression();
    tenExpression = new TenExpression();
    digitExpression = new DigitExpression();
  }

  ~NumberExpression() {
    delete hundredExpression;
    delete tenExpression;
    delete digitExpression;
  }

  void interpret(std::stringstream& context) override {
    hundredExpression->interpret(context);
    tenExpression->interpret(context);
    digitExpression->interpret(context);
  }
};

// Контекст

class Context {
 private:
  std::stringstream contextStream;

 public:
  Context(const std::string& context) { contextStream << context; }

  std::stringstream& getContextStream() { return contextStream; }
};

int main() {
  Context context("234");
  std::stringstream& contextStream = context.getContextStream();
  AbstractExpression* numberExpression = new NumberExpression();
  numberExpression->interpret(contextStream);
  delete numberExpression;
  return 0;
}
Будет напечатано:
двести тридцать четыре
import 'dart:io';

// Абстрактное выражение
abstract class AbstractExpression {
  void interpret(String context);
}

// Конкретная реализация терминального выражения для цифры
class DigitExpression implements AbstractExpression {
  final Map<String, String> digitMap = {
    '0': 'ноль',
    '1': 'один',
    '2': 'два',
    '3': 'три',
    '4': 'четыре',
    '5': 'пять',
    '6': 'шесть',
    '7': 'семь',
    '8': 'восемь',
    '9': 'девять',
  };

  @override
  void interpret(String context) {
    final digit = context.codeUnitAt(0);
    stdout.write(digitMap[String.fromCharCode(digit)] != null
        ? '${digitMap[String.fromCharCode(digit)]} '
        : '');
  }
}

// Конкретная реализация терминального выражения для сотен
class HundredExpression implements AbstractExpression {
  final Map<String, String> hundredMap = {
    '1': 'сто',
    '2': 'двести',
    '3': 'триста',
    '4': 'четыреста',
    '5': 'пятьсот',
    '6': 'шестьсот',
    '7': 'семьсот',
    '8': 'восемьсот',
    '9': 'девятьсот',
  };

  @override
  void interpret(String context) {
    final hundred = context.codeUnitAt(0);
    stdout.write(hundredMap[String.fromCharCode(hundred)] != null
        ? '${hundredMap[String.fromCharCode(hundred)]} '
        : '');
  }
}

// Конкретная реализация терминального выражения для десятков
class TenExpression implements AbstractExpression {
  final Map<String, String> tenMap = {
    '1': 'десять',
    '2': 'двадцать',
    '3': 'тридцать',
    '4': 'сорок',
    '5': 'пятьдесят',
    '6': 'шестьдесят',
    '7': 'семьдесят',
    '8': 'восемьдесят',
    '9': 'девяносто',
  };

  @override
  void interpret(String context) {
    final ten = context.codeUnitAt(0);
    stdout.write(tenMap[String.fromCharCode(ten)] != null
        ? '${tenMap[String.fromCharCode(ten)]} '
        : '');
  }
}

// Конкретная реализация нетерминального выражения для числа
class NumberExpression implements AbstractExpression {
  final AbstractExpression hundredExpression = HundredExpression();
  final AbstractExpression tenExpression = TenExpression();
  final AbstractExpression digitExpression = DigitExpression();

  @override
  void interpret(String context) {
    hundredExpression.interpret(context.substring(0, 1));
    tenExpression.interpret(context.substring(1, 2));
    digitExpression.interpret(context.substring(2, 3));
  }
}

void main() {
  final context = "234";
  final numberExpression = NumberExpression();
  numberExpression.interpret(context);
}
Будет напечатано:
двести тридцать четыре
Рейтинг: 0/5 - 0 голосов