summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/context/example/fiber/parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/context/example/fiber/parser.cpp')
-rw-r--r--src/boost/libs/context/example/fiber/parser.cpp127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/boost/libs/context/example/fiber/parser.cpp b/src/boost/libs/context/example/fiber/parser.cpp
new file mode 100644
index 000000000..fb1121b5c
--- /dev/null
+++ b/src/boost/libs/context/example/fiber/parser.cpp
@@ -0,0 +1,127 @@
+
+// Copyright Oliver Kowalke 2016.
+// 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 <cstdio>
+#include <cstdlib>
+#include <exception>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+
+#include <boost/context/fiber.hpp>
+
+namespace ctx = boost::context;
+
+/*
+ * grammar:
+ * P ---> E '\0'
+ * E ---> T {('+'|'-') T}
+ * T ---> S {('*'|'/') S}
+ * S ---> digit | '(' E ')'
+ */
+class Parser{
+ char next;
+ std::istream& is;
+ std::function<void(char)> cb;
+
+ char pull(){
+ return std::char_traits<char>::to_char_type(is.get());
+ }
+
+ void scan(){
+ do{
+ next=pull();
+ }
+ while(isspace(next));
+ }
+
+public:
+ Parser(std::istream& is_,std::function<void(char)> 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 (isdigit(next)){
+ cb(next);
+ scan();
+ }
+ else if(next=='('){
+ cb(next);
+ scan();
+ E();
+ if (next==')'){
+ cb(next);
+ scan();
+ }else{
+ throw std::runtime_error("parsing failed");
+ }
+ }
+ else{
+ throw std::runtime_error("parsing failed");
+ }
+ }
+};
+
+int main() {
+ try {
+ std::istringstream is("1+1");
+ // user-code pulls parsed data from parser
+ // invert control flow
+ char c;
+ bool done = false;
+ // execute parser in new execution context
+ ctx::fiber source{[&is,&c,&done](ctx::fiber && sink){
+ // create parser with callback function
+ Parser p( is,
+ [&sink,&c](char c_){
+ // resume main execution context
+ c = c_;
+ sink = std::move( sink).resume();
+ });
+ // start recursive parsing
+ p.run();
+ // signal termination
+ done = true;
+ // resume main execution context
+ return std::move(sink);
+ }};
+ source = std::move( source).resume();
+ while(!done){
+ printf("Parsed: %c\n",c);
+ source = std::move( source).resume();
+ }
+ std::cout << "main: done" << std::endl;
+ return EXIT_SUCCESS;
+ } catch (std::exception const& e) {
+ std::cerr << "exception: " << e.what() << std::endl;
+ }
+ return EXIT_FAILURE;
+}