2 // Copyright Oliver Kowalke 2014.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
14 #include <boost/context/all.hpp>
16 namespace ctx = boost::context;
21 * E ---> T {('+'|'-') T}
22 * T ---> S {('*'|'/') S}
23 * S ---> digit | '(' E ')'
28 std::function<void(char)> cb;
31 return std::char_traits<char>::to_char_type(is.get());
42 Parser(std::istream& is_,std::function<void(char)> cb_) :
43 next(), is(is_), cb(cb_)
54 while (next=='+'||next=='-'){
63 while (next=='*'||next=='/'){
83 throw std::runtime_error("parsing failed");
87 throw std::runtime_error("parsing failed");
94 std::istringstream is("1+1");
96 std::exception_ptr except;
98 // execute parser in new execution context
99 boost::context::execution_context<char> source(
100 [&is,&done,&except](ctx::execution_context<char> && sink,char){
101 // create parser with callback function
104 // resume main execution context
105 auto result = sink(ch);
106 sink = std::move(std::get<0>(result));
109 // start recursive parsing
112 // store other exceptions in exception-pointer
113 except = std::current_exception();
115 // set termination flag
117 // resume main execution context
118 return std::move( sink);
121 // user-code pulls parsed data from parser
122 // invert control flow
123 auto result = source('\0');
124 source = std::move(std::get<0>(result));
125 char c = std::get<1>(result);
127 std::rethrow_exception(except);
130 printf("Parsed: %c\n",c);
131 std::tie(source,c) = source('\0');
133 std::rethrow_exception(except);
137 std::cout << "main: done" << std::endl;
140 } catch ( std::exception const& e) {
141 std::cerr << "exception: " << e.what() << std::endl;