]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/context/example/v2/parser.cpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / context / example / v2 / parser.cpp
CommitLineData
7c673cae
FG
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
16namespace ctx = boost::context;
17
18/*
19 * grammar:
20 * P ---> E '\0'
21 * E ---> T {('+'|'-') T}
22 * T ---> S {('*'|'/') S}
23 * S ---> digit | '(' E ')'
24 */
25class Parser{
26 char next;
27 std::istream& is;
28 std::function<void(char)> cb;
29
30 char pull(){
31 return std::char_traits<char>::to_char_type(is.get());
32 }
33
34 void scan(){
35 do{
36 next=pull();
37 }
38 while(isspace(next));
39 }
40
41public:
42 Parser(std::istream& is_,std::function<void(char)> cb_) :
43 next(), is(is_), cb(cb_)
44 {}
45
46 void run() {
47 scan();
48 E();
49 }
50
51private:
52 void E(){
53 T();
54 while (next=='+'||next=='-'){
55 cb(next);
56 scan();
57 T();
58 }
59 }
60
61 void T(){
62 S();
63 while (next=='*'||next=='/'){
64 cb(next);
65 scan();
66 S();
67 }
68 }
69
70 void S(){
71 if (isdigit(next)){
72 cb(next);
73 scan();
74 }
75 else if(next=='('){
76 cb(next);
77 scan();
78 E();
79 if (next==')'){
80 cb(next);
81 scan();
82 }else{
83 throw std::runtime_error("parsing failed");
84 }
85 }
86 else{
87 throw std::runtime_error("parsing failed");
88 }
89 }
90};
91
92int main() {
93 try {
94 std::istringstream is("1+1");
95 bool done=false;
96 std::exception_ptr except;
97
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
102 Parser p( is,
103 [&sink](char ch){
104 // resume main execution context
105 auto result = sink(ch);
106 sink = std::move(std::get<0>(result));
107 });
108 try {
109 // start recursive parsing
110 p.run();
111 } catch (...) {
112 // store other exceptions in exception-pointer
113 except = std::current_exception();
114 }
115 // set termination flag
116 done=true;
117 // resume main execution context
118 return sink;
119 });
120
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);
126 if ( except) {
127 std::rethrow_exception(except);
128 }
129 while( ! done) {
130 printf("Parsed: %c\n",c);
131 std::tie(source,c) = source('\0');
132 if (except) {
133 std::rethrow_exception(except);
134 }
135 }
136
137 std::cout << "main: done" << std::endl;
138
139 return EXIT_SUCCESS;
140 } catch ( std::exception const& e) {
141 std::cerr << "exception: " << e.what() << std::endl;
142 }
143 return EXIT_FAILURE;
144}