diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index b991d60..2bf81d3 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -181,7 +181,7 @@ namespace chaiscript //! to the passed in values bool filter(const std::vector &vals, const Type_Conversions_State &t_conversions) const { - assert(m_arity == -1 || (m_arity > 1 && vals.size() == m_arity)); + assert(m_arity == -1 || (m_arity > 0 && static_cast(vals.size()) == m_arity)); if (m_arity < 0) { diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index aa07984..d4fce2d 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -72,17 +72,14 @@ namespace chaiscript chaiscript::detail::Dispatch_Engine m_engine; + std::unique_ptr m_parser; + /// Evaluates the given string in by parsing it and running the results through the evaluator Boxed_Value do_eval(const std::string &t_input, const std::string &t_filename = "__EVAL__", bool /* t_internal*/ = false) { try { - parser::ChaiScript_Parser parser; - if (parser.parse(t_input, t_filename)) { - //parser.show_match_stack(); - return parser.optimized_ast()->eval(m_engine); - } else { - return Boxed_Value(); - } + const auto p = m_parser->parse(t_input, t_filename); + return p->eval(m_engine); } catch (chaiscript::eval::detail::Return_Value &rv) { return rv.retval; @@ -180,8 +177,8 @@ namespace chaiscript m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval"); m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval"); - m_engine.add(fun([](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse"); - m_engine.add(fun([](const std::string &t_str){ return parse(t_str); }), "parse"); + m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse"); + m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse"); m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const"); @@ -221,7 +218,8 @@ namespace chaiscript ChaiScript(const ModulePtr &t_lib, std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) - : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)) + : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), + m_parser(std::make_unique>()) { if (m_module_paths.empty()) { @@ -245,7 +243,8 @@ namespace chaiscript /// \param[in] t_usepaths Vector of paths to search when attempting to "use" an included ChaiScript file ChaiScript( std::vector t_modulepaths = std::vector(), std::vector t_usepaths = std::vector()) - : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)) + : m_module_paths(std::move(t_modulepaths)), m_use_paths(std::move(t_usepaths)), + m_parser(std::make_unique>()) { if (m_module_paths.empty()) { @@ -321,18 +320,13 @@ namespace chaiscript } } - static AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false) + AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false) { - parser::ChaiScript_Parser parser; - if (parser.parse(t_input, "PARSE")) { - const auto ast = parser.optimized_ast(); - if (t_debug_print) { - parser.debug_print(ast); - } - return parser.optimized_ast(); - } else { - throw chaiscript::exception::eval_error("Unknown error while parsing"); + const auto ast = m_parser->parse(t_input, "PARSE"); + if (t_debug_print) { + m_parser->debug_print(ast); } + return ast; } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index e1597a8..526d735 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -56,7 +56,21 @@ namespace chaiscript }; } - class ChaiScript_Parser { + class ChaiScript_Parser_Base + { + public: + virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0; + virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0; + virtual ~ChaiScript_Parser_Base() = default; + ChaiScript_Parser_Base() = default; + ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default; + ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default; + ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete; + ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete; + }; + + template + class ChaiScript_Parser : public ChaiScript_Parser_Base { static std::array, detail::max_alphabet> build_alphabet() { @@ -276,24 +290,26 @@ namespace chaiscript Position m_position; - optimizer::For_Loop_Optimizer m_optimizer; + Optimizer m_optimizer; public: - ChaiScript_Parser() - : m_optimizer(optimizer::For_Loop_Optimizer()) + explicit ChaiScript_Parser(Optimizer optimizer=Optimizer()) + : m_optimizer(std::move(optimizer)) { m_match_stack.reserve(2); } - ChaiScript_Parser(const ChaiScript_Parser &) = delete; + ChaiScript_Parser(const ChaiScript_Parser &) = default; ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete; + ChaiScript_Parser(ChaiScript_Parser &&) = default; + ChaiScript_Parser &operator=(ChaiScript_Parser &&) = delete; /// test a char in an m_alphabet bool char_in_alphabet(char c, detail::Alphabet a) const { return m_alphabet[a][static_cast(c)]; } /// Prints the parsed ast_nodes as a tree - void debug_print(AST_NodePtr t, std::string prepend = "") const { + void debug_print(AST_NodePtr t, std::string prepend = "") const override { std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start().line << ", " << t->start().column << '\n'; for (unsigned int j = 0; j < t->children.size(); ++j) { debug_print(t->children[j], prepend + " "); @@ -301,10 +317,6 @@ namespace chaiscript } /// Returns the front-most AST node - AST_NodePtr ast() const { - if (m_match_stack.empty()) throw exception::eval_error("Attempted to access AST of failed parse."); - return m_match_stack.front(); - } static void optimize_returns(AST_NodePtr &p) @@ -327,10 +339,10 @@ namespace chaiscript } - AST_NodePtr optimized_ast(bool t_optimize_returns = true) { - AST_NodePtr p = ast(); - if (t_optimize_returns) { optimize_returns(p); } - return p; + AST_NodePtr ast(bool t_optimize_returns = true) { + auto ptr = m_match_stack.front(); + if (t_optimize_returns) { optimize_returns(ptr); } + return ptr; } @@ -1063,9 +1075,7 @@ namespace chaiscript const auto ev_stack_top = m_match_stack.size(); try { - ChaiScript_Parser parser; - parser.parse(eval_match, "instr eval"); - m_match_stack.push_back(parser.ast()); + m_match_stack.push_back(parse(eval_match, "instr eval")); } catch (const exception::eval_error &e) { throw exception::eval_error(e.what(), File_Position(start.line, start.col), *m_filename); } @@ -2342,8 +2352,15 @@ namespace chaiscript return retval; } + AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override + { + ChaiScript_Parser parser(*this); + + return parser.parse_internal(t_input, t_fname); + } + /// Parses the given input string, tagging parsed ast_nodes with the given m_filename. - bool parse(const std::string &t_input, std::string t_fname) { + AST_NodePtr parse_internal(const std::string &t_input, std::string t_fname) { m_position = Position(t_input.begin(), t_input.end()); m_filename = std::make_shared(std::move(t_fname)); @@ -2359,12 +2376,12 @@ namespace chaiscript throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname); } else { build_match(0); - // debug_print(ast()); - return true; } } else { - return false; + m_match_stack.push_back(chaiscript::make_shared()); } + + return ast(); } }; }