#ifndef PARSER_IMPL_HPP
#define PARSER_IMPL_HPP

#include <stack>
#include <string>
#include <iosfwd>
#include <functional>

struct interpreter_context;
class symbol_impl;
class symbol;
class owned_reference;
class array;
class function;

struct math_parser_impl {
    math_parser_impl(int argc, char* argv[]);
    ~math_parser_impl();

    void binary_operator(const std::string& op);
    void unary_operator(const std::string& op);

    void make_leaf(symbol_impl* s);
    void make_string(const std::string& s);
    void make_scalar(const std::string& s);
    void make_variable(const std::string& s);

    void error(const std::string& s);
    void warning(const std::string& s);
    void note(const std::string& s);

    symbol pop_symbol();

    void array_begin();
    void array_push();
    void array_end();

    void function_begin(const std::string& id);
    void function_param();
    void function_end();

    void assign_begin(const std::string& id);
    void assign_begin_no_eval();
    void assign_end();
    void assign_end_no_eval();

    void destroy(const std::string& id);
    void destroy_all();

    void print_identifier(const std::string& id);
    void print_help();
    void print_expression();

    void finish();

    bool allow_complex() const;

    void set_parse_function(const std::function<bool(const std::string&)>& p);

private :
    interpreter_context* context;

    std::string format_output(const std::string& s);

    std::function<bool(const std::string&)> parse;

    std::stack<symbol_impl*> symbol_stack;
    std::stack<array*> array_stack;
    std::stack<function*> function_stack;
    std::stack<std::string> assign_stack;

    std::string align;
};

#endif
