/*============================================================================= 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_MINI_C) #define BOOST_SPIRIT_MINI_C #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/include/phoenix_container.hpp> #include <boost/spirit/include/phoenix_statement.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/lexical_cast.hpp> #include <iostream> #include <fstream> #include <string> #include <vector> using boost::phoenix::function; using boost::phoenix::ref; using boost::phoenix::size; using namespace boost::spirit; using namespace boost::spirit::qi; /////////////////////////////////////////////////////////////////////////////// // 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_not, // boolean negate the top stack entry op_eq, // compare the top two stack entries for == op_neq, // compare the top two stack entries for != op_lt, // compare the top two stack entries for < op_lte, // compare the top two stack entries for <= op_gt, // compare the top two stack entries for > op_gte, // compare the top two stack entries for >= op_and, // logical and top two stack entries op_or, // logical or top two stack entries op_load, // load a variable op_store, // store a variable op_int, // push constant integer into the stack op_true, // push constant 0 into the stack op_false, // push constant 1 into the stack op_jump_if, // jump to an absolute position in the code if top stack // evaluates to false op_jump, // jump to an absolute position in the code op_stk_adj, // adjust the stack (for args and locals) op_call, // function call op_return // return from function }; class vmachine { public: vmachine(unsigned stackSize = 4096) : stack(stackSize) { } int execute( std::vector<int> const& code // the program code , std::vector<int>::const_iterator pc // program counter , std::vector<int>::iterator frame_ptr // start of arguments and locals ); std::vector<int> stack; }; /////////////////////////////////////////////////////////////////////////////// // A generic compiler that compiles 1 to 3 codes /////////////////////////////////////////////////////////////////////////////// struct function_info { int arity; int address; }; struct compile_op { template <typename A, typename B = unused_type, typename C = unused_type> struct result { typedef void type; }; compile_op(std::vector<int>& 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); } // special overload for function calls void operator()(function_info const& info, int got_nargs, bool& parse_result) const { if (got_nargs == info.arity) { code.push_back(op_call); code.push_back(info.arity); code.push_back(info.address); } else { parse_result = false; // fail the parse std::cerr << "wrong number of args" << std::endl; } } std::vector<int>& code; }; /////////////////////////////////////////////////////////////////////////////// // Our error handler /////////////////////////////////////////////////////////////////////////////// struct error_handler_ { template <typename, typename, typename> struct result { typedef void type; }; template <typename Iterator> void operator()( 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<error_handler_> const error_handler = error_handler_(); /////////////////////////////////////////////////////////////////////////////// // A functor that adds variables to our (variables) symbol-table /////////////////////////////////////////////////////////////////////////////// struct var_adder { template <typename> struct result { typedef void type; }; var_adder(symbols<char, int>& vars, int& nvars) : vars(vars), nvars(nvars) { } void operator()(std::string const& var) const { vars.add(var.begin(), var.end(), nvars++); }; symbols<char, int>& vars; int& nvars; }; /////////////////////////////////////////////////////////////////////////////// // A functor that adds functions to our (function) symbol-table /////////////////////////////////////////////////////////////////////////////// struct function_adder { template <typename, typename, typename> struct result { typedef void type; }; function_adder(symbols<char, function_info>& functions) : functions(functions) { } void operator()(std::string const& function_id, int arity, int address) const { function_info info = {arity, address}; functions.add(function_id.begin(), function_id.end(), info); }; symbols<char, function_info>& functions; }; /////////////////////////////////////////////////////////////////////////////// // A functor that resets the function-related state variables /////////////////////////////////////////////////////////////////////////////// struct function_state_reset { template <typename> struct result { typedef void type; }; function_state_reset( std::vector<int>& code , symbols<char, int>& vars , int& nvars) : code(code) , vars(vars) , nvars(nvars) { } void operator()(int address) const { code[address+1] = nvars; nvars = 0; // reset vars.clear(); // reset }; std::vector<int>& code; symbols<char, int>& vars; int& nvars; }; /////////////////////////////////////////////////////////////////////////////// // White-space and comments grammar definition /////////////////////////////////////////////////////////////////////////////// template <typename Iterator> struct white_space : grammar<Iterator> { white_space() : white_space::base_type(start) { using boost::spirit::ascii::char_; start = space // tab/space/cr/lf | "/*" >> *(char_ - "*/") >> "*/" // C-style comments ; } rule<Iterator> start; }; /////////////////////////////////////////////////////////////////////////////// // Our expression grammar and compiler /////////////////////////////////////////////////////////////////////////////// template <typename Iterator> struct expression : grammar<Iterator, white_space<Iterator> > { expression( std::vector<int>& code , symbols<char, int>& vars , symbols<char, function_info>& functions); typedef white_space<Iterator> white_space_; rule<Iterator, white_space_> expr, equality_expr, relational_expr , logical_expr, additive_expr, multiplicative_expr , unary_expr, primary_expr, variable ; rule<Iterator, locals<function_info, int>, white_space_> function_call; std::vector<int>& code; symbols<char, int>& vars; symbols<char, function_info>& functions; function<compile_op> op; }; /////////////////////////////////////////////////////////////////////////////// // Our statement grammar and compiler /////////////////////////////////////////////////////////////////////////////// template <typename Iterator> struct statement : grammar<Iterator, white_space<Iterator> > { statement(std::vector<int>& code, symbols<char, function_info>& functions); typedef white_space<Iterator> white_space_; std::vector<int>& code; symbols<char, int> vars; symbols<char, function_info>& functions; int nvars; bool has_return; expression<Iterator> expr; rule<Iterator, white_space_> statement_, statement_list, var_decl, compound_statement , return_statement; rule<Iterator, locals<int>, white_space_> if_statement; rule<Iterator, locals<int, int>, white_space_> while_statement; rule<Iterator, std::string(), white_space_> identifier; rule<Iterator, int(), white_space_> var_ref; rule<Iterator, locals<int>, white_space_> assignment; rule<Iterator, void(int), white_space_> assignment_rhs; function<var_adder> add_var; function<compile_op> op; }; /////////////////////////////////////////////////////////////////////////////// // Our program grammar and compiler /////////////////////////////////////////////////////////////////////////////// template <typename Iterator> struct program : grammar<Iterator, white_space<Iterator> > { program(std::vector<int>& code); typedef white_space<Iterator> white_space_; std::vector<int>& code; rule<Iterator, std::string(), white_space_> identifier; rule<Iterator, white_space_> start; typedef locals< std::string // function name , int // address > function_locals; symbols<char, function_info> functions; statement<Iterator> statement_; rule<Iterator, function_locals, white_space_> function; boost::phoenix::function<function_adder> add_function; boost::phoenix::function<function_state_reset> state_reset; boost::phoenix::function<compile_op> op; }; #endif