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
156 lines
4.9 KiB
//==============================================================================
|
|
//
|
|
// Copyright (c) 2015-
|
|
// Authors:
|
|
// * Joachim Klein <klein@tcs.inf.tu-dresden.de>
|
|
// * David Mueller <david.mueller@tcs.inf.tu-dresden.de>
|
|
//
|
|
//------------------------------------------------------------------------------
|
|
//
|
|
// 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 <exception>
|
|
#include <string>
|
|
|
|
namespace cpphoafparser {
|
|
|
|
/**
|
|
* Helper for keeping track of implicit edges.
|
|
*
|
|
* In `notifyBodyStart()`, call:<br>
|
|
* `helper = new ImplicitEdgeHelper(numberOfAPs);`
|
|
*
|
|
* In `addState()`, call:<br>
|
|
* `helper.startOfState(stateId);`
|
|
*
|
|
* In `addEdgeImplicit()`, call:<br>
|
|
* edgeIndex = helper.nextImplicitEdge();`
|
|
*
|
|
* In `notifyEndOfState()`, call:<br>
|
|
* `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
|