You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
4.9 KiB

  1. //==============================================================================
  2. //
  3. // Copyright (c) 2015-
  4. // Authors:
  5. // * Joachim Klein <klein@tcs.inf.tu-dresden.de>
  6. // * David Mueller <david.mueller@tcs.inf.tu-dresden.de>
  7. //
  8. //------------------------------------------------------------------------------
  9. //
  10. // This file is part of the cpphoafparser library,
  11. // http://automata.tools/hoa/cpphoafparser/
  12. //
  13. // The cpphoafparser library is free software; you can redistribute it and/or
  14. // modify it under the terms of the GNU Lesser General Public
  15. // License as published by the Free Software Foundation; either
  16. // version 2.1 of the License, or (at your option) any later version.
  17. //
  18. // The cpphoafparser library is distributed in the hope that it will be useful,
  19. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  21. // Lesser General Public License for more details.
  22. //
  23. // You should have received a copy of the GNU Lesser General Public
  24. // License along with this library; if not, write to the Free Software
  25. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. //
  27. //==============================================================================
  28. #ifndef CPPHOAFPARSER_IMPLICITEDGEHELPER_H
  29. #define CPPHOAFPARSER_IMPLICITEDGEHELPER_H
  30. #include "cpphoafparser/consumer/hoa_consumer_exception.hh"
  31. #include <exception>
  32. #include <string>
  33. namespace cpphoafparser {
  34. /**
  35. * Helper for keeping track of implicit edges.
  36. *
  37. * In `notifyBodyStart()`, call:<br>
  38. * `helper = new ImplicitEdgeHelper(numberOfAPs);`
  39. *
  40. * In `addState()`, call:<br>
  41. * `helper.startOfState(stateId);`
  42. *
  43. * In `addEdgeImplicit()`, call:<br>
  44. * edgeIndex = helper.nextImplicitEdge();`
  45. *
  46. * In `notifyEndOfState()`, call:<br>
  47. * `helper.endOfState();`
  48. */
  49. class ImplicitEdgeHelper
  50. {
  51. public:
  52. /** Constructor, pass number of atomic propositions */
  53. ImplicitEdgeHelper(unsigned int numberOfAPs) :
  54. numberOfAPs(numberOfAPs), stateId(0)
  55. {
  56. edgesPerState = ((std::size_t)1) << numberOfAPs;
  57. }
  58. /** Return the expected number of edges per state, i.e., 2^|AP|. */
  59. std::size_t getEdgesPerState()
  60. {
  61. return edgesPerState;
  62. }
  63. /** Notify the ImplicitEdgeHelper that a new state definition has been encountered.
  64. * @param newStateId the state index (for error message)
  65. * @throws std::logic_error if `startOfState()` is called before another state is finished with a call to `endOfState()
  66. */
  67. void startOfState(unsigned int newStateId)
  68. {
  69. if (inState) {
  70. throw std::logic_error("ImplicitEdgeHelper: startOfState("
  71. + std::to_string(newStateId)
  72. + ") without previous call to endOfState()");
  73. }
  74. edgeIndex = 0;
  75. stateId = newStateId;
  76. inState = true;
  77. }
  78. /** Notify the ImplicitEdgeHelper that the next implicit edge for the current state has been encountered.
  79. * Return the edge index.
  80. * @return the index of the current edge
  81. * @throws HOAConsumerException if the number of edges is more than 2^numberOfAPs
  82. * @throws std::logic_error if this function is called without a previous call to `startOfState()
  83. * */
  84. std::size_t nextImplicitEdge()
  85. {
  86. if (!inState) {
  87. throw std::logic_error("ImplicitEdgeHelper: nextImplicitEdge() without previous call to startOfState()");
  88. }
  89. unsigned long currentEdgeIndex = edgeIndex;
  90. edgeIndex++;
  91. if (currentEdgeIndex >= edgesPerState) {
  92. throw HOAConsumerException("For state "
  93. +std::to_string(stateId)
  94. +", more edges than allowed for "
  95. +std::to_string(numberOfAPs)
  96. +" atomic propositions");
  97. }
  98. return currentEdgeIndex;
  99. }
  100. /** Notify the ImplicitEdgeHelper that the current state definition is finished.
  101. * Checks the number of encountered implicit edges against the expected number.
  102. * If there are no implicit edges for the current state, that's fine as well.
  103. * @throws HOAConsumerException if there are more then zero and less then 2^numberOfAPs edges
  104. * @throws std::logic_error if `endOfState()` is called without previous call to `startOfState()`
  105. */
  106. void endOfState()
  107. {
  108. if (!inState) {
  109. throw std::logic_error("ImplicitEdgeHelper: endOfState() without previous call to startOfState()");
  110. }
  111. inState = false;
  112. if (edgeIndex >0 && edgeIndex != edgesPerState) {
  113. throw HOAConsumerException("For state "
  114. + std::to_string(stateId)
  115. + ", less edges than required for "
  116. + std::to_string(numberOfAPs)
  117. + " atomic propositions");
  118. }
  119. }
  120. private:
  121. /** The number of atomic propositions */
  122. unsigned int numberOfAPs;
  123. /** The index of the current edge */
  124. std::size_t edgeIndex = 0;
  125. /** The required number of edges per state */
  126. std::size_t edgesPerState;
  127. /** Are we currently in a state definition? */
  128. bool inState = false;
  129. /** The current state index (for error message) */
  130. std::size_t stateId = 0;
  131. };
  132. }
  133. #endif