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 <cctype>
8#include <cstdio>
9#include <exception>
10#include <functional>
11#include <iostream>
12#include <sstream>
13
14#include <boost/coroutine2/all.hpp>
15
16class parser_error : public std::runtime_error {
17public:
18 parser_error() :
19 std::runtime_error("parsing failed") {
20 }
21};
22
23/*
24 * grammar:
25 * P ---> E '\0'
26 * E ---> T {('+'|'-') T}
27 * T ---> S {('*'|'/') S}
28 * S ---> digit | '(' E ')'
29 */
30class Parser{
31 char next;
32 std::istream& is;
33 std::function<void(char)> cb;
34
35 char pull(){
36 return std::char_traits<char>::to_char_type(c: is.get());
37 }
38
39 void scan(){
40 do{
41 next=pull();
42 }
43 while(isspace(next));
44 }
45
46public:
47 Parser(std::istream& is_,std::function<void(char)> cb_) :
48 next(), is(is_), cb(cb_)
49 {}
50
51 void run() {
52 scan();
53 E();
54 }
55
56private:
57 void E(){
58 T();
59 while (next=='+'||next=='-'){
60 cb(next);
61 scan();
62 T();
63 }
64 }
65
66 void T(){
67 S();
68 while (next=='*'||next=='/'){
69 cb(next);
70 scan();
71 S();
72 }
73 }
74
75 void S(){
76 if (std::isdigit(next)){
77 cb(next);
78 scan();
79 }
80 else if(next=='('){
81 cb(next);
82 scan();
83 E();
84 if (next==')'){
85 cb(next);
86 scan();
87 }else{
88 throw parser_error();
89 }
90 }
91 else{
92 throw parser_error();
93 }
94 }
95};
96
97typedef boost::coroutines2::coroutine< char > coro_t;
98
99int main() {
100 try {
101 std::istringstream is("1+1");
102 // invert control flow
103 coro_t::pull_type seq(
104 [&is]( coro_t::push_type & yield) {
105 Parser p( is,
106 [&yield](char ch){
107 yield(ch);
108 });
109 p.run();
110 });
111 // user-code pulls parsed data from parser
112 for(char c:seq){
113 printf(format: "Parsed: %c\n",c);
114 }
115 std::cout << "\nDone" << std::endl;
116 return EXIT_SUCCESS;
117 } catch ( std::exception const& ex) {
118 std::cerr << "exception: " << ex.what() << std::endl;
119 }
120 return EXIT_FAILURE;
121}
122
123

source code of boost/libs/coroutine2/example/parser.cpp