]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/context/example/v1/parser.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / context / example / v1 / parser.cpp
1
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)
6
7 #include <cstdlib>
8 #include <exception>
9 #include <functional>
10 #include <iostream>
11 #include <memory>
12 #include <sstream>
13
14 #include <boost/context/all.hpp>
15
16 /*
17 * grammar:
18 * P ---> E '\0'
19 * E ---> T {('+'|'-') T}
20 * T ---> S {('*'|'/') S}
21 * S ---> digit | '(' E ')'
22 */
23 class Parser{
24 char next;
25 std::istream& is;
26 std::function<void(char)> cb;
27
28 char pull(){
29 return std::char_traits<char>::to_char_type(is.get());
30 }
31
32 void scan(){
33 do{
34 next=pull();
35 }
36 while(isspace(next));
37 }
38
39 public:
40 Parser(std::istream& is_,std::function<void(char)> cb_) :
41 next(), is(is_), cb(cb_)
42 {}
43
44 void run() {
45 scan();
46 E();
47 }
48
49 private:
50 void E(){
51 T();
52 while (next=='+'||next=='-'){
53 cb(next);
54 scan();
55 T();
56 }
57 }
58
59 void T(){
60 S();
61 while (next=='*'||next=='/'){
62 cb(next);
63 scan();
64 S();
65 }
66 }
67
68 void S(){
69 if (isdigit(next)){
70 cb(next);
71 scan();
72 }
73 else if(next=='('){
74 cb(next);
75 scan();
76 E();
77 if (next==')'){
78 cb(next);
79 scan();
80 }else{
81 throw std::runtime_error("parsing failed");
82 }
83 }
84 else{
85 throw std::runtime_error("parsing failed");
86 }
87 }
88 };
89
90 int main() {
91 try {
92 std::istringstream is("1+1");
93 bool done=false;
94 std::exception_ptr except;
95
96 // create handle to main execution context
97 auto sink(boost::context::execution_context::current());
98 // execute parser in new execution context
99 boost::context::execution_context source(
100 [&sink,&is,&done,&except](void*){
101 // create parser with callback function
102 Parser p(is,
103 [&sink](char ch){
104 // resume main execution context
105 sink(&ch);
106 });
107 try {
108 // start recursive parsing
109 p.run();
110 } catch (...) {
111 // store other exceptions in exception-pointer
112 except = std::current_exception();
113 }
114 // set termination flag
115 done=true;
116 // resume main execution context
117 sink();
118 });
119
120 // user-code pulls parsed data from parser
121 // invert control flow
122 void* vp = source();
123 if (except) {
124 std::rethrow_exception(except);
125 }
126 while( ! done) {
127 printf("Parsed: %c\n",* static_cast<char*>(vp));
128 vp = source();
129 if (except) {
130 std::rethrow_exception(except);
131 }
132 }
133 std::cout << "main: done" << std::endl;
134 return EXIT_SUCCESS;
135 } catch ( std::exception const& e) {
136 std::cerr << "exception: " << e.what() << std::endl;
137 }
138 return EXIT_FAILURE;
139 }