Парсер выводит пустую строку, как только встречает тригонометрию на входе

Имеется парсер, который должен различать в введённом в строку тексте математическое выражение и правильно его обрабатывать. Однако, если во вводимой строке появляется тригонометрическая функция (sin, cos и т.д.) то в качестве вывода программа возвращает пустую строку. Никак не получается понять, почему так происходит, подскажите пожалуйста, как исправить.

#include <iostream>
#include <cmath>
#include <map>
#include <stack>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

const double PI = 3.14159265358979323846;

struct Operation {
    int precedence;
    double (*func)(double, double);
};

map<string, Operation> MATH = {
    {"+", {1, [](double x, double y) { return x + y; }}},
    {"-", {1, [](double x, double y) { return x - y; }}},
    {"*", {2, [](double x, double y) { return x * y; }}},
    {"/", {2, [](double x, double y) { return x / y; }}},
    {"^", {3, [](double x, double y) { return pow(x, y); }}},
};

map<string, double(*)(double)> TRIGONOMETRY = {
    {"sin", sin},
    {"cos", cos},
    {"tan", tan},
    {"cot", [](double x) { return 1.0 / tan(x); }},
};

vector<string> parse(const string& formula) {
    vector<string> tokens;
    string number, trigonometry;
    
    for (size_t i = 0; i < formula.size(); ++i) {
        char s = formula[i];
        if (isalpha(s)) {
            trigonometry += s; // собираем тригонометрические функции
            // Проверяем, если у нас уже есть функция
            if (TRIGONOMETRY.count(trigonometry) || (i+1 == formula.size() || !isalnum(formula[i+1]))) {
                tokens.push_back(trigonometry);
                trigonometry = "";
            }
        } else if (isdigit(s) || s == '.') {
            number += s;
        } else {
            if (!number.empty()) {
                tokens.push_back(number);
                number = "";
            }
            if (s == '(' || s == ')') {
                tokens.push_back(string(1, s));
            } else if (MATH.count(string(1, s))) {
                tokens.push_back(string(1, s));
            }
        }
    }
    if (!number.empty()) {
        tokens.push_back(number);
    }
    return tokens;
}

vector<string> sortfunc(const vector<string>& parsingObject) {
    stack<string> stack;
    vector<string> output;

    for (const auto& token : parsingObject) {
        if (MATH.count(token)) {
            while (!stack.empty() && stack.top() != "(" &&
                   MATH[token].precedence <= MATH[stack.top()].precedence) {
                output.push_back(stack.top());
                stack.pop();
            }
            stack.push(token);
        } else if (token == ")") {
            while (!stack.empty()) {
                string x = stack.top();
                stack.pop();
                if (x == "(") break;
                output.push_back(x);
            }
        } else if (token == "(") {
            stack.push(token);
        } else {
            output.push_back(token);
        }
    }

    while (!stack.empty()) {
        output.push_back(stack.top());
        stack.pop();
    }

    return output;
}

double calculate(const vector<string>& pol) {
    stack<double> stack;

    for (const auto& token : pol) {
        if (TRIGONOMETRY.count(token)) {
            double x = stack.top();
            stack.pop();
            stack.push(TRIGONOMETRY[token](x));
        } else if (MATH.count(token)) {
            double y = stack.top();
            stack.pop();
            double x = stack.top();
            stack.pop();
            stack.push(MATH[token].func(x, y));
        } else if (token == "pi") {
            
            stack.push(PI);
        } else {
            stack.push(stod(token)); // Преобразование строки в число
        }
    }
    return stack.top();
}

double evaluate(const string& formula) {
    vector<string> parsed = parse(formula);
    vector<string> sorted = sortfunc(parsed);
    return calculate(sorted);
}

int main() {
    cout << evaluate("cos(pi) + 1 * 2 ^ 2") << endl;
    return 0;
}

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

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

Заменил соответствующую часть в функции parse:

// Проверяем, если у нас уже есть функция
if (TRIGONOMETRY.count(trigonometry) || (i+1 == formula.size() || !isalnum(formula[i+1]))) {

на:

// Проверяем, если у нас уже есть функция
if (TRIGONOMETRY.count(trigonometry) || (i+1 == formula.size() || !isalnum(formula[i+1]))) {

Если всё функционирует корректно и не было изменений, то в функции double calculate(const vector<string>& pol) строка:

double x = stack.top();

должна оставаться как есть, и любые операции с TRIGONOMETRY должны обрабатываться.

→ Ссылка