/*============================================================================= Copyright (c) 2001-2010 Joel de Guzman Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #if !defined(BOOST_SPIRIT_CALC6) #define BOOST_SPIRIT_CALC6 #include #include #include #include #include #include #include #include #include using boost::phoenix::function; using boost::phoenix::ref; using boost::spirit::qi::unused_type; namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; /////////////////////////////////////////////////////////////////////////////// // The Virtual Machine /////////////////////////////////////////////////////////////////////////////// enum byte_code { op_neg, // negate the top stack entry op_add, // add top two stack entries op_sub, // subtract top two stack entries op_mul, // multiply top two stack entries op_div, // divide top two stack entries op_load, // load a variable op_store, // store a variable op_int, // push constant integer into the stack }; class vmachine { public: vmachine(unsigned stackSize = 4096) : stack(stackSize) , stack_ptr(stack.begin()) { } std::vector const& get_stack() const { return stack; }; void execute(std::vector const& code, int nvars); private: std::vector stack; std::vector::iterator stack_ptr; }; /////////////////////////////////////////////////////////////////////////////// // A generic compiler that compiles 1 to 3 codes /////////////////////////////////////////////////////////////////////////////// struct compile_op { template struct result { typedef void type; }; compile_op(std::vector& code) : code(code) { } void operator()(int a) const { code.push_back(a); } void operator()(int a, int b) const { code.push_back(a); code.push_back(b); } void operator()(int a, int b, int c) const { code.push_back(a); code.push_back(b); code.push_back(c); } std::vector& code; }; /////////////////////////////////////////////////////////////////////////////// // Our error handler /////////////////////////////////////////////////////////////////////////////// struct error_handler_ { template struct result { typedef void type; }; template void operator()( qi::info const& what , Iterator err_pos, Iterator last) const { std::cout << "Error! Expecting " << what // what failed? << " here: \"" << std::string(err_pos, last) // iterators to error-pos, end << "\"" << std::endl ; } }; function const error_handler = error_handler_(); /////////////////////////////////////////////////////////////////////////////// // Our expression grammar and compiler /////////////////////////////////////////////////////////////////////////////// template struct expression : qi::grammar { expression(std::vector& code, qi::symbols& vars); qi::rule expr, additive_expr, multiplicative_expr , unary_expr, primary_expr, variable; std::vector& code; qi::symbols& vars; function op; }; /////////////////////////////////////////////////////////////////////////////// // Our statement grammar and compiler /////////////////////////////////////////////////////////////////////////////// struct var_adder { template struct result { typedef void type; }; var_adder(qi::symbols& vars) : vars(vars) { } void operator()(std::string const& var, int& nvars) const { vars.add(var.begin(), var.end(), nvars++); }; qi::symbols& vars; }; template struct statement : qi::grammar { statement(std::vector& code); std::vector& code; qi::symbols vars; int nvars; expression expr; qi::rule start, var_decl; qi::rule identifier; qi::rule var_ref; qi::rule, ascii::space_type> assignment; qi::rule assignment_rhs; function add_var; function op; }; #endif