1*0a6a1f1dSLionel Sambuc //
2*0a6a1f1dSLionel Sambuc // Automated Testing Framework (atf)
3*0a6a1f1dSLionel Sambuc //
4*0a6a1f1dSLionel Sambuc // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*0a6a1f1dSLionel Sambuc // All rights reserved.
6*0a6a1f1dSLionel Sambuc //
7*0a6a1f1dSLionel Sambuc // Redistribution and use in source and binary forms, with or without
8*0a6a1f1dSLionel Sambuc // modification, are permitted provided that the following conditions
9*0a6a1f1dSLionel Sambuc // are met:
10*0a6a1f1dSLionel Sambuc // 1. Redistributions of source code must retain the above copyright
11*0a6a1f1dSLionel Sambuc // notice, this list of conditions and the following disclaimer.
12*0a6a1f1dSLionel Sambuc // 2. Redistributions in binary form must reproduce the above copyright
13*0a6a1f1dSLionel Sambuc // notice, this list of conditions and the following disclaimer in the
14*0a6a1f1dSLionel Sambuc // documentation and/or other materials provided with the distribution.
15*0a6a1f1dSLionel Sambuc //
16*0a6a1f1dSLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*0a6a1f1dSLionel Sambuc // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*0a6a1f1dSLionel Sambuc // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*0a6a1f1dSLionel Sambuc // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*0a6a1f1dSLionel Sambuc // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*0a6a1f1dSLionel Sambuc // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*0a6a1f1dSLionel Sambuc // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*0a6a1f1dSLionel Sambuc // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*0a6a1f1dSLionel Sambuc // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*0a6a1f1dSLionel Sambuc // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*0a6a1f1dSLionel Sambuc // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*0a6a1f1dSLionel Sambuc // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*0a6a1f1dSLionel Sambuc //
29*0a6a1f1dSLionel Sambuc
30*0a6a1f1dSLionel Sambuc #if !defined(TOOLS_PARSER_HPP)
31*0a6a1f1dSLionel Sambuc #define TOOLS_PARSER_HPP
32*0a6a1f1dSLionel Sambuc
33*0a6a1f1dSLionel Sambuc #include <istream>
34*0a6a1f1dSLionel Sambuc #include <map>
35*0a6a1f1dSLionel Sambuc #include <ostream>
36*0a6a1f1dSLionel Sambuc #include <stdexcept>
37*0a6a1f1dSLionel Sambuc #include <string>
38*0a6a1f1dSLionel Sambuc #include <utility>
39*0a6a1f1dSLionel Sambuc #include <vector>
40*0a6a1f1dSLionel Sambuc
41*0a6a1f1dSLionel Sambuc namespace tools {
42*0a6a1f1dSLionel Sambuc namespace parser {
43*0a6a1f1dSLionel Sambuc
44*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
45*0a6a1f1dSLionel Sambuc // The "parse_error" class.
46*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
47*0a6a1f1dSLionel Sambuc
48*0a6a1f1dSLionel Sambuc class parse_error : public std::runtime_error,
49*0a6a1f1dSLionel Sambuc public std::pair< size_t, std::string > {
50*0a6a1f1dSLionel Sambuc mutable std::string m_msg;
51*0a6a1f1dSLionel Sambuc
52*0a6a1f1dSLionel Sambuc public:
53*0a6a1f1dSLionel Sambuc parse_error(size_t, std::string);
54*0a6a1f1dSLionel Sambuc ~parse_error(void) throw();
55*0a6a1f1dSLionel Sambuc
56*0a6a1f1dSLionel Sambuc const char* what(void) const throw();
57*0a6a1f1dSLionel Sambuc
58*0a6a1f1dSLionel Sambuc operator std::string(void) const;
59*0a6a1f1dSLionel Sambuc };
60*0a6a1f1dSLionel Sambuc
61*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
62*0a6a1f1dSLionel Sambuc // The "parse_errors" class.
63*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
64*0a6a1f1dSLionel Sambuc
65*0a6a1f1dSLionel Sambuc class parse_errors : public std::runtime_error,
66*0a6a1f1dSLionel Sambuc public std::vector< parse_error > {
67*0a6a1f1dSLionel Sambuc std::vector< parse_error > m_errors;
68*0a6a1f1dSLionel Sambuc mutable std::string m_msg;
69*0a6a1f1dSLionel Sambuc
70*0a6a1f1dSLionel Sambuc public:
71*0a6a1f1dSLionel Sambuc parse_errors(void);
72*0a6a1f1dSLionel Sambuc ~parse_errors(void) throw();
73*0a6a1f1dSLionel Sambuc
74*0a6a1f1dSLionel Sambuc const char* what(void) const throw();
75*0a6a1f1dSLionel Sambuc };
76*0a6a1f1dSLionel Sambuc
77*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
78*0a6a1f1dSLionel Sambuc // The "format_error" class.
79*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
80*0a6a1f1dSLionel Sambuc
81*0a6a1f1dSLionel Sambuc class format_error : public std::runtime_error {
82*0a6a1f1dSLionel Sambuc public:
83*0a6a1f1dSLionel Sambuc format_error(const std::string&);
84*0a6a1f1dSLionel Sambuc };
85*0a6a1f1dSLionel Sambuc
86*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
87*0a6a1f1dSLionel Sambuc // The "token" class.
88*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
89*0a6a1f1dSLionel Sambuc
90*0a6a1f1dSLionel Sambuc typedef int token_type;
91*0a6a1f1dSLionel Sambuc
92*0a6a1f1dSLionel Sambuc //!
93*0a6a1f1dSLionel Sambuc //! \brief Representation of a read token.
94*0a6a1f1dSLionel Sambuc //!
95*0a6a1f1dSLionel Sambuc //! A pair that contains the information of a token read from a stream.
96*0a6a1f1dSLionel Sambuc //! It contains the token's type and its associated data, if any.
97*0a6a1f1dSLionel Sambuc //!
98*0a6a1f1dSLionel Sambuc struct token {
99*0a6a1f1dSLionel Sambuc bool m_inited;
100*0a6a1f1dSLionel Sambuc size_t m_line;
101*0a6a1f1dSLionel Sambuc token_type m_type;
102*0a6a1f1dSLionel Sambuc std::string m_text;
103*0a6a1f1dSLionel Sambuc
104*0a6a1f1dSLionel Sambuc public:
105*0a6a1f1dSLionel Sambuc token(void);
106*0a6a1f1dSLionel Sambuc token(size_t, const token_type&, const std::string& = "");
107*0a6a1f1dSLionel Sambuc
108*0a6a1f1dSLionel Sambuc size_t lineno(void) const;
109*0a6a1f1dSLionel Sambuc const token_type& type(void) const;
110*0a6a1f1dSLionel Sambuc const std::string& text(void) const;
111*0a6a1f1dSLionel Sambuc
112*0a6a1f1dSLionel Sambuc operator bool(void) const;
113*0a6a1f1dSLionel Sambuc bool operator!(void) const;
114*0a6a1f1dSLionel Sambuc };
115*0a6a1f1dSLionel Sambuc
116*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
117*0a6a1f1dSLionel Sambuc // The "tokenizer" class.
118*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
119*0a6a1f1dSLionel Sambuc
120*0a6a1f1dSLionel Sambuc //!
121*0a6a1f1dSLionel Sambuc //! \brief A stream tokenizer.
122*0a6a1f1dSLionel Sambuc //!
123*0a6a1f1dSLionel Sambuc //! This template implements an extremely simple, line-oriented stream
124*0a6a1f1dSLionel Sambuc //! tokenizer. It is only able to recognize one character-long delimiters,
125*0a6a1f1dSLionel Sambuc //! random-length keywords, skip whitespace and, anything that does not
126*0a6a1f1dSLionel Sambuc //! match these rules is supposed to be a word.
127*0a6a1f1dSLionel Sambuc //!
128*0a6a1f1dSLionel Sambuc //! Parameter IS: The input stream's type.
129*0a6a1f1dSLionel Sambuc //!
130*0a6a1f1dSLionel Sambuc template< class IS >
131*0a6a1f1dSLionel Sambuc class tokenizer {
132*0a6a1f1dSLionel Sambuc IS& m_is;
133*0a6a1f1dSLionel Sambuc size_t m_lineno;
134*0a6a1f1dSLionel Sambuc token m_la;
135*0a6a1f1dSLionel Sambuc
136*0a6a1f1dSLionel Sambuc bool m_skipws;
137*0a6a1f1dSLionel Sambuc token_type m_eof_type, m_nl_type, m_text_type;
138*0a6a1f1dSLionel Sambuc
139*0a6a1f1dSLionel Sambuc std::map< char, token_type > m_delims_map;
140*0a6a1f1dSLionel Sambuc std::string m_delims_str;
141*0a6a1f1dSLionel Sambuc
142*0a6a1f1dSLionel Sambuc char m_quotech;
143*0a6a1f1dSLionel Sambuc token_type m_quotetype;
144*0a6a1f1dSLionel Sambuc
145*0a6a1f1dSLionel Sambuc std::map< std::string, token_type > m_keywords_map;
146*0a6a1f1dSLionel Sambuc
147*0a6a1f1dSLionel Sambuc token_type alloc_type(void);
148*0a6a1f1dSLionel Sambuc
149*0a6a1f1dSLionel Sambuc template< class TKZ >
150*0a6a1f1dSLionel Sambuc friend
151*0a6a1f1dSLionel Sambuc class parser;
152*0a6a1f1dSLionel Sambuc
153*0a6a1f1dSLionel Sambuc public:
154*0a6a1f1dSLionel Sambuc tokenizer(IS&, bool, const token_type&, const token_type&,
155*0a6a1f1dSLionel Sambuc const token_type&, size_t = 1);
156*0a6a1f1dSLionel Sambuc
157*0a6a1f1dSLionel Sambuc size_t lineno(void) const;
158*0a6a1f1dSLionel Sambuc
159*0a6a1f1dSLionel Sambuc void add_delim(char, const token_type&);
160*0a6a1f1dSLionel Sambuc void add_keyword(const std::string&, const token_type&);
161*0a6a1f1dSLionel Sambuc void add_quote(char, const token_type&);
162*0a6a1f1dSLionel Sambuc
163*0a6a1f1dSLionel Sambuc token next(void);
164*0a6a1f1dSLionel Sambuc std::string rest_of_line(void);
165*0a6a1f1dSLionel Sambuc };
166*0a6a1f1dSLionel Sambuc
167*0a6a1f1dSLionel Sambuc template< class IS >
tokenizer(IS & p_is,bool p_skipws,const token_type & p_eof_type,const token_type & p_nl_type,const token_type & p_text_type,size_t p_lineno)168*0a6a1f1dSLionel Sambuc tokenizer< IS >::tokenizer(IS& p_is,
169*0a6a1f1dSLionel Sambuc bool p_skipws,
170*0a6a1f1dSLionel Sambuc const token_type& p_eof_type,
171*0a6a1f1dSLionel Sambuc const token_type& p_nl_type,
172*0a6a1f1dSLionel Sambuc const token_type& p_text_type,
173*0a6a1f1dSLionel Sambuc size_t p_lineno) :
174*0a6a1f1dSLionel Sambuc m_is(p_is),
175*0a6a1f1dSLionel Sambuc m_lineno(p_lineno),
176*0a6a1f1dSLionel Sambuc m_skipws(p_skipws),
177*0a6a1f1dSLionel Sambuc m_eof_type(p_eof_type),
178*0a6a1f1dSLionel Sambuc m_nl_type(p_nl_type),
179*0a6a1f1dSLionel Sambuc m_text_type(p_text_type),
180*0a6a1f1dSLionel Sambuc m_quotech(-1)
181*0a6a1f1dSLionel Sambuc {
182*0a6a1f1dSLionel Sambuc }
183*0a6a1f1dSLionel Sambuc
184*0a6a1f1dSLionel Sambuc template< class IS >
185*0a6a1f1dSLionel Sambuc size_t
lineno(void) const186*0a6a1f1dSLionel Sambuc tokenizer< IS >::lineno(void)
187*0a6a1f1dSLionel Sambuc const
188*0a6a1f1dSLionel Sambuc {
189*0a6a1f1dSLionel Sambuc return m_lineno;
190*0a6a1f1dSLionel Sambuc }
191*0a6a1f1dSLionel Sambuc
192*0a6a1f1dSLionel Sambuc template< class IS >
193*0a6a1f1dSLionel Sambuc void
add_delim(char delim,const token_type & type)194*0a6a1f1dSLionel Sambuc tokenizer< IS >::add_delim(char delim, const token_type& type)
195*0a6a1f1dSLionel Sambuc {
196*0a6a1f1dSLionel Sambuc m_delims_map[delim] = type;
197*0a6a1f1dSLionel Sambuc m_delims_str += delim;
198*0a6a1f1dSLionel Sambuc }
199*0a6a1f1dSLionel Sambuc
200*0a6a1f1dSLionel Sambuc template< class IS >
201*0a6a1f1dSLionel Sambuc void
add_keyword(const std::string & keyword,const token_type & type)202*0a6a1f1dSLionel Sambuc tokenizer< IS >::add_keyword(const std::string& keyword,
203*0a6a1f1dSLionel Sambuc const token_type& type)
204*0a6a1f1dSLionel Sambuc {
205*0a6a1f1dSLionel Sambuc m_keywords_map[keyword] = type;
206*0a6a1f1dSLionel Sambuc }
207*0a6a1f1dSLionel Sambuc
208*0a6a1f1dSLionel Sambuc template< class IS >
209*0a6a1f1dSLionel Sambuc void
add_quote(char ch,const token_type & type)210*0a6a1f1dSLionel Sambuc tokenizer< IS >::add_quote(char ch, const token_type& type)
211*0a6a1f1dSLionel Sambuc {
212*0a6a1f1dSLionel Sambuc m_quotech = ch;
213*0a6a1f1dSLionel Sambuc m_quotetype = type;
214*0a6a1f1dSLionel Sambuc }
215*0a6a1f1dSLionel Sambuc
216*0a6a1f1dSLionel Sambuc template< class IS >
217*0a6a1f1dSLionel Sambuc token
next(void)218*0a6a1f1dSLionel Sambuc tokenizer< IS >::next(void)
219*0a6a1f1dSLionel Sambuc {
220*0a6a1f1dSLionel Sambuc if (m_la) {
221*0a6a1f1dSLionel Sambuc token t = m_la;
222*0a6a1f1dSLionel Sambuc m_la = token();
223*0a6a1f1dSLionel Sambuc if (t.type() == m_nl_type)
224*0a6a1f1dSLionel Sambuc m_lineno++;
225*0a6a1f1dSLionel Sambuc return t;
226*0a6a1f1dSLionel Sambuc }
227*0a6a1f1dSLionel Sambuc
228*0a6a1f1dSLionel Sambuc char ch;
229*0a6a1f1dSLionel Sambuc std::string text;
230*0a6a1f1dSLionel Sambuc
231*0a6a1f1dSLionel Sambuc bool done = false, quoted = false;
232*0a6a1f1dSLionel Sambuc token t(m_lineno, m_eof_type, "<<EOF>>");
233*0a6a1f1dSLionel Sambuc while (!done && m_is.get(ch).good()) {
234*0a6a1f1dSLionel Sambuc if (ch == m_quotech) {
235*0a6a1f1dSLionel Sambuc if (text.empty()) {
236*0a6a1f1dSLionel Sambuc bool escaped = false;
237*0a6a1f1dSLionel Sambuc while (!done && m_is.get(ch).good()) {
238*0a6a1f1dSLionel Sambuc if (!escaped) {
239*0a6a1f1dSLionel Sambuc if (ch == '\\')
240*0a6a1f1dSLionel Sambuc escaped = true;
241*0a6a1f1dSLionel Sambuc else if (ch == '\n') {
242*0a6a1f1dSLionel Sambuc m_la = token(m_lineno, m_nl_type, "<<NEWLINE>>");
243*0a6a1f1dSLionel Sambuc throw parse_error(t.lineno(),
244*0a6a1f1dSLionel Sambuc "Missing double quotes before "
245*0a6a1f1dSLionel Sambuc "end of line");
246*0a6a1f1dSLionel Sambuc } else if (ch == m_quotech)
247*0a6a1f1dSLionel Sambuc done = true;
248*0a6a1f1dSLionel Sambuc else
249*0a6a1f1dSLionel Sambuc text += ch;
250*0a6a1f1dSLionel Sambuc } else {
251*0a6a1f1dSLionel Sambuc text += ch;
252*0a6a1f1dSLionel Sambuc escaped = false;
253*0a6a1f1dSLionel Sambuc }
254*0a6a1f1dSLionel Sambuc }
255*0a6a1f1dSLionel Sambuc if (!m_is.good())
256*0a6a1f1dSLionel Sambuc throw parse_error(t.lineno(),
257*0a6a1f1dSLionel Sambuc "Missing double quotes before "
258*0a6a1f1dSLionel Sambuc "end of file");
259*0a6a1f1dSLionel Sambuc t = token(m_lineno, m_text_type, text);
260*0a6a1f1dSLionel Sambuc quoted = true;
261*0a6a1f1dSLionel Sambuc } else {
262*0a6a1f1dSLionel Sambuc m_is.putback(ch);
263*0a6a1f1dSLionel Sambuc done = true;
264*0a6a1f1dSLionel Sambuc }
265*0a6a1f1dSLionel Sambuc } else {
266*0a6a1f1dSLionel Sambuc typename std::map< char, token_type >::const_iterator idelim;
267*0a6a1f1dSLionel Sambuc idelim = m_delims_map.find(ch);
268*0a6a1f1dSLionel Sambuc if (idelim != m_delims_map.end()) {
269*0a6a1f1dSLionel Sambuc done = true;
270*0a6a1f1dSLionel Sambuc if (text.empty())
271*0a6a1f1dSLionel Sambuc t = token(m_lineno, (*idelim).second,
272*0a6a1f1dSLionel Sambuc std::string("") + ch);
273*0a6a1f1dSLionel Sambuc else
274*0a6a1f1dSLionel Sambuc m_is.putback(ch);
275*0a6a1f1dSLionel Sambuc } else if (ch == '\n') {
276*0a6a1f1dSLionel Sambuc done = true;
277*0a6a1f1dSLionel Sambuc if (text.empty())
278*0a6a1f1dSLionel Sambuc t = token(m_lineno, m_nl_type, "<<NEWLINE>>");
279*0a6a1f1dSLionel Sambuc else
280*0a6a1f1dSLionel Sambuc m_is.putback(ch);
281*0a6a1f1dSLionel Sambuc } else if (m_skipws && (ch == ' ' || ch == '\t')) {
282*0a6a1f1dSLionel Sambuc if (!text.empty())
283*0a6a1f1dSLionel Sambuc done = true;
284*0a6a1f1dSLionel Sambuc } else
285*0a6a1f1dSLionel Sambuc text += ch;
286*0a6a1f1dSLionel Sambuc }
287*0a6a1f1dSLionel Sambuc }
288*0a6a1f1dSLionel Sambuc
289*0a6a1f1dSLionel Sambuc if (!quoted && !text.empty()) {
290*0a6a1f1dSLionel Sambuc typename std::map< std::string, token_type >::const_iterator ikw;
291*0a6a1f1dSLionel Sambuc ikw = m_keywords_map.find(text);
292*0a6a1f1dSLionel Sambuc if (ikw != m_keywords_map.end())
293*0a6a1f1dSLionel Sambuc t = token(m_lineno, (*ikw).second, text);
294*0a6a1f1dSLionel Sambuc else
295*0a6a1f1dSLionel Sambuc t = token(m_lineno, m_text_type, text);
296*0a6a1f1dSLionel Sambuc }
297*0a6a1f1dSLionel Sambuc
298*0a6a1f1dSLionel Sambuc if (t.type() == m_nl_type)
299*0a6a1f1dSLionel Sambuc m_lineno++;
300*0a6a1f1dSLionel Sambuc
301*0a6a1f1dSLionel Sambuc return t;
302*0a6a1f1dSLionel Sambuc }
303*0a6a1f1dSLionel Sambuc
304*0a6a1f1dSLionel Sambuc template< class IS >
305*0a6a1f1dSLionel Sambuc std::string
rest_of_line(void)306*0a6a1f1dSLionel Sambuc tokenizer< IS >::rest_of_line(void)
307*0a6a1f1dSLionel Sambuc {
308*0a6a1f1dSLionel Sambuc std::string str;
309*0a6a1f1dSLionel Sambuc while (m_is.good() && m_is.peek() != '\n')
310*0a6a1f1dSLionel Sambuc str += m_is.get();
311*0a6a1f1dSLionel Sambuc return str;
312*0a6a1f1dSLionel Sambuc }
313*0a6a1f1dSLionel Sambuc
314*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
315*0a6a1f1dSLionel Sambuc // The "parser" class.
316*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
317*0a6a1f1dSLionel Sambuc
318*0a6a1f1dSLionel Sambuc template< class TKZ >
319*0a6a1f1dSLionel Sambuc class parser {
320*0a6a1f1dSLionel Sambuc TKZ& m_tkz;
321*0a6a1f1dSLionel Sambuc token m_last;
322*0a6a1f1dSLionel Sambuc parse_errors m_errors;
323*0a6a1f1dSLionel Sambuc bool m_thrown;
324*0a6a1f1dSLionel Sambuc
325*0a6a1f1dSLionel Sambuc public:
326*0a6a1f1dSLionel Sambuc parser(TKZ& tkz);
327*0a6a1f1dSLionel Sambuc ~parser(void);
328*0a6a1f1dSLionel Sambuc
329*0a6a1f1dSLionel Sambuc bool good(void) const;
330*0a6a1f1dSLionel Sambuc void add_error(const parse_error&);
331*0a6a1f1dSLionel Sambuc bool has_errors(void) const;
332*0a6a1f1dSLionel Sambuc
333*0a6a1f1dSLionel Sambuc token next(void);
334*0a6a1f1dSLionel Sambuc std::string rest_of_line(void);
335*0a6a1f1dSLionel Sambuc token reset(const token_type&);
336*0a6a1f1dSLionel Sambuc
337*0a6a1f1dSLionel Sambuc token
338*0a6a1f1dSLionel Sambuc expect(const token_type&,
339*0a6a1f1dSLionel Sambuc const std::string&);
340*0a6a1f1dSLionel Sambuc
341*0a6a1f1dSLionel Sambuc token
342*0a6a1f1dSLionel Sambuc expect(const token_type&,
343*0a6a1f1dSLionel Sambuc const token_type&,
344*0a6a1f1dSLionel Sambuc const std::string&);
345*0a6a1f1dSLionel Sambuc
346*0a6a1f1dSLionel Sambuc token
347*0a6a1f1dSLionel Sambuc expect(const token_type&,
348*0a6a1f1dSLionel Sambuc const token_type&,
349*0a6a1f1dSLionel Sambuc const token_type&,
350*0a6a1f1dSLionel Sambuc const std::string&);
351*0a6a1f1dSLionel Sambuc
352*0a6a1f1dSLionel Sambuc token
353*0a6a1f1dSLionel Sambuc expect(const token_type&,
354*0a6a1f1dSLionel Sambuc const token_type&,
355*0a6a1f1dSLionel Sambuc const token_type&,
356*0a6a1f1dSLionel Sambuc const token_type&,
357*0a6a1f1dSLionel Sambuc const std::string&);
358*0a6a1f1dSLionel Sambuc
359*0a6a1f1dSLionel Sambuc token
360*0a6a1f1dSLionel Sambuc expect(const token_type&,
361*0a6a1f1dSLionel Sambuc const token_type&,
362*0a6a1f1dSLionel Sambuc const token_type&,
363*0a6a1f1dSLionel Sambuc const token_type&,
364*0a6a1f1dSLionel Sambuc const token_type&,
365*0a6a1f1dSLionel Sambuc const token_type&,
366*0a6a1f1dSLionel Sambuc const token_type&,
367*0a6a1f1dSLionel Sambuc const std::string&);
368*0a6a1f1dSLionel Sambuc
369*0a6a1f1dSLionel Sambuc token
370*0a6a1f1dSLionel Sambuc expect(const token_type&,
371*0a6a1f1dSLionel Sambuc const token_type&,
372*0a6a1f1dSLionel Sambuc const token_type&,
373*0a6a1f1dSLionel Sambuc const token_type&,
374*0a6a1f1dSLionel Sambuc const token_type&,
375*0a6a1f1dSLionel Sambuc const token_type&,
376*0a6a1f1dSLionel Sambuc const token_type&,
377*0a6a1f1dSLionel Sambuc const token_type&,
378*0a6a1f1dSLionel Sambuc const std::string&);
379*0a6a1f1dSLionel Sambuc };
380*0a6a1f1dSLionel Sambuc
381*0a6a1f1dSLionel Sambuc template< class TKZ >
parser(TKZ & tkz)382*0a6a1f1dSLionel Sambuc parser< TKZ >::parser(TKZ& tkz) :
383*0a6a1f1dSLionel Sambuc m_tkz(tkz),
384*0a6a1f1dSLionel Sambuc m_thrown(false)
385*0a6a1f1dSLionel Sambuc {
386*0a6a1f1dSLionel Sambuc }
387*0a6a1f1dSLionel Sambuc
388*0a6a1f1dSLionel Sambuc template< class TKZ >
~parser(void)389*0a6a1f1dSLionel Sambuc parser< TKZ >::~parser(void)
390*0a6a1f1dSLionel Sambuc {
391*0a6a1f1dSLionel Sambuc if (!m_errors.empty() && !m_thrown)
392*0a6a1f1dSLionel Sambuc throw m_errors;
393*0a6a1f1dSLionel Sambuc }
394*0a6a1f1dSLionel Sambuc
395*0a6a1f1dSLionel Sambuc template< class TKZ >
396*0a6a1f1dSLionel Sambuc bool
good(void) const397*0a6a1f1dSLionel Sambuc parser< TKZ >::good(void)
398*0a6a1f1dSLionel Sambuc const
399*0a6a1f1dSLionel Sambuc {
400*0a6a1f1dSLionel Sambuc return m_tkz.m_is.good();
401*0a6a1f1dSLionel Sambuc }
402*0a6a1f1dSLionel Sambuc
403*0a6a1f1dSLionel Sambuc template< class TKZ >
404*0a6a1f1dSLionel Sambuc void
add_error(const parse_error & pe)405*0a6a1f1dSLionel Sambuc parser< TKZ >::add_error(const parse_error& pe)
406*0a6a1f1dSLionel Sambuc {
407*0a6a1f1dSLionel Sambuc m_errors.push_back(pe);
408*0a6a1f1dSLionel Sambuc }
409*0a6a1f1dSLionel Sambuc
410*0a6a1f1dSLionel Sambuc template< class TKZ >
411*0a6a1f1dSLionel Sambuc bool
has_errors(void) const412*0a6a1f1dSLionel Sambuc parser< TKZ >::has_errors(void)
413*0a6a1f1dSLionel Sambuc const
414*0a6a1f1dSLionel Sambuc {
415*0a6a1f1dSLionel Sambuc return !m_errors.empty();
416*0a6a1f1dSLionel Sambuc }
417*0a6a1f1dSLionel Sambuc
418*0a6a1f1dSLionel Sambuc template< class TKZ >
419*0a6a1f1dSLionel Sambuc token
next(void)420*0a6a1f1dSLionel Sambuc parser< TKZ >::next(void)
421*0a6a1f1dSLionel Sambuc {
422*0a6a1f1dSLionel Sambuc token t = m_tkz.next();
423*0a6a1f1dSLionel Sambuc
424*0a6a1f1dSLionel Sambuc m_last = t;
425*0a6a1f1dSLionel Sambuc
426*0a6a1f1dSLionel Sambuc if (t.type() == m_tkz.m_eof_type) {
427*0a6a1f1dSLionel Sambuc if (!m_errors.empty()) {
428*0a6a1f1dSLionel Sambuc m_thrown = true;
429*0a6a1f1dSLionel Sambuc throw m_errors;
430*0a6a1f1dSLionel Sambuc }
431*0a6a1f1dSLionel Sambuc }
432*0a6a1f1dSLionel Sambuc
433*0a6a1f1dSLionel Sambuc return t;
434*0a6a1f1dSLionel Sambuc }
435*0a6a1f1dSLionel Sambuc
436*0a6a1f1dSLionel Sambuc template< class TKZ >
437*0a6a1f1dSLionel Sambuc std::string
rest_of_line(void)438*0a6a1f1dSLionel Sambuc parser< TKZ >::rest_of_line(void)
439*0a6a1f1dSLionel Sambuc {
440*0a6a1f1dSLionel Sambuc return m_tkz.rest_of_line();
441*0a6a1f1dSLionel Sambuc }
442*0a6a1f1dSLionel Sambuc
443*0a6a1f1dSLionel Sambuc template< class TKZ >
444*0a6a1f1dSLionel Sambuc token
reset(const token_type & stop)445*0a6a1f1dSLionel Sambuc parser< TKZ >::reset(const token_type& stop)
446*0a6a1f1dSLionel Sambuc {
447*0a6a1f1dSLionel Sambuc token t = m_last;
448*0a6a1f1dSLionel Sambuc
449*0a6a1f1dSLionel Sambuc while (t.type() != m_tkz.m_eof_type && t.type() != stop)
450*0a6a1f1dSLionel Sambuc t = next();
451*0a6a1f1dSLionel Sambuc
452*0a6a1f1dSLionel Sambuc return t;
453*0a6a1f1dSLionel Sambuc }
454*0a6a1f1dSLionel Sambuc
455*0a6a1f1dSLionel Sambuc template< class TKZ >
456*0a6a1f1dSLionel Sambuc token
expect(const token_type & t1,const std::string & textual)457*0a6a1f1dSLionel Sambuc parser< TKZ >::expect(const token_type& t1,
458*0a6a1f1dSLionel Sambuc const std::string& textual)
459*0a6a1f1dSLionel Sambuc {
460*0a6a1f1dSLionel Sambuc token t = next();
461*0a6a1f1dSLionel Sambuc
462*0a6a1f1dSLionel Sambuc if (t.type() != t1)
463*0a6a1f1dSLionel Sambuc throw parse_error(t.lineno(),
464*0a6a1f1dSLionel Sambuc "Unexpected token `" + t.text() +
465*0a6a1f1dSLionel Sambuc "'; expected " + textual);
466*0a6a1f1dSLionel Sambuc
467*0a6a1f1dSLionel Sambuc return t;
468*0a6a1f1dSLionel Sambuc }
469*0a6a1f1dSLionel Sambuc
470*0a6a1f1dSLionel Sambuc template< class TKZ >
471*0a6a1f1dSLionel Sambuc token
expect(const token_type & t1,const token_type & t2,const std::string & textual)472*0a6a1f1dSLionel Sambuc parser< TKZ >::expect(const token_type& t1,
473*0a6a1f1dSLionel Sambuc const token_type& t2,
474*0a6a1f1dSLionel Sambuc const std::string& textual)
475*0a6a1f1dSLionel Sambuc {
476*0a6a1f1dSLionel Sambuc token t = next();
477*0a6a1f1dSLionel Sambuc
478*0a6a1f1dSLionel Sambuc if (t.type() != t1 && t.type() != t2)
479*0a6a1f1dSLionel Sambuc throw parse_error(t.lineno(),
480*0a6a1f1dSLionel Sambuc "Unexpected token `" + t.text() +
481*0a6a1f1dSLionel Sambuc "'; expected " + textual);
482*0a6a1f1dSLionel Sambuc
483*0a6a1f1dSLionel Sambuc return t;
484*0a6a1f1dSLionel Sambuc }
485*0a6a1f1dSLionel Sambuc
486*0a6a1f1dSLionel Sambuc template< class TKZ >
487*0a6a1f1dSLionel Sambuc token
expect(const token_type & t1,const token_type & t2,const token_type & t3,const std::string & textual)488*0a6a1f1dSLionel Sambuc parser< TKZ >::expect(const token_type& t1,
489*0a6a1f1dSLionel Sambuc const token_type& t2,
490*0a6a1f1dSLionel Sambuc const token_type& t3,
491*0a6a1f1dSLionel Sambuc const std::string& textual)
492*0a6a1f1dSLionel Sambuc {
493*0a6a1f1dSLionel Sambuc token t = next();
494*0a6a1f1dSLionel Sambuc
495*0a6a1f1dSLionel Sambuc if (t.type() != t1 && t.type() != t2 && t.type() != t3)
496*0a6a1f1dSLionel Sambuc throw parse_error(t.lineno(),
497*0a6a1f1dSLionel Sambuc "Unexpected token `" + t.text() +
498*0a6a1f1dSLionel Sambuc "'; expected " + textual);
499*0a6a1f1dSLionel Sambuc
500*0a6a1f1dSLionel Sambuc return t;
501*0a6a1f1dSLionel Sambuc }
502*0a6a1f1dSLionel Sambuc
503*0a6a1f1dSLionel Sambuc template< class TKZ >
504*0a6a1f1dSLionel Sambuc token
expect(const token_type & t1,const token_type & t2,const token_type & t3,const token_type & t4,const std::string & textual)505*0a6a1f1dSLionel Sambuc parser< TKZ >::expect(const token_type& t1,
506*0a6a1f1dSLionel Sambuc const token_type& t2,
507*0a6a1f1dSLionel Sambuc const token_type& t3,
508*0a6a1f1dSLionel Sambuc const token_type& t4,
509*0a6a1f1dSLionel Sambuc const std::string& textual)
510*0a6a1f1dSLionel Sambuc {
511*0a6a1f1dSLionel Sambuc token t = next();
512*0a6a1f1dSLionel Sambuc
513*0a6a1f1dSLionel Sambuc if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
514*0a6a1f1dSLionel Sambuc t.type() != t4)
515*0a6a1f1dSLionel Sambuc throw parse_error(t.lineno(),
516*0a6a1f1dSLionel Sambuc "Unexpected token `" + t.text() +
517*0a6a1f1dSLionel Sambuc "'; expected " + textual);
518*0a6a1f1dSLionel Sambuc
519*0a6a1f1dSLionel Sambuc return t;
520*0a6a1f1dSLionel Sambuc }
521*0a6a1f1dSLionel Sambuc
522*0a6a1f1dSLionel Sambuc template< class TKZ >
523*0a6a1f1dSLionel Sambuc token
expect(const token_type & t1,const token_type & t2,const token_type & t3,const token_type & t4,const token_type & t5,const token_type & t6,const token_type & t7,const std::string & textual)524*0a6a1f1dSLionel Sambuc parser< TKZ >::expect(const token_type& t1,
525*0a6a1f1dSLionel Sambuc const token_type& t2,
526*0a6a1f1dSLionel Sambuc const token_type& t3,
527*0a6a1f1dSLionel Sambuc const token_type& t4,
528*0a6a1f1dSLionel Sambuc const token_type& t5,
529*0a6a1f1dSLionel Sambuc const token_type& t6,
530*0a6a1f1dSLionel Sambuc const token_type& t7,
531*0a6a1f1dSLionel Sambuc const std::string& textual)
532*0a6a1f1dSLionel Sambuc {
533*0a6a1f1dSLionel Sambuc token t = next();
534*0a6a1f1dSLionel Sambuc
535*0a6a1f1dSLionel Sambuc if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
536*0a6a1f1dSLionel Sambuc t.type() != t4 && t.type() != t5 && t.type() != t6 &&
537*0a6a1f1dSLionel Sambuc t.type() != t7)
538*0a6a1f1dSLionel Sambuc throw parse_error(t.lineno(),
539*0a6a1f1dSLionel Sambuc "Unexpected token `" + t.text() +
540*0a6a1f1dSLionel Sambuc "'; expected " + textual);
541*0a6a1f1dSLionel Sambuc
542*0a6a1f1dSLionel Sambuc return t;
543*0a6a1f1dSLionel Sambuc }
544*0a6a1f1dSLionel Sambuc
545*0a6a1f1dSLionel Sambuc template< class TKZ >
546*0a6a1f1dSLionel Sambuc token
expect(const token_type & t1,const token_type & t2,const token_type & t3,const token_type & t4,const token_type & t5,const token_type & t6,const token_type & t7,const token_type & t8,const std::string & textual)547*0a6a1f1dSLionel Sambuc parser< TKZ >::expect(const token_type& t1,
548*0a6a1f1dSLionel Sambuc const token_type& t2,
549*0a6a1f1dSLionel Sambuc const token_type& t3,
550*0a6a1f1dSLionel Sambuc const token_type& t4,
551*0a6a1f1dSLionel Sambuc const token_type& t5,
552*0a6a1f1dSLionel Sambuc const token_type& t6,
553*0a6a1f1dSLionel Sambuc const token_type& t7,
554*0a6a1f1dSLionel Sambuc const token_type& t8,
555*0a6a1f1dSLionel Sambuc const std::string& textual)
556*0a6a1f1dSLionel Sambuc {
557*0a6a1f1dSLionel Sambuc token t = next();
558*0a6a1f1dSLionel Sambuc
559*0a6a1f1dSLionel Sambuc if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
560*0a6a1f1dSLionel Sambuc t.type() != t4 && t.type() != t5 && t.type() != t6 &&
561*0a6a1f1dSLionel Sambuc t.type() != t7 && t.type() != t8)
562*0a6a1f1dSLionel Sambuc throw parse_error(t.lineno(),
563*0a6a1f1dSLionel Sambuc "Unexpected token `" + t.text() +
564*0a6a1f1dSLionel Sambuc "'; expected " + textual);
565*0a6a1f1dSLionel Sambuc
566*0a6a1f1dSLionel Sambuc return t;
567*0a6a1f1dSLionel Sambuc }
568*0a6a1f1dSLionel Sambuc
569*0a6a1f1dSLionel Sambuc #define ATF_PARSER_CALLBACK(parser, func) \
570*0a6a1f1dSLionel Sambuc do { \
571*0a6a1f1dSLionel Sambuc if (!(parser).has_errors()) \
572*0a6a1f1dSLionel Sambuc func; \
573*0a6a1f1dSLionel Sambuc } while (false)
574*0a6a1f1dSLionel Sambuc
575*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
576*0a6a1f1dSLionel Sambuc // Header parsing.
577*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
578*0a6a1f1dSLionel Sambuc
579*0a6a1f1dSLionel Sambuc typedef std::map< std::string, std::string > attrs_map;
580*0a6a1f1dSLionel Sambuc
581*0a6a1f1dSLionel Sambuc class header_entry {
582*0a6a1f1dSLionel Sambuc std::string m_name;
583*0a6a1f1dSLionel Sambuc std::string m_value;
584*0a6a1f1dSLionel Sambuc attrs_map m_attrs;
585*0a6a1f1dSLionel Sambuc
586*0a6a1f1dSLionel Sambuc public:
587*0a6a1f1dSLionel Sambuc header_entry(void);
588*0a6a1f1dSLionel Sambuc header_entry(const std::string&, const std::string&,
589*0a6a1f1dSLionel Sambuc attrs_map = attrs_map());
590*0a6a1f1dSLionel Sambuc
591*0a6a1f1dSLionel Sambuc const std::string& name(void) const;
592*0a6a1f1dSLionel Sambuc const std::string& value(void) const;
593*0a6a1f1dSLionel Sambuc const attrs_map& attrs(void) const;
594*0a6a1f1dSLionel Sambuc bool has_attr(const std::string&) const;
595*0a6a1f1dSLionel Sambuc const std::string& get_attr(const std::string&) const;
596*0a6a1f1dSLionel Sambuc };
597*0a6a1f1dSLionel Sambuc
598*0a6a1f1dSLionel Sambuc typedef std::map< std::string, header_entry > headers_map;
599*0a6a1f1dSLionel Sambuc
600*0a6a1f1dSLionel Sambuc std::pair< size_t, headers_map > read_headers(std::istream&, size_t);
601*0a6a1f1dSLionel Sambuc void write_headers(const headers_map&, std::ostream&);
602*0a6a1f1dSLionel Sambuc void validate_content_type(const headers_map&, const std::string&, int);
603*0a6a1f1dSLionel Sambuc
604*0a6a1f1dSLionel Sambuc } // namespace parser
605*0a6a1f1dSLionel Sambuc } // namespace tools
606*0a6a1f1dSLionel Sambuc
607*0a6a1f1dSLionel Sambuc #endif // !defined(TOOLS_PARSER_HPP)
608