xref: /minix3/external/bsd/atf/dist/tools/parser.hpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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