#include <iostream>
#include <cctype>
#include <sstream>
#include <string>
#include <memory>
#include <stdexcept>
typedef std::istringstream point;

template <class T>
class calculator
{
    T number_value;
    T result;

    char get_token(point& input, char& curr_token)
    {

        char ch;
        do {    
            if (!input.get(ch))
            {
                return curr_token = 'E'; 
            }
        } while (ch != '\n' && isspace(ch));

        switch (ch)
        {
            case 0: 
                return curr_token = 'E';
            case '*':
                return curr_token = '*';
            case '/':
                return curr_token = '/';
            case '+':
                return curr_token = '+';
            case '-':
                return curr_token = '-';
            case '(':
                return curr_token = '(';
            case ')':
                return curr_token = ')';
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
            case '.':
                input.putback(ch); 
                input >> number_value; 
                return curr_token = 'N';
            default:
                throw std::logic_error("Bad token");
        }

    }

    T prim(point& input, bool get, char& curr_token)
    {
        if (get)
        {
            get_token(input, curr_token);
        }

        switch (curr_token)
        {
            case 'N':
            {
                T v = number_value;
                get_token(input, curr_token);
                return v;
            }
            case '-':
                return -prim(input, true, curr_token);
            case '(':
            {
                T e = expr(input, true, curr_token);
                if (curr_token != ')')
                {
                    throw "')' expected";
                }
                get_token(input, curr_token);
                return e;
            }
            default:
                throw std::logic_error("primary expected");
        }
    }

    T term(point& input, bool get, char& curr_token )
    {
        T result = prim(input, get, curr_token);

        for ( ; ; )
        {
            switch (curr_token)
            {
                case '*':
                    result *= prim(input, true, curr_token);
                    break;
                case '/':
                    if (T d = prim(input, true, curr_token))
                    {
                        result /= d;
                        break;
                    }
                    throw std::logic_error("Divide by 0");
                default:
                    return result;
            }
        }
    }

    T expr(point& input, bool get, char& curr_token)
    {
        T result = term(input, get, curr_token);

        for ( ; ; )
        {
            switch (curr_token)
            {
                case '+':
                    result += term(input, true, curr_token);
                    break;
                case '-':
                    result -= term(input, true, curr_token);
                    break;
                default:
                    return result;
            }
        }
    }

    void calculus(point& input)
    {
        char curr_token;

            while (input) {
                get_token(input, curr_token);
                if (curr_token == 'E') {
                    break;
                }

                if (curr_token == 'L') {
                    continue;
                }

                result = expr(input, false, curr_token);
            }
    }

public:
    calculator(point& input)
    {
        calculus(input);
    }

    T Get()
    {
        return result;
    }

};

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        std::cout << "error" << std::endl;
        return 1;
    }
    auto input = std::istringstream(argv[1]);
    try {
        calculator<int> a(input);
        std::cout<<a.Get()<<std::endl;
    }
    catch(std::logic_error&)
    {
        std::cout << "error" << std::endl;
        return 1;
    }
    return 0;
}
#include <iostream>
#include <cctype>
#include <sstream>
#include <string>
#include <memory>
#include <stdexcept>
typedef std::istringstream point;
//typedef std::shared_ptr<std::basic_istream<char>> point;
template <class T>
class calculator
{
    T number_value;
    T result;

    char get_token(point& input, char& curr_token)
    {

        char ch;
        do {    // Пропустить все пробельные символы кроме '\n'.
            if (!input.get(ch))
            {
                return curr_token = 'E'; // Завершить работу калькулятора.
            }
        } while (ch != '\n' && isspace(ch));

        switch (ch)
        {
            case 0: // При вводе символа конца файла, завершить работу калькулятора.
                return curr_token = 'E';
            case '*':
                return curr_token = '*';
            case '/':
                return curr_token = '/';
            case '+':
                return curr_token = '+';
            case '-':
                return curr_token = '-';
            case '(':
                return curr_token = '(';
            case ')':
                return curr_token = ')';
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
            case '.':
                input.putback(ch); // Положить назад в поток...
                input >> number_value; // И считать всю лексему.
                return curr_token = 'N';
            default:
                throw std::logic_error("Bad token");
        }

    }

    // prim() - обрабатывает первичные выражения.
    T prim(point& input, bool get, char& curr_token)
    {
        if (get)
        {
            get_token(input, curr_token);
        }

        switch (curr_token)
        {
            case 'N':
            {
                T v = number_value;
                get_token(input, curr_token);
                return v;
            }
            case '-':
                return -prim(input, true, curr_token);
            case '(':
            {
                T e = expr(input, true, curr_token);
                if (curr_token != ')')
                {
                    throw "')' expected";
                }
                get_token(input, curr_token);
                return e;
            }
            default:
                throw std::logic_error("primary expected");
        }
    }

// term() - умножение и деление.
    T term(point& input, bool get, char& curr_token )
    {
        T result = prim(input, get, curr_token);

        for ( ; ; )
        {
            switch (curr_token)
            {
                case '*':
                    result *= prim(input, true, curr_token);
                    break;
                case '/':
                    if (T d = prim(input, true, curr_token))
                    {
                        result /= d;
                        break;
                    }
                    throw std::logic_error("Divide by 0");
                default:
                    return result;
            }
        }
    }

// expr() - сложение и вычитание.
    T expr(point& input, bool get, char& curr_token)
    {
        T result = term(input, get, curr_token);

        for ( ; ; )
        {
            switch (curr_token)
            {
                case '+':
                    result += term(input, true, curr_token);
                    break;
                case '-':
                    result -= term(input, true, curr_token);
                    break;
                default:
                    return result;
            }
        }
    }

    void calculus(point& input)
    {
        char curr_token;

            while (input) {
                get_token(input, curr_token);
                if (curr_token == 'E') {
                    break;
                }

                // Снимает ответственность expr() за обработку пустых выражений.
                if (curr_token == 'L') {
                    continue;
                }

                // expr() -> term() -> prim() -> expr() ...
                result = expr(input, false, curr_token);
            }
    }

public:
    calculator(point& input)
    {
        calculus(input);
    }

    T Get()
    {
        return result;
    }

};

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        std::cout << "error" << std::endl;
        return 1;
    }
    auto input = std::istringstream(argv[1]);
    try {
        calculator<int> a(input);
        std::cout<<a.Get()<<std::endl;
    }
    catch(std::logic_error&)
    {
        std::cout << "error" << std::endl;
        return 1;
    }
    return 0;
}