#pragma once #include #include #include #include #include "lexer.hpp" #include "util/text.hpp" #include "util/error.hpp" namespace fsh { enum NodeType { COMMAND_LINE, COMMAND, PIPELINE_COMMAND, LREDIRECTS, RREDIRECTS, REDIRECTS, STRING_LITERAL, COMMAND_ARGUMENT, TOKEN }; class AstNode { friend class std::shared_ptr; public: NodeType gtype() { return type; } const std::string& gname() { return name; }; protected: using TokenType = Lexer::TokenType; AstNode(NodeType type, std::string name) : type(type), name(name) {} // Pokusa da napravi od narednih tokena zadati Node ako ne uspe vrati null template static std::shared_ptr Optional(std::list::iterator& it, std::shared_ptr& node_ptr); template static std::shared_ptr Optional(std::list::iterator& it) { std::shared_ptr node_ptr; return Optional(it, node_ptr); } // Pravi od narednih tokena zadati Node ako ne uspe izbaci AstBuildError template static std::shared_ptr Mandatory(std::list::iterator& it) { return T::build(it); } private: AstNode(); AstNode(const AstNode&); NodeType type; const std::string name; }; class ExecutableNode : public AstNode { public: virtual void print(int indent) {}; virtual void execute(std::istream& in, std::ostream& out) {} protected: ExecutableNode(NodeType type, std::string Name) : AstNode(type, Name) {} private: }; class AstBuildError : public util::LazyError { public: AstBuildError() {} }; class AstUnexpectedTypeError : public AstBuildError { public: AstUnexpectedTypeError(Lexer::TokenType type) : type(type){}; private: Lexer::TokenType type; std::string build_msg() const noexcept override { return (std::string) "Unexpected " + util::tokens[type]; }; }; class AstNoRedirectError : public AstBuildError { private: std::string build_msg() const noexcept override { return "No redirects provided"; }; }; }