Вычисление выражений в интерпретаторе

Пишу интерпретатор с типами переменных int, double, string. Парсер разбивает на элементы языка, но не знаю как правильно реализовать вычислений выражений. Вычисление реализовано как автомат по уровню операции и он в принципе работает, но я храню ответ в float, при присваивании если это int беру только целую часть. Для string я реализовал похожие функции.

У меня следующие вопросы

  1. Для каждого типа писать свой обработчик выражений?
  2. Если не для каждого типа, то в чем хранить ответ после разбора выражения?
  3. Если для каждого типа, то в случае как if,while какой тип выбрать?

Ответы (1 шт):

Автор решения: KoVadim

так как сам писал такое, то

Для каждого типа писать свой обработчик выражений?

да, а также возможно и для пар. У меня, к примеру, можно было строку умножать на целое ("**" * 2 == "****"), но это зависит от конкретных желаний.

Если не для каждого типа, то в чем хранить ответ после разбора выражения?

есть чудесный тип std::variant. И Вам подойдет std::variant<int, float, std::string>. Ну или свой тип, с помощью union, но это отдельная история, в которой очень легко выхватить UB.

Если для каждого типа, то в случае как if,while какой тип выбрать?

тут много вариантов. Можно воспользоваться get_if, я пользовался index. Так как index возвращает число от 0 до кол-ва типов-1 (с примера выше это получается 2), то можно сделать где то так

using myval = std::variant<int, float, std::string>;
myval a1,a2;

size_t op_index = a1.index() * 3 + a2.index();

switch(op_index) {
case 0: //int-int
   return myval(a1.get<int>() + a2.get<int>()); // прям так вызываем
case 3*2+1: // string-float
   throw ups();// а так нельзя.
}

но если такое лень для каждой операции писать, то можно воспользоваться перегрузками и передавать операцию как параметр в функцию выше.

Второй вариант заключается в том, что делается базовый тип и от него наследуются типы для каждого нужного - то есть, для числа и строки. А потом, с помощью двойной диспетчеризации разбираются операции. Я так пробовал, получилось сильно сильно сложнее и не поддерживаемо.

→ Ссылка