// Copyright Oliver Kowalke 2014. // 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 #include #include #include #include #include #include "coroutine.hpp" /* * grammar: * P ---> E '\0' * E ---> T {('+'|'-') T} * T ---> S {('*'|'/') S} * S ---> digit | '(' E ')' */ class Parser{ char next; std::istream& is; std::function cb; char pull(){ return std::char_traits::to_char_type(is.get()); } void scan(){ do{ next=pull(); } while(isspace(next)); } public: Parser(std::istream& is_,std::function cb_) : next(), is(is_), cb(cb_) {} void run() { scan(); E(); } private: void E(){ T(); while (next=='+'||next=='-'){ cb(next); scan(); T(); } } void T(){ S(); while (next=='*'||next=='/'){ cb(next); scan(); S(); } } void S(){ if (std::isdigit(next)){ cb(next); scan(); } else if(next=='('){ cb(next); scan(); E(); if (next==')'){ cb(next); scan(); }else{ exit(2); } } else{ exit(3); } } }; typedef coroutine coro_t; void foo() { std::istringstream is("1+1"); // invert control flow coro_t::pull_type seq( boost::context::fixedsize(), [&is]( coro_t::push_type & yield) { Parser p(is,[&yield](char ch){ yield(ch); }); p.run(); }); // user-code pulls parsed data from parser while(seq){ printf("Parsed: %c\n",seq.get()); seq(); } } int main() { std::thread t1( foo); std::thread t2( foo); t1.join(); t2.join(); }