• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2002 Juan Carlos Arevalo-Baeza
3     http://spirit.sourceforge.net/
4 
5     Use, modification and distribution is subject to the Boost Software
6     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7     http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 ///////////////////////////////////////////////////////////////////////////////
10 //
11 //  A parser for a comma separated list of numbers,
12 //  with positional error reporting
13 //  See the "Position Iterator" chapter in the User's Guide.
14 //
15 //  [ JCAB 9/28/2002 ]
16 //
17 ///////////////////////////////////////////////////////////////////////////////
18 #include <boost/spirit/include/classic_core.hpp>
19 #include <boost/spirit/include/classic_position_iterator.hpp>
20 #include <boost/spirit/include/classic_functor_parser.hpp>
21 #include <iostream>
22 #include <fstream>
23 #include <vector>
24 
25 ///////////////////////////////////////////////////////////////////////////////
26 using namespace std;
27 using namespace BOOST_SPIRIT_CLASSIC_NS;
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 //
31 //  Our error reporting parsers
32 //
33 ///////////////////////////////////////////////////////////////////////////////
operator <<(std::ostream & out,file_position const & lc)34 std::ostream& operator<<(std::ostream& out, file_position const& lc)
35 {
36     return out <<
37             "\nFile:\t" << lc.file <<
38             "\nLine:\t" << lc.line <<
39             "\nCol:\t" << lc.column << endl;
40 }
41 
42 struct error_report_parser {
43     char const* eol_msg;
44     char const* msg;
45 
error_report_parsererror_report_parser46     error_report_parser(char const* eol_msg_, char const* msg_):
47         eol_msg(eol_msg_),
48         msg    (msg_)
49     {}
50 
51     typedef nil_t result_t;
52 
53     template <typename ScannerT>
54     int
operator ()error_report_parser55     operator()(ScannerT const& scan, result_t& /*result*/) const
56     {
57         if (scan.at_end()) {
58             if (eol_msg) {
59                 file_position fpos = scan.first.get_position();
60                 cerr << fpos << eol_msg << endl;
61             }
62         } else {
63             if (msg) {
64                 file_position fpos = scan.first.get_position();
65                 cerr << fpos << msg << endl;
66             }
67         }
68 
69         return -1; // Fail.
70     }
71 
72 };
73 typedef functor_parser<error_report_parser> error_report_p;
74 
75 error_report_p
76 error_badnumber_or_eol =
77     error_report_parser(
78         "Expecting a number, but found the end of the file\n",
79         "Expecting a number, but found something else\n"
80     );
81 
82 error_report_p
83 error_badnumber =
84     error_report_parser(
85         0,
86         "Expecting a number, but found something else\n"
87     );
88 
89 error_report_p
90 error_comma =
91     error_report_parser(
92         0,
93         "Expecting a comma, but found something else\n"
94     );
95 
96 ///////////////////////////////////////////////////////////////////////////////
97 //
98 //  Our comma separated list parser
99 //
100 ///////////////////////////////////////////////////////////////////////////////
101 bool
parse_numbers(char const * filename,char const * str,vector<double> & v)102 parse_numbers(char const* filename, char const* str, vector<double>& v)
103 {
104     typedef position_iterator<char const*> iterator_t;
105     iterator_t begin(str, str + strlen(str), filename);
106     iterator_t end;
107     begin.set_tabchars(8);
108     return parse(begin, end,
109 
110         //  Begin grammar
111         (
112             (real_p[push_back_a(v)] | error_badnumber)
113          >> *(
114                 (',' | error_comma)
115              >> (real_p[push_back_a(v)] | error_badnumber_or_eol)
116             )
117         )
118         ,
119         //  End grammar
120 
121         space_p).full;
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////
125 //
126 //  Main program
127 //
128 ////////////////////////////////////////////////////////////////////////////
129 int
main(int argc,char ** argv)130 main(int argc, char **argv)
131 {
132     cout << "/////////////////////////////////////////////////////////\n\n";
133     cout << "\tAn error-reporting parser for Spirit...\n\n";
134     cout << "Parses a comma separated list of numbers from a file.\n";
135     cout << "The numbers will be inserted in a vector of numbers\n\n";
136     cout << "/////////////////////////////////////////////////////////\n\n";
137 
138     char str[65536];
139     char const* filename;
140 
141     if (argc > 1) {
142         filename = argv[1];
143         ifstream file(filename);
144         file.get(str, sizeof(str), '\0');
145     } else {
146         filename = "<cin>";
147         cin.get(str, sizeof(str), '\0');
148     }
149 
150     vector<double> v;
151     if (parse_numbers(filename, str, v))
152     {
153         cout << "-------------------------\n";
154         cout << "Parsing succeeded\n";
155         cout << str << " Parses OK: " << endl;
156 
157         for (vector<double>::size_type i = 0; i < v.size(); ++i)
158             cout << i << ": " << v[i] << endl;
159 
160         cout << "-------------------------\n";
161     }
162     else
163     {
164         cout << "-------------------------\n";
165         cout << "Parsing failed\n";
166         cout << "-------------------------\n";
167     }
168 
169     cout << "Bye... :-) \n\n";
170     return 0;
171 }
172 
173 
174