123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #ifndef MASTER_LEXER_STATE_H
- #define MASTER_LEXER_STATE_H 1
- #include <dns/master_lexer.h>
- #include <boost/function.hpp>
- namespace isc {
- namespace dns {
- namespace master_lexer_internal {
- /// \brief Tokenization state for \c MasterLexer.
- ///
- /// This is a base class of classes that represent various states of a single
- /// tokenization session of \c MasterLexer, i.e., the states used for a
- /// single call to \c MasterLexer::getNextToken().
- ///
- /// It follows the convention of the state design pattern: each derived class
- /// corresponds to a specific state, and the state transition takes place
- /// through the virtual method named \c handle(). The \c handle() method
- /// takes the main \c MasterLexer object that holds all necessary internal
- /// context, and updates it as necessary; each \c State derived class is
- /// completely stateless.
- ///
- /// The initial transition takes place in a static method of the base class,
- /// \c start(). This is mainly for implementation convenience; we need to
- /// pass options given to \c MasterLexer::getNextToken() for the initial
- /// state, so it makes more sense to separate the interface for the transition
- /// from the initial state.
- ///
- /// When an object of a specific state class completes the session, it
- /// normally sets the identified token in the lexer, and returns NULL;
- /// if more transition is necessary, it returns a pointer to the next state
- /// object.
- ///
- /// As is usual in the state design pattern, the \c State class is made
- /// a friend class of \c MasterLexer and can refer to its internal details.
- /// This is intentional; essentially its a part of \c MasterLexer and
- /// is defined as a separate class only for implementation clarity and better
- /// testability. It's defined in a publicly visible header, but that's only
- /// for testing purposes. No normal application or even no other classes of
- /// this library are expected to use this class.
- class State {
- public:
- /// \brief Virtual destructor.
- ///
- /// In our usage this actually doesn't matter, but some compilers complain
- /// about it and we need to silence them.
- virtual ~State() {}
- /// \brief Begin state transitions to get the next token.
- ///
- /// This is the first method that \c MasterLexer needs to call for a
- /// tokenization session. The lexer passes a reference to itself
- /// and options given in \c getNextToken().
- ///
- /// \throw MasterLexer::ReadError Unexpected I/O error
- /// \throw std::bad_alloc Internal resource allocation failure
- ///
- /// \param lexer The lexer object that holds the main context.
- /// \param options The options passed to getNextToken().
- /// \return A pointer to the next state object or NULL if the transition
- /// is completed.
- static const State* start(MasterLexer& lexer,
- MasterLexer::Options options);
- /// \brief Handle the process of one specific state.
- ///
- /// This method is expected to be called on the object returned by
- /// start(). In the usual state transition design pattern, it would
- /// return the next state. But as we noticed, we never have another
- /// state, so we simplify it by not returning anything instead of
- /// returning NULL every time.
- ///
- /// \throw MasterLexer::ReadError Unexpected I/O error
- /// \throw std::bad_alloc Internal resource allocation failure
- ///
- /// \param lexer The lexer object that holds the main context.
- virtual void handle(MasterLexer& lexer) const = 0;
- /// \brief Types of states.
- ///
- /// Specific states are basically hidden within the implementation,
- /// but we'd like to allow tests to examine them, so we provide
- /// a way to get an instance of a specific state.
- enum ID {
- CRLF, ///< Just seen a carriage-return character
- String, ///< Handling a string token
- QString ///< Handling a quoted string token
- };
- /// \brief Returns a \c State instance of the given state.
- ///
- /// This is provided only for testing purposes so tests can check
- /// the behavior of each state separately. \c MasterLexer shouldn't
- /// need this method.
- static const State& getInstance(ID state_id);
- /// \name Read-only accessors for testing purposes.
- ///
- /// These allow tests to inspect some selected portion of the internal
- /// states of \c MasterLexer. These shouldn't be used except for testing
- /// purposes.
- ///@{
- bool wasLastEOL(const MasterLexer& lexer) const;
- const MasterLexer::Token& getToken(const MasterLexer& lexer) const;
- size_t getParenCount(const MasterLexer& lexer) const;
- ///@}
- protected:
- /// \brief An accessor to the internal implementation class of
- /// \c MasterLexer.
- ///
- /// This is provided for specific derived classes as they are not direct
- /// friends of \c MasterLexer.
- ///
- /// \param lexer The lexer object that holds the main context.
- /// \return A pointer to the implementation class object of the given
- /// lexer. This is never NULL.
- MasterLexer::MasterLexerImpl* getLexerImpl(MasterLexer& lexer) const {
- return (lexer.impl_);
- }
- };
- } // namespace master_lexer_internal
- } // namespace dns
- } // namespace isc
- #endif // MASTER_LEXER_STATE_H
- // Local Variables:
- // mode: c++
- // End:
|