diff options
Diffstat (limited to 'tools/parser.hpp')
-rw-r--r-- | tools/parser.hpp | 607 |
1 files changed, 0 insertions, 607 deletions
diff --git a/tools/parser.hpp b/tools/parser.hpp deleted file mode 100644 index eb00cb4..0000000 --- a/tools/parser.hpp +++ /dev/null @@ -1,607 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_PARSER_HPP) -#define TOOLS_PARSER_HPP - -#include <istream> -#include <map> -#include <ostream> -#include <stdexcept> -#include <string> -#include <utility> -#include <vector> - -namespace tools { -namespace parser { - -// ------------------------------------------------------------------------ -// The "parse_error" class. -// ------------------------------------------------------------------------ - -class parse_error : public std::runtime_error, - public std::pair< size_t, std::string > { - mutable std::string m_msg; - -public: - parse_error(size_t, std::string); - ~parse_error(void) throw(); - - const char* what(void) const throw(); - - operator std::string(void) const; -}; - -// ------------------------------------------------------------------------ -// The "parse_errors" class. -// ------------------------------------------------------------------------ - -class parse_errors : public std::runtime_error, - public std::vector< parse_error > { - std::vector< parse_error > m_errors; - mutable std::string m_msg; - -public: - parse_errors(void); - ~parse_errors(void) throw(); - - const char* what(void) const throw(); -}; - -// ------------------------------------------------------------------------ -// The "format_error" class. -// ------------------------------------------------------------------------ - -class format_error : public std::runtime_error { -public: - format_error(const std::string&); -}; - -// ------------------------------------------------------------------------ -// The "token" class. -// ------------------------------------------------------------------------ - -typedef int token_type; - -//! -//! \brief Representation of a read token. -//! -//! A pair that contains the information of a token read from a stream. -//! It contains the token's type and its associated data, if any. -//! -struct token { - bool m_inited; - size_t m_line; - token_type m_type; - std::string m_text; - -public: - token(void); - token(size_t, const token_type&, const std::string& = ""); - - size_t lineno(void) const; - const token_type& type(void) const; - const std::string& text(void) const; - - operator bool(void) const; - bool operator!(void) const; -}; - -// ------------------------------------------------------------------------ -// The "tokenizer" class. -// ------------------------------------------------------------------------ - -//! -//! \brief A stream tokenizer. -//! -//! This template implements an extremely simple, line-oriented stream -//! tokenizer. It is only able to recognize one character-long delimiters, -//! random-length keywords, skip whitespace and, anything that does not -//! match these rules is supposed to be a word. -//! -//! Parameter IS: The input stream's type. -//! -template< class IS > -class tokenizer { - IS& m_is; - size_t m_lineno; - token m_la; - - bool m_skipws; - token_type m_eof_type, m_nl_type, m_text_type; - - std::map< char, token_type > m_delims_map; - std::string m_delims_str; - - char m_quotech; - token_type m_quotetype; - - std::map< std::string, token_type > m_keywords_map; - - token_type alloc_type(void); - - template< class TKZ > - friend - class parser; - -public: - tokenizer(IS&, bool, const token_type&, const token_type&, - const token_type&, size_t = 1); - - size_t lineno(void) const; - - void add_delim(char, const token_type&); - void add_keyword(const std::string&, const token_type&); - void add_quote(char, const token_type&); - - token next(void); - std::string rest_of_line(void); -}; - -template< class IS > -tokenizer< 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) : - m_is(p_is), - m_lineno(p_lineno), - m_skipws(p_skipws), - m_eof_type(p_eof_type), - m_nl_type(p_nl_type), - m_text_type(p_text_type), - m_quotech(-1) -{ -} - -template< class IS > -size_t -tokenizer< IS >::lineno(void) - const -{ - return m_lineno; -} - -template< class IS > -void -tokenizer< IS >::add_delim(char delim, const token_type& type) -{ - m_delims_map[delim] = type; - m_delims_str += delim; -} - -template< class IS > -void -tokenizer< IS >::add_keyword(const std::string& keyword, - const token_type& type) -{ - m_keywords_map[keyword] = type; -} - -template< class IS > -void -tokenizer< IS >::add_quote(char ch, const token_type& type) -{ - m_quotech = ch; - m_quotetype = type; -} - -template< class IS > -token -tokenizer< IS >::next(void) -{ - if (m_la) { - token t = m_la; - m_la = token(); - if (t.type() == m_nl_type) - m_lineno++; - return t; - } - - char ch; - std::string text; - - bool done = false, quoted = false; - token t(m_lineno, m_eof_type, "<<EOF>>"); - while (!done && m_is.get(ch).good()) { - if (ch == m_quotech) { - if (text.empty()) { - bool escaped = false; - while (!done && m_is.get(ch).good()) { - if (!escaped) { - if (ch == '\\') - escaped = true; - else if (ch == '\n') { - m_la = token(m_lineno, m_nl_type, "<<NEWLINE>>"); - throw parse_error(t.lineno(), - "Missing double quotes before " - "end of line"); - } else if (ch == m_quotech) - done = true; - else - text += ch; - } else { - text += ch; - escaped = false; - } - } - if (!m_is.good()) - throw parse_error(t.lineno(), - "Missing double quotes before " - "end of file"); - t = token(m_lineno, m_text_type, text); - quoted = true; - } else { - m_is.putback(ch); - done = true; - } - } else { - typename std::map< char, token_type >::const_iterator idelim; - idelim = m_delims_map.find(ch); - if (idelim != m_delims_map.end()) { - done = true; - if (text.empty()) - t = token(m_lineno, (*idelim).second, - std::string("") + ch); - else - m_is.putback(ch); - } else if (ch == '\n') { - done = true; - if (text.empty()) - t = token(m_lineno, m_nl_type, "<<NEWLINE>>"); - else - m_is.putback(ch); - } else if (m_skipws && (ch == ' ' || ch == '\t')) { - if (!text.empty()) - done = true; - } else - text += ch; - } - } - - if (!quoted && !text.empty()) { - typename std::map< std::string, token_type >::const_iterator ikw; - ikw = m_keywords_map.find(text); - if (ikw != m_keywords_map.end()) - t = token(m_lineno, (*ikw).second, text); - else - t = token(m_lineno, m_text_type, text); - } - - if (t.type() == m_nl_type) - m_lineno++; - - return t; -} - -template< class IS > -std::string -tokenizer< IS >::rest_of_line(void) -{ - std::string str; - while (m_is.good() && m_is.peek() != '\n') - str += m_is.get(); - return str; -} - -// ------------------------------------------------------------------------ -// The "parser" class. -// ------------------------------------------------------------------------ - -template< class TKZ > -class parser { - TKZ& m_tkz; - token m_last; - parse_errors m_errors; - bool m_thrown; - -public: - parser(TKZ& tkz); - ~parser(void); - - bool good(void) const; - void add_error(const parse_error&); - bool has_errors(void) const; - - token next(void); - std::string rest_of_line(void); - token reset(const token_type&); - - token - expect(const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const token_type&, - const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const std::string&); -}; - -template< class TKZ > -parser< TKZ >::parser(TKZ& tkz) : - m_tkz(tkz), - m_thrown(false) -{ -} - -template< class TKZ > -parser< TKZ >::~parser(void) -{ - if (!m_errors.empty() && !m_thrown) - throw m_errors; -} - -template< class TKZ > -bool -parser< TKZ >::good(void) - const -{ - return m_tkz.m_is.good(); -} - -template< class TKZ > -void -parser< TKZ >::add_error(const parse_error& pe) -{ - m_errors.push_back(pe); -} - -template< class TKZ > -bool -parser< TKZ >::has_errors(void) - const -{ - return !m_errors.empty(); -} - -template< class TKZ > -token -parser< TKZ >::next(void) -{ - token t = m_tkz.next(); - - m_last = t; - - if (t.type() == m_tkz.m_eof_type) { - if (!m_errors.empty()) { - m_thrown = true; - throw m_errors; - } - } - - return t; -} - -template< class TKZ > -std::string -parser< TKZ >::rest_of_line(void) -{ - return m_tkz.rest_of_line(); -} - -template< class TKZ > -token -parser< TKZ >::reset(const token_type& stop) -{ - token t = m_last; - - while (t.type() != m_tkz.m_eof_type && t.type() != stop) - t = next(); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const token_type& t2, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const token_type& t2, - const token_type& t3, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2 && t.type() != t3) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const token_type& t2, - const token_type& t3, - const token_type& t4, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2 && t.type() != t3 && - t.type() != t4) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::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) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2 && t.type() != t3 && - t.type() != t4 && t.type() != t5 && t.type() != t6 && - t.type() != t7) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::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) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2 && t.type() != t3 && - t.type() != t4 && t.type() != t5 && t.type() != t6 && - t.type() != t7 && t.type() != t8) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -#define ATF_PARSER_CALLBACK(parser, func) \ - do { \ - if (!(parser).has_errors()) \ - func; \ - } while (false) - -// ------------------------------------------------------------------------ -// Header parsing. -// ------------------------------------------------------------------------ - -typedef std::map< std::string, std::string > attrs_map; - -class header_entry { - std::string m_name; - std::string m_value; - attrs_map m_attrs; - -public: - header_entry(void); - header_entry(const std::string&, const std::string&, - attrs_map = attrs_map()); - - const std::string& name(void) const; - const std::string& value(void) const; - const attrs_map& attrs(void) const; - bool has_attr(const std::string&) const; - const std::string& get_attr(const std::string&) const; -}; - -typedef std::map< std::string, header_entry > headers_map; - -std::pair< size_t, headers_map > read_headers(std::istream&, size_t); -void write_headers(const headers_map&, std::ostream&); -void validate_content_type(const headers_map&, const std::string&, int); - -} // namespace parser -} // namespace tools - -#endif // !defined(TOOLS_PARSER_HPP) |