calc5.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 229 行
CPP
229 行
/*============================================================================= Copyright (c) 2001-2007 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)=============================================================================*//////////////////////////////////////////////////////////////////////////////////// Yet another calculator example! This time, we will compile to a simple// virtual machine. This is actually one of the very first Spirit example// circa 2000. Now, it's ported to Spirit2.//// [ JDG Sometime 2000 ] pre-boost// [ JDG September 18, 2002 ] spirit1// [ JDG April 8, 2007 ] spirit2/////////////////////////////////////////////////////////////////////////////////#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_object.hpp>#include <boost/spirit/include/phoenix_operator.hpp>#include <iostream>#include <string>#include <vector>using namespace boost::spirit;using namespace boost::spirit::qi;using namespace boost::spirit::ascii;using namespace boost::spirit::arg_names;using boost::phoenix::ref;using boost::phoenix::push_back;using boost::phoenix::val;using boost::phoenix::construct;///////////////////////////////////////////////////////////////////////////////// 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_int, // push constant integer into the stack};class vmachine{public: vmachine(unsigned stackSize = 4096) : stack(stackSize) , stack_ptr(stack.begin()) { } int top() const { return stack_ptr[-1]; }; void execute(std::vector<int> const& code);private: std::vector<int> stack; std::vector<int>::iterator stack_ptr;};void vmachine::execute(std::vector<int> const& code){ std::vector<int>::const_iterator pc = code.begin(); stack_ptr = stack.begin(); while (pc != code.end()) { switch (*pc++) { case op_neg: stack_ptr[-1] = -stack_ptr[-1]; break; case op_add: --stack_ptr; stack_ptr[-1] += stack_ptr[0]; break; case op_sub: --stack_ptr; stack_ptr[-1] -= stack_ptr[0]; break; case op_mul: --stack_ptr; stack_ptr[-1] *= stack_ptr[0]; break; case op_div: --stack_ptr; stack_ptr[-1] /= stack_ptr[0]; break; case op_int: *stack_ptr++ = *pc++; break; } }}///////////////////////////////////////////////////////////////////////////////// Our calculator grammar and compiler///////////////////////////////////////////////////////////////////////////////template <typename Iterator>struct calculator : grammar<Iterator, space_type>{ calculator(std::vector<int>& code) : calculator::base_type(expression) , code(code) { expression = term >> *( ('+' > term [push_back(ref(code), op_add)]) | ('-' > term [push_back(ref(code), op_sub)]) ) ; term = factor >> *( ('*' > factor [push_back(ref(code), op_mul)]) | ('/' > factor [push_back(ref(code), op_div)]) ) ; factor = uint_ [ push_back(ref(code), op_int), push_back(ref(code), _1) ] | '(' > expression > ')' | ('-' > factor [push_back(ref(code), op_neg)]) | ('+' > factor) ; expression.name("expression"); term.name("term"); factor.name("factor"); on_error<fail> ( expression , std::cout << val("Error! Expecting ") << _4 // what failed? << val(" here: \"") << construct<std::string>(_3, _2) // iterators to error-pos, end << val("\"") << std::endl ); } rule<Iterator, space_type> expression, term, factor; std::vector<int>& code;};template <typename Grammar>bool compile(Grammar const& calc, std::string const& expr){ std::string::const_iterator iter = expr.begin(); std::string::const_iterator end = expr.end(); bool r = phrase_parse(iter, end, calc, space); if (r && iter == end) { std::cout << "-------------------------\n"; std::cout << "Parsing succeeded\n"; std::cout << "-------------------------\n"; return true; } else { std::cout << "-------------------------\n"; std::cout << "Parsing failed\n"; std::cout << "-------------------------\n"; return false; }}///////////////////////////////////////////////////////////////////////////////// Main program///////////////////////////////////////////////////////////////////////////////intmain(){ std::cout << "/////////////////////////////////////////////////////////\n\n"; std::cout << "Expression parser...\n\n"; std::cout << "/////////////////////////////////////////////////////////\n\n"; std::cout << "Type an expression...or [q or Q] to quit\n\n"; typedef std::string::const_iterator iterator_type; typedef calculator<iterator_type> calculator; vmachine mach; // Our virtual machine std::vector<int> code; // Our VM code calculator calc(code); // Our grammar std::string str; while (std::getline(std::cin, str)) { if (str.empty() || str[0] == 'q' || str[0] == 'Q') break; code.clear(); if (::compile(calc, str)) { mach.execute(code); std::cout << "\n\nresult = " << mach.top() << std::endl; std::cout << "-------------------------\n\n"; } } std::cout << "Bye... :-) \n\n"; return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?