master_lexer_state.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef MASTER_LEXER_STATE_H
  15. #define MASTER_LEXER_STATE_H 1
  16. #include <dns/master_lexer.h>
  17. #include <boost/function.hpp>
  18. namespace isc {
  19. namespace dns {
  20. namespace master_lexer_internal {
  21. /// \brief Tokenization state for \c MasterLexer.
  22. ///
  23. /// This is a base class of classes that represent various states of a single
  24. /// tokenization session of \c MasterLexer, i.e., the states used for a
  25. /// single call to \c MasterLexer::getNextToken().
  26. ///
  27. /// It follows the convention of the state design pattern: each derived class
  28. /// corresponds to a specific state, and the state transition takes place
  29. /// through the virtual method named \c handle(). The \c handle() method
  30. /// takes the main \c MasterLexer object that holds all necessary internal
  31. /// context, and updates it as necessary; each \c State derived class is
  32. /// completely stateless.
  33. ///
  34. /// The initial transition takes place in a static method of the base class,
  35. /// \c start(). This is mainly for implementation convenience; we need to
  36. /// pass options given to \c MasterLexer::getNextToken() for the initial
  37. /// state, so it makes more sense to separate the interface for the transition
  38. /// from the initial state.
  39. ///
  40. /// When an object of a specific state class completes the session, it
  41. /// normally sets the identified token in the lexer, and returns NULL;
  42. /// if more transition is necessary, it returns a pointer to the next state
  43. /// object.
  44. ///
  45. /// As is usual in the state design pattern, the \c State class is made
  46. /// a friend class of \c MasterLexer and can refer to its internal details.
  47. /// This is intentional; essentially its a part of \c MasterLexer and
  48. /// is defined as a separate class only for implementation clarity and better
  49. /// testability. It's defined in a publicly visible header, but that's only
  50. /// for testing purposes. No normal application or even no other classes of
  51. /// this library are expected to use this class.
  52. class State {
  53. public:
  54. /// \brief Virtual destructor.
  55. ///
  56. /// In our usage this actually doesn't matter, but some compilers complain
  57. /// about it and we need to silence them.
  58. virtual ~State() {}
  59. /// \brief Begin state transitions to get the next token.
  60. ///
  61. /// This is the first method that \c MasterLexer needs to call for a
  62. /// tokenization session. The lexer passes a reference to itself
  63. /// and options given in \c getNextToken().
  64. ///
  65. /// \throw MasterLexer::ReadError Unexpected I/O error
  66. /// \throw std::bad_alloc Internal resource allocation failure
  67. ///
  68. /// \param lexer The lexer object that holds the main context.
  69. /// \param options The options passed to getNextToken().
  70. /// \return A pointer to the next state object or NULL if the transition
  71. /// is completed.
  72. static const State* start(MasterLexer& lexer,
  73. MasterLexer::Options options);
  74. /// \brief Handle the process of one specific state.
  75. ///
  76. /// This method is expected to be called on the object returned by
  77. /// start(). In the usual state transition design pattern, it would
  78. /// return the next state. But as we noticed, we never have another
  79. /// state, so we simplify it by not returning anything instead of
  80. /// returning NULL every time.
  81. ///
  82. /// \throw MasterLexer::ReadError Unexpected I/O error
  83. /// \throw std::bad_alloc Internal resource allocation failure
  84. ///
  85. /// \param lexer The lexer object that holds the main context.
  86. virtual void handle(MasterLexer& lexer) const = 0;
  87. /// \brief Types of states.
  88. ///
  89. /// Specific states are basically hidden within the implementation,
  90. /// but we'd like to allow tests to examine them, so we provide
  91. /// a way to get an instance of a specific state.
  92. enum ID {
  93. CRLF, ///< Just seen a carriage-return character
  94. String, ///< Handling a string token
  95. QString ///< Handling a quoted string token
  96. };
  97. /// \brief Returns a \c State instance of the given state.
  98. ///
  99. /// This is provided only for testing purposes so tests can check
  100. /// the behavior of each state separately. \c MasterLexer shouldn't
  101. /// need this method.
  102. static const State& getInstance(ID state_id);
  103. /// \name Read-only accessors for testing purposes.
  104. ///
  105. /// These allow tests to inspect some selected portion of the internal
  106. /// states of \c MasterLexer. These shouldn't be used except for testing
  107. /// purposes.
  108. ///@{
  109. bool wasLastEOL(const MasterLexer& lexer) const;
  110. const MasterLexer::Token& getToken(const MasterLexer& lexer) const;
  111. size_t getParenCount(const MasterLexer& lexer) const;
  112. ///@}
  113. protected:
  114. /// \brief An accessor to the internal implementation class of
  115. /// \c MasterLexer.
  116. ///
  117. /// This is provided for specific derived classes as they are not direct
  118. /// friends of \c MasterLexer.
  119. ///
  120. /// \param lexer The lexer object that holds the main context.
  121. /// \return A pointer to the implementation class object of the given
  122. /// lexer. This is never NULL.
  123. MasterLexer::MasterLexerImpl* getLexerImpl(MasterLexer& lexer) const {
  124. return (lexer.impl_);
  125. }
  126. };
  127. } // namespace master_lexer_internal
  128. } // namespace dns
  129. } // namespace isc
  130. #endif // MASTER_LEXER_STATE_H
  131. // Local Variables:
  132. // mode: c++
  133. // End: