//============================================================================== // // Copyright (c) 2015- // Authors: // * Joachim Klein // * David Mueller // //------------------------------------------------------------------------------ // // This file is part of the cpphoafparser library, // http://automata.tools/hoa/cpphoafparser/ // // The cpphoafparser library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // The cpphoafparser library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // //============================================================================== #ifndef CPPHOAFPARSER_IMPLICITEDGEHELPER_H #define CPPHOAFPARSER_IMPLICITEDGEHELPER_H #include "cpphoafparser/consumer/hoa_consumer_exception.hh" #include #include namespace cpphoafparser { /** * Helper for keeping track of implicit edges. * * In `notifyBodyStart()`, call:
* `helper = new ImplicitEdgeHelper(numberOfAPs);` * * In `addState()`, call:
* `helper.startOfState(stateId);` * * In `addEdgeImplicit()`, call:
* edgeIndex = helper.nextImplicitEdge();` * * In `notifyEndOfState()`, call:
* `helper.endOfState();` */ class ImplicitEdgeHelper { public: /** Constructor, pass number of atomic propositions */ ImplicitEdgeHelper(unsigned int numberOfAPs) : numberOfAPs(numberOfAPs), stateId(0) { edgesPerState = ((std::size_t)1) << numberOfAPs; } /** Return the expected number of edges per state, i.e., 2^|AP|. */ std::size_t getEdgesPerState() { return edgesPerState; } /** Notify the ImplicitEdgeHelper that a new state definition has been encountered. * @param newStateId the state index (for error message) * @throws std::logic_error if `startOfState()` is called before another state is finished with a call to `endOfState() */ void startOfState(unsigned int newStateId) { if (inState) { throw std::logic_error("ImplicitEdgeHelper: startOfState(" + std::to_string(newStateId) + ") without previous call to endOfState()"); } edgeIndex = 0; stateId = newStateId; inState = true; } /** Notify the ImplicitEdgeHelper that the next implicit edge for the current state has been encountered. * Return the edge index. * @return the index of the current edge * @throws HOAConsumerException if the number of edges is more than 2^numberOfAPs * @throws std::logic_error if this function is called without a previous call to `startOfState() * */ std::size_t nextImplicitEdge() { if (!inState) { throw std::logic_error("ImplicitEdgeHelper: nextImplicitEdge() without previous call to startOfState()"); } unsigned long currentEdgeIndex = edgeIndex; edgeIndex++; if (currentEdgeIndex >= edgesPerState) { throw HOAConsumerException("For state " +std::to_string(stateId) +", more edges than allowed for " +std::to_string(numberOfAPs) +" atomic propositions"); } return currentEdgeIndex; } /** Notify the ImplicitEdgeHelper that the current state definition is finished. * Checks the number of encountered implicit edges against the expected number. * If there are no implicit edges for the current state, that's fine as well. * @throws HOAConsumerException if there are more then zero and less then 2^numberOfAPs edges * @throws std::logic_error if `endOfState()` is called without previous call to `startOfState()` */ void endOfState() { if (!inState) { throw std::logic_error("ImplicitEdgeHelper: endOfState() without previous call to startOfState()"); } inState = false; if (edgeIndex >0 && edgeIndex != edgesPerState) { throw HOAConsumerException("For state " + std::to_string(stateId) + ", less edges than required for " + std::to_string(numberOfAPs) + " atomic propositions"); } } private: /** The number of atomic propositions */ unsigned int numberOfAPs; /** The index of the current edge */ std::size_t edgeIndex = 0; /** The required number of edges per state */ std::size_t edgesPerState; /** Are we currently in a state definition? */ bool inState = false; /** The current state index (for error message) */ std::size_t stateId = 0; }; } #endif