-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathqi_test_1.C
82 lines (72 loc) · 2.75 KB
/
qi_test_1.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Copyright (c) 2010 Peter Schueller
//
// 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 <vector>
#include <istream>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_multi_pass.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace classic = boost::spirit::classic;
// parse list of doubles from input stream
// throw exception (perhaps including filename) on errors
std::vector<double> parse(std::istream& input, const std::string& filename);
// main function
int main(int, char**)
{
try
{
for ( auto &&r : parse(std::cin, "STDIN"))
std::cout << r << std::endl;
}
catch(const std::exception& e)
{
std::cerr << "Exception: " << e.what() << std::endl;
return -1;
}
return 0;
}
// implementation
std::vector<double> parse(std::istream& input, const std::string& filename)
{
// iterate over stream input
typedef std::istreambuf_iterator<char> base_iterator_type;
base_iterator_type in_begin(input);
// convert input iterator to forward iterator, usable by spirit parser
typedef boost::spirit::multi_pass<base_iterator_type> forward_iterator_type;
forward_iterator_type fwd_begin = boost::spirit::make_default_multi_pass(in_begin);
forward_iterator_type fwd_end;
// wrap forward iterator with position iterator, to record the position
typedef classic::position_iterator2<forward_iterator_type> pos_iterator_type;
pos_iterator_type position_begin(fwd_begin, fwd_end, filename);
pos_iterator_type position_end;
// prepare output
std::vector<double> output;
// parse
try
{
qi::phrase_parse(
position_begin, position_end, // iterators over input
qi::double_ > *(',' > qi::double_) >> qi::eoi, // recognize list of doubles
ascii::space | '#' >> *(ascii::char_ - qi::eol) >> qi::eol, // comment skipper
output); // doubles are stored into this object
}
catch(const qi::expectation_failure<pos_iterator_type>& e)
{
const classic::file_position_base<std::string>& pos = e.first.get_position();
std::stringstream msg;
msg <<
"parse error at file " << pos.file <<
" line " << pos.line << " column " << pos.column << std::endl <<
"'" << e.first.get_currentline() << "'" << std::endl <<
std::setw(pos.column) << " " << "^- here";
throw std::runtime_error(msg.str());
}
// return result
return output;
}