#pragma once #ifndef CALC_AST_H #define CALC_AST_H #include <deque> #include <map> #include <memory> #include <string> namespace calc { class AST; using Variables = std::map<std::string, double>; using Functions = std::map<std::string, std::unique_ptr<AST>>; class AST { public: virtual double eval(const Variables&, const Functions&) const = 0; }; class Number : public AST { public: Number(double d); double eval(const Variables&, const Functions&) const override; private: double m_val; }; class Var : public AST { public: Var(std::string name); double eval(const Variables& ctx, const Functions&) const override; std::string getName() const; private: std::string m_name; }; class Binop : public AST { public: Binop(std::unique_ptr<AST>&& left, std::string op, std::unique_ptr<AST>&& right); double eval(const Variables& ctx, const Functions&) const override; private: std::unique_ptr<AST> m_left; std::unique_ptr<AST> m_right; std::string m_op; }; class Unop : public AST { public: Unop(std::string op, std::unique_ptr<AST>&& operand); double eval(const Variables&, const Functions&) const override; private: std::string m_op; std::unique_ptr<AST> m_operand; }; class FormalParameters : public AST { public: double eval(const Variables&, const Functions&) const override; void push_back(std::unique_ptr<AST>&& arg); std::deque<std::unique_ptr<AST>>::const_iterator begin(); std::deque<std::unique_ptr<AST>>::const_iterator end(); private: std::deque<std::unique_ptr<AST>> m_args; }; class FunctionArguments : public AST { public: double eval(const Variables&, const Functions&) const override; std::unique_ptr<AST>& operator[](std::size_t idx); void push_back(std::unique_ptr<AST>&& arg); std::size_t size() const; private: std::deque<std::unique_ptr<AST>> m_args; }; class FunctionCall : public AST { public: FunctionCall(std::string name, std::unique_ptr<FunctionArguments>&& arguments); double eval(const Variables&, const Functions&) const override; private: std::string m_name; std::unique_ptr<FunctionArguments> m_arguments; }; class Function : public AST { public: Function(std::deque<std::string> formalParams, std::unique_ptr<AST>&& body); double eval(const Variables&, const Functions&) const override; const std::deque<std::string>& getParams() const; private: std::deque<std::string> m_formalParams; std::unique_ptr<AST> m_body; }; } /* calc */ #endif //CALC_AST_H