diff options
Diffstat (limited to 'src/boost/libs/spirit/example/x3/calc/calc7')
11 files changed, 507 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/ast.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/ast.hpp new file mode 100644 index 00000000..600350ec --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/ast.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_CALC7_AST_HPP) +#define BOOST_SPIRIT_X3_CALC7_AST_HPP + +#include <boost/spirit/home/x3/support/ast/variant.hpp> +#include <boost/spirit/home/x3/support/ast/position_tagged.hpp> +#include <boost/fusion/include/io.hpp> +#include <list> + +namespace client { namespace ast +{ + namespace x3 = boost::spirit::x3; + + /////////////////////////////////////////////////////////////////////////// + // The AST + /////////////////////////////////////////////////////////////////////////// + struct nil {}; + struct signed_; + struct expression; + + struct operand : x3::variant< + nil + , unsigned int + , x3::forward_ast<signed_> + , x3::forward_ast<expression> + > + { + using base_type::base_type; + using base_type::operator=; + }; + + struct signed_ + { + char sign; + operand operand_; + }; + + struct operation + { + char operator_; + operand operand_; + }; + + struct expression + { + operand first; + std::list<operation> rest; + }; + + // print function for debugging + inline std::ostream& operator<<(std::ostream& out, nil) + { + out << "nil"; + return out; + } +}} + +#endif diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/ast_adapted.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/ast_adapted.hpp new file mode 100644 index 00000000..bd56cfc7 --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/ast_adapted.hpp @@ -0,0 +1,25 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_CALC7_AST_ADAPTED_HPP) +#define BOOST_SPIRIT_X3_CALC7_AST_ADAPTED_HPP + +#include "ast.hpp" +#include <boost/fusion/include/adapt_struct.hpp> + +BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_, + sign, operand_ +) + +BOOST_FUSION_ADAPT_STRUCT(client::ast::operation, + operator_, operand_ +) + +BOOST_FUSION_ADAPT_STRUCT(client::ast::expression, + first, rest +) + +#endif diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/compiler.cpp b/src/boost/libs/spirit/example/x3/calc/calc7/compiler.cpp new file mode 100644 index 00000000..8f6d6f09 --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/compiler.cpp @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (c) 2001-2014 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) +=============================================================================*/ +#include "compiler.hpp" +#include "vm.hpp" + +namespace client +{ + void compiler::operator()(ast::nil) const + { + BOOST_ASSERT(0); + } + + void compiler::operator()(unsigned int n) const + { + code.push_back(op_int); + code.push_back(n); + } + + void compiler::operator()(ast::operation const& x) const + { + boost::apply_visitor(*this, x.operand_); + switch (x.operator_) + { + case '+': code.push_back(op_add); break; + case '-': code.push_back(op_sub); break; + case '*': code.push_back(op_mul); break; + case '/': code.push_back(op_div); break; + default: BOOST_ASSERT(0); break; + } + } + + void compiler::operator()(ast::signed_ const& x) const + { + boost::apply_visitor(*this, x.operand_); + switch (x.sign) + { + case '-': code.push_back(op_neg); break; + case '+': break; + default: BOOST_ASSERT(0); break; + } + } + + void compiler::operator()(ast::expression const& x) const + { + boost::apply_visitor(*this, x.first); + for (ast::operation const& oper : x.rest) + { + (*this)(oper); + } + } +} diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/compiler.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/compiler.hpp new file mode 100644 index 00000000..3cf0ed84 --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/compiler.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_CALC7_COMPILER_HPP) +#define BOOST_SPIRIT_X3_CALC7_COMPILER_HPP + +#include "ast.hpp" + +namespace client +{ + /////////////////////////////////////////////////////////////////////////// + // The Compiler + /////////////////////////////////////////////////////////////////////////// + struct compiler + { + typedef void result_type; + + std::vector<int>& code; + compiler(std::vector<int>& code) + : code(code) {} + + void operator()(ast::nil) const; + void operator()(unsigned int n) const; + void operator()(ast::operation const& x) const; + void operator()(ast::signed_ const& x) const; + void operator()(ast::expression const& x) const; + }; +} + +#endif diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/error_handler.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/error_handler.hpp new file mode 100644 index 00000000..9517220d --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/error_handler.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_CALC7_ERROR_HANDLER_HPP) +#define BOOST_SPIRIT_X3_CALC7_ERROR_HANDLER_HPP + +#include <boost/spirit/home/x3.hpp> +#include <iostream> + +namespace client { namespace calculator_grammar +{ + //////////////////////////////////////////////////////////////////////////// + // Our error handler + //////////////////////////////////////////////////////////////////////////// + namespace x3 = boost::spirit::x3; + + struct error_handler + { + // Our error handler + template <typename Iterator, typename Exception, typename Context> + x3::error_handler_result + on_error(Iterator&, Iterator const& last, Exception const& x, Context const& context) + { + std::cout + << "Error! Expecting: " + << x.which() + << " here: \"" + << std::string(x.where(), last) + << "\"" + << std::endl + ; + return x3::error_handler_result::fail; + } + }; +}} + +#endif diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/expression.cpp b/src/boost/libs/spirit/example/x3/calc/calc7/expression.cpp new file mode 100644 index 00000000..3dcb694e --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/expression.cpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2001-2014 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) +=============================================================================*/ +#include "expression_def.hpp" + +namespace client { namespace calculator_grammar +{ + typedef std::string::const_iterator iterator_type; + typedef x3::phrase_parse_context<x3::ascii::space_type>::type context_type; + + BOOST_SPIRIT_INSTANTIATE(expression_type, iterator_type, context_type); +}} diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/expression.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/expression.hpp new file mode 100644 index 00000000..93568eaf --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/expression.hpp @@ -0,0 +1,26 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_CALC7_EXPRESSION_HPP) +#define BOOST_SPIRIT_X3_CALC7_EXPRESSION_HPP + +#include <boost/spirit/home/x3.hpp> +#include "ast.hpp" + +namespace client +{ + namespace x3 = boost::spirit::x3; + namespace calculator_grammar + { + struct expression_class; + typedef x3::rule<expression_class, ast::expression> expression_type; + BOOST_SPIRIT_DECLARE(expression_type); + } + + calculator_grammar::expression_type expression(); +} + +#endif diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/expression_def.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/expression_def.hpp new file mode 100644 index 00000000..dc73c288 --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/expression_def.hpp @@ -0,0 +1,71 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_CALC7_EXPRESSION_DEF_HPP) +#define BOOST_SPIRIT_X3_CALC7_EXPRESSION_DEF_HPP + +#include <boost/spirit/home/x3.hpp> +#include "ast.hpp" +#include "ast_adapted.hpp" +#include "expression.hpp" +#include "error_handler.hpp" + +namespace client { namespace calculator_grammar +{ + using x3::uint_; + using x3::char_; + + struct expression_class; + struct term_class; + struct factor_class; + + typedef x3::rule<expression_class, ast::expression> expression_type; + typedef x3::rule<term_class, ast::expression> term_type; + typedef x3::rule<factor_class, ast::operand> factor_type; + + expression_type const expression = "expression"; + term_type const term = "term"; + factor_type const factor = "factor"; + + auto const expression_def = + term + >> *( (char_('+') > term) + | (char_('-') > term) + ) + ; + + auto const term_def = + factor + >> *( (char_('*') > factor) + | (char_('/') > factor) + ) + ; + + auto const factor_def = + uint_ + | '(' > expression > ')' + | (char_('-') > factor) + | (char_('+') > factor) + ; + + BOOST_SPIRIT_DEFINE( + expression + , term + , factor + ); + + struct expression_class : error_handler {}; +}} + +namespace client +{ + calculator_grammar::expression_type expression() + { + return calculator_grammar::expression; + } +} + +#endif diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/main.cpp b/src/boost/libs/spirit/example/x3/calc/calc7/main.cpp new file mode 100644 index 00000000..5f71230d --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/main.cpp @@ -0,0 +1,81 @@ +/*============================================================================= + Copyright (c) 2001-2014 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) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// Same as calc6, but this version also shows off grammar modularization. +// Here you will see how expressions is built as a modular grammars. +// +// [ JDG Sometime 2000 ] pre-boost +// [ JDG September 18, 2002 ] spirit1 +// [ JDG April 8, 2007 ] spirit2 +// [ JDG February 18, 2011 ] Pure attributes. No semantic actions. +// [ JDG April 9, 2014 ] Spirit X3 (from qi calc6) +// [ JDG May 2, 2014 ] Modular grammar using BOOST_SPIRIT_DEFINE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "ast.hpp" +#include "vm.hpp" +#include "compiler.hpp" +#include "expression.hpp" +#include "error_handler.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// Main program +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + 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 client::ast::expression ast_expression; + typedef client::compiler compiler; + + std::string str; + while (std::getline(std::cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + using boost::spirit::x3::ascii::space; + + client::vmachine mach; // Our virtual machine + std::vector<int> code; // Our VM code + auto calc = client::expression(); // grammar + + ast_expression ast; // Our program (AST) + compiler compile(code); // Compiles the program + + iterator_type iter = str.begin(); + iterator_type const end = str.end(); + bool r = phrase_parse(iter, end, calc, space, ast); + + if (r && iter == end) + { + std::cout << "-------------------------\n"; + std::cout << "Parsing succeeded\n"; + compile(ast); + mach.execute(code); + std::cout << "\nResult: " << mach.top() << std::endl; + std::cout << "-------------------------\n"; + } + else + { + std::string rest(iter, end); + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "-------------------------\n"; + } + } + + std::cout << "Bye... :-) \n\n"; + return 0; +} diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/vm.cpp b/src/boost/libs/spirit/example/x3/calc/calc7/vm.cpp new file mode 100644 index 00000000..323d7217 --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/vm.cpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2014 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) +=============================================================================*/ +#include "vm.hpp" + +namespace client +{ + 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; + } + } + } +} diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/vm.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/vm.hpp new file mode 100644 index 00000000..2836efd3 --- /dev/null +++ b/src/boost/libs/spirit/example/x3/calc/calc7/vm.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2014 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_X3_CALC7_VM_HPP) +#define BOOST_SPIRIT_X3_CALC7_VM_HPP + +#include <vector> + +namespace client +{ + /////////////////////////////////////////////////////////////////////////// + // 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; + }; + +} + +#endif |