CE alte Probeklausur und aktuelle Folien
FoC aktuelle Folien
This commit is contained in:
parent
63af4b992e
commit
3076751364
BIN
ws2011/CE/Folien/gms-03-col.pdf
Normal file
BIN
ws2011/CE/Folien/gms-03-col.pdf
Normal file
Binary file not shown.
BIN
ws2011/CE/Probeklausur.pdf
Normal file
BIN
ws2011/CE/Probeklausur.pdf
Normal file
Binary file not shown.
BIN
ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011.zip
Normal file
BIN
ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011.zip
Normal file
Binary file not shown.
@ -0,0 +1,20 @@
|
||||
ACKNOWLEDGMENTS
|
||||
---------------
|
||||
|
||||
The ascii-soccer environment which was published
|
||||
under the GPL is contained in that distribution
|
||||
with special permission by Tucker Balch.
|
||||
|
||||
The "dot" tool from the GraphViz collection
|
||||
(http://www.graphviz.org) is used for behavior
|
||||
documentation purposes.
|
||||
|
||||
The LibXSLT (http://xmlsoft.org/XSLT/) library is used
|
||||
used for behavior documentation purposes.
|
||||
|
||||
This product includes software developed by the
|
||||
Apache Software Foundation (http://www.apache.org/).
|
||||
|
||||
This product includes DOTML developed by Martin Loetzsch
|
||||
(http://www.martin-loetzsch.de/DOTML).
|
||||
|
||||
@ -0,0 +1,348 @@
|
||||
/**
|
||||
* @file XabslAction.cpp
|
||||
*
|
||||
* Implementation of class Action and helper classes
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
|
||||
#include "XabslAction.h"
|
||||
#include "XabslOption.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
Action* Action::create(
|
||||
InputSource& input,
|
||||
NamedArray<Option*>& options,
|
||||
NamedArray<BasicBehavior*>& basicBehaviors,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state,
|
||||
ErrorHandler& errorHandler,
|
||||
const unsigned& time)
|
||||
{
|
||||
|
||||
char c[2];
|
||||
char buf[100];
|
||||
|
||||
input.readString(c,1);
|
||||
input.readString(buf,99);
|
||||
|
||||
switch (*c)
|
||||
{
|
||||
case 'o':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating reference to option \"%s\"",buf));
|
||||
|
||||
if (!options.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslAction::create(): unknown option \"%s\" was encountered",buf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActionOption* action = new ActionOption(time);
|
||||
action->option = options[buf];
|
||||
action->parameters = new ParameterAssignment(action->option->parameters, errorHandler);
|
||||
action->parameters->create(input,
|
||||
symbols,
|
||||
option,
|
||||
state);
|
||||
return action;
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating reference to basic behavior \"%s\"",buf));
|
||||
|
||||
if (!basicBehaviors.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslAction::create(): the subsequent basic behavior \"%s\" was not registered",buf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActionBasicBehavior* action = new ActionBasicBehavior(time);
|
||||
action->basicBehavior = basicBehaviors[buf];
|
||||
action->parameters = new ParameterAssignment(action->basicBehavior->parameters, errorHandler);
|
||||
action->parameters->create(input,
|
||||
symbols,
|
||||
option,
|
||||
state);
|
||||
return action;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating reference to decimal output symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.decimalOutputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslAction::create(): decimal output symbol \"%s\" does not exist",buf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActionDecimalOutputSymbol* action = new ActionDecimalOutputSymbol(time);
|
||||
action->decimalOutputSymbol = symbols.decimalOutputSymbols[buf];
|
||||
action->decimalOutputSymbolExpression = DecimalExpression::create(input,errorHandler,symbols,option,state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslAction::create(): could not create decimal expression for output symbol \"%s\"",buf);
|
||||
delete action;
|
||||
return 0;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
case 'b':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating reference to boolean output symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.booleanOutputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslAction::create(): boolean output symbol \"%s\" does not exist",buf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActionBooleanOutputSymbol* action = new ActionBooleanOutputSymbol(time);
|
||||
action->booleanOutputSymbol = symbols.booleanOutputSymbols[buf];
|
||||
action->booleanOutputSymbolExpression = BooleanExpression::create(input,errorHandler,symbols,option,state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslAction::create(): could not create boolean expression for output symbol \"%s\"",buf);
|
||||
delete action;
|
||||
return 0;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
case 'e':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating reference to enumerated output symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.enumeratedOutputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslAction::create(): enumerated output symbol \"%s\" does not exist",buf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActionEnumeratedOutputSymbol* action = new ActionEnumeratedOutputSymbol(time);
|
||||
action->enumeratedOutputSymbol = symbols.enumeratedOutputSymbols[buf];
|
||||
action->enumeratedOutputSymbolExpression = EnumeratedExpression::create(action->enumeratedOutputSymbol->enumeration,input,errorHandler,symbols,option,state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslAction::create(): could not create enumerated expression for output symbol \"%s\"",buf);
|
||||
delete action;
|
||||
return 0;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Action* Action::create(
|
||||
Behavior* behavior,
|
||||
ErrorHandler& errorHandler,
|
||||
const unsigned& time)
|
||||
{
|
||||
ActionBehavior* action = 0;
|
||||
if (Option* option = dynamic_cast<Option*>(behavior))
|
||||
{
|
||||
action = new ActionOption(time);
|
||||
static_cast<ActionOption*>(action)->option = option;
|
||||
}
|
||||
else if (BasicBehavior* basicBehavior = dynamic_cast<BasicBehavior*>(behavior))
|
||||
{
|
||||
action = new ActionBasicBehavior(time);
|
||||
static_cast<ActionBasicBehavior*>(action)->basicBehavior = basicBehavior;
|
||||
}
|
||||
if (action != 0)
|
||||
action->parameters = new ParameterAssignment(behavior->parameters, errorHandler);
|
||||
return action;
|
||||
}
|
||||
|
||||
ActionBehavior::~ActionBehavior()
|
||||
{
|
||||
if (parameters!=0)
|
||||
delete parameters;
|
||||
}
|
||||
|
||||
ActionDecimalOutputSymbol::~ActionDecimalOutputSymbol()
|
||||
{
|
||||
if (decimalOutputSymbolExpression!=0)
|
||||
delete decimalOutputSymbolExpression;
|
||||
}
|
||||
|
||||
ActionBooleanOutputSymbol::~ActionBooleanOutputSymbol()
|
||||
{
|
||||
if (booleanOutputSymbolExpression!=0)
|
||||
delete booleanOutputSymbolExpression;
|
||||
}
|
||||
|
||||
ActionEnumeratedOutputSymbol::~ActionEnumeratedOutputSymbol()
|
||||
{
|
||||
if (enumeratedOutputSymbolExpression!=0)
|
||||
delete enumeratedOutputSymbolExpression;
|
||||
}
|
||||
|
||||
void ActionBehavior::execute()
|
||||
{
|
||||
// execute subsequent option or basic behavior
|
||||
if (parameters->set())
|
||||
getBehavior()->parametersChanged();
|
||||
if (!getBehavior()->wasActive) getBehavior()->timeWhenActivated = time;
|
||||
getBehavior()->timeOfExecution = time - getBehavior()->timeWhenActivated;
|
||||
getBehavior()->execute();
|
||||
getBehavior()->isActive = true;
|
||||
}
|
||||
|
||||
void ActionDecimalOutputSymbol::execute()
|
||||
{
|
||||
decimalOutputSymbolValue = decimalOutputSymbolExpression->getValue();
|
||||
decimalOutputSymbol->setValue(decimalOutputSymbolValue);
|
||||
}
|
||||
|
||||
void ActionBooleanOutputSymbol::execute()
|
||||
{
|
||||
booleanOutputSymbolValue = booleanOutputSymbolExpression->getValue();
|
||||
booleanOutputSymbol->setValue(booleanOutputSymbolValue);
|
||||
}
|
||||
|
||||
void ActionEnumeratedOutputSymbol::execute()
|
||||
{
|
||||
enumeratedOutputSymbolValue = enumeratedOutputSymbolExpression->getValue();
|
||||
enumeratedOutputSymbol->setValue(enumeratedOutputSymbolValue);
|
||||
}
|
||||
|
||||
const Behavior* ActionOption::getBehavior() const
|
||||
{
|
||||
return option;
|
||||
}
|
||||
|
||||
const Behavior* ActionBasicBehavior::getBehavior() const
|
||||
{
|
||||
return basicBehavior;
|
||||
}
|
||||
|
||||
Behavior* ActionOption::getBehavior()
|
||||
{
|
||||
return option;
|
||||
}
|
||||
|
||||
Behavior* ActionBasicBehavior::getBehavior()
|
||||
{
|
||||
return basicBehavior;
|
||||
}
|
||||
|
||||
Behavior* Action::getBehavior()
|
||||
{
|
||||
if (ActionBehavior* action = dynamic_cast<ActionBehavior*>(this))
|
||||
return action->getBehavior();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Option* Action::getOption()
|
||||
{
|
||||
if (ActionOption* action = dynamic_cast<ActionOption*>(this))
|
||||
return action->option;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
BasicBehavior* Action::getBasicBehavior()
|
||||
{
|
||||
if (ActionBasicBehavior* action = dynamic_cast<ActionBasicBehavior*>(this))
|
||||
return action->basicBehavior;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Behavior* Action::getBehavior() const
|
||||
{
|
||||
if (const ActionBehavior* action = dynamic_cast<const ActionBehavior*>(this))
|
||||
return action->getBehavior();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Option* Action::getOption() const
|
||||
{
|
||||
if (const ActionOption* action = dynamic_cast<const ActionOption*>(this))
|
||||
return action->option;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const BasicBehavior* Action::getBasicBehavior() const
|
||||
{
|
||||
if (const ActionBasicBehavior* action = dynamic_cast<const ActionBasicBehavior*>(this))
|
||||
return action->basicBehavior;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ParameterAssignment* Action::getParameters()
|
||||
{
|
||||
if (ActionBehavior* action = dynamic_cast<ActionBehavior*>(this))
|
||||
return action->parameters;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const ParameterAssignment* Action::getParameters() const
|
||||
{
|
||||
if (const ActionBehavior* action = dynamic_cast<const ActionBehavior*>(this))
|
||||
return action->parameters;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const DecimalOutputSymbol* Action::getDecimalOutputSymbol() const
|
||||
{
|
||||
if (const ActionDecimalOutputSymbol* action = dynamic_cast<const ActionDecimalOutputSymbol*>(this))
|
||||
return action->decimalOutputSymbol;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const BooleanOutputSymbol* Action::getBooleanOutputSymbol() const
|
||||
{
|
||||
if (const ActionBooleanOutputSymbol* action = dynamic_cast<const ActionBooleanOutputSymbol*>(this))
|
||||
return action->booleanOutputSymbol;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const EnumeratedOutputSymbol* Action::getEnumeratedOutputSymbol() const
|
||||
{
|
||||
if (const ActionEnumeratedOutputSymbol* action = dynamic_cast<const ActionEnumeratedOutputSymbol*>(this))
|
||||
return action->enumeratedOutputSymbol;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
double Action::getDecimalOutputSymbolValue() const
|
||||
{
|
||||
if (const ActionDecimalOutputSymbol* action = dynamic_cast<const ActionDecimalOutputSymbol*>(this))
|
||||
return action->decimalOutputSymbolValue;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Action::getBooleanOutputSymbolValue() const
|
||||
{
|
||||
if (const ActionBooleanOutputSymbol* action = dynamic_cast<const ActionBooleanOutputSymbol*>(this))
|
||||
return action->booleanOutputSymbolValue;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int Action::getEnumeratedOutputSymbolValue() const
|
||||
{
|
||||
if (const ActionEnumeratedOutputSymbol* action = dynamic_cast<const ActionEnumeratedOutputSymbol*>(this))
|
||||
return action->enumeratedOutputSymbolValue;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -0,0 +1,317 @@
|
||||
/**
|
||||
* @file XabslAction.h
|
||||
*
|
||||
* Definition of class Action and Helper classes
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslAction_h_
|
||||
#define __XabslAction_h_
|
||||
|
||||
#include "XabslBasicBehavior.h"
|
||||
#include "XabslDecimalExpression.h"
|
||||
#include "XabslBooleanExpression.h"
|
||||
#include "XabslEnumeratedExpression.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
// class prototype needed for declaration of Action
|
||||
class Option;
|
||||
|
||||
/**
|
||||
* @class Action
|
||||
*
|
||||
* Represents an action execution. This is either a subsequent option or basic behavior to be executed, or an
|
||||
* output symbol assignment.
|
||||
*
|
||||
* @author Max Risler
|
||||
*/
|
||||
class Action
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
Action(const unsigned &time) :
|
||||
time(time)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Virtual destructor.
|
||||
*/
|
||||
virtual ~Action() {}
|
||||
|
||||
/**
|
||||
* Creates an action definition.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a state starts.
|
||||
* @param options All available options
|
||||
* @param basicBehaviors All available basicBehaviors
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
static Action* create(
|
||||
InputSource& input,
|
||||
NamedArray<Option*>& options,
|
||||
NamedArray<BasicBehavior*>& basicBehaviors,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state,
|
||||
ErrorHandler& errorHandler,
|
||||
const unsigned& time);
|
||||
|
||||
/**
|
||||
* Creates an action definition which just calls a single option or basic behavior
|
||||
* without setting any parameters.
|
||||
* @param behavior The referenced option or basic behavior.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
static Action* create(
|
||||
Behavior* behavior,
|
||||
ErrorHandler& errorHandler,
|
||||
const unsigned &time);
|
||||
|
||||
/** Execute the behavior or assign the output symbol */
|
||||
virtual void execute() = 0;
|
||||
|
||||
/** Returns a pointer to the option or basic behavior to be executed, or 0 if an output symbol is set */
|
||||
Behavior* getBehavior();
|
||||
const Behavior* getBehavior() const;
|
||||
|
||||
/** Returns a pointer to the option, if an option is to be executed, 0 otherwise */
|
||||
Option* getOption();
|
||||
const Option* getOption() const;
|
||||
|
||||
/** Returns a pointer to the basic behavior, if a basic behavior is to be executed, 0 otherwise */
|
||||
BasicBehavior* getBasicBehavior();
|
||||
const BasicBehavior* getBasicBehavior() const;
|
||||
|
||||
/** Returns a pointer to the parameter assignments for an option or basic behavior, or 0 if an output symbol is set */
|
||||
ParameterAssignment* getParameters();
|
||||
const ParameterAssignment* getParameters() const;
|
||||
|
||||
/** Returns a pointer to the output symbol, if a decimal output symbol is to be assigned, 0 otherwise */
|
||||
const DecimalOutputSymbol* getDecimalOutputSymbol() const;
|
||||
|
||||
/** Returns a pointer to the output symbol, if a boolean output symbol is to be assigned, 0 otherwise */
|
||||
const BooleanOutputSymbol* getBooleanOutputSymbol() const;
|
||||
|
||||
/** Returns a pointer to the output symbol, if an enumerated output symbol is to be assigned, 0 otherwise */
|
||||
const EnumeratedOutputSymbol* getEnumeratedOutputSymbol() const;
|
||||
|
||||
/** Returns the last symbol value, if a decimal output symbol is to be assigned, 0 otherwise */
|
||||
double getDecimalOutputSymbolValue() const;
|
||||
|
||||
/** Returns the last symbol value, if a boolean output symbol is to be assigned, 0 otherwise */
|
||||
bool getBooleanOutputSymbolValue() const;
|
||||
|
||||
/** Returns the last symbol value, if an enumerated output symbol is to be assigned, 0 otherwise */
|
||||
int getEnumeratedOutputSymbolValue() const;
|
||||
|
||||
protected:
|
||||
/** The system time in ms. */
|
||||
const unsigned& time;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ActionBehavior
|
||||
*
|
||||
* Represents an action execution. This is either a subsequent option or basic behavior to be executed.
|
||||
*
|
||||
* @author Max Risler
|
||||
*/
|
||||
class ActionBehavior : public Action
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
ActionBehavior(const unsigned& time) :
|
||||
Action(time),
|
||||
parameters(0)
|
||||
{}
|
||||
|
||||
/** Destructor */
|
||||
~ActionBehavior();
|
||||
|
||||
/**
|
||||
* Parameters of the option or basic behavior that is executed
|
||||
*/
|
||||
ParameterAssignment* parameters;
|
||||
|
||||
/**
|
||||
* The option or basic behavior that is executed
|
||||
*/
|
||||
virtual const Behavior* getBehavior() const = 0;
|
||||
virtual Behavior* getBehavior() = 0;
|
||||
|
||||
/** Execute the behavior */
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ActionBasicBehavior
|
||||
*
|
||||
* Represents an action execution. In this case a basic behavior is to be executed.
|
||||
*
|
||||
* @author Max Risler
|
||||
*/
|
||||
class ActionBasicBehavior : public ActionBehavior
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
ActionBasicBehavior(const unsigned& time) :
|
||||
ActionBehavior(time),
|
||||
basicBehavior(0)
|
||||
{}
|
||||
|
||||
BasicBehavior* basicBehavior;
|
||||
|
||||
virtual const Behavior* getBehavior() const;
|
||||
virtual Behavior* getBehavior();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ActionOption
|
||||
*
|
||||
* Represents an action execution. In this case an option is to be executed.
|
||||
*
|
||||
* @author Max Risler
|
||||
*/
|
||||
class ActionOption : public ActionBehavior
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
ActionOption(const unsigned& time) :
|
||||
ActionBehavior(time),
|
||||
option(0)
|
||||
{}
|
||||
|
||||
Option* option;
|
||||
|
||||
virtual const Behavior* getBehavior() const;
|
||||
virtual Behavior* getBehavior();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ActionDecimalOutputSymbol
|
||||
*
|
||||
* Represents an action execution, in this case a decimal output symbol assignment
|
||||
*
|
||||
* @author Max Risler
|
||||
*/
|
||||
class ActionDecimalOutputSymbol : public Action
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
ActionDecimalOutputSymbol(const unsigned& time) :
|
||||
Action(time),
|
||||
decimalOutputSymbol(0),
|
||||
decimalOutputSymbolExpression(0),
|
||||
decimalOutputSymbolValue(0)
|
||||
{}
|
||||
|
||||
/** Destructor */
|
||||
~ActionDecimalOutputSymbol();
|
||||
|
||||
/** A decimal output symbol that is set if the state is active, null when a behavior is executed or another output symbol is set */
|
||||
DecimalOutputSymbol* decimalOutputSymbol;
|
||||
/** The expression for the decimal output symbol that is set if the state is active */
|
||||
const DecimalExpression* decimalOutputSymbolExpression;
|
||||
/** Current decimal output symbol value, this is stored just for debugging purposes */
|
||||
double decimalOutputSymbolValue;
|
||||
|
||||
/** Execute the behavior */
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ActionBooleanOutputSymbol
|
||||
*
|
||||
* Represents an action execution, in this case a boolean output symbol assignment
|
||||
*
|
||||
* @author Max Risler
|
||||
*/
|
||||
class ActionBooleanOutputSymbol : public Action
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
ActionBooleanOutputSymbol(const unsigned& time) :
|
||||
Action(time),
|
||||
booleanOutputSymbol(0),
|
||||
booleanOutputSymbolExpression(0),
|
||||
booleanOutputSymbolValue(false)
|
||||
{}
|
||||
|
||||
/** Destructor */
|
||||
~ActionBooleanOutputSymbol();
|
||||
|
||||
/** A boolean output symbol that is set if the state is active, null when a behavior is executed or another output symbol is set */
|
||||
BooleanOutputSymbol* booleanOutputSymbol;
|
||||
/** The expression for the boolean output symbol that is set if the state is active */
|
||||
const BooleanExpression* booleanOutputSymbolExpression;
|
||||
/** Current boolean output symbol value, this is stored just for debugging purposes */
|
||||
bool booleanOutputSymbolValue;
|
||||
|
||||
/** Execute the behavior */
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ActionEnumeratedOutputSymbol
|
||||
*
|
||||
* Represents an action execution, in this case an enumerated output symbol assignment
|
||||
*
|
||||
* @author Max Risler
|
||||
*/
|
||||
class ActionEnumeratedOutputSymbol : public Action
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The system time in ms.
|
||||
*/
|
||||
ActionEnumeratedOutputSymbol(const unsigned& time) :
|
||||
Action(time),
|
||||
enumeratedOutputSymbol(0),
|
||||
enumeratedOutputSymbolExpression(0),
|
||||
enumeratedOutputSymbolValue(0)
|
||||
{}
|
||||
|
||||
/** Destructor */
|
||||
~ActionEnumeratedOutputSymbol();
|
||||
|
||||
/** An enumerated output symbol that is set if the state is active, null when a behavior is executed or another output symbol is set */
|
||||
EnumeratedOutputSymbol* enumeratedOutputSymbol;
|
||||
/** The expression for the enumerated output symbol that is set if the state is active */
|
||||
const EnumeratedExpression* enumeratedOutputSymbolExpression;
|
||||
/** Current enumerated output symbol value, this is stored just for debugging purposes */
|
||||
int enumeratedOutputSymbolValue;
|
||||
|
||||
/** Execute the behavior */
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslAction_h_
|
||||
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @file XabslAgent.cpp
|
||||
*
|
||||
* Implementation of class Agent
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
|
||||
#include "XabslAgent.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
Agent::Agent(const char* name, Behavior* rootOption,
|
||||
ErrorHandler& errorHandler, int index)
|
||||
: NamedItem(name), rootOption(rootOption), errorHandler(errorHandler), index(index)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("created agent \"%s\" with root option \"%s\"", n, rootOption->n));
|
||||
}
|
||||
|
||||
Behavior* Agent::getRootOption() const
|
||||
{
|
||||
return rootOption;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @file XabslAgent.h
|
||||
*
|
||||
* Definition of class Agent
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslAgent_h_
|
||||
#define __XabslAgent_h_
|
||||
|
||||
#include "XabslBehavior.h"
|
||||
#include "XabslTools.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class Agent
|
||||
*
|
||||
* Combines some options to an agent
|
||||
*
|
||||
* @author Martin Loetzsch
|
||||
*/
|
||||
class Agent : public NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the agent
|
||||
* @param rootOption A pointer to the initial option of the agent
|
||||
* @param errorHandler Is invoked when errors occur
|
||||
* @param index Index of the agent in array agents in corresponding engine
|
||||
*/
|
||||
Agent(const char* name, Behavior* rootOption,
|
||||
ErrorHandler& errorHandler, int index);
|
||||
|
||||
/** Returns the root option */
|
||||
Behavior* getRootOption() const;
|
||||
private:
|
||||
|
||||
/** A pointer to the root option */
|
||||
Behavior* rootOption;
|
||||
|
||||
/** Is invoked when errors occur */
|
||||
ErrorHandler& errorHandler;
|
||||
|
||||
/** Index of the agent in array agents in corresponding engine */
|
||||
int index;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // __XabslAgent_h_
|
||||
@ -0,0 +1,396 @@
|
||||
/**
|
||||
* @file XabslArray.h
|
||||
*
|
||||
* Declaration and implementation of template class NamedArray
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
* @author <a href="http://www.tzi.de/~roefer/">Thomas Ršfer</a>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __XabslArray_h_
|
||||
#define __XabslArray_h_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class NamedItem
|
||||
* A class that has a text label
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the item
|
||||
*/
|
||||
NamedItem(const char* name)
|
||||
{
|
||||
n = new char[strlen(name)+1];
|
||||
strcpy(n,name);
|
||||
}
|
||||
|
||||
/** Destructor. Deletes the name */
|
||||
virtual ~NamedItem() { delete[] n; }
|
||||
|
||||
/** The text label */
|
||||
char* n;
|
||||
};
|
||||
|
||||
/**
|
||||
* An element of an NamedArray.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
* @author <a href="http://www.tzi.de/~roefer/">Thomas Ršfer</a>
|
||||
*/
|
||||
template<class T> class NamedArrayElement : public NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param name A string label for the element.
|
||||
* @param element The new element.
|
||||
*/
|
||||
NamedArrayElement(const char* name, T element)
|
||||
: NamedItem(name), e(element) {}
|
||||
|
||||
/**
|
||||
* Destructor. If the element is a pointer, it has to be
|
||||
* deleted externally
|
||||
*/
|
||||
virtual ~NamedArrayElement() {}
|
||||
|
||||
/** The element */
|
||||
T e;
|
||||
};
|
||||
|
||||
/**
|
||||
* The class implements a dynamic array.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
* @author <a href="http://www.tzi.de/~roefer/">Thomas Ršfer</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
template <class T> class Array
|
||||
{
|
||||
public:
|
||||
/** Constructor */
|
||||
Array()
|
||||
{
|
||||
usedSize = 0;
|
||||
allocatedSize = 2;
|
||||
data = new T[allocatedSize];
|
||||
}
|
||||
|
||||
/** Destructor */
|
||||
virtual ~Array()
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
/** Assignment operator
|
||||
*\param other The other Array that is assigned to this one
|
||||
*\return A reference to this object after the assignment.
|
||||
*/
|
||||
Array<T>& operator=(const Array<T>& other)
|
||||
{
|
||||
delete[] data;
|
||||
usedSize = other.usedSize;
|
||||
allocatedSize = other.allocatedSize;
|
||||
data = new T[allocatedSize];
|
||||
for (int i = 0; i < usedSize; ++i)
|
||||
data[i]=other.data[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Copy constructor
|
||||
*\param other The other vector that is copied to this one
|
||||
*/
|
||||
Array(const Array<T>& other)
|
||||
{
|
||||
data = new T[0];
|
||||
*this = other;
|
||||
}
|
||||
|
||||
/** Clears the array */
|
||||
void clear()
|
||||
{
|
||||
delete[] data;
|
||||
usedSize = 0;
|
||||
allocatedSize = 2;
|
||||
data = new T[allocatedSize];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for a given array position.
|
||||
* Note that the function crashes if the required position is bigger than the
|
||||
* size of the array.
|
||||
*/
|
||||
T getElement(int pos) const
|
||||
{
|
||||
return data[pos];
|
||||
}
|
||||
|
||||
/**
|
||||
* The function appends a new element to the array.
|
||||
* @param element The new element.
|
||||
*/
|
||||
void append(T element)
|
||||
{
|
||||
if(usedSize == allocatedSize)
|
||||
{
|
||||
allocatedSize += allocatedSize / 2; // note that allocatedSize must be at least 2
|
||||
T* temp = new T[allocatedSize];
|
||||
for(int i = 0; i < getSize(); ++i)
|
||||
temp[i] = data[i];
|
||||
delete[] data;
|
||||
data = temp;
|
||||
}
|
||||
data[usedSize++] = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the value of an element in the array.
|
||||
* Note that the function crashes if the element does not exist.
|
||||
* @param pos The position of the element in the array.
|
||||
* @param value The new element.
|
||||
*/
|
||||
void setElement(int pos, T value)
|
||||
{
|
||||
data[pos] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function returns the number of elements in the array.
|
||||
* @return The length of the list.
|
||||
*/
|
||||
int getSize() const {return usedSize;}
|
||||
|
||||
/**
|
||||
* Returns the value for a given array position.
|
||||
* Note that the function crashes if the required position is bigger than the
|
||||
* size of the array.
|
||||
*/
|
||||
const T& operator[](int pos) const
|
||||
{
|
||||
return data[pos];
|
||||
}
|
||||
T& operator[](int pos)
|
||||
{
|
||||
while (pos >= usedSize) append(T());
|
||||
return data[pos];
|
||||
}
|
||||
|
||||
/** Removes the last element of the array */
|
||||
void removeLast()
|
||||
{
|
||||
if (usedSize > 0)
|
||||
usedSize--;
|
||||
}
|
||||
|
||||
operator Array<const T>&() {return this;}
|
||||
|
||||
protected:
|
||||
/** The array */
|
||||
T* data;
|
||||
|
||||
/** The number of elements in the array */
|
||||
int usedSize, allocatedSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* The class implements a dynamic array. Each array element can have a text label.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
* @author <a href="http://www.tzi.de/~roefer/">Thomas Ršfer</a>
|
||||
*/
|
||||
template <class T> class NamedArray : public Array<NamedArrayElement<T>*>
|
||||
{
|
||||
public:
|
||||
/** Destructor */
|
||||
virtual ~NamedArray()
|
||||
{
|
||||
for(int i = 0; i < this->getSize(); ++i)
|
||||
delete this->data[i];
|
||||
}
|
||||
|
||||
/** Assignment operator
|
||||
*\param other The other NamedArray that is assigned to this one
|
||||
*\return A reference to this object after the assignment.
|
||||
*/
|
||||
NamedArray<T>& operator=(const NamedArray<T>& other)
|
||||
{
|
||||
for(int i = 0; i < this->usedSize; ++i)
|
||||
delete this->data[i];
|
||||
delete[] this->data;
|
||||
this->usedSize = other.usedSize;
|
||||
this->allocatedSize = other.allocatedSize;
|
||||
this->data = new T[this->allocatedSize];
|
||||
for (int i = 0; i < this->usedSize; ++i)
|
||||
this->data[i]=new NamedArrayElement<T>(other.data[i]->n,other.data[i]->e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Clears the array */
|
||||
void clear()
|
||||
{
|
||||
for(int i = 0; i < this->getSize(); ++i)
|
||||
delete this->data[i];
|
||||
Array<NamedArrayElement<T>*>::clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for a given name.
|
||||
* If no element exists for the name, the default value is returned.
|
||||
* @param name The name element
|
||||
* @param defaultValue The value that is returned if no element exists for the name.
|
||||
* @return Either the element found or the default value.
|
||||
*/
|
||||
T getElement(const char* name, T defaultValue) const
|
||||
{
|
||||
int pos = find(name);
|
||||
if(pos < 0)
|
||||
return defaultValue;
|
||||
else
|
||||
return getElement(pos)->e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for a given name.
|
||||
* Note that the function crashes if the element does not exist.
|
||||
* @param name The name of the element
|
||||
*/
|
||||
T& getElement(const char* name) const
|
||||
{
|
||||
return getElement(find(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for a given array position.
|
||||
* Note that the function crashes if the required position is bigger than the
|
||||
* size of the array.
|
||||
*/
|
||||
T& getElement(int pos) const
|
||||
{
|
||||
return this->data[pos]->e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the array element for a given name.
|
||||
* Note that the function crashes if the element does not exist
|
||||
* @param name the name of the element
|
||||
*/
|
||||
NamedArrayElement<T>* getPElement(const char* name)
|
||||
{
|
||||
return this->data[find(name)];
|
||||
}
|
||||
|
||||
/** Returns the name of an element */
|
||||
const char* getName(int pos) const
|
||||
{
|
||||
return this->data[pos]->n;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function appends a new element to the array.
|
||||
* @param name A string label for the element.
|
||||
* @param element The new element.
|
||||
*/
|
||||
void append(const char* name, T element)
|
||||
{
|
||||
Array<NamedArrayElement<T>*>::append(new NamedArrayElement<T>(name,element));
|
||||
}
|
||||
void append(T element)
|
||||
{
|
||||
append("",element);
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the value of an element in the array.
|
||||
* Note that the function crashes if the element does not exist.
|
||||
* @param name A string label for the element.
|
||||
* @param value The new element.
|
||||
*/
|
||||
void setElement(const char* name, T value)
|
||||
{
|
||||
setElement(find(name),value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The function sets the value of an element in the array.
|
||||
* Note that the function crashes if the element does not exist.
|
||||
* @param pos The position of the element in the array.
|
||||
* @param value The new element.
|
||||
*/
|
||||
void setElement(int pos, T value)
|
||||
{
|
||||
this->data[pos]->e = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for a given array position.
|
||||
* Note that the function crashes if the required position is bigger than the
|
||||
* size of the array.
|
||||
*/
|
||||
T operator[](int pos) const
|
||||
{
|
||||
return getElement(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for a given name.
|
||||
* Note that the function crashes if the element does not exist.
|
||||
* @param name The name of the element
|
||||
*/
|
||||
T operator[](const char* name) const
|
||||
{
|
||||
return getElement(name);
|
||||
}
|
||||
|
||||
/** Returns whether an element for the given name exists */
|
||||
bool exists(const char* name) const
|
||||
{
|
||||
return find(name) >= 0;
|
||||
}
|
||||
|
||||
/** Removes the last element of the array */
|
||||
void removeLast()
|
||||
{
|
||||
if (this->usedSize > 0)
|
||||
delete this->data[--this->usedSize];
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Returns the index of an element with the given name.
|
||||
* @param name The name that is searched for.
|
||||
* @return The index of the element of -1 if the name does not exist.
|
||||
*/
|
||||
int find(const char* name) const
|
||||
{
|
||||
for(int i = 0; i < this->getSize(); ++i)
|
||||
if(!strcmp(getName(i),name))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // __XabslArray_h_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file XabslBasicBehavior.h
|
||||
*
|
||||
* Declaration class BasicBehavior
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslBasicBehavior_h_
|
||||
#define __XabslBasicBehavior_h_
|
||||
|
||||
#include "XabslTools.h"
|
||||
#include "XabslBehavior.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* The base class for basic behaviors that are used by the Engine
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
*/
|
||||
class BasicBehavior : public Behavior
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the basic behavior
|
||||
* @param errorHandler A reference to the error handler
|
||||
*/
|
||||
BasicBehavior(const char* name, ErrorHandler& errorHandler)
|
||||
: Behavior(name), index(-1)
|
||||
{
|
||||
parameters = new Parameters(errorHandler);
|
||||
};
|
||||
|
||||
/** Destructor */
|
||||
virtual ~BasicBehavior()
|
||||
{
|
||||
delete parameters;
|
||||
}
|
||||
|
||||
/** Registers the parameters. */
|
||||
virtual void registerParameters() {}
|
||||
|
||||
/** Index of the basic behavior in array basicBehaviors in corresponding engine */
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // __XabslBasicBehavior_h_
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file XabslBehavior.h
|
||||
*
|
||||
* Definition of class Behavior
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslBehavior_h_
|
||||
#define __XabslBehavior_h_
|
||||
|
||||
#include "XabslArray.h"
|
||||
#include "XabslSymbols.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class Behavior
|
||||
*
|
||||
* Parent class for Option and BasicBehavior
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class Behavior : public NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param name The name of the behavior. For debugging purposes.
|
||||
*/
|
||||
Behavior(const char* name) :
|
||||
NamedItem(name),
|
||||
isActive(false),
|
||||
wasActive(false),
|
||||
timeOfExecution(0),
|
||||
timeWhenActivated(0),
|
||||
parameters(0)
|
||||
{};
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Behavior() {};
|
||||
|
||||
/** the behavior is activated in the current path through the option graph */
|
||||
bool isActive;
|
||||
|
||||
/** the behavior was activated in the last path trough the option graph */
|
||||
bool wasActive;
|
||||
|
||||
/**
|
||||
* executes the behavior
|
||||
*/
|
||||
virtual void execute() = 0;
|
||||
|
||||
/** the time how long the option is already active */
|
||||
unsigned timeOfExecution;
|
||||
|
||||
/** The time, when the option was activated */
|
||||
unsigned timeWhenActivated;
|
||||
|
||||
/** The parameters of the behavior */
|
||||
Parameters* parameters;
|
||||
|
||||
/** Notify the software environment about a parameter change */
|
||||
virtual void parametersChanged() {};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslBehavior_h_
|
||||
@ -0,0 +1,477 @@
|
||||
/**
|
||||
* @file XabslBooleanExpression.cpp
|
||||
*
|
||||
* Implementation of BooleanExpression and derivates
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#include "XabslBooleanExpression.h"
|
||||
#include "XabslOption.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
BooleanExpression::~BooleanExpression()
|
||||
{
|
||||
}
|
||||
|
||||
BooleanExpression* BooleanExpression::create(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
char c[100];
|
||||
BooleanExpression* booleanOperand = 0;
|
||||
DecimalExpression* decimalOperand1 = 0;
|
||||
DecimalExpression* decimalOperand2 = 0;
|
||||
RelationalAndEqualityOperator* relationalAndEqualityOperator = 0;
|
||||
input.readString(c,1);
|
||||
|
||||
switch (*c)
|
||||
{
|
||||
case 'v':
|
||||
return new BooleanValue(input,errorHandler);
|
||||
case 'p':
|
||||
return new BooleanOptionParameterRef(input,errorHandler,option);
|
||||
case 'i':
|
||||
return new BooleanInputSymbolRef(input,errorHandler,symbols,option,state);
|
||||
case 'o':
|
||||
return new BooleanOutputSymbolRef(input,errorHandler,symbols);
|
||||
case 't':
|
||||
return new SubsequentOptionReachedTargetStateCondition(errorHandler, state);
|
||||
case 'c':
|
||||
return new EnumeratedInputSymbolComparison(input, errorHandler, symbols, option, state);
|
||||
case '&':
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating and operator"));
|
||||
|
||||
int numberOfOperands = (int)input.readValue();
|
||||
|
||||
AndOperator* andOperator = new AndOperator();
|
||||
|
||||
for (int i=0; i<numberOfOperands; i++)
|
||||
{
|
||||
if (!BooleanExpression::createOperand(booleanOperand, input, errorHandler, symbols, option, state))
|
||||
{
|
||||
delete andOperator;
|
||||
return 0;
|
||||
}
|
||||
|
||||
andOperator->addOperand(booleanOperand);
|
||||
}
|
||||
|
||||
return andOperator;
|
||||
}
|
||||
case '|':
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating or operator"));
|
||||
|
||||
int numberOfOperands = (int)input.readValue();
|
||||
|
||||
OrOperator* orOperator = new OrOperator();
|
||||
|
||||
for (int i=0; i<numberOfOperands; i++)
|
||||
{
|
||||
if (!BooleanExpression::createOperand(booleanOperand, input, errorHandler, symbols, option, state))
|
||||
{
|
||||
delete orOperator;
|
||||
return 0;
|
||||
}
|
||||
orOperator->addOperand(booleanOperand);
|
||||
}
|
||||
|
||||
return orOperator;
|
||||
}
|
||||
case '!':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating not operator"));
|
||||
|
||||
if (!BooleanExpression::createOperand(booleanOperand, input, errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
return new NotOperator(booleanOperand);
|
||||
case '=':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating == operator"));
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand1,input, errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand2,input, errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
relationalAndEqualityOperator = new EqualToOperator();
|
||||
relationalAndEqualityOperator->create(decimalOperand1,decimalOperand2);
|
||||
return relationalAndEqualityOperator;
|
||||
case 'n':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating != operator"));
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand1,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand2,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
relationalAndEqualityOperator = new NotEqualToOperator();
|
||||
relationalAndEqualityOperator->create(decimalOperand1,decimalOperand2);
|
||||
return relationalAndEqualityOperator;
|
||||
case '<':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating < operator"));
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand1,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand2,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
relationalAndEqualityOperator = new LessThanOperator();
|
||||
relationalAndEqualityOperator->create(decimalOperand1,decimalOperand2);
|
||||
return relationalAndEqualityOperator;
|
||||
case 'l':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating <= operator"));
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand1,input,errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand2,input,errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
relationalAndEqualityOperator = new LessThanOrEqualToOperator();
|
||||
relationalAndEqualityOperator->create(decimalOperand1,decimalOperand2);
|
||||
return relationalAndEqualityOperator;
|
||||
case '>':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating > operator"));
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand1,input,errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand2,input,errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
relationalAndEqualityOperator = new GreaterThanOperator();
|
||||
relationalAndEqualityOperator->create(decimalOperand1,decimalOperand2);
|
||||
return relationalAndEqualityOperator;
|
||||
case 'g':
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating >= operator"));
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand1,input,errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
if (!DecimalExpression::createOperand(decimalOperand2,input,errorHandler, symbols, option, state))
|
||||
return 0;
|
||||
|
||||
relationalAndEqualityOperator = new GreaterThanOrEqualToOperator();
|
||||
relationalAndEqualityOperator->create(decimalOperand1,decimalOperand2);
|
||||
return relationalAndEqualityOperator;
|
||||
case 'x':
|
||||
return new ConflictCondition(errorHandler, state);
|
||||
default:
|
||||
errorHandler.error("XabslBooleanExpression::create(): unknown expression type \"%c\"",*c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BooleanExpression::createOperand(BooleanExpression*& operand,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
operand = BooleanExpression::create(input,errorHandler,symbols,option,state);
|
||||
|
||||
if (operand == 0)
|
||||
{
|
||||
errorHandler.error("XabslBooleanExpression::createOperand(): created operand is 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslBooleanExpression::createOperand(): could not create operand");
|
||||
if (operand != 0) delete operand;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BooleanValue::BooleanValue(InputSource& input,
|
||||
ErrorHandler& errorHandler)
|
||||
{
|
||||
char buf[6];
|
||||
input.readString(buf,5);
|
||||
|
||||
value = (strcmp("true",buf) == 0);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("created boolean value: \"%s\"",value?"true":"false"));
|
||||
}
|
||||
|
||||
bool BooleanValue::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
BooleanOptionParameterRef::BooleanOptionParameterRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Option& option)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a reference to boolean option parameter \"%s\"",buf));
|
||||
|
||||
if (!option.parameters->boolean.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslBooleanOptionParameterRef::BooleanOptionParameterRef(): boolean option parameter \"%s\" does not exist",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
parameter = option.parameters->boolean.getPElement(buf)->e;
|
||||
}
|
||||
|
||||
bool BooleanOptionParameterRef::getValue() const
|
||||
{
|
||||
return *parameter;
|
||||
}
|
||||
|
||||
AndOperator::AndOperator()
|
||||
{
|
||||
operands.clear();
|
||||
}
|
||||
|
||||
AndOperator::~AndOperator()
|
||||
{
|
||||
for (int i=0; i< operands.getSize(); i++)
|
||||
{
|
||||
if (operands[i]!=0) delete operands[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool AndOperator::getValue() const
|
||||
{
|
||||
for (int i=0; i< operands.getSize(); i++)
|
||||
{
|
||||
if (operands[i]->getValue() == false) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndOperator::addOperand(BooleanExpression* operand)
|
||||
{
|
||||
operands.append(operand);
|
||||
}
|
||||
|
||||
OrOperator::OrOperator()
|
||||
{
|
||||
operands.clear();
|
||||
}
|
||||
|
||||
OrOperator::~OrOperator()
|
||||
{
|
||||
for (int i=0; i< operands.getSize(); i++)
|
||||
{
|
||||
if (operands[i]!=0) delete operands[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool OrOperator::getValue() const
|
||||
{
|
||||
for (int i=0; i< operands.getSize(); i++)
|
||||
{
|
||||
if (operands[i]->getValue() == true) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void OrOperator::addOperand(BooleanExpression* operand)
|
||||
{
|
||||
operands.append(operand);
|
||||
}
|
||||
|
||||
NotOperator::NotOperator(BooleanExpression* operand1) :
|
||||
operand1(operand1)
|
||||
{
|
||||
}
|
||||
|
||||
NotOperator::~NotOperator()
|
||||
{
|
||||
if (operand1!=0) delete operand1;
|
||||
}
|
||||
|
||||
bool NotOperator::getValue() const
|
||||
{
|
||||
return !(operand1->getValue());
|
||||
}
|
||||
|
||||
BooleanInputSymbolRef::BooleanInputSymbolRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state) :
|
||||
symbol(0), parameters(0)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating reference to boolean input symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.booleanInputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslBooleanInputSymbolRef::XabslBooleanInputSymbolRef(): boolean input symbol \"%s\" was not registered at the engine",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
symbol = symbols.booleanInputSymbols[buf];
|
||||
|
||||
parameters = new ParameterAssignment(&symbol->parameters, errorHandler);
|
||||
|
||||
parameters->create(input, symbols, option, state);
|
||||
}
|
||||
|
||||
BooleanInputSymbolRef::~BooleanInputSymbolRef()
|
||||
{
|
||||
if (parameters != 0)
|
||||
delete parameters;
|
||||
}
|
||||
|
||||
bool BooleanInputSymbolRef::getValue() const
|
||||
{
|
||||
// set the symbol parameters
|
||||
if (parameters->set())
|
||||
symbol->parametersChanged();
|
||||
|
||||
return symbol->getValue();
|
||||
}
|
||||
|
||||
BooleanOutputSymbolRef::BooleanOutputSymbolRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a reference to a boolean output symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.booleanOutputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslBooleanOutputSymbolRef::BooleanOutputSymbolRef(): boolean output symbol \"%s\" was not registered",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
symbol = symbols.booleanOutputSymbols[buf];
|
||||
}
|
||||
|
||||
bool BooleanOutputSymbolRef::getValue() const
|
||||
{
|
||||
return symbol->getValue();
|
||||
}
|
||||
|
||||
SubsequentOptionReachedTargetStateCondition::SubsequentOptionReachedTargetStateCondition(
|
||||
ErrorHandler& errorHandler,
|
||||
State& state)
|
||||
: state(state)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a \"subsequent-option-reached-target-state\" element"));
|
||||
}
|
||||
|
||||
bool SubsequentOptionReachedTargetStateCondition::getValue() const
|
||||
{
|
||||
bool anySubsequentBehaviorReachedTargetState = false;
|
||||
for (int i = 0; i < state.actions.getSize(); i++)
|
||||
if (ActionOption* subsequentAction = dynamic_cast<ActionOption*>(state.actions[i]))
|
||||
if (subsequentAction->option->getOptionReachedATargetState())
|
||||
anySubsequentBehaviorReachedTargetState = true;
|
||||
return anySubsequentBehaviorReachedTargetState;
|
||||
}
|
||||
|
||||
ConflictCondition::ConflictCondition(
|
||||
ErrorHandler& errorHandler,
|
||||
State& state)
|
||||
: state(state)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a \"conflict\" element"));
|
||||
}
|
||||
|
||||
bool ConflictCondition::getValue() const
|
||||
{
|
||||
return state.getConflict();
|
||||
}
|
||||
|
||||
EnumeratedInputSymbolComparison::EnumeratedInputSymbolComparison(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
if (!EnumeratedExpression::createOperand(operand1,NULL,input,errorHandler,symbols,option,state))
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedInputSymbolComparison::EnumeratedInputSymbolComparison(): could not create enumerated expression");
|
||||
operand1 = operand2 = 0;
|
||||
return;
|
||||
}
|
||||
if (!EnumeratedExpression::createOperand(operand2,operand1->enumeration,input,errorHandler,symbols,option,state))
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedInputSymbolComparison::EnumeratedInputSymbolComparison(): could not create enumerated expression");
|
||||
operand2 = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EnumeratedInputSymbolComparison::~EnumeratedInputSymbolComparison()
|
||||
{
|
||||
if (operand1!=0) delete operand1;
|
||||
if (operand2!=0) delete operand2;
|
||||
}
|
||||
|
||||
bool EnumeratedInputSymbolComparison::getValue() const
|
||||
{
|
||||
return (operand1->getValue() == operand2->getValue());
|
||||
}
|
||||
|
||||
void RelationalAndEqualityOperator::create(DecimalExpression* operand1,
|
||||
DecimalExpression* operand2)
|
||||
{
|
||||
this->operand1 = operand1;
|
||||
this->operand2 = operand2;
|
||||
}
|
||||
|
||||
RelationalAndEqualityOperator ::~RelationalAndEqualityOperator ()
|
||||
{
|
||||
if (operand1!=0) delete operand1;
|
||||
if (operand2!=0) delete operand2;
|
||||
}
|
||||
|
||||
bool EqualToOperator::getValue() const
|
||||
{
|
||||
return (operand1->getValue() == operand2->getValue());
|
||||
}
|
||||
|
||||
bool NotEqualToOperator::getValue() const
|
||||
{
|
||||
return (operand1->getValue() != operand2->getValue());
|
||||
}
|
||||
|
||||
bool LessThanOperator::getValue() const
|
||||
{
|
||||
return (operand1->getValue() < operand2->getValue());
|
||||
}
|
||||
|
||||
bool LessThanOrEqualToOperator::getValue() const
|
||||
{
|
||||
return (operand1->getValue() <= operand2->getValue());
|
||||
}
|
||||
|
||||
bool GreaterThanOperator::getValue() const
|
||||
{
|
||||
return (operand1->getValue() > operand2->getValue());
|
||||
}
|
||||
|
||||
bool GreaterThanOrEqualToOperator::getValue() const
|
||||
{
|
||||
return (operand1->getValue() >= operand2->getValue());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,495 @@
|
||||
/**
|
||||
* @file XabslBooleanExpression.h
|
||||
*
|
||||
* Definition of BooleanExpression and derivates
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslBooleanExpression_h_
|
||||
#define __XabslBooleanExpression_h_
|
||||
|
||||
#include "XabslDecimalExpression.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class BooleanExpression
|
||||
*
|
||||
* Base class for all boolean expressions inside an option graph.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class BooleanExpression
|
||||
{
|
||||
public:
|
||||
/** Evaluates the boolean expression. */
|
||||
virtual bool getValue() const = 0;
|
||||
|
||||
/**
|
||||
* Creates a boolean expression depending on the input.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a boolean expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
static BooleanExpression* create(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
virtual ~BooleanExpression() = 0;
|
||||
|
||||
/**
|
||||
* Creates a boolean expression depending on the input.
|
||||
* Uses the create() function to create boolean operands.
|
||||
* @param operand The expression to be created
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a boolean operand starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
* @return If the creation was successful
|
||||
*/
|
||||
static bool createOperand(
|
||||
BooleanExpression*& operand,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class BooleanValue
|
||||
*
|
||||
* Represents a boolean value.
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class BooleanValue : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the value
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a value starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
*/
|
||||
BooleanValue(InputSource& input,
|
||||
ErrorHandler& errorHandler);
|
||||
|
||||
/**
|
||||
* Constructor. Creates an expression for a fixed boolean value
|
||||
* @param value The boolean value
|
||||
*/
|
||||
BooleanValue(bool value) : value(value) {}
|
||||
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual bool getValue() const;
|
||||
|
||||
private:
|
||||
/** The value */
|
||||
bool value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class BooleanOptionParameterRef
|
||||
*
|
||||
* Represents a reference to a decimal option parameter.
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class BooleanOptionParameterRef : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the reference
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where the expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param option The current option
|
||||
*/
|
||||
BooleanOptionParameterRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Option& option);
|
||||
|
||||
/** Calculates the value of the boolean expression. */
|
||||
virtual bool getValue() const;
|
||||
|
||||
private:
|
||||
/** A pointer to the parameter */
|
||||
bool* parameter;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class AndOperator
|
||||
*
|
||||
* Represents an 'and' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class AndOperator : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/** Constructor */
|
||||
AndOperator();
|
||||
|
||||
/** Destructor. Deletes the two operands */
|
||||
~AndOperator();
|
||||
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const;
|
||||
|
||||
/** Adds an operand to the operands array */
|
||||
void addOperand(BooleanExpression* operand);
|
||||
|
||||
private:
|
||||
/** the 2+n operands of the operator */
|
||||
Array<BooleanExpression*> operands;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class OrOperator
|
||||
*
|
||||
* Represents an 'or' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class OrOperator : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/** Constructor */
|
||||
OrOperator();
|
||||
|
||||
/** Destructor. Deletes the two operands */
|
||||
~OrOperator();
|
||||
|
||||
/** Evaluates the boolean expression. */
|
||||
virtual bool getValue() const;
|
||||
|
||||
/** Adds an operand to the operands array */
|
||||
void addOperand(BooleanExpression* operand);
|
||||
|
||||
private:
|
||||
/** the 2+n operands of the operator */
|
||||
Array<BooleanExpression*> operands;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class NotOperator
|
||||
*
|
||||
* Represents an 'not' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class NotOperator : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the element.
|
||||
* @param operand1 A boolean expression
|
||||
*/
|
||||
NotOperator(BooleanExpression* operand1);
|
||||
|
||||
/** Destructor. Deletes the operand */
|
||||
~NotOperator();
|
||||
|
||||
/** Evaluates the boolean expression. */
|
||||
virtual bool getValue() const;
|
||||
|
||||
private:
|
||||
/** operand 1 */
|
||||
BooleanExpression* operand1;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class BooleanInputSymbolRef
|
||||
*
|
||||
* Represents an 'boolean-input-symbol-ref' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class BooleanInputSymbolRef : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the element
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
BooleanInputSymbolRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
~BooleanInputSymbolRef();
|
||||
|
||||
/** Evaluates the boolean expression. */
|
||||
virtual bool getValue() const;
|
||||
|
||||
private:
|
||||
/** The referenced symbol */
|
||||
BooleanInputSymbol* symbol;
|
||||
|
||||
/** The parameter assignments of the referenced symbol */
|
||||
ParameterAssignment* parameters;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class BooleanOutputSymbolRef
|
||||
*
|
||||
* Represents a reference to a boolean input symbol.
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class BooleanOutputSymbolRef : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the boolean expression. */
|
||||
virtual bool getValue() const;
|
||||
|
||||
/**
|
||||
* Constructor. Creates the function call depending on the input.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where the function reference starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
*/
|
||||
BooleanOutputSymbolRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols);
|
||||
|
||||
private:
|
||||
/** The referenced symbol */
|
||||
BooleanOutputSymbol* symbol;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class SubsequentOptionReachedTargetStateCondition
|
||||
*
|
||||
* Represents an 'subsequent-option-reached-target-state' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class SubsequentOptionReachedTargetStateCondition : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the element.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param state The current state
|
||||
*/
|
||||
SubsequentOptionReachedTargetStateCondition(
|
||||
ErrorHandler& errorHandler,
|
||||
State& state);
|
||||
|
||||
/** Evaluates the boolean expression. */
|
||||
virtual bool getValue() const;
|
||||
|
||||
private:
|
||||
/** The state */
|
||||
State& state;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ConflictCondition
|
||||
*
|
||||
* Represents an 'conflict' element of the option graph
|
||||
*
|
||||
* @author Max Risler
|
||||
*/
|
||||
class ConflictCondition : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the element.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param state The current state
|
||||
*/
|
||||
ConflictCondition(
|
||||
ErrorHandler& errorHandler,
|
||||
State& state);
|
||||
|
||||
/** Evaluates the boolean expression. */
|
||||
virtual bool getValue() const;
|
||||
|
||||
private:
|
||||
/** The state */
|
||||
State& state;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EnumeratedInputSymbolComparison
|
||||
*
|
||||
* Represents an 'enumerated-input-symbol-comparison' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class EnumeratedInputSymbolComparison : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the element
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
EnumeratedInputSymbolComparison(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor. Deletes the two operands */
|
||||
~EnumeratedInputSymbolComparison();
|
||||
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const;
|
||||
|
||||
protected:
|
||||
/** operand 1 */
|
||||
const EnumeratedExpression* operand1;
|
||||
|
||||
/** operand 2 */
|
||||
const EnumeratedExpression* operand2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class RelationalAndEqualityOperator
|
||||
*
|
||||
* Base class for the operators <, <=, >, >=, == and !=
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class RelationalAndEqualityOperator : public BooleanExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates the element.
|
||||
* @param operand1 A decimal expression
|
||||
* @param operand2 A decimal expression
|
||||
*/
|
||||
void create(DecimalExpression* operand1,
|
||||
DecimalExpression* operand2);
|
||||
|
||||
/** Destructor. Deletes the two operands */
|
||||
~RelationalAndEqualityOperator();
|
||||
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const = 0;
|
||||
|
||||
protected:
|
||||
/** operand 1 */
|
||||
DecimalExpression* operand1;
|
||||
|
||||
/** operand 2 */
|
||||
DecimalExpression* operand2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EqualToOperator
|
||||
*
|
||||
* Represents an 'equal-to' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class EqualToOperator : public RelationalAndEqualityOperator
|
||||
{
|
||||
public:
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class NotEqualToOperator
|
||||
*
|
||||
* Represents an 'not-equal-to' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class NotEqualToOperator : public RelationalAndEqualityOperator
|
||||
{
|
||||
public:
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LessThanOperator
|
||||
*
|
||||
* Represents an 'less-than' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class LessThanOperator : public RelationalAndEqualityOperator
|
||||
{
|
||||
public:
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LessThanOrEqualToOperator
|
||||
*
|
||||
* Represents an 'less-than-or-equal-to' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class LessThanOrEqualToOperator : public RelationalAndEqualityOperator
|
||||
{
|
||||
public:
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class GreaterThanOperator
|
||||
*
|
||||
* Represents an 'greater-than' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class GreaterThanOperator : public RelationalAndEqualityOperator
|
||||
{
|
||||
public:
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class GreaterThanOrEqualToOperator
|
||||
*
|
||||
* Represents an 'greater-than-or-equal-to' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class GreaterThanOrEqualToOperator : public RelationalAndEqualityOperator
|
||||
{
|
||||
public:
|
||||
/** Evaluates the boolean expression.*/
|
||||
virtual bool getValue() const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslBooleanExpression_h_
|
||||
@ -0,0 +1,238 @@
|
||||
/**
|
||||
* @file XabslCoopState.h
|
||||
*
|
||||
* Definition of class CoopState and Helper classes
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslCoopState_h_
|
||||
#define __XabslCoopState_h_
|
||||
|
||||
#include "XabslState.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class CoopState
|
||||
*
|
||||
* Represents a state which has features to connect to other cooperating agents
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class CoopState : public State
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Does not create the state.
|
||||
* @param name The name of the state. For debugging purposes.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param time The system time in ms.
|
||||
* @param optionIndex Index of the corresponding option this state belongs to
|
||||
* @param index Index of the state in array states in corresponding option
|
||||
* @param agentPriority Priority value of the agent, used for solving conflicts in cooperative state assignment
|
||||
* @param synchronizationTicks Number of execution cycles that is required for synchonization with other agents, i.e time from sending a message until answer is received
|
||||
*/
|
||||
CoopState(const char* name,
|
||||
ErrorHandler& errorHandler,
|
||||
const unsigned& time,
|
||||
int optionIndex,
|
||||
int index,
|
||||
const int& agentPriority,
|
||||
const int& synchronizationTicks) :
|
||||
State(name, errorHandler, time, optionIndex, index),
|
||||
numberOfAgentsExecuting(0),
|
||||
numberOfAgentsEntering(0),
|
||||
numberOfAgentsInOption(0),
|
||||
highestPriorityOfAgentsEntering(0),
|
||||
entering(false),
|
||||
enterCount(0),
|
||||
agentPriority(agentPriority),
|
||||
synchronizationTicks(synchronizationTicks)
|
||||
{};
|
||||
|
||||
/** Number of other agents currently executing this state, not including myself */
|
||||
int numberOfAgentsExecuting;
|
||||
|
||||
/** Number of other agents currently trying to execute this state, but are blocked due to cooperating agents, not including myself */
|
||||
int numberOfAgentsEntering;
|
||||
|
||||
/** Number of other agents currently executing the option corresponding to this state, not including myself */
|
||||
int numberOfAgentsInOption;
|
||||
|
||||
/** Highest priority values of agents currently entering this state, not including myself */
|
||||
int highestPriorityOfAgentsEntering;
|
||||
|
||||
/** Flag whether the agent is currently trying to execute this state, but is blocked due to cooperating agents */
|
||||
bool entering;
|
||||
|
||||
/** Counter for number of cycles that the enter flag of this state is set */
|
||||
int enterCount;
|
||||
|
||||
/** Priority value of the agent, used for solving conflicts in cooperative state assignment */
|
||||
const int &agentPriority;
|
||||
|
||||
/** Number of execution cycles that is required for synchonization with other agents, i.e time from sending a message until answer is received */
|
||||
const int &synchronizationTicks;
|
||||
|
||||
/** Prepare for processing incoming team messages. This resets previously processed messages. */
|
||||
void prepareIncomingMessages()
|
||||
{
|
||||
numberOfAgentsExecuting = numberOfAgentsEntering = numberOfAgentsInOption = 0;
|
||||
if (entering)
|
||||
enterCount++;
|
||||
else
|
||||
enterCount = 0;
|
||||
entering = false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @class SynchronizedState
|
||||
*
|
||||
* Represents a state which can only be entered by all agents simultaneously
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class SynchronizedState : public CoopState
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Does not create the state.
|
||||
* @param name The name of the state. For debugging purposes.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param time The system time in ms.
|
||||
* @param optionIndex Index of the corresponding option this state belongs to
|
||||
* @param index Index of the state in array states in corresponding option
|
||||
* @param agentPriority Priority value of the agent, used for solving conflicts in cooperative state assignment
|
||||
* @param synchronizationTicks Number of execution cycles that is required for synchonization with other agents, i.e time from sending a message until answer is received
|
||||
*/
|
||||
SynchronizedState(const char* name,
|
||||
ErrorHandler& errorHandler,
|
||||
const unsigned& time,
|
||||
int optionIndex,
|
||||
int index,
|
||||
const int& agentPriority,
|
||||
const int& synchronizationTicks,
|
||||
int minAgents) :
|
||||
CoopState(name, errorHandler, time, optionIndex, index, agentPriority, synchronizationTicks), minAgents(minAgents)
|
||||
{};
|
||||
|
||||
/** Minimum number of agents that have to enter the state at once */
|
||||
int minAgents;
|
||||
|
||||
/** Check whether this state can be entered, or whether entering is blocked due to cooperating agents */
|
||||
virtual bool coopCheck()
|
||||
{
|
||||
entering = true;
|
||||
return (numberOfAgentsInOption >= minAgents &&
|
||||
numberOfAgentsExecuting + numberOfAgentsEntering == numberOfAgentsInOption &&
|
||||
enterCount > synchronizationTicks / 2);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class CapacityState
|
||||
*
|
||||
* Represents a state which can only be entered by at most the given number of agents simultaneously
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class CapacityState : public CoopState
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Does not create the state.
|
||||
* @param name The name of the state. For debugging purposes.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param time The system time in ms.
|
||||
* @param optionIndex Index of the corresponding option this state belongs to
|
||||
* @param index Index of the state in array states in corresponding option
|
||||
* @param agentPriority Priority value of the agent, used for solving conflicts in cooperative state assignment
|
||||
* @param synchronizationTicks Number of execution cycles that is required for synchonization with other agents, i.e time from sending a message until answer is received
|
||||
* @param capacity Number of agents that can enter the state simultaneously
|
||||
*/
|
||||
CapacityState(const char* name,
|
||||
ErrorHandler& errorHandler,
|
||||
const unsigned& time,
|
||||
int optionIndex,
|
||||
int index,
|
||||
const int& agentPriority,
|
||||
const int& synchronizationTicks,
|
||||
int capacity) :
|
||||
CoopState(name, errorHandler, time, optionIndex, index, agentPriority, synchronizationTicks), capacity(capacity), conflict(false)
|
||||
{};
|
||||
|
||||
/** Number of agents that can enter the state simultaneously */
|
||||
int capacity;
|
||||
|
||||
/** Whether this state is currently conflicted, i.e. there are more robots executing than the given capacity.*/
|
||||
bool conflict;
|
||||
|
||||
/** Whether this state is currently conflicted, i.e. there are more robots executing than the given capacity.*/
|
||||
virtual bool getConflict()
|
||||
{
|
||||
return conflict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the decision tree and determines the next active state (can be the same).
|
||||
*/
|
||||
virtual State* getNextState()
|
||||
{
|
||||
conflict = numberOfAgentsExecuting >= capacity;
|
||||
//if (conflict)
|
||||
//{
|
||||
// errorHandler.message("xabsl::CapacityState::getNextState(): Conflict detected in capacity state \"%s\". Number of agents executing is %d while the capacity is %d. Number of synchronization ticks might need to be increased; current value is %d.",n,numberOfAgentsExecuting,capacity,synchronizationTicks);
|
||||
//}
|
||||
return CoopState::getNextState();
|
||||
}
|
||||
|
||||
/** Check whether this state can be entered, or whether entering is blocked due to cooperating agents */
|
||||
virtual bool coopCheck()
|
||||
{
|
||||
//if (numberOfAgentsInOption < capacity)
|
||||
//{
|
||||
// // no potential conflict for state capacity => enter state
|
||||
// return true;
|
||||
//}
|
||||
//else
|
||||
if (numberOfAgentsExecuting >= capacity)
|
||||
{
|
||||
// state is currently busy
|
||||
entering = true;
|
||||
return false;
|
||||
}
|
||||
else if (numberOfAgentsExecuting + numberOfAgentsEntering >= capacity && highestPriorityOfAgentsEntering > agentPriority)
|
||||
{
|
||||
// state seems to have available capacity but other agents with higher priority want to enter it
|
||||
entering = true;
|
||||
return false;
|
||||
}
|
||||
else if (numberOfAgentsExecuting + numberOfAgentsEntering >= capacity && highestPriorityOfAgentsEntering == agentPriority)
|
||||
{
|
||||
// another agent wants to enter the state that has the same priority
|
||||
errorHandler.message("xabsl::CapacityState::coopCheck(): Conflict detected in capacity state \"%s\". Multiple agents with the same priority value %d are trying to execute the state.",n,agentPriority);
|
||||
// in order to resolve the conflict we do not set enter flag
|
||||
// if both agents remove their flag at the same time this situation might repeat indefinitely
|
||||
return false;
|
||||
}
|
||||
else if (enterCount < synchronizationTicks)
|
||||
{
|
||||
// state seems to have available capacity => set enter flag and wait specified tick count
|
||||
entering = true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// enter state only after enter count has reached specified count
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslCoopState_h_
|
||||
@ -0,0 +1,342 @@
|
||||
/**
|
||||
* @file XabslDecimalExpression.cpp
|
||||
*
|
||||
* Implementation of DecimalExpression and derivates
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#include "XabslOption.h"
|
||||
#include "XabslDecimalExpression.h"
|
||||
#include "XabslBooleanExpression.h"
|
||||
#include "XabslEnumeratedExpression.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
DecimalExpression::~DecimalExpression()
|
||||
{
|
||||
}
|
||||
|
||||
DecimalExpression* DecimalExpression::create(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
char c[100];
|
||||
input.readString(c,1);
|
||||
ArithmeticOperator* arithmeticOperator;
|
||||
DecimalExpression* operand1;
|
||||
DecimalExpression* operand2;
|
||||
|
||||
switch (*c)
|
||||
{
|
||||
case 'i':
|
||||
return new DecimalInputSymbolRef(input,errorHandler,symbols,option,state);
|
||||
case 'o':
|
||||
return new DecimalOutputSymbolRef(input,errorHandler,symbols);
|
||||
case 'c':
|
||||
// constants are treates as decimal values (there is no difference from the engines point of view.)
|
||||
case 'v':
|
||||
return new DecimalValue(input,errorHandler);
|
||||
case 'p':
|
||||
return new DecimalOptionParameterRef(input,errorHandler,option);
|
||||
case '+':
|
||||
if (!DecimalExpression::createOperand(operand1,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
if (!DecimalExpression::createOperand(operand2,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating + operator"));
|
||||
arithmeticOperator = new PlusOperator();
|
||||
arithmeticOperator->create(operand1,operand2);
|
||||
return arithmeticOperator;
|
||||
case '-':
|
||||
if (!DecimalExpression::createOperand(operand1,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
if (!DecimalExpression::createOperand(operand2,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating - operator"));
|
||||
arithmeticOperator = new MinusOperator();
|
||||
arithmeticOperator->create(operand1,operand2);
|
||||
return arithmeticOperator;
|
||||
case '*':
|
||||
if (!DecimalExpression::createOperand(operand1,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
if (!DecimalExpression::createOperand(operand2,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating * operator"));
|
||||
arithmeticOperator = new MultiplyOperator();
|
||||
arithmeticOperator->create(operand1,operand2);
|
||||
return arithmeticOperator;
|
||||
case 'd':
|
||||
if (!DecimalExpression::createOperand(operand1,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
if (!DecimalExpression::createOperand(operand2,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating / operator"));
|
||||
arithmeticOperator = new DivideOperator();
|
||||
arithmeticOperator->create(operand1,operand2);
|
||||
return arithmeticOperator;
|
||||
|
||||
case '%':
|
||||
if (!DecimalExpression::createOperand(operand1,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
if (!DecimalExpression::createOperand(operand2,input,errorHandler,symbols,option,state))
|
||||
return 0;
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating % operator"));
|
||||
arithmeticOperator = new ModOperator();
|
||||
arithmeticOperator->create(operand1,operand2);
|
||||
return arithmeticOperator;
|
||||
case 's':
|
||||
return new TimeRef(errorHandler,state.timeOfStateExecution);
|
||||
case 't':
|
||||
return new TimeRef(errorHandler,option.timeOfExecution);
|
||||
case 'q':
|
||||
return new ConditionalDecimalExpression(input,errorHandler,symbols,option,state);
|
||||
default:
|
||||
errorHandler.error("XabslDecimalExpression::create(): unknown expression type: \"%c\"",*c);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool DecimalExpression::createOperand(DecimalExpression*& operand,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
operand = DecimalExpression::create(input,errorHandler,symbols,option,state);
|
||||
|
||||
if (operand == 0)
|
||||
{
|
||||
errorHandler.error("XabslDecimalExpression::createOperand(): created operand is 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslDecimalExpression::createOperand(): could not create operand");
|
||||
if (operand != 0) delete operand;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DecimalValue::DecimalValue(InputSource& input,
|
||||
ErrorHandler& errorHandler)
|
||||
{
|
||||
value = input.readValue();
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("created decimal value: \"%.2f\"",value));
|
||||
}
|
||||
|
||||
double DecimalValue::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
DecimalOptionParameterRef::DecimalOptionParameterRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Option& option)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a reference to decimal option parameter \"%s\"",buf));
|
||||
|
||||
if (!option.parameters->decimal.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslDecimalOptionParameterRef::DecimalOptionParameterRef(): decimal option parameter \"%s\" does not exist",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
parameter = option.parameters->decimal.getPElement(buf)->e;
|
||||
}
|
||||
|
||||
double DecimalOptionParameterRef::getValue() const
|
||||
{
|
||||
return *parameter;
|
||||
}
|
||||
|
||||
void ArithmeticOperator::create(DecimalExpression* operand1, DecimalExpression* operand2)
|
||||
{
|
||||
this->operand1 = operand1;
|
||||
this->operand2 = operand2;
|
||||
}
|
||||
|
||||
ArithmeticOperator::~ArithmeticOperator()
|
||||
{
|
||||
if (operand1 != 0) delete operand1;
|
||||
if (operand2 != 0) delete operand2;
|
||||
}
|
||||
|
||||
double PlusOperator::getValue() const
|
||||
{
|
||||
return operand1->getValue() + operand2->getValue();
|
||||
}
|
||||
|
||||
double MinusOperator::getValue() const
|
||||
{
|
||||
return operand1->getValue() - operand2->getValue();
|
||||
}
|
||||
|
||||
double MultiplyOperator::getValue() const
|
||||
{
|
||||
return operand1->getValue() * operand2->getValue();
|
||||
}
|
||||
|
||||
double DivideOperator::getValue() const
|
||||
{
|
||||
double o2 = operand2->getValue();
|
||||
if (o2==0)
|
||||
return operand1->getValue() / 0.0000001;
|
||||
else
|
||||
return operand1->getValue() / o2;
|
||||
}
|
||||
|
||||
double ModOperator::getValue() const
|
||||
{
|
||||
return (int)operand1->getValue() % (int)operand2->getValue();
|
||||
}
|
||||
|
||||
TimeRef::TimeRef(ErrorHandler& errorHandler,
|
||||
unsigned& time) :
|
||||
time(time)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a reference to state or option execution time"));
|
||||
}
|
||||
|
||||
double TimeRef::getValue() const
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
DecimalInputSymbolRef::DecimalInputSymbolRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state) :
|
||||
symbol(0), parameters(0)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a reference to decimal input symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.decimalInputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslDecimalInputSymbolRef::DecimalInputSymbolRef(): decimal input symbol \"%s\" was not registered",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
symbol = symbols.decimalInputSymbols[buf];
|
||||
|
||||
parameters = new ParameterAssignment(&symbol->parameters, errorHandler);
|
||||
|
||||
parameters->create(input, symbols, option, state);
|
||||
}
|
||||
|
||||
DecimalInputSymbolRef::~DecimalInputSymbolRef()
|
||||
{
|
||||
if (parameters != 0)
|
||||
delete parameters;
|
||||
}
|
||||
|
||||
double DecimalInputSymbolRef::getValue() const
|
||||
{
|
||||
// set the symbol parameters
|
||||
if (parameters->set())
|
||||
symbol->parametersChanged();
|
||||
|
||||
return symbol->getValue();
|
||||
}
|
||||
|
||||
DecimalOutputSymbolRef::DecimalOutputSymbolRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a reference to a decimal output symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.decimalOutputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslDecimalOutputSymbolRef::DecimalOutputSymbolRef(): decimal output symbol \"%s\" was not registered",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
symbol = symbols.decimalOutputSymbols[buf];
|
||||
}
|
||||
|
||||
double DecimalOutputSymbolRef::getValue() const
|
||||
{
|
||||
return symbol->getValue();
|
||||
}
|
||||
|
||||
ConditionalDecimalExpression::ConditionalDecimalExpression(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a question mark operator"));
|
||||
|
||||
condition = BooleanExpression::create(input,errorHandler,symbols,option,state);
|
||||
|
||||
if (condition == 0)
|
||||
{
|
||||
errorHandler.error("XabslQuestionMarkOperator::QuestionMarkOperator(): created condition is 0");
|
||||
return;
|
||||
}
|
||||
else if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslQuestionMarkOperator::QuestionMarkOperator(): could not create condition");
|
||||
delete condition;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DecimalExpression::createOperand(expression1,input,errorHandler,symbols,option,state))
|
||||
{
|
||||
errorHandler.error("XabslQuestionMarkOperator::QuestionMarkOperator(): could not create decimal expression1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DecimalExpression::createOperand(expression2,input,errorHandler,symbols,option,state))
|
||||
{
|
||||
errorHandler.error("XabslQuestionMarkOperator::QuestionMarkOperator(): could not create decimal expression2");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ConditionalDecimalExpression::~ConditionalDecimalExpression()
|
||||
{
|
||||
if (condition!=0) delete condition;
|
||||
if (expression1!=0) delete expression1;
|
||||
if (expression2!=0) delete expression2;
|
||||
}
|
||||
|
||||
double ConditionalDecimalExpression::getValue() const
|
||||
{
|
||||
if (condition->getValue())
|
||||
{
|
||||
return expression1->getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return expression2->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,383 @@
|
||||
/**
|
||||
* @file XabslDecimalExpression.h
|
||||
*
|
||||
* Definition of DecimalExpression and derivates
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslDecimalExpression_h_
|
||||
#define __XabslDecimalExpression_h_
|
||||
|
||||
#include "XabslSymbols.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
// class prototypes used by symbol parameters / conditional expressions
|
||||
class BooleanExpression;
|
||||
class EnumeratedExpression;
|
||||
class Option;
|
||||
class State;
|
||||
|
||||
/**
|
||||
* @class DecimalExpression
|
||||
*
|
||||
* Base class for all decimal expressions inside an option graph.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class DecimalExpression
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const = 0;
|
||||
|
||||
/**
|
||||
* Creates a decimal expression depending on the input.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a decimal expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
static DecimalExpression* create(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
virtual ~DecimalExpression() = 0;
|
||||
|
||||
/**
|
||||
* Creates a decimal expression depending on the input.
|
||||
* Uses the create() function to create decimal operands.
|
||||
* @param operand The expression to be created
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a decimal operand starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
* @return If the creation was successful
|
||||
*/
|
||||
static bool createOperand(
|
||||
DecimalExpression*& operand,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DecimalValue
|
||||
*
|
||||
* Represents a decimal value.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class DecimalValue : public DecimalExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the value
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a value starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
*/
|
||||
DecimalValue(InputSource& input,
|
||||
ErrorHandler& errorHandler);
|
||||
|
||||
/**
|
||||
* Constructor. Creates an expression for a fixed decimal value
|
||||
* @param value The decimal value
|
||||
*/
|
||||
DecimalValue(double value) : value(value) {}
|
||||
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
|
||||
private:
|
||||
/** The value */
|
||||
double value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DecimalOptionParameterRef
|
||||
*
|
||||
* Represents a reference to a decimal option parameter.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class DecimalOptionParameterRef : public DecimalExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the reference
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where the expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param option The current option
|
||||
*/
|
||||
DecimalOptionParameterRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Option& option);
|
||||
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
|
||||
private:
|
||||
/** A pointer to the parameter */
|
||||
double* parameter;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ArithmeticOperator
|
||||
*
|
||||
* Base class for the +, -, *, / and % operator.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class ArithmeticOperator : public DecimalExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates the operator
|
||||
* @param operand1 The first operand
|
||||
* @param operand2 The second operand
|
||||
*/
|
||||
void create(DecimalExpression* operand1, DecimalExpression* operand2);
|
||||
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const = 0;
|
||||
|
||||
/** Destructor. Deletes the operands */
|
||||
~ArithmeticOperator();
|
||||
|
||||
protected:
|
||||
/** The first operand */
|
||||
DecimalExpression* operand1;
|
||||
|
||||
/** The second operand */
|
||||
DecimalExpression* operand2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class PlusOperator
|
||||
*
|
||||
* Represents a + operator in the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class PlusOperator : public ArithmeticOperator
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class MinusOperator
|
||||
*
|
||||
* Represents a - operator in the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class MinusOperator : public ArithmeticOperator
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class MultiplyOperator
|
||||
*
|
||||
* Represents a * operator in the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class MultiplyOperator : public ArithmeticOperator
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DivideOperator
|
||||
*
|
||||
* Represents a / operator in the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class DivideOperator : public ArithmeticOperator
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ModOperator
|
||||
*
|
||||
* Represents a % operator in the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class ModOperator : public ArithmeticOperator
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class TimeRef
|
||||
*
|
||||
* Represents a time-of-option-execution or time-of-state-execution element in the option graph
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class TimeRef : public DecimalExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param time the referenced time
|
||||
*/
|
||||
TimeRef(ErrorHandler& errorHandler,
|
||||
unsigned& time);
|
||||
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
|
||||
private:
|
||||
/** The referenced time */
|
||||
unsigned& time;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DecimalInputSymbolRef
|
||||
*
|
||||
* Represents a reference to a decimal input symbol.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class DecimalInputSymbolRef : public DecimalExpression
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
|
||||
/**
|
||||
* Constructor. Creates the function call depending on the input.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where the function reference starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
DecimalInputSymbolRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
~DecimalInputSymbolRef();
|
||||
|
||||
private:
|
||||
/** The referenced symbol */
|
||||
DecimalInputSymbol* symbol;
|
||||
|
||||
/** The parameter assignments of the referenced symbol */
|
||||
ParameterAssignment* parameters;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DecimalOutputSymbolRef
|
||||
*
|
||||
* Represents a reference to a decimal input symbol.
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class DecimalOutputSymbolRef : public DecimalExpression
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
|
||||
/**
|
||||
* Constructor. Creates the function call depending on the input.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where the function reference starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
*/
|
||||
DecimalOutputSymbolRef(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols);
|
||||
|
||||
private:
|
||||
/** The referenced symbol */
|
||||
DecimalOutputSymbol* symbol;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ConditionalDecimalExpression
|
||||
*
|
||||
* Represents an ANSI C (condition?expression:expression) question mark operator
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class ConditionalDecimalExpression : public DecimalExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the expression
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
ConditionalDecimalExpression(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
~ConditionalDecimalExpression();
|
||||
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual double getValue() const;
|
||||
|
||||
private:
|
||||
/** The condition */
|
||||
BooleanExpression* condition;
|
||||
|
||||
/** The expression that is returned when the condition evaluates true */
|
||||
DecimalExpression* expression1;
|
||||
|
||||
/** The expression that is returned when the condition evaluates false */
|
||||
DecimalExpression* expression2;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslDecimalExpression_h_
|
||||
@ -0,0 +1,552 @@
|
||||
/**
|
||||
* @file XabslEngine.cpp
|
||||
*
|
||||
* Implementation of class Engine
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
*/
|
||||
|
||||
#include "XabslEngine.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
Engine::Engine(ErrorHandler& e,unsigned (*pTimeFunction)())
|
||||
: Symbols(e), selectedAgent(0),
|
||||
errorHandler(e), initialized(false), pTimeFunction(pTimeFunction),
|
||||
agentPriority(0),
|
||||
synchronizationTicks(0),
|
||||
timeOfExecutionStart(pTimeFunction())
|
||||
{
|
||||
}
|
||||
|
||||
Engine::~Engine()
|
||||
{
|
||||
int i;
|
||||
for (i=0; i< options.getSize(); i++)
|
||||
if (options[i]!=0)
|
||||
delete options[i];
|
||||
for (i=0; i< agents.getSize(); i++)
|
||||
if (agents[i]!=0)
|
||||
delete agents[i];
|
||||
for (i=0; i< rootActions.getSize(); i++)
|
||||
if (rootActions[i]!=0)
|
||||
delete rootActions[i];
|
||||
}
|
||||
|
||||
void Engine::execute()
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
errorHandler.error("execute(): Call createOptionGraph before first execute.");
|
||||
return;
|
||||
}
|
||||
|
||||
timeOfExecutionStart = pTimeFunction();
|
||||
resetOutputSymbols();
|
||||
|
||||
for (int i=0; i< rootActions.getSize(); i++)
|
||||
rootActions[i]->execute();
|
||||
|
||||
for (int i=0; i < options.getSize(); i++)
|
||||
{
|
||||
options[i]->wasActive = options[i]->isActive;
|
||||
options[i]->isActive = false;
|
||||
}
|
||||
|
||||
for (int i=0;i<basicBehaviors.getSize();i++)
|
||||
{
|
||||
basicBehaviors[i]->wasActive = basicBehaviors[i]->isActive;
|
||||
basicBehaviors[i]->isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::createOptionGraph(InputSource& input)
|
||||
{
|
||||
int i;
|
||||
char buf1[100],buf2[100];
|
||||
|
||||
errorHandler.errorsOccurred = false;
|
||||
timeOfExecutionStart = pTimeFunction();
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
errorHandler.error("createOptionGraph(): Don't call this function twice");
|
||||
return;
|
||||
}
|
||||
if (!input.open())
|
||||
{
|
||||
errorHandler.error("createOptionGraph(): Can't open input source");
|
||||
return;
|
||||
}
|
||||
|
||||
// create internal enumerations
|
||||
int numberOfInternalEnumerations = (int)input.readValue();
|
||||
for (i=0; i < numberOfInternalEnumerations; i++)
|
||||
{
|
||||
input.readString(buf1, 99);
|
||||
int numberOfElements = (int)input.readValue();
|
||||
for (int j=0; j < numberOfElements; j++)
|
||||
{
|
||||
input.readString(buf2, 99);
|
||||
registerEnumElement(buf1, buf2, j);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslEngine::createOptionGraph(): could not register internal enumeration \"%s\"",buf1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create internal symbols
|
||||
int numberOfInternalSymbols = (int)input.readValue();
|
||||
for (i=0; i < numberOfInternalSymbols; i++)
|
||||
{
|
||||
char c[2];
|
||||
input.readString(c,1);
|
||||
switch (c[0])
|
||||
{
|
||||
case 'd':
|
||||
input.readString(buf1,99);
|
||||
internalDecimalSymbols.append(buf1, 0);
|
||||
registerDecimalOutputSymbol(buf1, &(internalDecimalSymbols.getElement(internalDecimalSymbols.getSize() - 1)));
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslEngine::createOptionGraph(): could not register internal decimal symbol \"%s\"",buf1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
input.readString(buf1,99);
|
||||
internalBooleanSymbols.append(buf1, false);
|
||||
registerBooleanOutputSymbol(buf1, &(internalBooleanSymbols.getElement(internalBooleanSymbols.getSize() - 1)));
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslEngine::createOptionGraph(): could not register internal boolean symbol \"%s\"",buf1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
input.readString(buf1,99);
|
||||
if (!enumerations.exists(buf1))
|
||||
{
|
||||
errorHandler.error("XabslEngine::createOptionGraph(): enumeration \"%s\" was not registered",buf1);
|
||||
return;
|
||||
}
|
||||
const Enumeration* enumeration = enumerations[buf1];
|
||||
if (enumeration->enumElements.getSize() == 0)
|
||||
{
|
||||
errorHandler.error("XabslEngine::createOptionGraph(): no enumeration elements for \"%s\" were registered",buf1);
|
||||
return;
|
||||
}
|
||||
input.readString(buf2,99);
|
||||
internalEnumeratedSymbols.append(buf2, enumeration->enumElements[0]->v);
|
||||
registerEnumeratedOutputSymbol(buf2, buf1, &(internalEnumeratedSymbols.getElement(internalEnumeratedSymbols.getSize() - 1)));
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslEngine::createOptionGraph(): could not register internal enumerated symbol \"%s\"",buf2);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the total number of options in the intermediate code
|
||||
int numberOfOptions = (int)input.readValue();
|
||||
|
||||
// create empty options
|
||||
for (i=0; i< numberOfOptions; i++)
|
||||
{
|
||||
input.readString(buf1,99);
|
||||
options.append(buf1,new Option(buf1,input,errorHandler,*this,timeOfExecutionStart,i));
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslEngine::createOptionGraph(): could not create option \"%s\"",options[i]->n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registered %i options",numberOfOptions));
|
||||
|
||||
// create the options and its states
|
||||
for (i=0; i< numberOfOptions; i++)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating option \"%s\"",options[i]->n));
|
||||
options[i]->create(input,options,basicBehaviors,*this,agentPriority,synchronizationTicks);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslEngine::createOptionGraph(): could not create option \"%s\"",options[i]->n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// create the agents
|
||||
int numberOfAgents = (int)input.readValue();
|
||||
for (i=0; i< numberOfAgents; i++)
|
||||
{
|
||||
input.readString(buf1,99);
|
||||
input.readString(buf2,99);
|
||||
agents.append(buf1,new Agent(buf1,options[buf2],errorHandler, i));
|
||||
}
|
||||
|
||||
// check for loops in the option graph
|
||||
for (i=0;i<agents.getSize();i++)
|
||||
{
|
||||
if (Option* option = dynamic_cast<Option*>(agents[i]->getRootOption()))
|
||||
{
|
||||
int size = countActions(option) + 1;
|
||||
ActionBehavior** currentOptionPath = new ActionBehavior*[size];
|
||||
|
||||
currentOptionPath[0] = dynamic_cast<ActionBehavior*>(Action::create(option, errorHandler, timeOfExecutionStart));
|
||||
|
||||
// call recursively the checkForLoops function
|
||||
if (checkForLoops(option, currentOptionPath, 1, size))
|
||||
{
|
||||
errorHandler.error("createOptionGraph(): The created option graph contains loops");
|
||||
};
|
||||
|
||||
delete currentOptionPath[0];
|
||||
delete[] currentOptionPath;
|
||||
}
|
||||
}
|
||||
|
||||
// create array of cooperating states
|
||||
for (i=0;i<options.getSize();i++)
|
||||
for (int j=0;j<options[i]->states.getSize();j++)
|
||||
if (CoopState* state = dynamic_cast<CoopState*>(options[i]->states[j]))
|
||||
coopStates.append(state);
|
||||
|
||||
selectedAgent = agents[0];
|
||||
setRootAction();
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("selected agent: \"%s\"",selectedAgent->n));
|
||||
input.close();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
bool Engine::checkForLoops(Option* currentOption, ActionBehavior* currentOptionTree[], int currentLength, int maxSize)
|
||||
{
|
||||
int i,j,k,l;
|
||||
|
||||
for (i=0; i<currentOption->states.getSize(); i++)
|
||||
{
|
||||
int newLength = currentLength;
|
||||
|
||||
for (j=0; j<currentOption->states[i]->actions.getSize(); j++)
|
||||
{
|
||||
if (ActionBehavior* nextAction = dynamic_cast<ActionBehavior*>(currentOption->states[i]->actions[j]))
|
||||
{
|
||||
for(k=0; k<newLength; k++)
|
||||
{
|
||||
// check for the subsequent option of each state whether the referenced
|
||||
// option is contained in the current option tree
|
||||
if (nextAction->getBehavior() == currentOptionTree[k]->getBehavior())
|
||||
{
|
||||
errorHandler.error("checkForLoops() : state \"%s\" in option \"%s\" references subsequent behavior \"%s\", which is already included in another possible activation tree.",
|
||||
currentOption->states[i]->n,
|
||||
currentOption->n,
|
||||
nextAction->getBehavior()->n);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(newLength>=maxSize)
|
||||
{
|
||||
errorHandler.error("checkForLoops() : max size exceeded when processing state \"%s\" in option \"%s\".",
|
||||
currentOption->states[i]->n,
|
||||
currentOption->n);
|
||||
return true;
|
||||
}
|
||||
|
||||
currentOptionTree[newLength++] = nextAction;
|
||||
}
|
||||
}
|
||||
|
||||
// recursion
|
||||
for (k = currentLength; k < newLength; k++)
|
||||
{
|
||||
int recursionLength = newLength;
|
||||
for (l = currentLength; l < newLength; l++)
|
||||
{
|
||||
if (l != k)
|
||||
{
|
||||
addActions(currentOptionTree[l], currentOptionTree, recursionLength, maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (ActionOption* nextAction = dynamic_cast<ActionOption*>(currentOptionTree[k]))
|
||||
{
|
||||
if (checkForLoops(nextAction->option, currentOptionTree, recursionLength, maxSize))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Engine::addActions(ActionBehavior* actionToAdd, ActionBehavior* currentOptionTree[], int& currentLength, int maxSize)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
if (ActionOption* optionToAdd = dynamic_cast<ActionOption*>(actionToAdd))
|
||||
{
|
||||
for (i=0; i<optionToAdd->option->states.getSize(); i++)
|
||||
{
|
||||
for (j=0; j<optionToAdd->option->states[i]->actions.getSize(); j++)
|
||||
{
|
||||
if (ActionBehavior* nextAction = dynamic_cast<ActionBehavior*>(optionToAdd->option->states[i]->actions[j]))
|
||||
{
|
||||
if(currentLength>=maxSize)
|
||||
{
|
||||
errorHandler.error("checkForLoops() : max size exceeded when processing state \"%s\" in option \"%s\".",
|
||||
optionToAdd->option->states[i]->n,
|
||||
optionToAdd->option->n);
|
||||
return;
|
||||
}
|
||||
currentOptionTree[currentLength++] = nextAction;
|
||||
addActions(nextAction, currentOptionTree, currentLength, maxSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Engine::countActions(Option* option)
|
||||
{
|
||||
int i,j;
|
||||
int count = 0;
|
||||
for (i=0; i<option->states.getSize(); i++)
|
||||
{
|
||||
for (j=0; j<option->states[i]->actions.getSize(); j++)
|
||||
{
|
||||
if (ActionBehavior* nextAction = dynamic_cast<ActionBehavior*>(option->states[i]->actions[j]))
|
||||
{
|
||||
count++;
|
||||
if (ActionOption* nextOption = dynamic_cast<ActionOption*>(nextAction))
|
||||
{
|
||||
count += countActions(nextOption->option);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void Engine::registerBasicBehavior(BasicBehavior& basicBehavior)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering basic behavior \"%s\"",basicBehavior.n));
|
||||
|
||||
if (basicBehaviors.exists(basicBehavior.n))
|
||||
{
|
||||
errorHandler.error("registerBasicBehavior(): basic behavior \"%s\" was already registered",basicBehavior.n);
|
||||
return;
|
||||
}
|
||||
|
||||
basicBehavior.parameters->registerEnumerations(enumerations);
|
||||
basicBehavior.registerParameters();
|
||||
|
||||
basicBehavior.index = basicBehaviors.getSize();
|
||||
basicBehaviors.append(basicBehavior.n,&basicBehavior);
|
||||
}
|
||||
|
||||
void Engine::clearRootActions()
|
||||
{
|
||||
for (int i=0; i< rootActions.getSize(); i++)
|
||||
if (rootActions[i]!=0)
|
||||
delete rootActions[i];
|
||||
rootActions.clear();
|
||||
}
|
||||
|
||||
bool Engine::addRootAction(const char* name, bool isOption)
|
||||
{
|
||||
if (isOption)
|
||||
{
|
||||
// check if the option exists
|
||||
if (!options.exists(name)) return false;
|
||||
|
||||
// set the current root option to the requested option
|
||||
addRootAction(options[name]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// check if the basic behavior exists
|
||||
if (!basicBehaviors.exists(name)) return false;
|
||||
|
||||
// set the current root option to the requested option
|
||||
addRootAction(basicBehaviors[name]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Engine::setRootAction(const char* name, bool isOption)
|
||||
{
|
||||
clearRootActions();
|
||||
return addRootAction(name, isOption);
|
||||
}
|
||||
|
||||
void Engine::setRootAction()
|
||||
{
|
||||
setRootAction(selectedAgent->getRootOption());
|
||||
}
|
||||
|
||||
void Engine::addRootAction(Behavior* behavior)
|
||||
{
|
||||
rootActions.append(Action::create(behavior, errorHandler, timeOfExecutionStart));
|
||||
}
|
||||
|
||||
void Engine::setRootAction(Behavior* behavior)
|
||||
{
|
||||
clearRootActions();
|
||||
addRootAction(behavior);
|
||||
}
|
||||
|
||||
bool Engine::addRootActionDecimalOutputSymbol(const char* name, double value)
|
||||
{
|
||||
if (!decimalOutputSymbols.exists(name)) return false;
|
||||
|
||||
ActionDecimalOutputSymbol* action = new ActionDecimalOutputSymbol(timeOfExecutionStart);
|
||||
action->decimalOutputSymbol = decimalOutputSymbols[name];
|
||||
action->decimalOutputSymbolExpression = new DecimalValue(value);
|
||||
rootActions.append(action);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Engine::addRootActionBooleanOutputSymbol(const char* name, bool value)
|
||||
{
|
||||
if (!booleanOutputSymbols.exists(name)) return false;
|
||||
|
||||
ActionBooleanOutputSymbol* action = new ActionBooleanOutputSymbol(timeOfExecutionStart);
|
||||
action->booleanOutputSymbol = booleanOutputSymbols[name];
|
||||
action->booleanOutputSymbolExpression = new BooleanValue(value);
|
||||
rootActions.append(action);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Engine::addRootActionEnumeratedOutputSymbol(const char* name, const char* value)
|
||||
{
|
||||
if (!enumeratedOutputSymbols.exists(name) || !enumeratedOutputSymbols[name]->enumeration->enumElements.exists(value))
|
||||
return false;
|
||||
|
||||
ActionEnumeratedOutputSymbol* action = new ActionEnumeratedOutputSymbol(timeOfExecutionStart);
|
||||
action->enumeratedOutputSymbol = enumeratedOutputSymbols[name];
|
||||
action->enumeratedOutputSymbolExpression = new EnumeratedValue(enumeratedOutputSymbols[name]->enumeration, enumeratedOutputSymbols[name]->enumeration->enumElements[value]->v);
|
||||
rootActions.append(action);
|
||||
return true;
|
||||
}
|
||||
|
||||
const Action* Engine::getRootAction(int i) const
|
||||
{
|
||||
return rootActions[i];
|
||||
}
|
||||
|
||||
Action* Engine::getRootAction(int i)
|
||||
{
|
||||
return rootActions[i];
|
||||
}
|
||||
|
||||
const Array<Action*>& Engine::getRootActions() const
|
||||
{
|
||||
return rootActions;
|
||||
}
|
||||
|
||||
Array<Action*>& Engine::getRootActions()
|
||||
{
|
||||
return rootActions;
|
||||
}
|
||||
|
||||
const char* Engine::getSelectedAgentName() const
|
||||
{
|
||||
if (selectedAgent)
|
||||
return selectedAgent->n;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Engine::setSelectedAgent(const char* name)
|
||||
{
|
||||
if (!agents.exists(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Agent* newAgent = agents[name];
|
||||
|
||||
if (selectedAgent != newAgent)
|
||||
{
|
||||
selectedAgent = newAgent;
|
||||
setRootAction();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Engine::reset()
|
||||
{
|
||||
int i;
|
||||
for (i=0; i< options.getSize(); i++)
|
||||
{
|
||||
options[i]->wasActive = false;
|
||||
}
|
||||
for (i=0; i< basicBehaviors.getSize(); i++)
|
||||
{
|
||||
basicBehaviors[i]->wasActive = false;
|
||||
}
|
||||
errorHandler.errorsOccurred = false;
|
||||
}
|
||||
|
||||
void Engine::prepareIncomingMessages()
|
||||
{
|
||||
for (int i=0; i<coopStates.getSize(); i++)
|
||||
{
|
||||
coopStates[i]->prepareIncomingMessages();
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::processIncomingMessage(const TeamMessage& message)
|
||||
{
|
||||
for (int i=0; i<message.coopStatesExecuted.getSize(); i++)
|
||||
coopStates[message.coopStatesExecuted[i]]->numberOfAgentsExecuting++;
|
||||
|
||||
for (int i=0; i<message.coopStatesEntering.getSize(); i++)
|
||||
{
|
||||
if (coopStates[message.coopStatesEntering[i]]->numberOfAgentsEntering == 0 ||
|
||||
coopStates[message.coopStatesEntering[i]]->highestPriorityOfAgentsEntering < message.agentPriority)
|
||||
coopStates[message.coopStatesEntering[i]]->highestPriorityOfAgentsEntering = message.agentPriority;
|
||||
coopStates[message.coopStatesEntering[i]]->numberOfAgentsEntering++;
|
||||
}
|
||||
|
||||
for (int i=0; i<message.coopStatesOptionExecuted.getSize(); i++)
|
||||
coopStates[message.coopStatesOptionExecuted[i]]->numberOfAgentsInOption++;
|
||||
}
|
||||
|
||||
void Engine::generateOutgoingMessage(TeamMessage& message)
|
||||
{
|
||||
message.reset();
|
||||
for (int i=0; i<coopStates.getSize(); i++)
|
||||
{
|
||||
// is option currently active?
|
||||
if (options[coopStates[i]->optionIndex]->wasActive)
|
||||
{
|
||||
message.coopStatesOptionExecuted.append(i);
|
||||
// is state currently active?
|
||||
if (options[coopStates[i]->optionIndex]->activeState == coopStates[i])
|
||||
{
|
||||
message.coopStatesExecuted.append(i);
|
||||
}
|
||||
else if (coopStates[i]->entering)
|
||||
{
|
||||
message.coopStatesEntering.append(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
message.agentPriority = agentPriority;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,248 @@
|
||||
/**
|
||||
* @file XabslEngine.h
|
||||
*
|
||||
* Declaration class Engine
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslEngine_h_
|
||||
#define __XabslEngine_h_
|
||||
|
||||
#include "XabslAgent.h"
|
||||
#include "XabslOption.h"
|
||||
#include "XabslCoopState.h"
|
||||
#include "XabslTeamMessage.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* Executes a behavior that was specified in the Xabsl language.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias JŸngel</a>
|
||||
*/
|
||||
class Engine : public Symbols
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param e Is invoked when there are problems during initialization
|
||||
* @param pTimeFunction a pointer to a function that returns the system time in ms.
|
||||
*/
|
||||
Engine(ErrorHandler& e, unsigned (*pTimeFunction)());
|
||||
|
||||
/** Destructor */
|
||||
~Engine();
|
||||
|
||||
/**
|
||||
* Executes the engine for the selected agent starting from the root option.
|
||||
* (Including the selected basic behavior)
|
||||
*/
|
||||
void execute();
|
||||
|
||||
/**
|
||||
* Reads the intermediate code from an input source and creates the option graph.
|
||||
* Note that the basic behaviors and symbols have to be registered before that function is
|
||||
* called.
|
||||
*/
|
||||
void createOptionGraph(InputSource& input);
|
||||
|
||||
/**
|
||||
* Registers a basic behavior at the engine.
|
||||
* This must be done before the intermediate code is read.
|
||||
* @param basicBehavior A reference to the basic behavior
|
||||
*/
|
||||
void registerBasicBehavior(BasicBehavior& basicBehavior);
|
||||
|
||||
/**
|
||||
* Sets the selected Agent.
|
||||
* If the last selected agent was different from the new one,
|
||||
* the root option is changed depending on the new agent.
|
||||
* @param name The name of the agent
|
||||
* @return if the requested agent exists
|
||||
*/
|
||||
bool setSelectedAgent(const char* name);
|
||||
|
||||
/**
|
||||
* Resets all active options.
|
||||
* Next cycle will execute initial state of currently set root option.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* The time of the start of the current engine execution
|
||||
*/
|
||||
unsigned timeOfExecutionStart;
|
||||
|
||||
/** The agents of the engine */
|
||||
NamedArray<Agent*> agents;
|
||||
|
||||
/** The selected agent */
|
||||
Agent* selectedAgent;
|
||||
|
||||
/** The options of the engine */
|
||||
NamedArray<Option*> options;
|
||||
|
||||
/** The actions for the execution of the start of the option graph */
|
||||
Array<Action*> rootActions;
|
||||
|
||||
/** The registered basic behaviors of the engine */
|
||||
NamedArray<BasicBehavior*> basicBehaviors;
|
||||
|
||||
/** Is invoked when there are problems during initialization */
|
||||
ErrorHandler& errorHandler;
|
||||
|
||||
/**
|
||||
* A recursive function that is used to check for loops in the option graph.
|
||||
* @param currentOption The option to be checked
|
||||
* @param currentOptionTree An array of the currently traced option tree
|
||||
* @param currentLength The length of the current option tree array
|
||||
* @param maxSize maximum allowed size of the array
|
||||
* @return If true, then a loop was detected.
|
||||
*/
|
||||
bool checkForLoops(Option* currentOption, ActionBehavior* currentOptionTree[], int currentLength, int maxSize);
|
||||
|
||||
/** A recursive function that generates a list of actions referenced from a starting option
|
||||
* This is used by checkForLoops.
|
||||
* @param actionToAdd The option whose referenced actions are to be added to the current array
|
||||
* @param currentOptionTree An array to which the referenced options are to be added
|
||||
* @param currentLength The current length of the array. Actions will be appended at the end of the array. currentLength will increase accordingly.
|
||||
* @param maxSize maximum allowed size of the array
|
||||
*/
|
||||
void addActions(ActionBehavior* actionToAdd, ActionBehavior* currentOptionTree[], int& currentLength, int maxSize);
|
||||
|
||||
/**
|
||||
* Rescursively count the number of actions referenced from an option
|
||||
* @param option A pointer to the option for which the referenced options are counted.
|
||||
* @return Number of actions */
|
||||
int countActions(Option* option);
|
||||
|
||||
/** If true, the engine was successfully initialized */
|
||||
bool initialized;
|
||||
|
||||
/** A pointer to a function that returns the system time in ms. */
|
||||
unsigned (*pTimeFunction)();
|
||||
|
||||
/** Arrays containing internal symbol values */
|
||||
NamedArray<double> internalDecimalSymbols;
|
||||
NamedArray<bool> internalBooleanSymbols;
|
||||
NamedArray<int> internalEnumeratedSymbols;
|
||||
|
||||
/** Array of states which are used for cooperating agents */
|
||||
Array<CoopState*> coopStates;
|
||||
|
||||
/** Priority value of the agent, used for solving conflicts in cooperative state assignment */
|
||||
int agentPriority;
|
||||
|
||||
/** Number of execution cycles that is required for synchonization with other agents, i.e time from sending a message until answer is received */
|
||||
int synchronizationTicks;
|
||||
|
||||
public:
|
||||
//!@name Debugging Interface
|
||||
//!@{
|
||||
|
||||
/** Returns the agents of the engine */
|
||||
const NamedArray<Agent*>& getAgents() const {return agents;}
|
||||
|
||||
/** Return the options of the engine */
|
||||
const NamedArray<Option*>& getOptions() const {return options;}
|
||||
|
||||
/** Returns the registered basic behaviors of the engine */
|
||||
const NamedArray<BasicBehavior*>& getBasicBehaviors() const {return basicBehaviors;}
|
||||
|
||||
/**
|
||||
* Clears the list of actions executed starting the option graph.
|
||||
*/
|
||||
void clearRootActions();
|
||||
|
||||
/**
|
||||
* Adds a given option or basic behavior to the list of actions executed starting the option graph.
|
||||
* Can be called to test a single option or basic behavior.
|
||||
* @param name The name of the option or basic behavior
|
||||
* @param isOption True for an option, false for a basic behavior
|
||||
* @return When false, the option is not known to the engine
|
||||
*/
|
||||
bool addRootAction(const char* name, bool isOption = true);
|
||||
|
||||
/**
|
||||
* Executes the option graph starting from a given option or basic behavior.
|
||||
* Can be called to test a single option or basic behavior.
|
||||
* @param name The name of the option or basic behavior
|
||||
* @param isOption True for an option, false for a basic behavior
|
||||
* @return When false, the option is not known to the engine
|
||||
*/
|
||||
bool setRootAction(const char* name, bool isOption = true);
|
||||
|
||||
/**
|
||||
* Sets the root option of the selected agent
|
||||
*/
|
||||
void setRootAction();
|
||||
|
||||
/**
|
||||
* Adds the specified option or basic behavior to the list of root actions.
|
||||
*/
|
||||
void addRootAction(Behavior* behavior);
|
||||
|
||||
/**
|
||||
* Adds a decimal output symbol assignment to the list of root actions.
|
||||
*/
|
||||
bool addRootActionDecimalOutputSymbol(const char* name, double value);
|
||||
|
||||
/**
|
||||
* Adds a boolean output symbol assignment to the list of root actions.
|
||||
*/
|
||||
bool addRootActionBooleanOutputSymbol(const char* name, bool value);
|
||||
|
||||
/**
|
||||
* Adds an enumerated output symbol assignment to the list of root actions.
|
||||
*/
|
||||
bool addRootActionEnumeratedOutputSymbol(const char* name, const char* value);
|
||||
|
||||
/**
|
||||
* Sets the root option to the specified option or basic behavior
|
||||
*/
|
||||
void setRootAction(Behavior* behavior);
|
||||
|
||||
/** Returns the selected root actions */
|
||||
const Action* getRootAction(int i) const;
|
||||
|
||||
/** Returns the selected root actions */
|
||||
Action* getRootAction(int i);
|
||||
|
||||
/** Returns the selected root actions */
|
||||
const Array<Action*>& getRootActions() const;
|
||||
|
||||
/** Returns the selected root actions */
|
||||
Array<Action*>& getRootActions();
|
||||
|
||||
/** Returns the name of the selected agent */
|
||||
const char* getSelectedAgentName() const;
|
||||
|
||||
/** Prepare for processing incoming team messages. This resets previously processed messages. */
|
||||
void prepareIncomingMessages();
|
||||
|
||||
/** Process an incoming team message from another agent */
|
||||
void processIncomingMessage(const TeamMessage& message);
|
||||
|
||||
/** Generate the outgoing team message to be sent to other agents */
|
||||
void generateOutgoingMessage(TeamMessage& message);
|
||||
|
||||
/** Set the number of execution cycles that is required for synchonization with other agents, i.e time from sending a message until answer is received */
|
||||
void setSynchronizationTicks(int ticks) {synchronizationTicks = ticks;}
|
||||
|
||||
/** Sets the priority value of the agent, used for solving conflicts in cooperative state assignment */
|
||||
void setAgentPriority(int priority) {agentPriority = priority;}
|
||||
//!@}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // __XabslEngine_h_
|
||||
|
||||
@ -0,0 +1,264 @@
|
||||
/**
|
||||
* @file XabslEnumeratedExpression.cpp
|
||||
*
|
||||
* Implementation of EnumeratedExpression and derivates
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#include "XabslEnumeratedExpression.h"
|
||||
#include "XabslOption.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
EnumeratedExpression::~EnumeratedExpression()
|
||||
{
|
||||
}
|
||||
|
||||
EnumeratedExpression* EnumeratedExpression::create(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
char c[2];
|
||||
input.readString(c,1);
|
||||
|
||||
switch (*c)
|
||||
{
|
||||
case 'v':
|
||||
return new EnumeratedValue(enumeration, input,errorHandler);
|
||||
case 'p':
|
||||
return new EnumeratedOptionParameterRef(enumeration, input,errorHandler,option);
|
||||
case 'i':
|
||||
return new EnumeratedInputSymbolRef(enumeration, input,errorHandler,symbols,option,state);
|
||||
case 'o':
|
||||
return new EnumeratedOutputSymbolRef(enumeration, input,errorHandler,symbols);
|
||||
case 'q':
|
||||
return new ConditionalEnumeratedExpression(enumeration, input,errorHandler,symbols,option,state);
|
||||
default:
|
||||
errorHandler.error("XabslEnumeratedExpression::create(): unknown expression type \"%c\"",*c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EnumeratedExpression::createOperand(const EnumeratedExpression*& operand,
|
||||
const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
operand = EnumeratedExpression::create(enumeration,input,errorHandler,symbols,option,state);
|
||||
|
||||
if (operand == 0)
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedExpression::createOperand(): created operand is 0");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedExpression::createOperand(): could not create operand");
|
||||
if (operand != 0) delete operand;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EnumeratedValue::EnumeratedValue(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
if (enumeration == NULL)
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedValue::EnumeratedValue(): enumerated value can not be created without specifying enumeration");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enumeration->enumElements.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedValue::EnumeratedValue(): enum element \"%s\" of enumeration \"%s\" was not registered", buf, enumeration->n);
|
||||
return;
|
||||
}
|
||||
|
||||
value = enumeration->enumElements[buf]->v;
|
||||
this->enumeration = enumeration;
|
||||
}
|
||||
|
||||
int EnumeratedValue::getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
EnumeratedOptionParameterRef::EnumeratedOptionParameterRef(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Option& option)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a reference to enumerated option parameter \"%s\"",buf));
|
||||
|
||||
if (!option.parameters->enumerated.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedOptionParameterRef::EnumeratedOptionParameterRef(): enumerated option parameter \"%s\" does not exist",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
parameter = option.parameters->enumerated.getPElement(buf)->e;
|
||||
this->enumeration = option.parameters->enumerations[buf];
|
||||
if (enumeration != NULL && enumeration != this->enumeration)
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedOptionParameterRef::EnumeratedOptionParameterRef(): enumeration input symbol \"%s\" does not match enumeration type \"%s\"", buf, enumeration->n);
|
||||
}
|
||||
}
|
||||
|
||||
int EnumeratedOptionParameterRef::getValue() const
|
||||
{
|
||||
return *parameter;
|
||||
}
|
||||
|
||||
EnumeratedInputSymbolRef::EnumeratedInputSymbolRef(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state) :
|
||||
symbol(0), parameters(0)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating reference to enumerated input symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.enumeratedInputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedInputSymbolRef::XabslEnumeratedInputSymbolRef(): enumerated input symbol \"%s\" was not registered at the engine",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
symbol = symbols.enumeratedInputSymbols[buf];
|
||||
this->enumeration = symbol->enumeration;
|
||||
|
||||
if (enumeration != NULL && enumeration != this->enumeration)
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedInputSymbolRef::XabslEnumeratedInputSymbolRef(): enumeration input symbol \"%s\" does not match enumeration type \"%s\"", buf, enumeration->n);
|
||||
}
|
||||
|
||||
parameters = new ParameterAssignment(&symbol->parameters, errorHandler);
|
||||
|
||||
parameters->create(input, symbols, option, state);
|
||||
}
|
||||
|
||||
EnumeratedInputSymbolRef::~EnumeratedInputSymbolRef()
|
||||
{
|
||||
if (parameters != 0)
|
||||
delete parameters;
|
||||
}
|
||||
|
||||
int EnumeratedInputSymbolRef::getValue() const
|
||||
{
|
||||
// set the symbol parameters
|
||||
if (parameters->set())
|
||||
symbol->parametersChanged();
|
||||
|
||||
return symbol->getValue();
|
||||
}
|
||||
|
||||
EnumeratedOutputSymbolRef::EnumeratedOutputSymbolRef(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a reference to an enumerated output symbol \"%s\"",buf));
|
||||
|
||||
if (!symbols.enumeratedOutputSymbols.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedOutputSymbolRef::EnumeratedOutputSymbolRef(): enumerated output symbol \"%s\" was not registered",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
symbol = symbols.enumeratedOutputSymbols[buf];
|
||||
this->enumeration = symbol->enumeration;
|
||||
|
||||
if (enumeration != NULL && enumeration != this->enumeration)
|
||||
{
|
||||
errorHandler.error("XabslEnumeratedInputSymbolRef::XabslEnumeratedInputSymbolRef(): enumeration input symbol \"%s\" does not match enumeration type \"%s\"", buf, enumeration->n);
|
||||
}
|
||||
}
|
||||
|
||||
int EnumeratedOutputSymbolRef::getValue() const
|
||||
{
|
||||
return symbol->getValue();
|
||||
}
|
||||
|
||||
ConditionalEnumeratedExpression::ConditionalEnumeratedExpression(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a question mark operator"));
|
||||
|
||||
condition = BooleanExpression::create(input,errorHandler,symbols,option,state);
|
||||
|
||||
if (condition == 0)
|
||||
{
|
||||
errorHandler.error("XabslQuestionMarkOperator::QuestionMarkOperator(): created condition is 0");
|
||||
return;
|
||||
}
|
||||
else if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslQuestionMarkOperator::QuestionMarkOperator(): could not create condition");
|
||||
delete condition;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EnumeratedExpression::createOperand(expression1,enumeration,input,errorHandler,symbols,option,state))
|
||||
{
|
||||
errorHandler.error("XabslQuestionMarkOperator::QuestionMarkOperator(): could not create decimal expression1");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EnumeratedExpression::createOperand(expression2,enumeration,input,errorHandler,symbols,option,state))
|
||||
{
|
||||
errorHandler.error("XabslQuestionMarkOperator::QuestionMarkOperator(): could not create decimal expression2");
|
||||
return;
|
||||
}
|
||||
this->enumeration = enumeration;
|
||||
}
|
||||
|
||||
ConditionalEnumeratedExpression::~ConditionalEnumeratedExpression()
|
||||
{
|
||||
if (condition!=0) delete condition;
|
||||
if (expression1!=0) delete expression1;
|
||||
if (expression2!=0) delete expression2;
|
||||
}
|
||||
|
||||
int ConditionalEnumeratedExpression::getValue() const
|
||||
{
|
||||
if (condition->getValue())
|
||||
{
|
||||
return expression1->getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return expression2->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,266 @@
|
||||
/**
|
||||
* @file XabslEnumeratedExpression.h
|
||||
*
|
||||
* Definition of EnumeratedExpression and derivates
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslEnumeratedExpression_h_
|
||||
#define __XabslEnumeratedExpression_h_
|
||||
|
||||
#include "XabslSymbols.h"
|
||||
#include "XabslDecimalExpression.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class EnumeratedExpression
|
||||
*
|
||||
* Base class for all enumerated expressions inside an option graph.
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class EnumeratedExpression
|
||||
{
|
||||
public:
|
||||
/** Evaluates the enumerated expression. */
|
||||
virtual int getValue() const = 0;
|
||||
|
||||
/**
|
||||
* Creates an enumerated expression depending on the input.
|
||||
* @param enumeration A reference to the enumeration which is the domain of this expression
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a enumerated expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
static EnumeratedExpression* create(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/**
|
||||
* Creates an enumerated expression depending on the input.
|
||||
* Uses the create() function to create enumerated operands.
|
||||
* @param operand The expression to be created
|
||||
* @param enumeration A reference to the enumeration which is the domain of this expression
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a decimal operand starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
* @return If the creation was successful
|
||||
*/
|
||||
static bool createOperand(
|
||||
const EnumeratedExpression*& operand,
|
||||
const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
virtual ~EnumeratedExpression() = 0;
|
||||
|
||||
const Enumeration* enumeration;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EnumeratedValue
|
||||
*
|
||||
* Represents a enumerated value.
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class EnumeratedValue : public EnumeratedExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the value
|
||||
* @param enumeration A reference to the enumeration which is the domain of this expression
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a value starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
*/
|
||||
EnumeratedValue(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler);
|
||||
|
||||
/**
|
||||
* Constructor. Creates an expression for a fixed enumerated value
|
||||
* @param value The enumerated value
|
||||
*/
|
||||
EnumeratedValue(const Enumeration* enumeration, int value) :
|
||||
value(value)
|
||||
{
|
||||
this->enumeration = enumeration;
|
||||
}
|
||||
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual int getValue() const;
|
||||
|
||||
private:
|
||||
/** The value */
|
||||
int value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EnumeratedOptionParameterRef
|
||||
*
|
||||
* Represents a reference to a enumerated option parameter.
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class EnumeratedOptionParameterRef : public EnumeratedExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the reference
|
||||
* @param enumeration A reference to the enumeration which is the domain of this expression
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where the expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param option The current option
|
||||
*/
|
||||
EnumeratedOptionParameterRef(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Option& option);
|
||||
|
||||
/** Calculates the value of the enumerated expression. */
|
||||
virtual int getValue() const;
|
||||
|
||||
private:
|
||||
/** A pointer to the parameter */
|
||||
int* parameter;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EnumeratedInputSymbolRef
|
||||
*
|
||||
* Represents an 'enumerated-input-symbol-ref' element of the option graph
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class EnumeratedInputSymbolRef : public EnumeratedExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the element
|
||||
* @param enumeration A reference to the enumeration which is the domain of this expression
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
EnumeratedInputSymbolRef(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
~EnumeratedInputSymbolRef();
|
||||
|
||||
/** Evaluates the enumerated expression. */
|
||||
virtual int getValue() const;
|
||||
|
||||
private:
|
||||
/** The referenced symbol */
|
||||
EnumeratedInputSymbol* symbol;
|
||||
|
||||
/** The parameter assignments of the referenced symbol */
|
||||
ParameterAssignment* parameters;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EnumeratedOutputSymbolRef
|
||||
*
|
||||
* Represents a reference to a enumerated input symbol.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class EnumeratedOutputSymbolRef : public EnumeratedExpression
|
||||
{
|
||||
public:
|
||||
/** Calculates the value of the enumerated expression. */
|
||||
virtual int getValue() const;
|
||||
|
||||
/**
|
||||
* Constructor. Creates the function call depending on the input.
|
||||
* @param enumeration A reference to the enumeration which is the domain of this expression
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where the function reference starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
*/
|
||||
EnumeratedOutputSymbolRef(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols);
|
||||
|
||||
private:
|
||||
/** The referenced symbol */
|
||||
const EnumeratedOutputSymbol* symbol;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ConditionalEnumeratedExpression
|
||||
*
|
||||
* Represents an ANSI C (condition?expression:expression) question mark operator
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class ConditionalEnumeratedExpression : public EnumeratedExpression
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the expression
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a expression starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
ConditionalEnumeratedExpression(const Enumeration* enumeration,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
~ConditionalEnumeratedExpression();
|
||||
|
||||
/** Calculates the value of the decimal expression. */
|
||||
virtual int getValue() const;
|
||||
|
||||
private:
|
||||
/** The condition */
|
||||
const BooleanExpression* condition;
|
||||
|
||||
/** The expression that is returned when the condition evaluates true */
|
||||
const EnumeratedExpression* expression1;
|
||||
|
||||
/** The expression that is returned when the condition evaluates false */
|
||||
const EnumeratedExpression* expression2;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslEnumeratedExpression_h_
|
||||
@ -0,0 +1,190 @@
|
||||
/**
|
||||
* @file XabslOption.cpp
|
||||
*
|
||||
* Implementation of class Option and helper classes
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#include "XabslOption.h"
|
||||
#include "XabslCoopState.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
OptionParameters::OptionParameters(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols) : Parameters(errorHandler)
|
||||
{
|
||||
int numberOfOptionParameters = (int)input.readValue();
|
||||
char buf[100];
|
||||
char c[2];
|
||||
for (int i=0; i< numberOfOptionParameters; i++)
|
||||
{
|
||||
input.readString(c,1);
|
||||
switch (c[0])
|
||||
{
|
||||
case 'd':
|
||||
input.readString(buf,99);
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal option parameter \"%s\"",buf));
|
||||
decimal.append(buf, new double(0));
|
||||
break;
|
||||
case 'b':
|
||||
input.readString(buf,99);
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean option parameter \"%s\"",buf));
|
||||
boolean.append(buf, new bool(false));
|
||||
break;
|
||||
case 'e':
|
||||
input.readString(buf,99);
|
||||
if (!symbols.enumerations.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslOptionParameters::OptionParameters(): enumeration \"%s\" was not registered",buf);
|
||||
return;
|
||||
}
|
||||
const Enumeration* enumeration = symbols.enumerations[buf];
|
||||
if (enumeration->enumElements.getSize() == 0)
|
||||
{
|
||||
errorHandler.error("XabslOptionParameters::OptionParameters(): no enumeration elements for \"%s\" were registered",buf);
|
||||
return;
|
||||
}
|
||||
input.readString(buf,99);
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated option parameter \"%s\"",buf));
|
||||
enumerated.append(buf, new int(enumeration->enumElements[0]->v));
|
||||
enumerations.append(buf,enumeration);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OptionParameters::~OptionParameters()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < decimal.getSize(); i++)
|
||||
delete decimal[i];
|
||||
for (i = 0; i < boolean.getSize(); i++)
|
||||
delete boolean[i];
|
||||
for (i = 0; i < enumerated.getSize(); i++)
|
||||
delete enumerated[i];
|
||||
}
|
||||
|
||||
Option::Option(const char* name,
|
||||
InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
const unsigned& time,
|
||||
int index)
|
||||
: Behavior(name), activeState(0),
|
||||
initialState(0), errorHandler(errorHandler),
|
||||
time(time),
|
||||
index(index)
|
||||
|
||||
{
|
||||
parameters = new OptionParameters(input, errorHandler, symbols);
|
||||
}
|
||||
|
||||
Option::~Option()
|
||||
{
|
||||
for (int i=0;i<states.getSize();i++)
|
||||
if (states[i]!=0)
|
||||
delete states[i];
|
||||
delete parameters;
|
||||
}
|
||||
|
||||
void Option::create(InputSource& input,
|
||||
NamedArray<Option*>& options,
|
||||
NamedArray<BasicBehavior*>& basicBehaviors,
|
||||
Symbols& symbols,
|
||||
const int& agentPriority,
|
||||
const int& synchronizationTicks
|
||||
)
|
||||
{
|
||||
int i;
|
||||
|
||||
// the number of states of the option
|
||||
int numberOfStates = (int)input.readValue();
|
||||
|
||||
char stateName[100];
|
||||
char c[2];
|
||||
|
||||
// register all states to the array
|
||||
for (i=0; i< numberOfStates; i++)
|
||||
{
|
||||
input.readString(stateName, 99);
|
||||
// cooperative state or not
|
||||
input.readString(c,1);
|
||||
switch (*c)
|
||||
{
|
||||
case 'n':
|
||||
states.append(stateName, new State(stateName,errorHandler,time,index,i));
|
||||
break;
|
||||
case 's':
|
||||
states.append(stateName, new SynchronizedState(stateName,errorHandler,time,index,i,agentPriority,synchronizationTicks,(int)input.readValue()));
|
||||
break;
|
||||
case 'c':
|
||||
states.append(stateName, new CapacityState(stateName,errorHandler,time,index,i,agentPriority,synchronizationTicks,(int)input.readValue()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
XABSL_DEBUG_INIT(errorHandler.message("XabslOption::create(): registered %i states",numberOfStates));
|
||||
|
||||
// set the initial state
|
||||
input.readString(stateName,99);
|
||||
initialState = states[stateName];
|
||||
activeState = initialState;
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("XabslOption::create(): initial state: \"%s\"",initialState->n));
|
||||
|
||||
// create the states and their subelements
|
||||
for (i=0; i< numberOfStates; i++)
|
||||
{
|
||||
states[i]->create(input, options, basicBehaviors, states, symbols);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslOption::create(): could not create state \"%s\"",states[i]->n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Option::execute()
|
||||
{
|
||||
if (isActive)
|
||||
{
|
||||
errorHandler.error("XabslOption::execute(): option \"%s\" is contained in activation tree more than once. Aborting execution.",n);
|
||||
return;
|
||||
}
|
||||
if (!wasActive)
|
||||
{
|
||||
activeState = initialState;
|
||||
activeState->reset();
|
||||
}
|
||||
|
||||
State* newState = activeState->getNextState();
|
||||
if (newState != activeState)
|
||||
{
|
||||
activeState = newState;
|
||||
activeState->reset();
|
||||
}
|
||||
|
||||
for (int j=0; j < activeState->actions.getSize(); j++)
|
||||
{
|
||||
activeState->actions[j]->execute();
|
||||
}
|
||||
}
|
||||
|
||||
bool Option::getOptionReachedATargetState() const
|
||||
{
|
||||
if (wasActive && activeState->isTargetState())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* @file XabslOption.h
|
||||
*
|
||||
* Definition of class Option and Helper classes
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslOption_h_
|
||||
#define __XabslOption_h_
|
||||
|
||||
#include "XabslState.h"
|
||||
#include "XabslBehavior.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class OptionParameters
|
||||
*
|
||||
* Represents the current set of parameters of an option or basic behavior
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class OptionParameters : public Parameters
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where an option starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
*/
|
||||
OptionParameters(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols);
|
||||
|
||||
/** Destructor */
|
||||
~OptionParameters();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Option
|
||||
*
|
||||
* Represents a single option written in
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class Option : public Behavior
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Does not create the option.
|
||||
* @param name The name of the option. For debugging purposes.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where an option starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param time The system time in ms.
|
||||
* @param Index of the option in array options in corresponding engine
|
||||
*/
|
||||
Option(const char* name, InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
const unsigned& time,
|
||||
int index);
|
||||
|
||||
/** Destructor. Deletes the states */
|
||||
~Option();
|
||||
|
||||
/**
|
||||
* Creates the option and it's states from the intermediate code.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where an option starts.
|
||||
* @param options All other options
|
||||
* @param basicBehaviors All basic behaviors
|
||||
* @param symbols All available symbols
|
||||
* @param agentPriority Priority value of the agent, used for solving conflicts in cooperative state assignment
|
||||
* @param synchronizationTicks Number of execution cycles that is required for synchonization with other agents, i.e time from sending a message until answer is received
|
||||
*/
|
||||
void create(InputSource& input,
|
||||
NamedArray<Option*>& options,
|
||||
NamedArray<BasicBehavior*>& basicBehaviors,
|
||||
Symbols& symbols,
|
||||
const int& agentPriority,
|
||||
const int& synchronizationTicks);
|
||||
|
||||
/**
|
||||
* Executes the option. The state machine is carried out to determine the subsequent
|
||||
* option or the subsequent basic behavior. Output symbols are set.
|
||||
*/
|
||||
virtual void execute();
|
||||
|
||||
/** The states of the option */
|
||||
NamedArray<State*> states;
|
||||
|
||||
/** A pointer to the active state. If 0, then no state is active */
|
||||
State* activeState;
|
||||
|
||||
/** Returns wheter the option reached a target state */
|
||||
bool getOptionReachedATargetState() const;
|
||||
|
||||
/** Index of the option in array options in corresponding engine */
|
||||
int index;
|
||||
|
||||
private:
|
||||
|
||||
/** A pointer to the initial state */
|
||||
State* initialState;
|
||||
|
||||
/** Used for error handling */
|
||||
ErrorHandler& errorHandler;
|
||||
|
||||
/** The system time in ms. */
|
||||
const unsigned& time;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslOption_h_
|
||||
@ -0,0 +1,312 @@
|
||||
/**
|
||||
* @file XabslParameters.cpp
|
||||
*
|
||||
* Implementation of class Parameters
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#include "XabslParameters.h"
|
||||
#include "XabslSymbols.h"
|
||||
#include "XabslOption.h"
|
||||
#include "XabslDecimalExpression.h"
|
||||
#include "XabslBooleanExpression.h"
|
||||
#include "XabslEnumeratedExpression.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
void Parameters::reset()
|
||||
{
|
||||
for (int i=0; i<decimal.getSize(); i++) *decimal[i] = 0;
|
||||
for (int i=0; i<boolean.getSize(); i++) *boolean[i] = false;
|
||||
for (int i=0; i<enumerated.getSize(); i++) *enumerated[i] = enumerations[i]->enumElements[0]->v;
|
||||
}
|
||||
|
||||
void Parameters::registerEnumerations(NamedArray<Enumeration*>& enumerations)
|
||||
{
|
||||
pEnumerations = &enumerations;
|
||||
}
|
||||
|
||||
void Parameters::registerDecimal(const char* name, double& parameter)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal parameter \"%s\"",name));
|
||||
|
||||
if (decimal.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDecimalParameter(): decimal parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
decimal.append(name,¶meter);
|
||||
parameter = 0;
|
||||
}
|
||||
|
||||
void Parameters::registerBoolean(const char* name, bool& parameter)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean parameter \"%s\"",name));
|
||||
|
||||
if (boolean.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanParameter(): boolean parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
boolean.append(name,¶meter);
|
||||
parameter = false;
|
||||
}
|
||||
|
||||
void Parameters::registerEnumerated(const char* name, const char* enumName, int& parameter)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated parameter \"%s\"",name));
|
||||
|
||||
if (pEnumerations == 0)
|
||||
{
|
||||
errorHandler.error("XabslParameters::registerEnumerated(): call Parameters::registerEnumerations first");
|
||||
return;
|
||||
}
|
||||
if (enumerated.exists(name))
|
||||
{
|
||||
errorHandler.error("XabslParameters::registerEnumerated(): enumerated parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
if (!pEnumerations->exists(enumName))
|
||||
{
|
||||
errorHandler.error("XabslParameters::registerEnumerated(): enumeration \"%s\" was not registered",enumName);
|
||||
return;
|
||||
}
|
||||
const Enumeration* enumeration = (*pEnumerations)[enumName];
|
||||
if (enumeration->enumElements.getSize() == 0)
|
||||
{
|
||||
errorHandler.error("XabslParameters::registerEnumerated(): no enumeration elements for \"%s\" were registered",enumName);
|
||||
return;
|
||||
}
|
||||
|
||||
enumerations.append(name, enumeration);
|
||||
enumerated.append(name,¶meter);
|
||||
|
||||
parameter = enumeration->enumElements[0]->v;
|
||||
}
|
||||
|
||||
ParameterAssignment::ParameterAssignment(
|
||||
Parameters* refParameters,
|
||||
ErrorHandler& errorHandler) :
|
||||
Parameters(errorHandler)
|
||||
{
|
||||
for (int i = 0; i < refParameters->decimal.getSize(); i++)
|
||||
{
|
||||
decimal.append(refParameters->decimal.getName(i), refParameters->decimal.getElement(i));
|
||||
decimalValues.append(refParameters->decimal.getName(i), 0);
|
||||
decimalExpressions.append(refParameters->decimal.getName(i), new DecimalValue(0));
|
||||
}
|
||||
for (int i = 0; i < refParameters->boolean.getSize(); i++)
|
||||
{
|
||||
boolean.append(refParameters->boolean.getName(i), refParameters->boolean.getElement(i));
|
||||
booleanValues.append(refParameters->boolean.getName(i), false);
|
||||
booleanExpressions.append(refParameters->boolean.getName(i), new BooleanValue(false));
|
||||
}
|
||||
for (int i = 0; i < refParameters->enumerated.getSize(); i++)
|
||||
{
|
||||
enumerated.append(refParameters->enumerated.getName(i), refParameters->enumerated.getElement(i));
|
||||
enumeratedValues.append(refParameters->enumerated.getName(i), false);
|
||||
enumeratedExpressions.append(refParameters->enumerated.getName(i), new EnumeratedValue(refParameters->enumerations[i], 0));
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterAssignment::create(
|
||||
InputSource& input,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
int i;
|
||||
// read the parameters
|
||||
int numberOfParameters = (int)input.readValue();
|
||||
|
||||
for (i = 0; i<numberOfParameters; i++)
|
||||
{
|
||||
char c[2];
|
||||
char buf[100];
|
||||
input.readString(c,1);
|
||||
switch(c[0])
|
||||
{
|
||||
case 'd':
|
||||
{
|
||||
input.readString(buf,99);
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating expession for set decimal parameter \"%s\"",buf));
|
||||
|
||||
const DecimalExpression* exp = DecimalExpression::create(input,errorHandler,symbols,option,state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslParameterAssignment::create(): could not create decimal expression for parameter \"%s\"",buf);
|
||||
return;
|
||||
}
|
||||
if (!setDecimalParameter(buf, exp)) return;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
{
|
||||
input.readString(buf,99);
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating expession for set boolean parameter \"%s\"",buf));
|
||||
|
||||
const BooleanExpression* exp = BooleanExpression::create(input,errorHandler,symbols,option,state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslParameterAssignment::create(): could not create boolean expression for parameter \"%s\"",buf);
|
||||
return;
|
||||
}
|
||||
if (!setBooleanParameter(buf, exp)) return;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
{
|
||||
input.readString(buf,99);
|
||||
if(!symbols.enumerations.exists(buf))
|
||||
{
|
||||
errorHandler.error("XabslParameterAssignment::create(): enumeration \"%s\" was not registered",buf);
|
||||
return;
|
||||
}
|
||||
const Enumeration* enumeration = symbols.enumerations[buf];
|
||||
|
||||
input.readString(buf,99);
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating expession for set enumerated parameter \"%s\"",buf));
|
||||
const EnumeratedExpression* exp = EnumeratedExpression::create(enumeration,input,errorHandler,symbols,option,state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslParameterAssignment::create(): could not create enumerated expression for parameter \"%s\"",buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setEnumeratedParameter(buf, exp)) return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParameterAssignment::~ParameterAssignment()
|
||||
{
|
||||
for (int i=0; i<decimalExpressions.getSize(); i++)
|
||||
delete decimalExpressions[i];
|
||||
for (int i=0; i<booleanExpressions.getSize(); i++)
|
||||
delete booleanExpressions[i];
|
||||
for (int i=0; i<enumeratedExpressions.getSize(); i++)
|
||||
delete enumeratedExpressions[i];
|
||||
}
|
||||
|
||||
bool ParameterAssignment::setDecimalParameter(const char* param, const DecimalExpression* exp)
|
||||
{
|
||||
if (!decimalExpressions.exists(param))
|
||||
{
|
||||
errorHandler.error("XabslParameterAssignment::setDecimalParameter(): decimal parameter \"%s\" does not exist", param);
|
||||
delete exp;
|
||||
return false;
|
||||
}
|
||||
delete decimalExpressions[param];
|
||||
decimalExpressions.setElement(param, exp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParameterAssignment::setBooleanParameter(const char* param, const BooleanExpression* exp)
|
||||
{
|
||||
if (!booleanExpressions.exists(param))
|
||||
{
|
||||
errorHandler.error("XabslParameterAssignment::setBooleanParameter(): boolean parameter \"%s\" does not exist",param);
|
||||
delete exp;
|
||||
return false;
|
||||
}
|
||||
delete booleanExpressions[param];
|
||||
booleanExpressions.setElement(param, exp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParameterAssignment::setEnumeratedParameter(const char* param, const EnumeratedExpression* exp)
|
||||
{
|
||||
if (!enumeratedExpressions.exists(param))
|
||||
{
|
||||
errorHandler.error("XabslParameterAssignment::create(): enumerated parameter \"%s\" does not exist",param);
|
||||
delete exp;
|
||||
return false;
|
||||
}
|
||||
if (exp->enumeration != enumeratedExpressions[param]->enumeration)
|
||||
{
|
||||
errorHandler.error("XabslParameterAssignment::create(): type mismatch on enumerated parameter \"%s\", expected \"%s\", found \"%s\"", param, enumeratedExpressions[param]->enumeration->n, exp->enumeration->n);
|
||||
return false;
|
||||
}
|
||||
delete enumeratedExpressions[param];
|
||||
enumeratedExpressions.setElement(param, exp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParameterAssignment::setDecimalParameter(const char* param, double value)
|
||||
{
|
||||
return setDecimalParameter(param, new DecimalValue(value));
|
||||
}
|
||||
|
||||
bool ParameterAssignment::setBooleanParameter(const char* param, bool value)
|
||||
{
|
||||
return setBooleanParameter(param, new BooleanValue(value));
|
||||
}
|
||||
|
||||
bool ParameterAssignment::setEnumeratedParameter(const char* param, const Enumeration* enumeration, int value)
|
||||
{
|
||||
return setEnumeratedParameter(param, new EnumeratedValue(enumeration, value));
|
||||
}
|
||||
|
||||
bool ParameterAssignment::setEnumeratedParameter(const char* param, const char* value)
|
||||
{
|
||||
if (!enumeratedExpressions.exists(param))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!enumeratedExpressions[param]->enumeration->enumElements.exists(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return setEnumeratedParameter(param, enumeratedExpressions[param]->enumeration, enumeratedExpressions[param]->enumeration->enumElements[value]->v);
|
||||
}
|
||||
}
|
||||
|
||||
bool ParameterAssignment::set()
|
||||
{
|
||||
int i;
|
||||
bool parametersChanged = false;
|
||||
|
||||
// Set the parameters.
|
||||
for (i=0; i<decimal.getSize(); i++)
|
||||
{
|
||||
decimalValues.setElement(i, decimalExpressions[i]->getValue());
|
||||
if (*decimal[i] != decimalValues[i])
|
||||
{
|
||||
parametersChanged = true;
|
||||
*decimal[i] = decimalValues[i];
|
||||
}
|
||||
}
|
||||
for (i=0; i<boolean.getSize(); i++)
|
||||
{
|
||||
booleanValues.setElement(i, booleanExpressions[i]->getValue());
|
||||
if (*boolean[i] != booleanValues[i])
|
||||
{
|
||||
parametersChanged = true;
|
||||
*boolean[i] = booleanValues[i];
|
||||
}
|
||||
}
|
||||
for (i=0; i<enumerated.getSize(); i++)
|
||||
{
|
||||
enumeratedValues.setElement(i, enumeratedExpressions[i]->getValue());
|
||||
if (*enumerated[i] != enumeratedValues[i])
|
||||
{
|
||||
parametersChanged = true;
|
||||
*enumerated[i] = enumeratedValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
return parametersChanged;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @file XabslParameters.h
|
||||
*
|
||||
* Definition of class Parameters
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslParameters_h_
|
||||
#define __XabslParameters_h_
|
||||
|
||||
#include "XabslTools.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
// class prototypes needed for declaration of Parameters
|
||||
class Symbols;
|
||||
class Enumeration;
|
||||
class Option;
|
||||
class State;
|
||||
class DecimalExpression;
|
||||
class BooleanExpression;
|
||||
class EnumeratedExpression;
|
||||
|
||||
/**
|
||||
* @class Parameters
|
||||
*
|
||||
* Represents the current set of parameters of a behavior or an input symbol
|
||||
*/
|
||||
class Parameters
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
*/
|
||||
Parameters(ErrorHandler& errorHandler)
|
||||
: errorHandler(errorHandler), pEnumerations(0)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Parameters() {};
|
||||
|
||||
|
||||
/** Reset all parameters to default values (=0) */
|
||||
void reset();
|
||||
|
||||
/** The decimal parameters */
|
||||
NamedArray<double*> decimal;
|
||||
|
||||
/** The boolean parameters */
|
||||
NamedArray<bool*> boolean;
|
||||
|
||||
/** The enumerated parameters */
|
||||
NamedArray<int*> enumerated;
|
||||
|
||||
/** The enumeration domain of the enumerated parameters */
|
||||
NamedArray<const Enumeration*> enumerations;
|
||||
|
||||
/**
|
||||
* Registers a reference to the enumerations of the engine
|
||||
* This is only required when registerEnumerated is called afterwards
|
||||
*/
|
||||
void registerEnumerations(NamedArray<Enumeration*>& enumerations);
|
||||
|
||||
/**
|
||||
* Registers a reference to a decimal parameter at the parameters array.
|
||||
* @param name The name of the parameter
|
||||
* @param parameter The reference to a parameter
|
||||
*/
|
||||
void registerDecimal(const char* name, double& parameter);
|
||||
|
||||
/**
|
||||
* Registers a reference to a boolean parameter at the parameters array.
|
||||
* @param name The name of the parameter
|
||||
* @param parameter The reference to a parameter
|
||||
*/
|
||||
void registerBoolean(const char* name, bool& parameter);
|
||||
|
||||
/**
|
||||
* Registers a reference to an enumerated parameter at the parameters array.
|
||||
* @param name The name of the parameter
|
||||
* @param enumName The name of the corresponding enumeration
|
||||
* @param parameter The reference to a parameter
|
||||
*/
|
||||
void registerEnumerated(const char* name, const char* enumName, int& parameter);
|
||||
|
||||
protected:
|
||||
/** Used for error handling */
|
||||
ErrorHandler& errorHandler;
|
||||
|
||||
private:
|
||||
/** Pointer to the enumerations of the engine */
|
||||
NamedArray<Enumeration*>* pEnumerations;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class ParameterAssignment
|
||||
*
|
||||
* Represents the assignment of parameters of a subsequent basic behaviors or an option or an input symbol
|
||||
*/
|
||||
class ParameterAssignment : public Parameters
|
||||
{
|
||||
public:
|
||||
/** Constructor.
|
||||
* @param refParameters The referenced set of parameters
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
*/
|
||||
ParameterAssignment(
|
||||
Parameters* refParameters,
|
||||
ErrorHandler& errorHandler
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates the parameter assignment.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a state starts.
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
void create(
|
||||
InputSource& input,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
~ParameterAssignment();
|
||||
|
||||
/** Adds a decimal parameter assignment
|
||||
* @param param name of the parameter
|
||||
* @param exp expression to be set to the parameter value when executing
|
||||
* @return False, if an error occurred
|
||||
*/
|
||||
bool setDecimalParameter(const char* param, const DecimalExpression* exp);
|
||||
/** Adds a decimal parameter assignment
|
||||
* @param param name of the parameter
|
||||
* @param value value to be set to the parameter value when executing
|
||||
* @return False, if an error occurred
|
||||
*/
|
||||
bool setDecimalParameter(const char* param, double value);
|
||||
|
||||
/** Adds a boolean parameter assignment
|
||||
* @param param name of the parameter
|
||||
* @param exp expression to be set to the parameter value when executing
|
||||
* @return False, if an error occurred
|
||||
*/
|
||||
bool setBooleanParameter(const char* param, const BooleanExpression* exp);
|
||||
/** Adds a boolean parameter assignment
|
||||
* @param param name of the parameter
|
||||
* @param value value to be set to the parameter value when executing
|
||||
* @return False, if an error occurred
|
||||
*/
|
||||
bool setBooleanParameter(const char* param, bool value);
|
||||
|
||||
/** Adds an enumerated parameter assignment
|
||||
* @param param name of the parameter
|
||||
* @param exp expression to be set to the parameter value when executing
|
||||
* @return False, if an error occurred
|
||||
*/
|
||||
bool setEnumeratedParameter(const char* param, const EnumeratedExpression* exp);
|
||||
/** Adds an enumerated parameter assignment
|
||||
* @param param name of the parameter
|
||||
* @param value value to be set to the parameter value when executing
|
||||
* @return False, if an error occurred
|
||||
*/
|
||||
bool setEnumeratedParameter(const char* param, const Enumeration* enumeration, int value);
|
||||
/** Adds an enumerated parameter assignment
|
||||
* @param param name of the parameter
|
||||
* @param value value to be set to the parameter value when executing
|
||||
* @return False, if an error occurred
|
||||
*/
|
||||
bool setEnumeratedParameter(const char* param, const char* value);
|
||||
|
||||
/** Current parameter values, these are stored just for debugging purposes */
|
||||
NamedArray<double> decimalValues;
|
||||
NamedArray<bool> booleanValues;
|
||||
NamedArray<int> enumeratedValues;
|
||||
|
||||
/** Decimal expressions for the parameters */
|
||||
NamedArray<const DecimalExpression*> decimalExpressions;
|
||||
/** Boolean expressions for the parameters */
|
||||
NamedArray<const BooleanExpression*> booleanExpressions;
|
||||
/** Enumerated expressions for the parameters */
|
||||
NamedArray<const EnumeratedExpression*> enumeratedExpressions;
|
||||
|
||||
/**
|
||||
* sets parameter variables to current expression values
|
||||
* returns true when parameter values have been changed
|
||||
*/
|
||||
bool set();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // __XabslParameters_h_
|
||||
|
||||
|
||||
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @file XabslState.cpp
|
||||
*
|
||||
* Implementation of class State and helper classes
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#include "XabslState.h"
|
||||
#include "XabslOption.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
State* TransitionToState::getNextState()
|
||||
{
|
||||
return nextState;
|
||||
}
|
||||
|
||||
State::State(const char* name, ErrorHandler& errorHandler,
|
||||
const unsigned& time,
|
||||
int optionIndex,
|
||||
int index)
|
||||
: NamedItem(name),
|
||||
targetState(false),
|
||||
errorHandler(errorHandler),
|
||||
decisionTree(0),
|
||||
time(time),
|
||||
optionIndex(optionIndex),
|
||||
index(index)
|
||||
{
|
||||
}
|
||||
|
||||
State::~State()
|
||||
{
|
||||
if (decisionTree != 0) delete decisionTree;
|
||||
for (int i=0; i<actions.getSize(); i++)
|
||||
delete actions[i];
|
||||
}
|
||||
|
||||
void State::create(InputSource& input,
|
||||
NamedArray<Option*>& options,
|
||||
NamedArray<BasicBehavior*>& basicBehaviors,
|
||||
NamedArray<State*>& states,
|
||||
Symbols& symbols)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating state \"%s\"",n));
|
||||
|
||||
char c[100];
|
||||
int i;
|
||||
|
||||
// target state or not
|
||||
input.readString(c,1);
|
||||
if (*c == '1')
|
||||
{
|
||||
targetState = true;
|
||||
}
|
||||
|
||||
// subsequent option, basic behaviors and output symbol assignments
|
||||
int numberOfActions = (int)input.readValue();
|
||||
|
||||
subsequentOption = 0;
|
||||
for(i = 0; i< numberOfActions; i++)
|
||||
{
|
||||
Action* action =
|
||||
Action::create(input,
|
||||
options,
|
||||
basicBehaviors,
|
||||
symbols,
|
||||
*options[optionIndex],
|
||||
*this,
|
||||
errorHandler,
|
||||
time);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslState::create(): could not create action for state \"%s\"",n);
|
||||
return;
|
||||
}
|
||||
if (subsequentOption == 0)
|
||||
if (ActionOption* actionOption = dynamic_cast<ActionOption*>(action))
|
||||
subsequentOption = actionOption->option;
|
||||
actions.append(action);
|
||||
}
|
||||
|
||||
// transition to state or if / else block
|
||||
decisionTree = Statement::createStatement(input,errorHandler,symbols,*options[optionIndex],*this);
|
||||
if (errorHandler.errorsOccurred)
|
||||
errorHandler.error("XabslState::create(): could not create decision tree for state \"%s\"",n);
|
||||
}
|
||||
|
||||
State* State::getNextState()
|
||||
{
|
||||
timeOfStateExecution = time - timeWhenStateWasActivated;
|
||||
|
||||
State* nextState = decisionTree->getNextState();
|
||||
|
||||
return nextState->coopCheck() ? nextState : this;
|
||||
}
|
||||
|
||||
void State::reset()
|
||||
{
|
||||
timeWhenStateWasActivated = time;
|
||||
timeOfStateExecution = 0;
|
||||
}
|
||||
|
||||
bool State::isTargetState() const
|
||||
{
|
||||
return targetState;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* @file XabslState.h
|
||||
*
|
||||
* Definition of class State and Helper classes
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslState_h_
|
||||
#define __XabslState_h_
|
||||
|
||||
#include "XabslStatement.h"
|
||||
#include "XabslBasicBehavior.h"
|
||||
#include "XabslDecimalExpression.h"
|
||||
#include "XabslBooleanExpression.h"
|
||||
#include "XabslEnumeratedExpression.h"
|
||||
#include "XabslAction.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
// class prototype needed for declaration of State
|
||||
class Option;
|
||||
|
||||
/**
|
||||
* @class State
|
||||
*
|
||||
* Represents a single state written in
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class State : public NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Does not create the state.
|
||||
* @param name The name of the state. For debugging purposes.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param time The system time in ms.
|
||||
* @param optionIndex Index of the corresponding option this state belongs to
|
||||
* @param index Index of the state in array states in corresponding option
|
||||
*/
|
||||
State(const char* name,
|
||||
ErrorHandler& errorHandler,
|
||||
const unsigned& time,
|
||||
int optionIndex,
|
||||
int index);
|
||||
|
||||
/** Destructor */
|
||||
~State();
|
||||
|
||||
/**
|
||||
* Creates the state and it's subelements from the intermediate code.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a state starts.
|
||||
* @param options All available options
|
||||
* @param basicBehaviors All available basicBehaviors
|
||||
* @param states All states of the option
|
||||
* @param symbols All available symbols
|
||||
*/
|
||||
void create(InputSource& input,
|
||||
NamedArray<Option*>& options,
|
||||
NamedArray<BasicBehavior*>& basicBehaviors,
|
||||
NamedArray<State*>& states,
|
||||
Symbols& symbols);
|
||||
|
||||
/**
|
||||
* Executes the decision tree and determines the next active state (can be the same).
|
||||
*/
|
||||
virtual State* getNextState();
|
||||
|
||||
/** The actions of the state */
|
||||
Array<Action*> actions;
|
||||
|
||||
/**
|
||||
* The first subsequent option that is executed after that option if the state is active.
|
||||
* If 0, no subsequent option is executed after that option.
|
||||
* This pointer is present just for compatibility reasons, please use getactions instead
|
||||
*/
|
||||
Option* subsequentOption;
|
||||
|
||||
/** The time how long the state is already active */
|
||||
unsigned timeOfStateExecution;
|
||||
|
||||
/** Sets the time when the state was activated to 0 */
|
||||
void reset();
|
||||
|
||||
/** Returns wheter the state is a target state */
|
||||
bool isTargetState() const;
|
||||
|
||||
/** Index of the state in array states in corresponding option */
|
||||
int index;
|
||||
|
||||
/** The time, when the state was activated */
|
||||
unsigned timeWhenStateWasActivated;
|
||||
|
||||
/** Index of the corresponding option this state belongs to */
|
||||
int optionIndex;
|
||||
|
||||
/** Check whether this state can be entered, or whether entering is blocked due to cooperating agents */
|
||||
virtual bool coopCheck() {return true;}
|
||||
|
||||
/** Whether this state is currently conflicted, i.e whether cooperation conditions are violated */
|
||||
virtual bool getConflict() {return false;}
|
||||
|
||||
protected:
|
||||
|
||||
/** If true, the state is a target state */
|
||||
bool targetState;
|
||||
|
||||
/** Used for error handling */
|
||||
ErrorHandler& errorHandler;
|
||||
|
||||
/** The root element of the decision tree */
|
||||
Statement* decisionTree;
|
||||
|
||||
/** The system time in ms. */
|
||||
const unsigned& time;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslState_h_
|
||||
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @file XabslStatement.cpp
|
||||
*
|
||||
* Implementation of class Statement and helper classes
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#include "XabslStatement.h"
|
||||
#include "XabslState.h"
|
||||
#include "XabslOption.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
Statement* Statement::createStatement(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state)
|
||||
{
|
||||
char c[100];
|
||||
|
||||
input.readString(c,1);
|
||||
|
||||
switch (*c)
|
||||
{
|
||||
case 't':
|
||||
return new TransitionToState(input, errorHandler, option);
|
||||
case 'i':
|
||||
return new IfElseBlock(input, errorHandler, symbols, option, state);
|
||||
default:
|
||||
errorHandler.error("XabslStatement::create(): unknown type \"%c\"",*c);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Statement::~Statement()
|
||||
{
|
||||
}
|
||||
|
||||
IfElseBlock::IfElseBlock(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state) :
|
||||
ifCondition(0), ifStatement(0), elseStatement(0)
|
||||
{
|
||||
|
||||
// if case
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating if statement"));
|
||||
|
||||
ifCondition = BooleanExpression::create(input, errorHandler, symbols, option, state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslIfElseBlock::IfElseBlock(): could not create if condition");
|
||||
return;
|
||||
}
|
||||
|
||||
ifStatement = Statement::createStatement(input, errorHandler, symbols, option, state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
{
|
||||
errorHandler.error("XabslIfElseBlock::IfElseBlock(): could not create if statement");
|
||||
return;
|
||||
}
|
||||
|
||||
// else case
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating else statement"));
|
||||
|
||||
elseStatement = Statement::createStatement(input, errorHandler, symbols, option, state);
|
||||
if (errorHandler.errorsOccurred)
|
||||
errorHandler.error("XabslIfElseBlock::IfElseBlock(): could not create else statement");
|
||||
|
||||
}
|
||||
|
||||
IfElseBlock::~IfElseBlock()
|
||||
{
|
||||
if (ifCondition != 0) delete ifCondition;
|
||||
if (ifStatement != 0) delete ifStatement;
|
||||
|
||||
int i;
|
||||
for (i=0; i<elseIfStatements.getSize(); i++)
|
||||
{
|
||||
if (elseIfConditions[i] != 0)
|
||||
delete elseIfConditions[i];
|
||||
if (elseIfStatements[i] != 0)
|
||||
delete elseIfStatements[i];
|
||||
}
|
||||
|
||||
if (elseStatement != 0) delete elseStatement;
|
||||
}
|
||||
|
||||
State* IfElseBlock::getNextState()
|
||||
{
|
||||
if (ifCondition->getValue()) return ifStatement->getNextState();
|
||||
|
||||
for (int i=0; i<elseIfConditions.getSize(); i++)
|
||||
{
|
||||
if (elseIfConditions[i]->getValue()) return elseIfStatements[i]->getNextState();
|
||||
}
|
||||
|
||||
return elseStatement->getNextState();
|
||||
}
|
||||
|
||||
TransitionToState::TransitionToState(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Option& option)
|
||||
{
|
||||
char buf[100];
|
||||
input.readString(buf,99);
|
||||
|
||||
nextState = option.states[buf];
|
||||
|
||||
XABSL_DEBUG_INIT(errorHandler.message("creating a transition to state \"%s\"",nextState->n));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,131 @@
|
||||
/**
|
||||
* @file XabslStatement.h
|
||||
*
|
||||
* Definition of class Statement and Helper classes
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslStatement_h_
|
||||
#define __XabslStatement_h_
|
||||
|
||||
#include "XabslBooleanExpression.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
// class prototype needed for the declaration of Statement
|
||||
class State;
|
||||
|
||||
/**
|
||||
* @class Statement
|
||||
*
|
||||
* An element of a decision that that determines a transition to a state.
|
||||
* It can be either a transition to a state or a if/else-if/else block containing other statements.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class Statement
|
||||
{
|
||||
public:
|
||||
/** Executes the statement and determines the next active state (can be the same). */
|
||||
virtual State* getNextState() = 0;
|
||||
|
||||
/**
|
||||
* Creates a statement depending on the input.
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a statement starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
static Statement* createStatement(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state);
|
||||
|
||||
/** Destructor */
|
||||
virtual ~Statement() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class IfElseBlock
|
||||
*
|
||||
* An element of a decision tree that that contains of an if - (else-if) - else block
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class IfElseBlock : public Statement
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the if / else statement
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a transition starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param symbols All available symbols
|
||||
* @param option The current option
|
||||
* @param state The current state
|
||||
*/
|
||||
IfElseBlock(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Symbols& symbols,
|
||||
Option& option,
|
||||
State& state
|
||||
);
|
||||
|
||||
/** Destructor. Deletes all statements and conditions */
|
||||
~IfElseBlock();
|
||||
|
||||
/** Executes the statement and determines the next active state (can be the same). */
|
||||
virtual State* getNextState();
|
||||
|
||||
private:
|
||||
/** The boolean expression that is evaluated for the if case */
|
||||
BooleanExpression* ifCondition;
|
||||
|
||||
/** The statement that is executed if the if condition is true */
|
||||
Statement* ifStatement;
|
||||
|
||||
/** The boolean expressions for the else-if cases */
|
||||
NamedArray<BooleanExpression*> elseIfConditions;
|
||||
|
||||
/** The statements that are executed if the else-if condition are true */
|
||||
NamedArray<Statement*> elseIfStatements;
|
||||
|
||||
/** The statement that is executed if all if and else-if conditions fail */
|
||||
Statement* elseStatement;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Represents a transition to a state inside a decision tree
|
||||
*/
|
||||
class TransitionToState : public Statement
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor. Creates the transition object
|
||||
* @param input An input source for the intermediate code. It must be opened and read until
|
||||
* A position where a transition starts.
|
||||
* @param errorHandler A reference to a ErrorHandler instance
|
||||
* @param option The current option
|
||||
*/
|
||||
TransitionToState(InputSource& input,
|
||||
ErrorHandler& errorHandler,
|
||||
Option& option);
|
||||
|
||||
/** Executes the statement and determines the next active state (can be the same). */
|
||||
virtual State* getNextState();
|
||||
|
||||
private:
|
||||
/** The state where that transition points to */
|
||||
State* nextState;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // __XabslStatement_h_
|
||||
@ -0,0 +1,464 @@
|
||||
/**
|
||||
* @file XabslSymbols.cpp
|
||||
*
|
||||
* Implementation of class Symbols and helper classes
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#include "XabslSymbols.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
Enumeration::~Enumeration()
|
||||
{
|
||||
int i;
|
||||
for (i=0; i< enumElements.getSize(); i++)
|
||||
{
|
||||
delete enumElements[i];
|
||||
}
|
||||
}
|
||||
|
||||
Symbols::~Symbols()
|
||||
{
|
||||
int i;
|
||||
for (i=0; i< enumerations.getSize(); i++) delete enumerations[i];
|
||||
for (i=0; i< decimalInputSymbols.getSize(); i++) delete decimalInputSymbols[i];
|
||||
for (i=0; i< booleanInputSymbols.getSize(); i++) delete booleanInputSymbols[i];
|
||||
for (i=0; i< enumeratedInputSymbols.getSize(); i++) delete enumeratedInputSymbols[i];
|
||||
for (i=0; i< decimalOutputSymbols.getSize(); i++) delete decimalOutputSymbols[i];
|
||||
for (i=0; i< booleanOutputSymbols.getSize(); i++) delete booleanOutputSymbols[i];
|
||||
for (i=0; i< enumeratedOutputSymbols.getSize(); i++) delete enumeratedOutputSymbols[i];
|
||||
}
|
||||
|
||||
void Symbols::registerEnumElement(const char* symbolName, const char* name, int value)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enum element \"%s\" for enumeration \"%s\"",name, symbolName));
|
||||
|
||||
if (!enumerations.exists(symbolName))
|
||||
{
|
||||
enumerations.append(symbolName, new Enumeration(symbolName, enumerations.getSize()));
|
||||
}
|
||||
if (enumerations[symbolName]->enumElements.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumElement(): enum element \"%s\" for enumeration \"%s\" was already registered.", name, symbolName);
|
||||
return;
|
||||
}
|
||||
enumerations[symbolName]->enumElements.append(name, new EnumElement(name,value));
|
||||
}
|
||||
|
||||
void Symbols::registerDecimalInputSymbol(const char* name, const double* pVariable)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal input symbol \"%s\"",name));
|
||||
|
||||
if (decimalInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
decimalInputSymbols.append(name,new DecimalInputSymbol(name, pVariable, errorHandler, decimalInputSymbols.getSize()));
|
||||
}
|
||||
|
||||
|
||||
void Symbols::registerDecimalInputSymbol
|
||||
(const char* name,
|
||||
double (*pFunction)())
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal input symbol \"%s\"",name));
|
||||
|
||||
if (decimalInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
decimalInputSymbols.append(name,new DecimalInputSymbol(name, pFunction, errorHandler, decimalInputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerDecimalInputSymbolParametersChanged(const char* name,
|
||||
void (*pFunction)())
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering parameter change notification for decimal input symbol\"%s\"",name));
|
||||
|
||||
if (!decimalInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbolParametersChanged(): symbol \"%s\" was not registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
decimalInputSymbols[name]->pParametersChanged = pFunction;
|
||||
}
|
||||
|
||||
void Symbols::registerDecimalInputSymbolDecimalParameter(const char* symbolName,
|
||||
const char* name, double* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal parameter \"%s\" for decimal input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!decimalInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbolDecimalParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (decimalInputSymbols[symbolName]->parameters.decimal.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbolDecimalParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
decimalInputSymbols[symbolName]->parameters.decimal.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerDecimalInputSymbolBooleanParameter(const char* symbolName,
|
||||
const char* name, bool* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean parameter \"%s\" for decimal input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!decimalInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbolBooleanParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (decimalInputSymbols[symbolName]->parameters.boolean.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbolBooleanParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
decimalInputSymbols[symbolName]->parameters.boolean.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerDecimalInputSymbolEnumeratedParameter(const char* symbolName,
|
||||
const char* name, const char* enumName, int* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated parameter \"%s\" for decimal input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!decimalInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbolEnumeratedParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (decimalInputSymbols[symbolName]->parameters.enumerated.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDecimalInputSymbolEnumeratedParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enumerations.exists(enumName))
|
||||
{
|
||||
enumerations.append(enumName, new Enumeration(enumName, enumerations.getSize()));
|
||||
}
|
||||
decimalInputSymbols[symbolName]->parameters.enumerations.append(name,enumerations.getElement(enumName));
|
||||
decimalInputSymbols[symbolName]->parameters.enumerated.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerBooleanInputSymbol(const char* name, const bool* pVariable)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean input symbol \"%s\"",name));
|
||||
|
||||
if (booleanInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
booleanInputSymbols.append(name,new BooleanInputSymbol(name, pVariable, errorHandler, booleanInputSymbols.getSize()));
|
||||
}
|
||||
|
||||
|
||||
void Symbols::registerBooleanInputSymbol(const char* name,
|
||||
bool (*pFunction)())
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean input symbol \"%s\"",name));
|
||||
|
||||
if (booleanInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
booleanInputSymbols.append(name,new BooleanInputSymbol(name, pFunction, errorHandler, booleanInputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerBooleanInputSymbolParametersChanged(const char* name,
|
||||
void (*pFunction)())
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering parameter change notification for boolean input symbol\"%s\"",name));
|
||||
|
||||
if (!booleanInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbolParametersChanged(): symbol \"%s\" was not registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
booleanInputSymbols[name]->pParametersChanged = pFunction;
|
||||
}
|
||||
|
||||
void Symbols::registerBooleanInputSymbolDecimalParameter(const char* symbolName,
|
||||
const char* name, double* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal parameter \"%s\" for boolean input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!booleanInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbolDecimalParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (booleanInputSymbols[symbolName]->parameters.decimal.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbolDecimalParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
booleanInputSymbols[symbolName]->parameters.decimal.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerBooleanInputSymbolBooleanParameter(const char* symbolName,
|
||||
const char* name, bool* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean parameter \"%s\" for boolean input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!booleanInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbolBooleanParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (booleanInputSymbols[symbolName]->parameters.boolean.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbolBooleanParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
booleanInputSymbols[symbolName]->parameters.boolean.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerBooleanInputSymbolEnumeratedParameter(const char* symbolName,
|
||||
const char* name, const char* enumName, int* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated parameter \"%s\" for boolean input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!booleanInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbolEnumeratedParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (booleanInputSymbols[symbolName]->parameters.enumerated.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanInputSymbolEnumeratedParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
if (!enumerations.exists(enumName))
|
||||
{
|
||||
enumerations.append(enumName, new Enumeration(enumName, enumerations.getSize()));
|
||||
}
|
||||
booleanInputSymbols[symbolName]->parameters.enumerations.append(name,enumerations.getElement(enumName));
|
||||
booleanInputSymbols[symbolName]->parameters.enumerated.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerEnumeratedInputSymbol(const char* name, const char* enumName, const int* pVariable)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated input symbol \"%s\"",name));
|
||||
|
||||
if (enumeratedInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
if (!enumerations.exists(enumName))
|
||||
{
|
||||
enumerations.append(enumName, new Enumeration(enumName, enumerations.getSize()));
|
||||
}
|
||||
enumeratedInputSymbols.append(name,new EnumeratedInputSymbol(name, enumerations[enumName], pVariable, errorHandler, enumeratedInputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerEnumeratedInputSymbol(const char* name, const char* enumName,
|
||||
int (*pFunction)())
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated input symbol \"%s\"",name));
|
||||
|
||||
if (enumeratedInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
if (!enumerations.exists(enumName))
|
||||
{
|
||||
enumerations.append(enumName, new Enumeration(enumName, enumerations.getSize()));
|
||||
}
|
||||
enumeratedInputSymbols.append(name,new EnumeratedInputSymbol(name, enumerations[enumName], pFunction, errorHandler, enumeratedInputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerEnumeratedInputSymbolParametersChanged(const char* name,
|
||||
void (*pFunction)())
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering parameter change notification for enumerated input symbol\"%s\"",name));
|
||||
|
||||
if (!enumeratedInputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbolParametersChanged(): symbol \"%s\" was not registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
enumeratedInputSymbols[name]->pParametersChanged = pFunction;
|
||||
}
|
||||
|
||||
void Symbols::registerEnumeratedInputSymbolDecimalParameter(const char* symbolName,
|
||||
const char* name, double* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal parameter \"%s\" for enumerated input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!enumeratedInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbolDecimalParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (enumeratedInputSymbols[symbolName]->parameters.decimal.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbolDecimalParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
enumeratedInputSymbols[symbolName]->parameters.decimal.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerEnumeratedInputSymbolBooleanParameter(const char* symbolName,
|
||||
const char* name, bool* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean parameter \"%s\" for enumerated input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!enumeratedInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbolBooleanParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (enumeratedInputSymbols[symbolName]->parameters.boolean.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbolBooleanParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
|
||||
enumeratedInputSymbols[symbolName]->parameters.boolean.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerEnumeratedInputSymbolEnumeratedParameter(const char* symbolName,
|
||||
const char* name, const char* enumName, int* pParam)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated parameter \"%s\" for enumerated input symbol\"%s\"",name, symbolName));
|
||||
|
||||
if (!enumeratedInputSymbols.exists(symbolName))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbolEnumeratedParameter(): symbol \"%s\" was not registered",symbolName);
|
||||
return;
|
||||
}
|
||||
if (enumeratedInputSymbols[symbolName]->parameters.enumerated.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedInputSymbolEnumeratedParameter(): parameter \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
if (!enumerations.exists(enumName))
|
||||
{
|
||||
enumerations.append(enumName, new Enumeration(enumName, enumerations.getSize()));
|
||||
}
|
||||
enumeratedInputSymbols[symbolName]->parameters.enumerations.append(name,enumerations.getElement(enumName));
|
||||
enumeratedInputSymbols[symbolName]->parameters.enumerated.append(name,pParam);
|
||||
}
|
||||
|
||||
void Symbols::registerDecimalOutputSymbol(const char* name, double* pVariable)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal output symbol \"%s\"",name));
|
||||
|
||||
if (decimalOutputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDcimalOutputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
decimalOutputSymbols.append(name,new DecimalOutputSymbol(name, pVariable, decimalOutputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerDecimalOutputSymbol(const char* name,
|
||||
void (*pSetFunction)(double),
|
||||
double (*pGetFunction)()
|
||||
)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering decimal output symbol \"%s\"",name));
|
||||
|
||||
if (decimalOutputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerDecimalOutputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
decimalOutputSymbols.append(name,new DecimalOutputSymbol(name, pSetFunction, pGetFunction, decimalOutputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerBooleanOutputSymbol(const char* name, bool* pVariable)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean output symbol \"%s\"",name));
|
||||
|
||||
if (booleanOutputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanOutputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
booleanOutputSymbols.append(name,new BooleanOutputSymbol(name, pVariable, booleanOutputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerBooleanOutputSymbol(const char* name,
|
||||
void (*pSetFunction)(bool),
|
||||
bool (*pGetFunction)()
|
||||
)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering boolean output symbol \"%s\"",name));
|
||||
|
||||
if (booleanOutputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerBooleanOutputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
booleanOutputSymbols.append(name,new BooleanOutputSymbol(name, pSetFunction, pGetFunction, booleanOutputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerEnumeratedOutputSymbol(const char* name, const char* enumName, int* pVariable)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated output symbol \"%s\"",name));
|
||||
|
||||
if (enumeratedOutputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedOutputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
if (!enumerations.exists(enumName))
|
||||
{
|
||||
enumerations.append(enumName, new Enumeration(enumName, enumerations.getSize()));
|
||||
}
|
||||
enumeratedOutputSymbols.append(name,new EnumeratedOutputSymbol(name, enumerations[enumName], pVariable, enumeratedOutputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::registerEnumeratedOutputSymbol(const char* name, const char* enumName,
|
||||
void (*pSetFunction)(int),
|
||||
int (*pGetFunction)()
|
||||
)
|
||||
{
|
||||
XABSL_DEBUG_INIT(errorHandler.message("registering enumerated output symbol \"%s\"",name));
|
||||
|
||||
if (enumeratedOutputSymbols.exists(name))
|
||||
{
|
||||
errorHandler.error("registerEnumeratedOutputSymbol(): symbol \"%s\" was already registered",name);
|
||||
return;
|
||||
}
|
||||
if (!enumerations.exists(enumName))
|
||||
{
|
||||
enumerations.append(enumName, new Enumeration(enumName, enumerations.getSize()));
|
||||
}
|
||||
enumeratedOutputSymbols.append(name,new EnumeratedOutputSymbol(name, enumerations[enumName], pSetFunction, pGetFunction, enumeratedOutputSymbols.getSize()));
|
||||
}
|
||||
|
||||
void Symbols::resetOutputSymbols()
|
||||
{
|
||||
for (int i=0;i<decimalOutputSymbols.getSize();i++)
|
||||
decimalOutputSymbols[i]->activeValueWasSet = false;
|
||||
for (int i=0;i<booleanOutputSymbols.getSize();i++)
|
||||
booleanOutputSymbols[i]->activeValueWasSet = false;
|
||||
for (int i=0;i<enumeratedOutputSymbols.getSize();i++)
|
||||
enumeratedOutputSymbols[i]->activeValueWasSet = false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,635 @@
|
||||
/**
|
||||
* @file XabslSymbols.h
|
||||
*
|
||||
* Definition of class Symbols and helper classes
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslSymbols_h_
|
||||
#define __XabslSymbols_h_
|
||||
|
||||
#include "XabslTools.h"
|
||||
#include "XabslParameters.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class EnumElement
|
||||
* Represents an enum element that is part of an enumerated input or output symbol.
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class EnumElement : public NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the enum element as specified in the XML formalization
|
||||
* @param value The value for the element from the software environment
|
||||
*/
|
||||
EnumElement(const char* name, int value)
|
||||
: NamedItem(name), v(value) {};
|
||||
|
||||
/** The enum value from a function or variable in the software environment */
|
||||
int v;
|
||||
};
|
||||
/**
|
||||
* @class Enumeration
|
||||
*
|
||||
* Represents a list of enum elements
|
||||
*/
|
||||
class Enumeration : public NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the enumeration as specified in the XML formalization
|
||||
* @param index Index of the enumeration in array enumerations in corresponding engine
|
||||
*/
|
||||
Enumeration(const char* name, int index) : NamedItem(name), index(index) {};
|
||||
|
||||
/** Destructor. Deletes the enum elements */
|
||||
~Enumeration();
|
||||
|
||||
/**
|
||||
* Assigns an enum value from a function or variable in the software environment
|
||||
* to the enum-element string in the XML formalization.
|
||||
*/
|
||||
NamedArray<EnumElement*> enumElements;
|
||||
|
||||
/** Index of the enumeration in array enumerations in corresponding engine */
|
||||
int index;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Template for the input symbol classes
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
template<class T> class InputSymbol : public NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pVariable A pointer to the variable that the symbol stands for
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
InputSymbol(const char* name, const T* pVariable, ErrorHandler& errorHandler, int index)
|
||||
: NamedItem(name), parameters(errorHandler), pV(pVariable), pF(0), pParametersChanged(0), index(index), lastValue(0)
|
||||
{};
|
||||
|
||||
|
||||
/** Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pFunction A pointer to a boolean returning function in the software environment
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
InputSymbol(const char* name,
|
||||
T (*pFunction)(),
|
||||
ErrorHandler& errorHandler, int index)
|
||||
: NamedItem(name), parameters(errorHandler), pV(0), pF(pFunction), pParametersChanged(0), index(index), lastValue(0) {};
|
||||
|
||||
/** returns the value of the symbol */
|
||||
T getValue()
|
||||
{ if (pF!=0) return lastValue = (*pF)(); else return lastValue = *pV; }
|
||||
|
||||
/** Notify the software environment about a parameter change */
|
||||
void parametersChanged() const
|
||||
{ if (pParametersChanged!=0) (*pParametersChanged)(); }
|
||||
|
||||
/** The parameters of the input symbol*/
|
||||
Parameters parameters;
|
||||
|
||||
/** A Pointer to a parameter change notification function in the software environment */
|
||||
void (*pParametersChanged)();
|
||||
|
||||
/** Index of the symbol in array in corresponding engine */
|
||||
int index;
|
||||
|
||||
/** Last queried value of the input symbol */
|
||||
T lastValue;
|
||||
|
||||
private:
|
||||
/** A pointer to a variable in the software environment */
|
||||
const T* pV;
|
||||
|
||||
/** A pointer to a T returning function in the software environment */
|
||||
T (*pF)();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DecimalInputSymbol
|
||||
*
|
||||
* Represents a decimal input symbol of the Engine
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class DecimalInputSymbol : public InputSymbol<double>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pVariable A pointer to the variable that the symbol stands for
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
DecimalInputSymbol(const char* name, const double* pVariable, ErrorHandler& errorHandler, int index)
|
||||
: InputSymbol<double>(name, pVariable, errorHandler, index)
|
||||
{};
|
||||
|
||||
/** Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pFunction A pointer to a double returning function in the software environment
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
DecimalInputSymbol(const char* name,
|
||||
double (*pFunction)(),
|
||||
ErrorHandler& errorHandler, int index)
|
||||
: InputSymbol<double>(name, pFunction, errorHandler, index) {};
|
||||
};
|
||||
|
||||
/**
|
||||
* @class BooleanInputSymbol
|
||||
*
|
||||
* Represents a boolean input symbol of the Engine
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class BooleanInputSymbol : public InputSymbol<bool>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pVariable A pointer to the variable that the symbol stands for
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
BooleanInputSymbol(const char* name, const bool* pVariable, ErrorHandler& errorHandler, int index)
|
||||
: InputSymbol<bool>(name, pVariable, errorHandler, index)
|
||||
{};
|
||||
|
||||
/** Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pFunction A pointer to a boolean returning function in the software environment
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
BooleanInputSymbol(const char* name,
|
||||
bool (*pFunction)(),
|
||||
ErrorHandler& errorHandler, int index)
|
||||
: InputSymbol<bool>(name, pFunction, errorHandler, index) {};
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EnumeratedInputSymbol
|
||||
*
|
||||
* Represents a enumerated input symbol of the Engine
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class EnumeratedInputSymbol : public InputSymbol<int>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pVariable A pointer to the variable that the symbol stands for
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
EnumeratedInputSymbol(const char* name, Enumeration* enumeration, const int* pVariable,
|
||||
ErrorHandler& errorHandler, int index)
|
||||
: InputSymbol<int>(name, pVariable, errorHandler, index), enumeration(enumeration)
|
||||
{};
|
||||
|
||||
/** Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param enumeration Pointer to the list of enumeration elements
|
||||
* @param pFunction A pointer to an int returning function in the software environment
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
EnumeratedInputSymbol(const char* name, Enumeration* enumeration,
|
||||
int (*pFunction)(),
|
||||
ErrorHandler& errorHandler, int index)
|
||||
: InputSymbol<int>(name, pFunction, errorHandler, index), enumeration(enumeration) {};
|
||||
|
||||
/** Pointer to the list of enumeration elements */
|
||||
Enumeration* enumeration;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class OutputSymbol
|
||||
*
|
||||
* A Template for the output symbol classes
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
template<class T> class OutputSymbol : public NamedItem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pVariable A pointer to the variable that the symbol stands for
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
OutputSymbol(const char* name, T* pVariable, int index)
|
||||
: NamedItem(name), activeValueWasSet(false), pV(pVariable), pSetF(0), pGetF(0), index(index), lastValue(0)
|
||||
{};
|
||||
|
||||
|
||||
/** Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pSetFunction A pointer to a boolean accepting function in the software environment
|
||||
* @param pGetFunction A pointer to a boolean returning function in the software environment
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
OutputSymbol(const char* name,
|
||||
void (*pSetFunction)(T),
|
||||
T (*pGetFunction)(), int index)
|
||||
: NamedItem(name), activeValueWasSet(false), pV(0), pSetF(pSetFunction), pGetF(pGetFunction), index(index), lastValue(0)
|
||||
{};
|
||||
|
||||
|
||||
/** Set the value of the symbol. */
|
||||
void setValue(T value)
|
||||
{
|
||||
if (pSetF!=0)
|
||||
{
|
||||
(*pSetF)(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pV=value;
|
||||
}
|
||||
lastValue = value;
|
||||
activeValueWasSet = true;
|
||||
}
|
||||
|
||||
/** Returns the current value of the symbol. */
|
||||
T getValue() const
|
||||
{
|
||||
if (pGetF!=0)
|
||||
{
|
||||
return (*pGetF)();
|
||||
}
|
||||
else
|
||||
{
|
||||
return *pV;
|
||||
}
|
||||
}
|
||||
|
||||
/** If true, the value was set during the last execution of the option graph. */
|
||||
bool activeValueWasSet;
|
||||
|
||||
/** Index of the symbol in array in corresponding engine */
|
||||
int index;
|
||||
|
||||
/** Last set value of the output symbol */
|
||||
T lastValue;
|
||||
|
||||
private:
|
||||
/** A pointer to a variable in the software environment */
|
||||
T* pV;
|
||||
|
||||
/** A pointer to a function that sets the value of the symbol in the software environment */
|
||||
void (*pSetF)(T);
|
||||
|
||||
/** A pointer to a function that gets the value of the symbol from the software environment */
|
||||
T (*pGetF)();
|
||||
};
|
||||
|
||||
/**
|
||||
* @class DecimalOutputSymbol
|
||||
*
|
||||
* Represents a decimal output symbol of the Engine
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class DecimalOutputSymbol : public OutputSymbol<double>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pVariable A pointer to the variable that the symbol stands for
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
DecimalOutputSymbol(const char* name, double* pVariable, int index)
|
||||
: OutputSymbol<double>(name, pVariable, index)
|
||||
{};
|
||||
|
||||
/** Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pSetFunction A pointer to a function in the software environment that sets the value of the symbol
|
||||
* @param pGetFunction A pointer to a function in the software environment that returns the value of the symbol
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
DecimalOutputSymbol(const char* name,
|
||||
void (*pSetFunction)(double),
|
||||
double (*pGetFunction)(), int index)
|
||||
: OutputSymbol<double>(name, pSetFunction, pGetFunction, index)
|
||||
{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @class BooleanOutputSymbol
|
||||
*
|
||||
* Represents a boolean output symbol of the Engine
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*
|
||||
*/
|
||||
class BooleanOutputSymbol : public OutputSymbol<bool>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pVariable A pointer to the variable that the symbol stands for
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
BooleanOutputSymbol(const char* name, bool* pVariable, int index)
|
||||
: OutputSymbol<bool>(name, pVariable, index)
|
||||
{};
|
||||
|
||||
/** Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param pSetFunction A pointer to a function in the software environment that sets the value of the symbol
|
||||
* @param pGetFunction A pointer to a function in the software environment that returns the value of the symbol
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
BooleanOutputSymbol(const char* name,
|
||||
void (*pSetFunction)(bool),
|
||||
bool (*pGetFunction)(), int index)
|
||||
: OutputSymbol<bool>(name, pSetFunction, pGetFunction, index)
|
||||
{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EnumeratedOutputSymbol
|
||||
*
|
||||
* Represents a enumerated output symbol of the Engine
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
class EnumeratedOutputSymbol : public OutputSymbol<int>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param enumeration Pointer to the list of enumeration elements
|
||||
* @param pVariable A pointer to the variable that the symbol stands for
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
EnumeratedOutputSymbol(const char* name, Enumeration* enumeration, int* pVariable, int index)
|
||||
: OutputSymbol<int>(name, pVariable, index), enumeration(enumeration)
|
||||
{};
|
||||
|
||||
|
||||
/** Constructor
|
||||
* @param name The name of the symbol, for debugging purposes
|
||||
* @param enumeration Pointer to the list of enumeration elements
|
||||
* @param pSetFunction A pointer to a function in the software environment that sets the value of the symbol
|
||||
* @param pGetFunction A pointer to a function in the software environment that returns the value of the symbol
|
||||
* @param index Index of the symbol in array in corresponding engine
|
||||
*/
|
||||
EnumeratedOutputSymbol(const char* name, Enumeration* enumeration,
|
||||
void (*pSetFunction)(int),
|
||||
int (*pGetFunction)(), int index)
|
||||
: OutputSymbol<int>(name, pSetFunction, pGetFunction, index), enumeration(enumeration)
|
||||
{};
|
||||
|
||||
/** Pointer to the list of enumeration elements */
|
||||
Enumeration* enumeration;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Symbols
|
||||
*
|
||||
* Handles the symbols of the Engine.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class Symbols
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param errorHandler Is invoked when errors occur
|
||||
*/
|
||||
Symbols(ErrorHandler& errorHandler)
|
||||
: errorHandler(errorHandler) {};
|
||||
|
||||
/** Destructor */
|
||||
virtual ~Symbols();
|
||||
|
||||
/**
|
||||
* Registers an enum element for an enumeration.
|
||||
* @param enumName The name of the enumeration
|
||||
* @param name The name of the enum element
|
||||
* @param value The value of the element
|
||||
*/
|
||||
void registerEnumElement(const char* enumName,
|
||||
const char* name, int value);
|
||||
|
||||
/**
|
||||
* Registers the address of a variable for a decimal input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pVariable A pointer to a variable in the software environment
|
||||
*/
|
||||
void registerDecimalInputSymbol(const char* name, const double* pVariable);
|
||||
|
||||
/**
|
||||
* Registers the address of a function for a decimal input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pFunction A pointer to a function that calculates a value for the symbol
|
||||
*/
|
||||
void registerDecimalInputSymbol(const char* name,
|
||||
double (*pFunction)());
|
||||
|
||||
/**
|
||||
* Registers the address of a function for parameter change notification for a decimal input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pFunction A pointer to the parameter change notification function
|
||||
*/
|
||||
void registerDecimalInputSymbolParametersChanged(const char* name,
|
||||
void (*pFunction)());
|
||||
|
||||
/**
|
||||
* Registers a parameter of a parameterized decimal input symbol.
|
||||
* @param symbolName The name of the symbol
|
||||
* @param name The name of the parameter
|
||||
* @param pParam A pointer to the parameter
|
||||
*/
|
||||
void registerDecimalInputSymbolDecimalParameter(const char* symbolName,
|
||||
const char* name, double* pParam);
|
||||
void registerDecimalInputSymbolBooleanParameter(const char* symbolName,
|
||||
const char* name, bool* pParam);
|
||||
void registerDecimalInputSymbolEnumeratedParameter(const char* symbolName,
|
||||
const char* name, const char* enumName, int* pParam);
|
||||
|
||||
/**
|
||||
* Registers the address of a variable for a boolean input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pVariable A pointer to a variable in the software environment
|
||||
*/
|
||||
void registerBooleanInputSymbol(const char* name, const bool* pVariable);
|
||||
|
||||
/**
|
||||
* Registers the address of a function for a boolean input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pFunction A pointer to a function that calculates a value for the symbol
|
||||
*/
|
||||
void registerBooleanInputSymbol(const char* name,
|
||||
bool (*pFunction)());
|
||||
|
||||
/**
|
||||
* Registers the address of a function for parameter change notification for a boolean input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pFunction A pointer to the parameter change notification function
|
||||
*/
|
||||
void registerBooleanInputSymbolParametersChanged(const char* name,
|
||||
void (*pFunction)());
|
||||
|
||||
/**
|
||||
* Registers a parameter of a parameterized boolean input symbol.
|
||||
* @param symbolName The name of the symbol
|
||||
* @param name The name of the parameter
|
||||
* @param pParam A pointer to the parameter
|
||||
*/
|
||||
void registerBooleanInputSymbolDecimalParameter(const char* symbolName,
|
||||
const char* name, double* pParam);
|
||||
void registerBooleanInputSymbolBooleanParameter(const char* symbolName,
|
||||
const char* name, bool* pParam);
|
||||
void registerBooleanInputSymbolEnumeratedParameter(const char* symbolName,
|
||||
const char* name, const char* enumName, int* pParam);
|
||||
|
||||
/**
|
||||
* Registers the address of a variable for a enumerated input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param enumName The name of the associated enumeration
|
||||
* @param pVariable A pointer to a variable in the software environment
|
||||
*/
|
||||
void registerEnumeratedInputSymbol(const char* name, const char* enumName, const int* pVariable);
|
||||
|
||||
/**
|
||||
* Registers the address of a function for a enumerated input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param enumName The name of the associated enumeration
|
||||
* @param pFunction A pointer to a function that calculates a value for the symbol
|
||||
*/
|
||||
void registerEnumeratedInputSymbol(const char* name, const char* enumName,
|
||||
int (*pFunction)());
|
||||
|
||||
/**
|
||||
* Registers the address of a function for parameter change notification for an enumerated input symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pFunction A pointer to the parameter change notification function
|
||||
*/
|
||||
void registerEnumeratedInputSymbolParametersChanged(const char* name,
|
||||
void (*pFunction)());
|
||||
|
||||
/**
|
||||
* Registers a parameter of an enumerated input symbol.
|
||||
* @param symbolName The name of the symbol
|
||||
* @param name The name of the parameter
|
||||
* @param pParam A pointer to the parameter
|
||||
*/
|
||||
void registerEnumeratedInputSymbolDecimalParameter(const char* symbolName,
|
||||
const char* name, double* pParam);
|
||||
void registerEnumeratedInputSymbolBooleanParameter(const char* symbolName,
|
||||
const char* name, bool* pParam);
|
||||
void registerEnumeratedInputSymbolEnumeratedParameter(const char* symbolName,
|
||||
const char* name, const char* enumName, int* pParam);
|
||||
|
||||
/**
|
||||
* Registers the address of a variable for a decimal output symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pVariable A pointer to a variable in the software environment
|
||||
*/
|
||||
void registerDecimalOutputSymbol(const char* name, double* pVariable);
|
||||
|
||||
/**
|
||||
* Registers the address of a function for a decimal output symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pSetFunction A pointer to a function that sets a value for the symbol
|
||||
* @param pGetFunction A pointer to a function that returns a value for the symbol
|
||||
*/
|
||||
void registerDecimalOutputSymbol(const char* name,
|
||||
void (*pSetFunction)(double),
|
||||
double (*pGetFunction)()
|
||||
);
|
||||
|
||||
/**
|
||||
* Registers the address of a variable for a boolean output symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pVariable A pointer to a variable in the software environment
|
||||
*/
|
||||
void registerBooleanOutputSymbol(const char* name, bool* pVariable);
|
||||
|
||||
/**
|
||||
* Registers the address of a function for a boolean output symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param pSetFunction A pointer to a function that sets a value for the symbol
|
||||
* @param pGetFunction A pointer to a function that returns a value for the symbol
|
||||
*/
|
||||
void registerBooleanOutputSymbol(const char* name,
|
||||
void (*pSetFunction)(bool),
|
||||
bool (*pGetFunction)()
|
||||
);
|
||||
|
||||
/**
|
||||
* Registers the address of a variable for a enumerated output symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param enumName The name of the associated enumeration
|
||||
* @param pVariable A pointer to a variable in the software environment
|
||||
*/
|
||||
void registerEnumeratedOutputSymbol(const char* name, const char* enumName, int* pVariable);
|
||||
|
||||
/**
|
||||
* Registers the address of a function for a enumerated output symbol.
|
||||
* @param name The name of the symbol
|
||||
* @param enumName The name of the associated enumeration
|
||||
* @param pSetFunction A pointer to a function that sets a value for the symbol
|
||||
* @param pGetFunction A pointer to a function that returns a value for the symbol
|
||||
*/
|
||||
void registerEnumeratedOutputSymbol(const char* name, const char* enumName,
|
||||
void (*pSetFunction)(int),
|
||||
int (*pGetFunction)()
|
||||
);
|
||||
|
||||
/** Sets all output symbols to unset */
|
||||
void resetOutputSymbols();
|
||||
|
||||
/** The enumerations */
|
||||
NamedArray<Enumeration*> enumerations;
|
||||
|
||||
/** The decimal input symbols */
|
||||
NamedArray<DecimalInputSymbol*> decimalInputSymbols;
|
||||
|
||||
/** The boolean input symbols */
|
||||
NamedArray<BooleanInputSymbol*> booleanInputSymbols;
|
||||
|
||||
/** The enumerated input symbols */
|
||||
NamedArray<EnumeratedInputSymbol*> enumeratedInputSymbols;
|
||||
|
||||
/** The decimal output symbols */
|
||||
NamedArray<DecimalOutputSymbol*> decimalOutputSymbols;
|
||||
|
||||
/** The boolean output symbols */
|
||||
NamedArray<BooleanOutputSymbol*> booleanOutputSymbols;
|
||||
|
||||
/** The enumerated output symbols */
|
||||
NamedArray<EnumeratedOutputSymbol*> enumeratedOutputSymbols;
|
||||
|
||||
private:
|
||||
/** Is invoked when errors occur */
|
||||
ErrorHandler& errorHandler;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslSymbols_h_
|
||||
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file XabslTeamMessage.h
|
||||
*
|
||||
* Definition of class TeamMessage
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslTeamMessage_h_
|
||||
#define __XabslTeamMessage_h_
|
||||
|
||||
#include "XabslArray.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* @class TeamMessage
|
||||
*
|
||||
* Represents an incoming or outgoing message transmitted from/to other cooperating agents
|
||||
*
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
*/
|
||||
class TeamMessage
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
TeamMessage() : agentPriority(0)
|
||||
{};
|
||||
|
||||
/** An array containing indexes of currently executed cooperative states */
|
||||
Array<int> coopStatesExecuted;
|
||||
|
||||
/** An array containing indexes of cooperative states, currently trying to be executed but blocked due to cooperating agents */
|
||||
Array<int> coopStatesEntering;
|
||||
|
||||
/** An array containing indexes of cooperative states, whose corresponding option is being executed */
|
||||
Array<int> coopStatesOptionExecuted;
|
||||
|
||||
/** Priority value of the agent, used for solving conflicts in cooperative state assignment */
|
||||
int agentPriority;
|
||||
|
||||
/** Reset the content of the message */
|
||||
void reset()
|
||||
{
|
||||
coopStatesExecuted.clear();
|
||||
coopStatesEntering.clear();
|
||||
coopStatesOptionExecuted.clear();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslTeamMessage_h_
|
||||
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file XabslTools.cpp
|
||||
*
|
||||
* Implementation of several helper classes for the Engine.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
*/
|
||||
|
||||
#include "XabslTools.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
void ErrorHandler::error(const char* format, ...)
|
||||
{
|
||||
// get the argument list
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
|
||||
// print the expression to the buffer
|
||||
vsprintf(messageBuffer,format,args);
|
||||
|
||||
printError(messageBuffer);
|
||||
|
||||
// delete the argument list
|
||||
va_end(args);
|
||||
errorsOccurred = true;
|
||||
}
|
||||
|
||||
void ErrorHandler::message(const char* format, ...)
|
||||
{
|
||||
// get the argument list
|
||||
va_list args;
|
||||
va_start(args,format);
|
||||
|
||||
// print the expression to the buffer
|
||||
vsprintf(messageBuffer,format,args);
|
||||
|
||||
printMessage(messageBuffer);
|
||||
|
||||
// delete the argument list
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* @file XabslTools.h
|
||||
*
|
||||
* Definition of several helper classes for the Engine.
|
||||
*
|
||||
* @author <a href="http://www.martin-loetzsch.de">Martin Loetzsch</a>
|
||||
* @author <a href="http://www.sim.informatik.tu-darmstadt.de/pers/card/risler.html">Max Risler</a>
|
||||
* @author <a href="http://www.informatik.hu-berlin.de/~juengel">Matthias Juengel</a>
|
||||
*/
|
||||
|
||||
#ifndef __XabslTools_h_
|
||||
#define __XabslTools_h_
|
||||
|
||||
#include "XabslArray.h"
|
||||
|
||||
namespace xabsl
|
||||
{
|
||||
|
||||
/**
|
||||
* A Engine helper class for reading input data from files or from memory.
|
||||
*/
|
||||
class InputSource
|
||||
{
|
||||
public:
|
||||
/** Virtual destructor */
|
||||
virtual ~InputSource() {}
|
||||
|
||||
/** opens the source that contains the intermediate code */
|
||||
virtual bool open() = 0;
|
||||
|
||||
/** closes the source */
|
||||
virtual void close() = 0;
|
||||
|
||||
/** reads a numeric value from the input source */
|
||||
virtual double readValue() = 0;
|
||||
|
||||
/**
|
||||
* reads a string from the input source
|
||||
* @param destination The position where to write the string
|
||||
* @param maxLength the maximum length of the string
|
||||
* @return if the read succeded
|
||||
*/
|
||||
virtual bool readString(char* destination, int maxLength) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Engine helper class for handling errors and debug messages
|
||||
*/
|
||||
class ErrorHandler
|
||||
{
|
||||
public:
|
||||
/** constructor */
|
||||
ErrorHandler() : errorsOccurred(false) {};
|
||||
|
||||
/** virtual destructor */
|
||||
virtual ~ErrorHandler() {}
|
||||
|
||||
/**
|
||||
* Prints out an error
|
||||
* @param text The text to display
|
||||
*/
|
||||
virtual void printError(const char* text) = 0;
|
||||
|
||||
/**
|
||||
* Prints out a message
|
||||
* @param text The text to display
|
||||
*/
|
||||
virtual void printMessage(const char* text) = 0;
|
||||
|
||||
/**
|
||||
* Formats a error message and calls the printError() function.
|
||||
* @param format Format string as used by printf defined in stdio.h.
|
||||
* @param ... See printf in stdio.h.
|
||||
*/
|
||||
void error(const char* format, ...);
|
||||
|
||||
/**
|
||||
* Formats a message and calls the printMessage() function
|
||||
* @param format Format string as used by printf defined in stdio.h.
|
||||
* @param ... See printf in stdio.h.
|
||||
*/
|
||||
void message(const char* format, ...);
|
||||
|
||||
/** if errors occurred */
|
||||
bool errorsOccurred;
|
||||
|
||||
private:
|
||||
/** a buffer for errors and debug messages */
|
||||
char messageBuffer[300];
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef TimeFunction
|
||||
* A pointer to a function that returns the current system time.
|
||||
*/
|
||||
typedef unsigned (*TimeFunction)();
|
||||
|
||||
// If that macro is defined, the engine prints a lot of debug messages during initialization
|
||||
//#define _DO_DEBUG_INIT
|
||||
|
||||
/** Expressions inside that macro are only executed if XABSL_DEBUG_INIT is defined */
|
||||
#ifdef _DO_DEBUG_INIT
|
||||
#define XABSL_DEBUG_INIT(expression) expression
|
||||
#else
|
||||
#define XABSL_DEBUG_INIT(expression) /**/
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif //__XabslTools_h_
|
||||
@ -0,0 +1,230 @@
|
||||
# XabslMakefile
|
||||
#
|
||||
# Generates the documentation and intermediate code for a Xabsl project.
|
||||
#
|
||||
# author: Martin Loetzsch, Max Risler
|
||||
#
|
||||
# This Makefile should be included into a custom Makefile inside the directory, where the Xabsl sources are.
|
||||
# Inside this custom Makefile these Variables have to be set:
|
||||
# All paths are relative to the source files and the custom Makefile.
|
||||
#
|
||||
# AGENTS_FILE: File containing agent definitions
|
||||
# SOURCES: List of all XABSL source files
|
||||
#
|
||||
# XABSL_OUTPUT_DIR: Directory where the intermediate code shall be generated
|
||||
# XABSL_TEMP_DIR: Directory where XABSL compiler will store temporary files
|
||||
# INTERMEDIATE_CODE: The filename of the intermediate code to be generated
|
||||
# DEBUG_SYMBOLS: The filename of the debug symbols to be generated
|
||||
# XML_OUTPUT_DIR: Directory where the xml files should be generated
|
||||
# DOC_OUTPUT_DIR: Directory for the documentation output
|
||||
#
|
||||
# XABSL_COMPILER_DIR: Directory which contains the Xabsl compiler
|
||||
# XABSL_COMPILER_OPTIONS: Additional optional parameters for the XABSL compiler
|
||||
#
|
||||
# XSLT: An XSLT processor that can process XInclude statements (with necessary parameters)
|
||||
# DOT: Path of the dot tool
|
||||
# DOTML_DIR: Directory that contains the DotML Schemas and XSLT stylesheets
|
||||
# XABSL_XSL_DIR: Directory which contains the Xabsl XSLT Stylesheets
|
||||
|
||||
|
||||
# General documentation output files
|
||||
DOC_INDEX_HTML = $(DOC_OUTPUT_DIR)/index.html
|
||||
DOC_AGENTS_HTML = $(DOC_OUTPUT_DIR)/agents.html
|
||||
DOC_SYMBOLS_INDEX_HTML = $(DOC_OUTPUT_DIR)/symbols.html
|
||||
DOC_OPTION_INDEX_HTML = $(DOC_OUTPUT_DIR)/options.html
|
||||
DOC_BASIC_BEHAVIOR_INDEX_HTML = $(DOC_OUTPUT_DIR)/basic-behaviors.html
|
||||
DOC_STYLES_CSS = $(DOC_OUTPUT_DIR)/styles.css
|
||||
|
||||
|
||||
# Documentation XSLT Stylesheets
|
||||
DOC_INDEX_XSL = $(XABSL_XSL_DIR)/generate-documentation.index.xsl
|
||||
DOC_MENU_XSL = $(XABSL_XSL_DIR)/generate-documentation.menu.xsl
|
||||
DOC_SYMBOLS_XSL = $(XABSL_XSL_DIR)/generate-documentation.symbols.xsl
|
||||
DOC_SYMBOLS_INDEX_XSL = $(XABSL_XSL_DIR)/generate-documentation.symbols-index.xsl
|
||||
DOC_AGENTS_XSL = $(XABSL_XSL_DIR)/generate-documentation.agents.xsl
|
||||
DOC_BASIC_BEHAVIORS_XSL = $(XABSL_XSL_DIR)/generate-documentation.basic-behaviors.xsl
|
||||
DOC_BASIC_BEHAVIOR_INDEX_XSL = $(XABSL_XSL_DIR)/generate-documentation.basic-behavior-index.xsl
|
||||
DOC_OPTION_XSL = $(XABSL_XSL_DIR)/generate-documentation.option.xsl
|
||||
DOC_OPTION_INDEX_XSL = $(XABSL_XSL_DIR)/generate-documentation.option-index.xsl
|
||||
DOC_OPTION_TREE_XSL = $(XABSL_XSL_DIR)/generate-documentation.option-tree.xsl
|
||||
DOC_PSEUDO_CODE_XSL = $(XABSL_XSL_DIR)/generate-documentation.pseudo-code.xsl
|
||||
DOC_PARAMETERS_XSL = $(XABSL_XSL_DIR)/generate-documentation.parameters.xsl
|
||||
REMOVE_COMMENTS_XSL = $(XABSL_XSL_DIR)/remove-comments.xsl
|
||||
|
||||
# XSLT Stylesheet for debug symbols
|
||||
DEBUG_SYMBOLS_XSL = $(XABSL_XSL_DIR)/generate-debug-symbols.xsl
|
||||
|
||||
# XML output files
|
||||
XML_SYMBOL_FILES := $(shell bash -c "shopt -s nullglob;echo $(XML_OUTPUT_DIR)/Symbols/*.xml")
|
||||
XML_BASIC_BEHAVIOR_FILES := $(shell bash -c "shopt -s nullglob;echo $(XML_OUTPUT_DIR)/BasicBehaviors/*.xml")
|
||||
XML_OPTION_FILES := $(shell bash -c "shopt -s nullglob;echo $(XML_OUTPUT_DIR)/Options/*.xml")
|
||||
XML_FILES = $(XML_OUTPUT_DIR)/agents.xml $(XML_OUTPUT_DIR)/options.xml $(XML_OUTPUT_DIR)/symbol-and-basic-behavior-files.dtd $(XML_SYMBOL_FILES) $(XML_BASIC_BEHAVIOR_FILES) $(XML_OPTION_FILES)
|
||||
|
||||
# Documentation output files
|
||||
DOC_SYMBOL_FILES = $(shell echo $(XML_SYMBOL_FILES) |sed "s%[^ ]*/%%g;s%\([^ ]*\)\.xml%$(DOC_OUTPUT_DIR)/symbols.\1.html%g")
|
||||
DOC_BASIC_BEHAVIOR_FILES = $(shell echo $(XML_BASIC_BEHAVIOR_FILES) |sed "s%[^ ]*/%%g;s%\([^ ]*\)\.xml%$(DOC_OUTPUT_DIR)/basic-behaviors.\1.html%g")
|
||||
DOC_OPTION_FILES = $(shell echo $(XML_OPTION_FILES) |sed "s%[^ ]*/%%g;s%\([^ ]*\)\.xml%$(DOC_OUTPUT_DIR)/option.\1.html%g")
|
||||
|
||||
# Generate intermediate code, documentation
|
||||
all: $(XABSL_OUTPUT_DIR)/$(INTERMEDIATE_CODE) DOCUMENTATION DS
|
||||
|
||||
# Some shortcuts for common targets:
|
||||
DOC: DOCUMENTATION
|
||||
|
||||
rebuild: clean
|
||||
@make all
|
||||
|
||||
# Removes the documentation output directory, the intermediate code, the xml output directory and temp directory.
|
||||
clean:
|
||||
@rm -f $(XABSL_TEMP_DIR)/xabsl.*.dump
|
||||
@rm -f $(XABSL_OUTPUT_DIR)/$(INTERMEDIATE_CODE)
|
||||
@rm -f $(XABSL_OUTPUT_DIR)/$(DEBUG_SYMBOLS)
|
||||
@rm -rf $(XML_OUTPUT_DIR)
|
||||
@rm -rf $(DOC_OUTPUT_DIR)
|
||||
|
||||
# Shortcuts for intermediate code and debug symbols
|
||||
IC : $(XABSL_OUTPUT_DIR)/$(INTERMEDIATE_CODE)
|
||||
DS :
|
||||
@make -s XML
|
||||
@make -s $(XABSL_OUTPUT_DIR)/$(DEBUG_SYMBOLS)
|
||||
|
||||
# Generate intermediate code
|
||||
$(XABSL_OUTPUT_DIR)/$(INTERMEDIATE_CODE) : $(SOURCES)
|
||||
@echo compiling to intermediate code $(XABSL_OUTPUT_DIR)/$(INTERMEDIATE_CODE)
|
||||
@make -s -C $(XABSL_COMPILER_DIR)
|
||||
@ruby $(XABSL_COMPILER_DIR)/xabsl.rb $(XABSL_COMPILER_OPTIONS) -I $(XABSL_TEMP_DIR) -i $(XABSL_OUTPUT_DIR)/$(INTERMEDIATE_CODE) $(AGENTS_FILE)
|
||||
|
||||
# Call xabsl compiler for generating xml code
|
||||
# Since there is an unknown number of source files this step is always done
|
||||
XML : $(SOURCES)
|
||||
@echo compiling to xml output in $(XML_OUTPUT_DIR)
|
||||
@make -s -C $(XABSL_COMPILER_DIR)
|
||||
@ruby $(XABSL_COMPILER_DIR)/xabsl.rb $(XABSL_COMPILER_OPTIONS) -I $(XABSL_TEMP_DIR) -x $(XABSL_TEMP_DIR)/new $(AGENTS_FILE)
|
||||
|
||||
@mkdir -p $(XML_OUTPUT_DIR)/Symbols
|
||||
@mkdir -p $(XML_OUTPUT_DIR)/Options
|
||||
@mkdir -p $(XML_OUTPUT_DIR)/BasicBehaviors
|
||||
@for xmlfile in `find $(XABSL_TEMP_DIR)/new -type f -printf %P\\\\n`; do \
|
||||
if test -f $(XML_OUTPUT_DIR)/$$xmlfile; then \
|
||||
if test -n "$$(diff $(XABSL_TEMP_DIR)/new/$$xmlfile $(XML_OUTPUT_DIR)/$$xmlfile)"; then \
|
||||
mv -f $(XABSL_TEMP_DIR)/new/$$xmlfile $(XML_OUTPUT_DIR)/$$xmlfile; \
|
||||
fi; \
|
||||
else \
|
||||
mv $(XABSL_TEMP_DIR)/new/$$xmlfile $(XML_OUTPUT_DIR)/$$xmlfile; \
|
||||
fi; \
|
||||
done
|
||||
@rm -rf $(XABSL_TEMP_DIR)/new
|
||||
|
||||
$(XML_OUTPUT_DIR)/agents.xinclude-processed.xml: $(XML_FILES) \
|
||||
$(REMOVE_COMMENTS_XSL)
|
||||
@if test -f $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml; then rm -f $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml; fi
|
||||
@echo generating `pwd`/$(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@$(XSLT) -o $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml $(REMOVE_COMMENTS_XSL) $(XML_OUTPUT_DIR)/agents.xml
|
||||
|
||||
# Generates a intermediate xml file for the option trees of all options
|
||||
$(XML_OUTPUT_DIR)/option-tree.xml: $(DOC_OPTION_TREE_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@echo generating $@
|
||||
@$(XSLT) -o $(XABSL_TEMP_DIR)/new/option-tree.xml $(DOC_OPTION_TREE_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@if test -f $(XML_OUTPUT_DIR)/option-tree.xml; then \
|
||||
if test -n "$$(diff $(XABSL_TEMP_DIR)/new/option-tree.xml $(XML_OUTPUT_DIR)/option-tree.xml)"; then \
|
||||
mv -f $(XABSL_TEMP_DIR)/new/option-tree.xml $(XML_OUTPUT_DIR)/option-tree.xml; \
|
||||
fi; \
|
||||
else \
|
||||
mv $(XABSL_TEMP_DIR)/new/option-tree.xml $(XML_OUTPUT_DIR)/option-tree.xml; \
|
||||
fi
|
||||
@rm -rf $(XABSL_TEMP_DIR)/new
|
||||
|
||||
# Generate documentation in two steps, first generate xml output, next generate html files
|
||||
# Building in separate steps is necessary since first step generates files needed by second
|
||||
DOCUMENTATION:
|
||||
@make -s XML
|
||||
@make -s HTML
|
||||
|
||||
# Documenation needs and output directory, the .css file, and index pages and a page for each symbols, basic-behaviors, and options file.
|
||||
HTML: $(DOC_OUTPUT_DIR) \
|
||||
$(DOC_OUTPUT_DIR)/svg \
|
||||
$(XML_OUTPUT_DIR)/option-tree.xml \
|
||||
$(DOC_STYLES_CSS) \
|
||||
$(DOC_INDEX_HTML) \
|
||||
$(DOC_SYMBOLS_INDEX_HTML) \
|
||||
$(DOC_BASIC_BEHAVIOR_INDEX_HTML) \
|
||||
$(DOC_OPTION_INDEX_HTML) \
|
||||
$(DOC_AGENTS_HTML) \
|
||||
$(DOC_SYMBOL_FILES) \
|
||||
$(DOC_BASIC_BEHAVIOR_FILES) \
|
||||
$(DOC_OPTION_FILES)
|
||||
|
||||
|
||||
# Generic rule for symbol documentation
|
||||
$(DOC_OUTPUT_DIR)/symbols.%.html: $(XML_OUTPUT_DIR)/Symbols/%.xml $(DOC_MENU_XSL) $(DOC_SYMBOLS_XSL)
|
||||
@echo generating $@
|
||||
@$(XSLT) -o $@ $(DOC_SYMBOLS_XSL) $<
|
||||
|
||||
# Generic rule for option documentation
|
||||
$(DOC_OUTPUT_DIR)/option.%.html: $(XML_OUTPUT_DIR)/Options/%.xml $(XML_OUTPUT_DIR)/option-tree.xml $(DOC_OPTION_XSL) $(DOC_PSEUDO_CODE_XSL) $(DOC_PARAMETERS_XSL) $(DOC_MENU_XSL)
|
||||
@echo generating $@
|
||||
@$(XSLT) --path $(XML_OUTPUT_DIR) --stringparam option-tree-xml option-tree.xml -o $@.temp $(DOC_OPTION_XSL) $<
|
||||
@$(XSLT) -o $@ $(DOTML_DIR)/embed-svg-graphics.xsl $@.temp
|
||||
@DOTML_DIR=$(DOTML_DIR) DOT=$(DOT) DOTML_XSLT="$(XSLT) (XSL) (INPUT)" $(DOTML_DIR)/generate-svg-graphics.bash $@.temp $(DOC_OUTPUT_DIR)
|
||||
@rm $@.temp
|
||||
|
||||
# Generic rule for basic behavior documentation
|
||||
$(DOC_OUTPUT_DIR)/basic-behaviors.%.html: $(XML_OUTPUT_DIR)/BasicBehaviors/%.xml $(DOC_MENU_XSL) $(DOC_BASIC_BEHAVIORS_XSL) $(DOC_PARAMETERS_XSL)
|
||||
@echo generating $@
|
||||
@$(XSLT) -o $@ $(DOC_BASIC_BEHAVIORS_XSL) $<
|
||||
|
||||
# Generates the index page
|
||||
$(DOC_INDEX_HTML): $(DOC_MENU_XSL) $(DOC_INDEX_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@echo generating $@
|
||||
@$(XSLT) -o $(DOC_INDEX_HTML) $(DOC_INDEX_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
|
||||
# Generates the option index page
|
||||
$(DOC_OPTION_INDEX_HTML): $(XML_OUTPUT_DIR)/option-tree.xml $(XML_OUTPUT_DIR)/options.xml $(DOC_OPTION_INDEX_XSL) $(DOC_MENU_XSL)
|
||||
@echo generating $@
|
||||
@$(XSLT) --path $(XML_OUTPUT_DIR) --stringparam option-tree-xml option-tree.xml -o $@.temp $(DOC_OPTION_INDEX_XSL) $(XML_OUTPUT_DIR)/options.xml
|
||||
@$(XSLT) -o $@ $(DOTML_DIR)/embed-svg-graphics.xsl $@.temp
|
||||
@DOTML_DIR=$(DOTML_DIR) DOT=$(DOT) DOTML_XSLT="$(XSLT) (XSL) (INPUT)" $(DOTML_DIR)/generate-svg-graphics.bash $@.temp $(DOC_OUTPUT_DIR)
|
||||
@rm $@.temp
|
||||
|
||||
# Generates the agent index page
|
||||
$(DOC_AGENTS_HTML): $(DOC_AGENTS_XSL) $(DOC_MENU_XSL) $(XML_OUTPUT_DIR)/option-tree.xml $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@echo generating $@
|
||||
@$(XSLT) --path $(XML_OUTPUT_DIR) --stringparam option-tree-xml option-tree.xml -o $@.temp $(DOC_AGENTS_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@$(XSLT) -o $@ $(DOTML_DIR)/embed-svg-graphics.xsl $@.temp
|
||||
@DOTML_DIR=$(DOTML_DIR) DOT=$(DOT) DOTML_XSLT="$(XSLT) (XSL) (INPUT)" $(DOTML_DIR)/generate-svg-graphics.bash $@.temp $(DOC_OUTPUT_DIR)
|
||||
@rm $@.temp
|
||||
|
||||
# Generates the basic behavior index page
|
||||
$(DOC_BASIC_BEHAVIOR_INDEX_HTML): $(DOC_BASIC_BEHAVIOR_INDEX_XSL) $(DOC_MENU_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@echo generating $@
|
||||
@$(XSLT) -o $(DOC_BASIC_BEHAVIOR_INDEX_HTML) $(DOC_BASIC_BEHAVIOR_INDEX_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
|
||||
# Generates the symbols index page
|
||||
$(DOC_SYMBOLS_INDEX_HTML): $(DOC_SYMBOLS_INDEX_XSL) $(DOC_MENU_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@echo generating $@
|
||||
@$(XSLT) -o $(DOC_SYMBOLS_INDEX_HTML) $(DOC_SYMBOLS_INDEX_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
|
||||
# Generates the debug symbols
|
||||
$(XABSL_OUTPUT_DIR)/$(DEBUG_SYMBOLS): $(DEBUG_SYMBOLS_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
@echo generating $@
|
||||
@$(XSLT) -o $(XABSL_OUTPUT_DIR)/$(DEBUG_SYMBOLS) $(DEBUG_SYMBOLS_XSL) $(XML_OUTPUT_DIR)/agents.xinclude-processed.xml
|
||||
|
||||
# Copies documentation.css to the documentation output directory
|
||||
$(DOC_STYLES_CSS): $(XABSL_XSL_DIR)/documentation.css
|
||||
@cp $(XABSL_XSL_DIR)/documentation.css $(DOC_OUTPUT_DIR)/styles.css
|
||||
|
||||
# Generates the output directory for intermediate code
|
||||
$(XABSL_OUTPUT_DIR):
|
||||
@mkdir -p $(XABSL_OUTPUT_DIR)
|
||||
|
||||
# Generates the output directory for xml code
|
||||
$(XML_OUTPUT_DIR):
|
||||
@mkdir -p $(XML_OUTPUT_DIR)
|
||||
|
||||
# Generates the output directory for documentation
|
||||
$(DOC_OUTPUT_DIR):
|
||||
@mkdir -p $(DOC_OUTPUT_DIR)
|
||||
|
||||
# The path where the SVG graphics generated for the documentation of options and agents are stored.
|
||||
$(DOC_OUTPUT_DIR)/svg:
|
||||
@mkdir -p $(DOC_OUTPUT_DIR)/svg
|
||||
@ -0,0 +1,28 @@
|
||||
SOURCES=constants.rb \
|
||||
errors.rb \
|
||||
language_elements.rb \
|
||||
symbol_table.rb \
|
||||
symbols.rb \
|
||||
syntax_tree_builder.rb \
|
||||
tokenizer.rb \
|
||||
translator.rb \
|
||||
translator_base.rb \
|
||||
xml_parser.rb \
|
||||
xabsl.rb \
|
||||
vcproj.rb
|
||||
|
||||
.PHONY: parser clean
|
||||
|
||||
all: parser timestamp
|
||||
|
||||
timestamp: $(SOURCES) Makefile
|
||||
@touch timestamp
|
||||
|
||||
parser: xabsl_parser.tab.rb
|
||||
|
||||
xabsl_parser.tab.rb: xabsl_parser.y.rb
|
||||
@ruby racc/racc -v xabsl_parser.y.rb
|
||||
|
||||
clean:
|
||||
@rm -f xabsl_parser.output xabsl_parser.tab.rb
|
||||
@rm -f timestamp
|
||||
@ -0,0 +1,152 @@
|
||||
module Translator
|
||||
|
||||
VERBOSE = false
|
||||
PARANOIA = true
|
||||
ENDL = "\r\n"
|
||||
|
||||
#tag for parsing an option file
|
||||
TAG_OPTION = 'option'
|
||||
TAG_STATE = 'state'
|
||||
TAG_SBB = 'subsequent-basic-behavior'
|
||||
TAG_SP = 'set-parameter'
|
||||
TAG_SEOS = 'set-enumerated-output-symbol'
|
||||
TAG_SDOS = 'set-decimal-output-symbol'
|
||||
TAG_SBOS = 'set-boolean-output-symbol'
|
||||
TAG_SO = 'subsequent-option'
|
||||
TAG_DT = 'decision-tree'
|
||||
TAG_OPR = 'option-parameter-ref'
|
||||
TAG_DV = 'decimal-value'
|
||||
TAG_BV = 'boolean-value'
|
||||
TAG_IF = 'if'
|
||||
TAG_ELSE = 'else'
|
||||
TAG_COND = 'condition'
|
||||
TAG_TTS = 'transition-to-state'
|
||||
TAG_GT = 'greater-than'
|
||||
TAG_LT = 'less-than'
|
||||
TAG_GTEQ = 'greater-than-or-equal-to'
|
||||
TAG_LTEQ = 'less-than-or-equal-to'
|
||||
TAG_EQ = 'equal-to'
|
||||
TAG_NEQ = 'not-equal-to'
|
||||
TAG_PLUS = 'plus'
|
||||
TAG_MINUS = 'minus'
|
||||
TAG_DISR = 'decimal-input-symbol-ref'
|
||||
TAG_BISR = 'boolean-input-symbol-ref'
|
||||
TAG_EISR = 'enumerated-input-symbol-ref'
|
||||
TAG_DOSR = 'decimal-output-symbol-ref'
|
||||
TAG_BOSR = 'boolean-output-symbol-ref'
|
||||
TAG_EOSR = 'enumerated-output-symbol-ref'
|
||||
TAG_AND = 'and'
|
||||
TAG_OR = 'or'
|
||||
TAG_WP = 'with-parameter'
|
||||
TAG_EISC = 'enumerated-input-symbol-comparison'
|
||||
TAG_CDT = 'common-decision-tree'
|
||||
TAG_COMMON_ACTION = 'common-action'
|
||||
TAG_CR = 'constant-ref'
|
||||
TAG_TOSX = 'time-of-state-execution'
|
||||
TAG_TOOX = 'time-of-option-execution'
|
||||
TAG_NOT = 'not'
|
||||
TAG_SORTS = 'subsequent-option-reached-target-state'
|
||||
TAG_CONFLICT = 'conflict'
|
||||
TAG_MPL = 'multiply'
|
||||
TAG_DIV = 'divide'
|
||||
TAG_MOD = 'mod'
|
||||
TAG_CE = 'conditional-expression'
|
||||
TAG_EX1 = 'expression1'
|
||||
TAG_EX2 = 'expression2'
|
||||
TAG_EV = 'enum-element-ref'
|
||||
|
||||
#tags for parsing an option-defintions file
|
||||
TAG_ODS = 'option-definitions'
|
||||
TAG_OD = 'option-definition'
|
||||
TAG_DPARA = 'decimal-parameter'
|
||||
TAG_BPARA = 'boolean-parameter'
|
||||
TAG_EPARA = 'enumerated-parameter'
|
||||
|
||||
#tags for symbol files
|
||||
TAG_BASIC_BEHAVIORS = 'basic-behaviors'
|
||||
TAG_SYMBOLS = 'symbols'
|
||||
TAG_DIS = 'decimal-input-symbol'
|
||||
TAG_DOS = 'decimal-output-symbol'
|
||||
TAG_E = 'enumeration'
|
||||
TAG_ENUM = 'enum-element'
|
||||
TAG_EIS = 'enumerated-input-symbol'
|
||||
TAG_EOS = 'enumerated-output-symbol'
|
||||
TAG_BIS = 'boolean-input-symbol'
|
||||
TAG_BOS = 'boolean-output-symbol'
|
||||
TAG_CONST = 'constant'
|
||||
TAG_BBS = 'basic-behaviors'
|
||||
TAG_BB = 'basic-behavior'
|
||||
|
||||
#Tags for agent files
|
||||
TAG_AGENT_COLLECTION = 'agent-collection'
|
||||
TAG_AGENT = 'agent'
|
||||
TAG_TITLE = 'title'
|
||||
TAG_SOFTWARE_ENVIRONMENT = 'software-environment'
|
||||
TAG_PLATFORM = 'platform'
|
||||
TAG_OPTIONS = 'options'
|
||||
TAG_XINCLUDE = 'xi:include'
|
||||
|
||||
#tokens for parsing a xtc file
|
||||
TOKEN_TRUE = 'true'
|
||||
TOKEN_FALSE = 'false'
|
||||
TOKEN_OPTION = 'option'
|
||||
TOKEN_INITIAL = 'initial'
|
||||
TOKEN_TARGET = 'target'
|
||||
TOKEN_STATE = 'state'
|
||||
TOKEN_COMMON = 'common'
|
||||
TOKEN_DECISION = 'decision'
|
||||
TOKEN_ACTION = 'action'
|
||||
TOKEN_STAY = 'stay'
|
||||
TOKEN_TTS = 'goto'
|
||||
TOKEN_IF = 'if'
|
||||
TOKEN_ELSE = 'else'
|
||||
TOKEN_TOSX = 'state_time'
|
||||
TOKEN_TOOX = 'option_time'
|
||||
TOKEN_SORTS = 'action_done'
|
||||
TOKEN_AGENT = 'agent'
|
||||
TOKEN_FUNCTION = 'function'
|
||||
TOKEN_ENUM = 'enum'
|
||||
TOKEN_INPUT = 'input'
|
||||
TOKEN_OUTPUT = 'output'
|
||||
TOKEN_BOOL = 'bool'
|
||||
TOKEN_FLOAT = 'float'
|
||||
TOKEN_CONST = 'const'
|
||||
TOKEN_NAMESPACE = 'namespace'
|
||||
TOKEN_BEHAVIOR = 'behavior'
|
||||
TOKEN_INCLUDE = 'include'
|
||||
TOKEN_INTERNAL = 'internal'
|
||||
TOKEN_CAPACITY = 'capacity'
|
||||
TOKEN_SYNCHRONIZED = 'synchronized'
|
||||
TOKEN_CONFLICT = 'conflict'
|
||||
|
||||
#Attributes
|
||||
ATTR_NAME = 'name'
|
||||
ATTR_MEASURE = 'measure'
|
||||
ATTR_RANGE = 'range'
|
||||
ATTR_DESCRIPTION = 'description'
|
||||
ATTR_REF = 'ref'
|
||||
ATTR_VALUE = 'value'
|
||||
ATTR_IS_TARGET_STATE = 'is-target-state'
|
||||
ATTR_INITIAL_STATE = 'initial-state'
|
||||
ATTR_TITLE = 'title'
|
||||
ATTR_ID = 'id'
|
||||
ATTR_ROOT_OPTION = 'root-option'
|
||||
ATTR_ENUM = 'enumeration'
|
||||
ATTR_INTERNAL = 'internal'
|
||||
ATTR_CAPACITY = 'capacity'
|
||||
ATTR_SYNCHRONIZED = 'synchronized'
|
||||
|
||||
ATTR_XMLNS = 'xmlns'
|
||||
ATTR_XMLNS_XSI = 'xmlns:xsi'
|
||||
ATTR_XSI_SCHEMALOCATION = 'xsi:schemaLocation'
|
||||
ATTR_XMLNS_XI = 'xmlns:xi'
|
||||
ATTR_HREF = 'href'
|
||||
|
||||
#filenames
|
||||
OPTION_DEFINITIONS_FILE = 'options.xml'
|
||||
OPTION_DEFINITIONS_ENTITY = 'options'
|
||||
DTD_INCLUDE_FILE = 'symbol-and-basic-behavior-files.dtd'
|
||||
DTD_INCLUDE_ENTITY = 'symbol-and-basic-behavior-files'
|
||||
AGENT_COLLECTION_FILE = 'agents.xml'
|
||||
TIMESTAMP_FILE = File.join(File.expand_path(File.dirname(__FILE__)), 'timestamp')
|
||||
end
|
||||
@ -0,0 +1,396 @@
|
||||
module Translator
|
||||
|
||||
|
||||
class ErrorHandler < CompilerContextWorker
|
||||
|
||||
attr_reader :messages
|
||||
|
||||
def initialize(compiler_context)
|
||||
super
|
||||
@messages = []
|
||||
end
|
||||
|
||||
def error(message)
|
||||
#suppress output of following messages
|
||||
unless [ParameterMissing, NamingWarning].include?(message.class)
|
||||
messages << message
|
||||
#$stderr.puts visual_studio_format(message)
|
||||
end
|
||||
end
|
||||
|
||||
def visual_studio_format(message)
|
||||
type_string = ''
|
||||
if (message.class <= CompilerWarning)
|
||||
type_string = "warning"
|
||||
elsif(message.class <= CompilerError || message.class <= RuntimeError)
|
||||
type_string = "error"
|
||||
else
|
||||
type_string = "warning"
|
||||
end
|
||||
|
||||
filename = File.expand_path(cc.cu.src_fullname)
|
||||
filename.sub!(/\A\/cygdrive\/([a-zA-Z])/) do |match|
|
||||
"#{$1.upcase}:"
|
||||
end
|
||||
filename.gsub!(/\//, '\\')
|
||||
|
||||
if message.respond_to?(:line_nr) && !message.line_nr.nil?
|
||||
line = "(#{message.line_nr})"
|
||||
else
|
||||
line = '(0)'
|
||||
end
|
||||
|
||||
result = "#{filename}#{line} : #{type_string} X#{message.errno}: #{message.message}" << ENDL
|
||||
if message.respond_to?(:token) && !message.token.nil?
|
||||
cc.tz.get_code_context(message.token, 100).each do |string|
|
||||
result += string << ENDL
|
||||
end
|
||||
end
|
||||
|
||||
#if message.respond_to?(:backtrace)
|
||||
# $stderr.puts message.backtrace
|
||||
#end
|
||||
|
||||
return result
|
||||
|
||||
end
|
||||
|
||||
def format(message)
|
||||
|
||||
type_string = ''
|
||||
if (message.class <= CompilerWarning)
|
||||
type_string = "WARNING "
|
||||
elsif(message.class <= CompilerError || message.class <= RuntimeError)
|
||||
type_string = "ERROR "
|
||||
else
|
||||
type_string = "MESSAGE "
|
||||
end
|
||||
|
||||
result = "#{type_string} X#{message.errno} "
|
||||
result += "#{File.basename(cc.cu.src_filename)}"
|
||||
result += ":#{message.line_nr}" if message.respond_to?(:line_nr) && !message.line_nr.nil?
|
||||
result += ENDL
|
||||
|
||||
result += " #{message.class.name}" << ENDL if LOG.info?
|
||||
result += " #{message.message}" << ENDL unless message.message.nil? || message.message.empty?
|
||||
|
||||
if !message.token.nil?
|
||||
cols = ENV['COLUMNS'].to_i
|
||||
cols = 80 if cols <= 80
|
||||
cc.tz.get_code_context(message.token, cols - 3).each do |string|
|
||||
result += " #{string}" << ENDL
|
||||
end
|
||||
elsif !message.sample.nil?
|
||||
result += " #{message.sample}" << ENDL
|
||||
elsif !message.line_nr.nil?
|
||||
result += " #{cc.tz.get_code_line(message.line_nr)}" << ENDL
|
||||
end
|
||||
result += ENDL
|
||||
|
||||
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CompilerMessage < RuntimeError
|
||||
|
||||
attr_accessor :line_nr
|
||||
attr_accessor :sample
|
||||
attr_accessor :message
|
||||
attr_reader :token
|
||||
attr_reader :error
|
||||
attr_reader :errno
|
||||
|
||||
def initialize(compiler_context)
|
||||
@cc = compiler_context
|
||||
end
|
||||
|
||||
def token=(token)
|
||||
if token.nil?
|
||||
$stderr.puts "token information not available"
|
||||
else
|
||||
@token = token
|
||||
@line_nr = @token.line_nr
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#fatal errors stop the compiling process almost at once
|
||||
class CompilerFatal < CompilerMessage
|
||||
end
|
||||
|
||||
class InternalError < CompilerMessage
|
||||
def initialize(message = 'internal error')
|
||||
super
|
||||
@errno = 2357
|
||||
end
|
||||
end
|
||||
|
||||
class CompilerWarning < CompilerMessage
|
||||
end
|
||||
|
||||
class CompilerError < CompilerMessage
|
||||
end
|
||||
|
||||
class DoubleIncludeError < CompilerError
|
||||
def initialize(compiler_context, filename)
|
||||
super(compiler_context)
|
||||
self.message = "File '#{filename}' is included more than once"
|
||||
@errno = 9001
|
||||
end
|
||||
end
|
||||
|
||||
class FileOpenError < CompilerError
|
||||
def initialize(compiler_context, filename)
|
||||
super(compiler_context)
|
||||
self.message = "unable to open file '#{filename}'"
|
||||
@errno = 2375
|
||||
end
|
||||
end
|
||||
|
||||
class FileTypeError < CompilerError
|
||||
def initialize(compiler_context, filename)
|
||||
super(compiler_context)
|
||||
self.message = "File '#{filename}' doesn't have extension .xabsl"
|
||||
@errno = 7253
|
||||
end
|
||||
end
|
||||
|
||||
class SyntaxError < CompilerFatal
|
||||
def initialize(compiler_context)
|
||||
super(compiler_context)
|
||||
self.message = "syntax error."
|
||||
@errno = 2537
|
||||
end
|
||||
end
|
||||
|
||||
class SemanticWarning < CompilerWarning
|
||||
end
|
||||
|
||||
class SemanticError < CompilerError
|
||||
end
|
||||
|
||||
class UnexpectedEndOfFile < SyntaxError
|
||||
def initialize(compiler_context)
|
||||
super(compiler_context)
|
||||
self.message = "unexpected end of file."
|
||||
@errno = 2555
|
||||
end
|
||||
end
|
||||
|
||||
class TokenizerError < SyntaxError
|
||||
def initialize(compiler_context, line_nr, sample)
|
||||
super(compiler_context)
|
||||
self.line_nr = line_nr
|
||||
self.sample = sample
|
||||
self.message = "illegal characters encountered."
|
||||
@errno = 2573
|
||||
end
|
||||
end
|
||||
|
||||
class UnevenStringDelimiterError < SyntaxError
|
||||
def initialize(compiler_context, delimiter)
|
||||
super(compiler_context)
|
||||
self.line_nr = line_nr
|
||||
self.sample = sample
|
||||
self.message = "uneven count of string delimiters '#{delimiter}' encountered."
|
||||
@errno = 2735
|
||||
end
|
||||
end
|
||||
|
||||
class ParenthesisError < SyntaxError
|
||||
def initialize(compiler_context, left_string, left_count, right_string, right_count)
|
||||
super(compiler_context)
|
||||
self.message = "counted #{left_count} left parenthesis '#{left_string}' and #{right_count} right parenthesis."
|
||||
@errno = 2753
|
||||
end
|
||||
end
|
||||
|
||||
class ClosingCommentError < SyntaxError
|
||||
def initialize(compiler_context, line_nr)
|
||||
super(compiler_context)
|
||||
self.line_nr = line_nr
|
||||
self.message = "misplaced end-of-comment detected"
|
||||
@errno = 3257
|
||||
end
|
||||
end
|
||||
|
||||
class ClosingCommentMissingError < SyntaxError
|
||||
def initialize(compiler_context, line_nr)
|
||||
super(compiler_context)
|
||||
self.line_nr = line_nr
|
||||
self.message = "end-of-comment missing."
|
||||
@errno = 3275
|
||||
end
|
||||
end
|
||||
|
||||
class NamespaceSeparation < SemanticError
|
||||
def initialize(compiler_context, token, symbol)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "namespace '#{compiler_context.sc.to_code(symbol)}' can contain either symbols or behaviors. offending declaration is '#{token}'."
|
||||
@errno = 3527
|
||||
end
|
||||
end
|
||||
|
||||
class EmptyNamespaceWarning < SemanticWarning
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "namespace '#{token.to_s}' is empty."
|
||||
@errno = 3572
|
||||
end
|
||||
end
|
||||
|
||||
class ParameterMultipleSetting < SemanticError
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "parameter '#{token.to_s}' is set more than once."
|
||||
@errno = 3725
|
||||
end
|
||||
end
|
||||
|
||||
class ParameterMissing < SemanticWarning
|
||||
def initialize(compiler_context, call_token, missing_symbol)
|
||||
super(compiler_context)
|
||||
self.token = call_token
|
||||
self.message = "parameter '#{compiler_context.sc.to_code(missing_symbol)}' is missing in call to '#{call_token.to_s}'."
|
||||
@errno = 3752
|
||||
end
|
||||
end
|
||||
|
||||
class DomainSymbolExpected < SemanticError
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "domain symbol expected instead of '#{token.to_s}'."
|
||||
@errno = 5237
|
||||
end
|
||||
end
|
||||
|
||||
class MismatchingDomain < SemanticError
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "'#{token.to_s}' has mismatching domain."
|
||||
@errno = 5255
|
||||
end
|
||||
end
|
||||
|
||||
class InitialStateMissing < SemanticError
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "initial state is missing on option '#{token.to_s}'."
|
||||
@errno = 5273
|
||||
end
|
||||
end
|
||||
|
||||
class InitialStateMultipleDefinition < SemanticError
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "multiple initial state definitions, '#{token.to_s}'."
|
||||
@errno = 5327
|
||||
end
|
||||
end
|
||||
|
||||
class MultipleDefinitions < SemanticError
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "'#{token.to_s}' is defined more than once."
|
||||
@errno = 5372
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class TypeMismatch < SemanticError
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "type mismatch on '#{token.to_s}'."
|
||||
@errno = 5525
|
||||
end
|
||||
end
|
||||
|
||||
class EnumTypeMismatch < SemanticError
|
||||
def initialize(compiler_context, token, enum1, enum2)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "enumeration mismatch on '#{token.to_s}' expected '#{enum1.identifier}' found '#{enum2.identifier}'."
|
||||
@errno = 5526
|
||||
end
|
||||
end
|
||||
|
||||
class NoMatchingSymbolFound < SemanticError
|
||||
def initialize(compiler_context, token, domain_symbol, symbol_classes)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "no matching symbol found for '#{token.to_s}' "
|
||||
self.message += "with domain '#{compiler_context.sc.to_code(domain_symbol)}' " unless domain_symbol.nil?
|
||||
self.message += "and symbol class in #{symbol_classes.inspect}."
|
||||
@errno = 5552
|
||||
end
|
||||
end
|
||||
|
||||
class MultipleMatchingSymbolsFound < SemanticError
|
||||
def initialize(compiler_context, token, domain_symbol, symbol_classes, symbols)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "multiple matching symbol found for '#{token.to_s}' "
|
||||
self.message += "with domain '#{compiler_context.sc.to_code(domain_symbol)}' " unless domain_symbol.nil?
|
||||
self.message += "and symbol class in #{symbol_classes.inspect}: "
|
||||
symbols.each do |symbol|
|
||||
self.message += "#{symbol.class.name}"
|
||||
self.message += " with domain '#{compiler_context.sc.to_code(symbol.domain_symbol)}'" if symbol.class <= DomainValueSymbol && !symbol.domain_symbol.nil?
|
||||
self.message += ", "
|
||||
end
|
||||
@errno = 5723
|
||||
end
|
||||
end
|
||||
|
||||
class UnexpectedLE < SemanticError
|
||||
def initialize(compiler_context, token, le, parent)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "unexpected language element '#{le.tag}' for '#{parent.tag}'"
|
||||
@errno = 5732
|
||||
end
|
||||
end
|
||||
|
||||
class NamingWarning < SemanticWarning
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "file should be named like option or namespace"
|
||||
@errno = 7235
|
||||
end
|
||||
end
|
||||
|
||||
class DecisionTreeMustStartWithElse < SemanticWarning
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "decision tree has to start with else when the option has a common decision tree"
|
||||
@errno = 7325
|
||||
end
|
||||
end
|
||||
|
||||
class DecisionTreeMustNotStartWithElse < SemanticError
|
||||
def initialize(compiler_context, token)
|
||||
super(compiler_context)
|
||||
self.token = token
|
||||
self.message = "decision tree must not start with else when the option has no common decision tree"
|
||||
@errno = 7352
|
||||
end
|
||||
end
|
||||
|
||||
#unused errnos
|
||||
#7523
|
||||
#7532
|
||||
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
||||
#
|
||||
# compat.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
unless [].respond_to?(:map!)
|
||||
class Array
|
||||
if [].respond_to?(:collect!)
|
||||
alias map! collect!
|
||||
else
|
||||
alias map! filter
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
unless [].respond_to?(:map)
|
||||
module Enumerable
|
||||
alias map collect
|
||||
end
|
||||
end
|
||||
|
||||
def bug!( msg )
|
||||
raise '[Racc BUG] ' + msg
|
||||
end
|
||||
@ -0,0 +1,112 @@
|
||||
#
|
||||
# compiler.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
require 'racc/compat'
|
||||
require 'racc/grammarfileparser'
|
||||
require 'racc/grammar'
|
||||
require 'racc/state'
|
||||
require 'racc/output'
|
||||
|
||||
|
||||
module Racc
|
||||
|
||||
class Compiler
|
||||
|
||||
attr_reader :filename
|
||||
|
||||
attr_reader :parser
|
||||
attr_reader :ruletable
|
||||
attr_reader :symboltable
|
||||
attr_reader :statetable
|
||||
attr_reader :formatter
|
||||
|
||||
attr_accessor :debug_parser
|
||||
attr_accessor :convert_line
|
||||
attr_accessor :omit_action
|
||||
attr_accessor :result_var
|
||||
|
||||
def verbose=( f )
|
||||
@verbose = f
|
||||
end
|
||||
|
||||
attr_accessor :debug
|
||||
attr_accessor :d_parse
|
||||
attr_accessor :d_rule
|
||||
attr_accessor :d_token
|
||||
attr_accessor :d_state
|
||||
attr_accessor :d_la
|
||||
attr_accessor :d_prec
|
||||
|
||||
def initialize
|
||||
@debug_parser = false
|
||||
@verbose = false
|
||||
@convert_line = true
|
||||
@omit_action = true
|
||||
@result_var = true
|
||||
|
||||
@debug = false
|
||||
@d_parse = false
|
||||
@d_rule = false
|
||||
@d_token = false
|
||||
@d_state = false
|
||||
@d_la = false
|
||||
@d_prec = false
|
||||
end
|
||||
|
||||
def parse( str, fname = '-' )
|
||||
$stderr.puts 'parsing grammar file...' if @verbose
|
||||
|
||||
# must be this order
|
||||
@symboltable = SymbolTable.new(self)
|
||||
@ruletable = RuleTable.new(self)
|
||||
@parser = GrammarFileParser.new(self)
|
||||
|
||||
@filename = fname
|
||||
@parser.parse(str)
|
||||
end
|
||||
|
||||
def compile
|
||||
nfa
|
||||
dfa
|
||||
end
|
||||
|
||||
def nfa
|
||||
$stderr.puts 'initializing state machine...' if @verbose
|
||||
@statetable = StateTable.new(self)
|
||||
@ruletable.init
|
||||
@statetable.init
|
||||
end
|
||||
|
||||
def dfa
|
||||
if @verbose
|
||||
$stderr.puts "resolving #{@statetable.size} states..."
|
||||
b = Process.times.utime
|
||||
end
|
||||
@statetable.determine
|
||||
if @verbose
|
||||
e = Process.times.utime
|
||||
$stderr.puts "all resolved in #{e - b} sec"
|
||||
end
|
||||
end
|
||||
|
||||
def source( f )
|
||||
$stderr.puts 'creating table file...' if @verbose
|
||||
CodeGenerator.new(self).output f
|
||||
end
|
||||
|
||||
def output( f )
|
||||
$stderr.puts 'creating .output file...' if @verbose
|
||||
VerboseOutputter.new(self).output f
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end # module Racc
|
||||
@ -0,0 +1,844 @@
|
||||
#
|
||||
# grammar.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
require 'racc/compat'
|
||||
require 'racc/iset'
|
||||
|
||||
|
||||
module Racc
|
||||
|
||||
class UserAction
|
||||
|
||||
def initialize( str, lineno )
|
||||
@val = (str.strip.empty? ? nil : str)
|
||||
@lineno = lineno
|
||||
end
|
||||
|
||||
attr_reader :val
|
||||
attr_reader :lineno
|
||||
|
||||
def name
|
||||
'{action}'
|
||||
end
|
||||
|
||||
alias inspect name
|
||||
|
||||
end
|
||||
|
||||
|
||||
class OrMark
|
||||
|
||||
def initialize( lineno )
|
||||
@lineno = lineno
|
||||
end
|
||||
|
||||
def name
|
||||
'|'
|
||||
end
|
||||
|
||||
alias inspect name
|
||||
|
||||
attr_reader :lineno
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Prec
|
||||
|
||||
def initialize( tok, lineno )
|
||||
@val = tok
|
||||
@lineno = lineno
|
||||
end
|
||||
|
||||
def name
|
||||
'='
|
||||
end
|
||||
|
||||
alias inspect name
|
||||
|
||||
attr_reader :val
|
||||
attr_reader :lineno
|
||||
|
||||
end
|
||||
|
||||
|
||||
#########################################################################
|
||||
########################### ################################
|
||||
########################### rule ################################
|
||||
########################### ################################
|
||||
#########################################################################
|
||||
|
||||
|
||||
#
|
||||
# RuleTable
|
||||
#
|
||||
# stands grammar. Each items of @rules are Rule object.
|
||||
#
|
||||
|
||||
class RuleTable
|
||||
|
||||
def initialize( racc )
|
||||
@racc = racc
|
||||
@symboltable = racc.symboltable
|
||||
|
||||
@d_token = racc.d_token
|
||||
@d_rule = racc.d_rule
|
||||
@d_state = racc.d_state
|
||||
|
||||
@rules = []
|
||||
@hashval = 4 # size of dummy rule
|
||||
@start = nil
|
||||
@sprec = nil
|
||||
@emb = 1
|
||||
@expect = nil
|
||||
|
||||
@end_rule = false
|
||||
end
|
||||
|
||||
###
|
||||
### register
|
||||
###
|
||||
|
||||
def register_rule_from_array( arr )
|
||||
sym = arr.shift
|
||||
case sym
|
||||
when OrMark, UserAction, Prec
|
||||
raise ParseError, "#{sym.lineno}: unexpected token #{sym.name}"
|
||||
end
|
||||
new = []
|
||||
arr.each do |i|
|
||||
case i
|
||||
when OrMark
|
||||
register_rule sym, new
|
||||
new = []
|
||||
when Prec
|
||||
raise ParseError, "'=<prec>' used twice in one rule" if @sprec
|
||||
@sprec = i.val
|
||||
else
|
||||
new.push i
|
||||
end
|
||||
end
|
||||
register_rule sym, new
|
||||
end
|
||||
|
||||
def register_rule( targ, list )
|
||||
if targ
|
||||
@prev_target = targ
|
||||
else
|
||||
targ = @prev_target
|
||||
end
|
||||
|
||||
if UserAction === list[-1]
|
||||
act = list.pop
|
||||
else
|
||||
act = UserAction.new('', 0)
|
||||
end
|
||||
list.map! {|t| (UserAction === t) ? embed_symbol(t) : t }
|
||||
|
||||
reg_rule targ, list, act
|
||||
@start ||= targ
|
||||
@sprec = nil
|
||||
end
|
||||
|
||||
def reg_rule( targ, list, act )
|
||||
@rules.push Rule.new(targ, list, act, @rules.size + 1, @hashval, @sprec)
|
||||
@hashval += (list.size + 1)
|
||||
end
|
||||
|
||||
def embed_symbol( act )
|
||||
sym = @symboltable.get("@#{@emb}".intern, true)
|
||||
@emb += 1
|
||||
reg_rule sym, [], act
|
||||
sym
|
||||
end
|
||||
|
||||
def end_register_rule
|
||||
@end_rule = true
|
||||
raise RaccError, 'no rule in input' if @rules.empty?
|
||||
end
|
||||
|
||||
def register_start( tok )
|
||||
raise ParseError, "'start' defined twice'" if @start
|
||||
@start = tok
|
||||
end
|
||||
|
||||
def register_option( option )
|
||||
case option.sub(/\Ano_/, '')
|
||||
when 'omit_action_call'
|
||||
@racc.omit_action = ((/\Ano_/ === option) ? false : true)
|
||||
when 'result_var'
|
||||
@racc.result_var = ((/\Ano_/ === option) ? false : true)
|
||||
else
|
||||
raise ParseError, "unknown option '#{option}'"
|
||||
end
|
||||
end
|
||||
|
||||
def expect( n = nil )
|
||||
return @expect unless n
|
||||
raise ParseError, "'expect' exist twice" if @expect
|
||||
@expect = n
|
||||
end
|
||||
|
||||
###
|
||||
### accessor
|
||||
###
|
||||
|
||||
attr_reader :start
|
||||
|
||||
def []( x )
|
||||
@rules[x]
|
||||
end
|
||||
|
||||
def each_rule( &block )
|
||||
@rules.each(&block)
|
||||
end
|
||||
|
||||
alias each each_rule
|
||||
|
||||
def each_index( &block )
|
||||
@rules.each_index(&block)
|
||||
end
|
||||
|
||||
def each_with_index( &block )
|
||||
@rules.each_with_index(&block)
|
||||
end
|
||||
|
||||
def size
|
||||
@rules.size
|
||||
end
|
||||
|
||||
def to_s
|
||||
"<Racc::RuleTable>"
|
||||
end
|
||||
|
||||
###
|
||||
### process
|
||||
###
|
||||
|
||||
def init
|
||||
#
|
||||
# add dummy rule
|
||||
#
|
||||
tmp = Rule.new(@symboltable.dummy,
|
||||
[ @start, @symboltable.anchor, @symboltable.anchor ],
|
||||
UserAction.new('', 0),
|
||||
0, 0, nil)
|
||||
# id hash prec
|
||||
@rules.unshift tmp
|
||||
@rules.freeze
|
||||
|
||||
rule = ptr = tmp = tok = t = nil
|
||||
|
||||
#
|
||||
# t.heads
|
||||
#
|
||||
@rules.each do |rule|
|
||||
rule.target.heads.push rule.ptrs[0]
|
||||
end
|
||||
|
||||
#
|
||||
# t.terminal?, self_null?
|
||||
#
|
||||
@symboltable.each do |t|
|
||||
t.term = t.heads.empty?
|
||||
if t.terminal?
|
||||
t.snull = false
|
||||
next
|
||||
end
|
||||
|
||||
tmp = false
|
||||
t.heads.each do |ptr|
|
||||
if ptr.reduce?
|
||||
tmp = true
|
||||
break
|
||||
end
|
||||
end
|
||||
t.snull = tmp
|
||||
end
|
||||
|
||||
@symboltable.fix
|
||||
|
||||
#
|
||||
# t.locate
|
||||
#
|
||||
@rules.each do |rule|
|
||||
tmp = nil
|
||||
rule.ptrs.each do |ptr|
|
||||
unless ptr.reduce?
|
||||
tok = ptr.dereference
|
||||
tok.locate.push ptr
|
||||
tmp = tok if tok.terminal?
|
||||
end
|
||||
end
|
||||
rule.set_prec tmp
|
||||
end
|
||||
|
||||
#
|
||||
# t.expand
|
||||
#
|
||||
@symboltable.each_nonterm {|t| compute_expand t }
|
||||
|
||||
#
|
||||
# t.nullable?, rule.nullable?
|
||||
#
|
||||
compute_nullable
|
||||
|
||||
#
|
||||
# t.useless?, rule.useless?
|
||||
#
|
||||
compute_useless
|
||||
end
|
||||
|
||||
def compute_expand( t )
|
||||
puts "expand> #{t.to_s}" if @d_token
|
||||
t.expand = _compute_expand(t, ISet.new, [])
|
||||
puts "expand< #{t.to_s}: #{t.expand.to_s}" if @d_token
|
||||
end
|
||||
|
||||
def _compute_expand( t, ret, lock )
|
||||
if tmp = t.expand
|
||||
ret.update tmp
|
||||
return ret
|
||||
end
|
||||
|
||||
tok = h = nil
|
||||
|
||||
ret.update_a t.heads
|
||||
t.heads.each do |ptr|
|
||||
tok = ptr.dereference
|
||||
if tok and tok.nonterminal?
|
||||
unless lock[tok.ident]
|
||||
lock[tok.ident] = true
|
||||
_compute_expand tok, ret, lock
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
def compute_nullable
|
||||
@rules.each {|r| r.null = false }
|
||||
@symboltable.each {|t| t.null = false }
|
||||
|
||||
r = @rules.dup
|
||||
s = @symboltable.nonterminals
|
||||
|
||||
begin
|
||||
rs = r.size
|
||||
ss = s.size
|
||||
check_r_nullable r
|
||||
check_s_nullable s
|
||||
end until rs == r.size and ss == s.size
|
||||
end
|
||||
|
||||
def check_r_nullable( r )
|
||||
r.delete_if do |rl|
|
||||
rl.null = true
|
||||
rl.symbols.each do |t|
|
||||
unless t.nullable?
|
||||
rl.null = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
rl.nullable?
|
||||
end
|
||||
end
|
||||
|
||||
def check_s_nullable( s )
|
||||
s.delete_if do |t|
|
||||
t.heads.each do |ptr|
|
||||
if ptr.rule.nullable?
|
||||
t.null = true
|
||||
break
|
||||
end
|
||||
end
|
||||
t.nullable?
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
### WHAT IS "USELESS"?
|
||||
###
|
||||
def compute_useless
|
||||
t = del = save = nil
|
||||
|
||||
@symboltable.each_terminal {|t| t.useless = false }
|
||||
@symboltable.each_nonterm {|t| t.useless = true }
|
||||
@rules.each {|r| r.useless = true }
|
||||
|
||||
r = @rules.dup
|
||||
s = @symboltable.nonterminals
|
||||
begin
|
||||
rs = r.size
|
||||
ss = s.size
|
||||
check_r_useless r
|
||||
check_s_useless s
|
||||
end until r.size == rs and s.size == ss
|
||||
end
|
||||
|
||||
def check_r_useless( r )
|
||||
t = rule = nil
|
||||
r.delete_if do |rule|
|
||||
rule.useless = false
|
||||
rule.symbols.each do |t|
|
||||
if t.useless?
|
||||
rule.useless = true
|
||||
break
|
||||
end
|
||||
end
|
||||
not rule.useless?
|
||||
end
|
||||
end
|
||||
|
||||
def check_s_useless( s )
|
||||
t = ptr = nil
|
||||
s.delete_if do |t|
|
||||
t.heads.each do |ptr|
|
||||
unless ptr.rule.useless?
|
||||
t.useless = false
|
||||
break
|
||||
end
|
||||
end
|
||||
not t.useless?
|
||||
end
|
||||
end
|
||||
|
||||
end # class RuleTable
|
||||
|
||||
|
||||
#
|
||||
# Rule
|
||||
#
|
||||
# stands one rule of grammar.
|
||||
#
|
||||
|
||||
class Rule
|
||||
|
||||
def initialize( targ, syms, act, rid, hval, prec )
|
||||
@target = targ
|
||||
@symbols = syms
|
||||
@action = act.val
|
||||
@lineno = act.lineno
|
||||
@ident = rid
|
||||
@hash = hval
|
||||
@prec = @specified_prec = prec
|
||||
|
||||
@null = nil
|
||||
@useless = nil
|
||||
|
||||
@ptrs = tmp = []
|
||||
syms.each_with_index do |t,i|
|
||||
tmp.push LocationPointer.new(self, i, t)
|
||||
end
|
||||
tmp.push LocationPointer.new(self, syms.size, nil)
|
||||
end
|
||||
|
||||
attr_reader :target
|
||||
attr_reader :symbols
|
||||
|
||||
attr_reader :action
|
||||
attr_reader :lineno
|
||||
|
||||
attr_reader :ident
|
||||
attr_reader :hash
|
||||
attr_reader :ptrs
|
||||
|
||||
attr_reader :prec
|
||||
attr_reader :specified_prec
|
||||
|
||||
def set_prec( t )
|
||||
@prec ||= t
|
||||
end
|
||||
|
||||
def nullable?() @null end
|
||||
def null=(n) @null = n end
|
||||
|
||||
def useless?() @useless end
|
||||
def useless=(u) @useless = u end
|
||||
|
||||
def inspect
|
||||
"#<rule #{@ident} (#{@target})>"
|
||||
end
|
||||
|
||||
def ==( other )
|
||||
Rule === other and @ident == other.ident
|
||||
end
|
||||
|
||||
def []( idx )
|
||||
@symbols[idx]
|
||||
end
|
||||
|
||||
def size
|
||||
@symbols.size
|
||||
end
|
||||
|
||||
def empty?
|
||||
@symbols.empty?
|
||||
end
|
||||
|
||||
def to_s
|
||||
'#<rule#{@ident}>'
|
||||
end
|
||||
|
||||
def accept?
|
||||
if tok = @symbols[-1]
|
||||
tok.anchor?
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def each( &block )
|
||||
@symbols.each(&block)
|
||||
end
|
||||
|
||||
end # class Rule
|
||||
|
||||
|
||||
#
|
||||
# LocationPointer
|
||||
#
|
||||
# set of rule and position in it's rhs.
|
||||
# note that number of pointer is more than rule's rhs array,
|
||||
# because pointer points right of last symbol when reducing.
|
||||
#
|
||||
|
||||
class LocationPointer
|
||||
|
||||
def initialize( rule, i, sym )
|
||||
@rule = rule
|
||||
@index = i
|
||||
@symbol = sym
|
||||
@ident = @rule.hash + i
|
||||
@reduce = sym.nil?
|
||||
end
|
||||
|
||||
attr_reader :rule
|
||||
attr_reader :index
|
||||
attr_reader :symbol
|
||||
|
||||
alias dereference symbol
|
||||
|
||||
attr_reader :ident
|
||||
alias hash ident
|
||||
attr_reader :reduce
|
||||
alias reduce? reduce
|
||||
|
||||
def to_s
|
||||
sprintf('(%d,%d %s)',
|
||||
@rule.ident, @index, (reduce?() ? '#' : @symbol.to_s))
|
||||
end
|
||||
|
||||
alias inspect to_s
|
||||
|
||||
def eql?( ot )
|
||||
@hash == ot.hash
|
||||
end
|
||||
|
||||
alias == eql?
|
||||
|
||||
def head?
|
||||
@index == 0
|
||||
end
|
||||
|
||||
def next
|
||||
@rule.ptrs[@index + 1] or ptr_bug!
|
||||
end
|
||||
|
||||
alias increment next
|
||||
|
||||
def before( len )
|
||||
@rule.ptrs[@index - len] or ptr_bug!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ptr_bug!
|
||||
bug! "pointer not exist: self: #{to_s}"
|
||||
end
|
||||
|
||||
end # class LocationPointer
|
||||
|
||||
|
||||
#########################################################################
|
||||
########################### ################################
|
||||
########################### symbol ################################
|
||||
########################### ################################
|
||||
#########################################################################
|
||||
|
||||
#
|
||||
# SymbolTable
|
||||
#
|
||||
# the table of symbols.
|
||||
# each items of @symbols are Sym
|
||||
#
|
||||
|
||||
class SymbolTable
|
||||
|
||||
include Enumerable
|
||||
|
||||
def initialize( racc )
|
||||
@chk = {}
|
||||
@symbols = []
|
||||
@token_list = nil
|
||||
@prec_table = []
|
||||
|
||||
@end_conv = false
|
||||
@end_prec = false
|
||||
|
||||
@dummy = get(:$start, true)
|
||||
@anchor = get(:$end, true) # ID 0
|
||||
@error = get(:error, false) # ID 1
|
||||
|
||||
@anchor.conv = 'false'
|
||||
@error.conv = 'Object.new'
|
||||
end
|
||||
|
||||
attr_reader :dummy
|
||||
attr_reader :anchor
|
||||
attr_reader :error
|
||||
|
||||
def get( val, dummy = false )
|
||||
unless ret = @chk[val]
|
||||
@chk[val] = ret = Sym.new(val, dummy)
|
||||
@symbols.push ret
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
|
||||
def register_token( toks )
|
||||
@token_list ||= []
|
||||
@token_list.concat toks
|
||||
end
|
||||
|
||||
|
||||
def register_prec( assoc, toks )
|
||||
if @end_prec
|
||||
raise ParseError, "'prec' block is defined twice"
|
||||
end
|
||||
toks.push assoc
|
||||
@prec_table.push toks
|
||||
end
|
||||
|
||||
def end_register_prec( rev )
|
||||
@end_prec = true
|
||||
|
||||
return if @prec_table.empty?
|
||||
|
||||
top = @prec_table.size - 1
|
||||
@prec_table.each_with_index do |toks, idx|
|
||||
ass = toks.pop
|
||||
toks.each do |tok|
|
||||
tok.assoc = ass
|
||||
if rev
|
||||
tok.prec = top - idx
|
||||
else
|
||||
tok.prec = idx
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def register_conv( tok, str )
|
||||
if @end_conv
|
||||
raise ParseError, "'convert' block is defined twice"
|
||||
end
|
||||
tok.conv = str
|
||||
end
|
||||
|
||||
def end_register_conv
|
||||
@end_conv = true
|
||||
end
|
||||
|
||||
|
||||
def fix
|
||||
#
|
||||
# initialize table
|
||||
#
|
||||
term = []
|
||||
nt = []
|
||||
t = i = nil
|
||||
@symbols.each do |t|
|
||||
(t.terminal? ? term : nt).push t
|
||||
end
|
||||
@symbols = term + nt
|
||||
@nt_base = term.size
|
||||
@terms = terminals
|
||||
@nterms = nonterminals
|
||||
|
||||
@symbols.each_with_index do |t, i|
|
||||
t.ident = i
|
||||
end
|
||||
|
||||
return unless @token_list
|
||||
|
||||
#
|
||||
# check if decleared symbols are really terminal
|
||||
#
|
||||
toks = @symbols[2, @nt_base - 2]
|
||||
@token_list.uniq!
|
||||
@token_list.each do |t|
|
||||
unless toks.delete t
|
||||
$stderr.puts "racc warning: terminal #{t} decleared but not used"
|
||||
end
|
||||
end
|
||||
toks.each do |t|
|
||||
unless String === t.value
|
||||
$stderr.puts "racc warning: terminal #{t} used but not decleared"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def []( id )
|
||||
@symbols[id]
|
||||
end
|
||||
|
||||
attr_reader :nt_base
|
||||
|
||||
def nt_max
|
||||
@symbols.size
|
||||
end
|
||||
|
||||
def each( &block )
|
||||
@symbols.each(&block)
|
||||
end
|
||||
|
||||
def terminals( &block )
|
||||
@symbols[0, @nt_base]
|
||||
end
|
||||
|
||||
def each_terminal( &block )
|
||||
@terms.each(&block)
|
||||
end
|
||||
|
||||
def nonterminals
|
||||
@symbols[@nt_base, @symbols.size - @nt_base]
|
||||
end
|
||||
|
||||
def each_nonterm( &block )
|
||||
@nterms.each(&block)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Sym
|
||||
#
|
||||
# stands symbol (terminal and nonterminal).
|
||||
# This class is not named Symbol because there is
|
||||
# a class 'Symbol' after ruby 1.5.
|
||||
#
|
||||
|
||||
class Sym
|
||||
|
||||
def initialize( val, dummy )
|
||||
@ident = nil
|
||||
@value = val
|
||||
@dummy = dummy
|
||||
|
||||
@term = nil
|
||||
@nterm = nil
|
||||
@conv = nil
|
||||
@prec = nil
|
||||
|
||||
@heads = []
|
||||
@locate = []
|
||||
@snull = nil
|
||||
@null = nil
|
||||
@expand = nil
|
||||
|
||||
@useless = nil
|
||||
|
||||
# for human
|
||||
@to_s = if @value.respond_to?(:id2name)
|
||||
then @value.id2name
|
||||
else @value.to_s.inspect
|
||||
end
|
||||
# for ruby source
|
||||
@uneval = if @value.respond_to?(:id2name)
|
||||
then ':' + @value.id2name
|
||||
else @value.to_s.inspect
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class << self
|
||||
def once_writer( nm )
|
||||
nm = nm.id2name
|
||||
module_eval(<<-EOS)
|
||||
def #{nm}=( v )
|
||||
bug! unless @#{nm}.nil?
|
||||
@#{nm} = v
|
||||
end
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# attributes
|
||||
#
|
||||
|
||||
once_writer :ident
|
||||
attr_reader :ident
|
||||
|
||||
alias hash ident
|
||||
|
||||
attr_reader :value
|
||||
|
||||
def dummy?() @dummy end
|
||||
|
||||
def terminal?() @term end
|
||||
def nonterminal?() @nterm end
|
||||
|
||||
def term=( t )
|
||||
bug! unless @term.nil?
|
||||
@term = t
|
||||
@nterm = !t
|
||||
end
|
||||
|
||||
def conv=( str ) @conv = @uneval = str end
|
||||
attr_reader :conv
|
||||
|
||||
attr_accessor :prec
|
||||
attr_accessor :assoc
|
||||
|
||||
def to_s() @to_s.dup end
|
||||
def uneval() @uneval.dup end
|
||||
alias inspect to_s
|
||||
|
||||
#
|
||||
# computed
|
||||
#
|
||||
|
||||
attr_reader :heads
|
||||
attr_reader :locate
|
||||
|
||||
once_writer :snull
|
||||
def self_null?() @snull end
|
||||
|
||||
def nullable?() @null end
|
||||
def null=(n) @null = n end
|
||||
|
||||
once_writer :expand
|
||||
attr_reader :expand
|
||||
|
||||
def useless=(f) @useless = f end
|
||||
def useless?() @useless end
|
||||
|
||||
end # class Sym
|
||||
|
||||
end # module Racc
|
||||
@ -0,0 +1,521 @@
|
||||
#
|
||||
# This file is automatically generated. DO NOT MODIFY!!
|
||||
#
|
||||
# grammerfileparser.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
require 'racc/compat'
|
||||
require 'racc/parser'
|
||||
require 'racc/grammarfilescanner'
|
||||
require 'racc/usercodeparser'
|
||||
|
||||
|
||||
module Racc
|
||||
|
||||
class GrammarFileParser < Parser
|
||||
|
||||
def initialize( racc )
|
||||
@yydebug = racc.d_parse && Racc_debug_parser
|
||||
@ruletable = racc.ruletable
|
||||
@symboltable = racc.symboltable
|
||||
|
||||
@class_name = nil
|
||||
@super_class = nil
|
||||
end
|
||||
|
||||
attr_reader :class_name
|
||||
attr_reader :super_class
|
||||
|
||||
def parse( str )
|
||||
@scanner = GrammarFileScanner.new(str)
|
||||
@scanner.debug = @yydebug
|
||||
do_parse
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def next_token
|
||||
@scanner.scan
|
||||
end
|
||||
|
||||
def on_error( tok, val, _values )
|
||||
if val.respond_to?(:id2name)
|
||||
v = val.id2name
|
||||
elsif String === val
|
||||
v = val
|
||||
else
|
||||
v = val.inspect
|
||||
end
|
||||
raise ParseError, "#{@scanner.lineno}: unexpected token '#{v}'"
|
||||
end
|
||||
|
||||
|
||||
##### racc 1.4.4 generates ###
|
||||
|
||||
racc_reduce_table = [
|
||||
0, 0, :racc_error,
|
||||
6, 25, :_reduce_1,
|
||||
1, 26, :_reduce_2,
|
||||
3, 26, :_reduce_3,
|
||||
1, 30, :_reduce_4,
|
||||
4, 30, :_reduce_5,
|
||||
0, 27, :_reduce_none,
|
||||
2, 27, :_reduce_none,
|
||||
3, 31, :_reduce_8,
|
||||
1, 31, :_reduce_none,
|
||||
2, 31, :_reduce_10,
|
||||
2, 31, :_reduce_11,
|
||||
2, 31, :_reduce_12,
|
||||
2, 31, :_reduce_13,
|
||||
2, 32, :_reduce_14,
|
||||
3, 32, :_reduce_15,
|
||||
3, 33, :_reduce_16,
|
||||
3, 33, :_reduce_17,
|
||||
1, 37, :_reduce_none,
|
||||
2, 37, :_reduce_none,
|
||||
2, 38, :_reduce_20,
|
||||
2, 38, :_reduce_21,
|
||||
2, 38, :_reduce_22,
|
||||
1, 35, :_reduce_23,
|
||||
2, 35, :_reduce_24,
|
||||
2, 35, :_reduce_none,
|
||||
1, 34, :_reduce_26,
|
||||
1, 34, :_reduce_27,
|
||||
1, 28, :_reduce_28,
|
||||
0, 28, :_reduce_none,
|
||||
1, 39, :_reduce_30,
|
||||
2, 39, :_reduce_31,
|
||||
2, 39, :_reduce_32,
|
||||
2, 39, :_reduce_33,
|
||||
1, 40, :_reduce_none,
|
||||
1, 40, :_reduce_35,
|
||||
2, 40, :_reduce_36,
|
||||
1, 40, :_reduce_37,
|
||||
1, 36, :_reduce_38,
|
||||
2, 36, :_reduce_39,
|
||||
1, 29, :_reduce_none,
|
||||
0, 29, :_reduce_none ]
|
||||
|
||||
racc_reduce_n = 42
|
||||
|
||||
racc_shift_n = 66
|
||||
|
||||
racc_action_table = [
|
||||
28, 47, 28, 42, 28, 28, 33, 34, 35, 27,
|
||||
43, 27, 28, 27, 27, 49, 50, 44, 45, 63,
|
||||
63, 27, 28, 33, 34, 35, 14, 63, 52, 9,
|
||||
17, 27, 18, 20, 11, 13, 28, 63, 15, 16,
|
||||
28, 28, 28, 61, 28, 27, 28, 28, 28, 27,
|
||||
27, 27, 8, 27, 9, 27, 27, 27, 58, 25,
|
||||
33, 34, 35, 54, 33, 34, 35, 24, 59, 22,
|
||||
4, 10, 1, 6, 4, 65 ]
|
||||
|
||||
racc_action_check = [
|
||||
29, 29, 44, 22, 57, 56, 16, 16, 16, 29,
|
||||
23, 44, 41, 57, 56, 29, 29, 29, 29, 57,
|
||||
56, 41, 55, 15, 15, 15, 7, 41, 30, 21,
|
||||
7, 55, 7, 7, 7, 7, 33, 55, 7, 7,
|
||||
38, 35, 18, 38, 34, 33, 20, 17, 14, 38,
|
||||
35, 18, 5, 34, 5, 20, 17, 14, 36, 13,
|
||||
36, 36, 36, 31, 31, 31, 31, 11, 37, 9,
|
||||
8, 6, 0, 2, 1, 60 ]
|
||||
|
||||
racc_action_pointer = [
|
||||
70, 69, 73, nil, nil, 48, 71, 23, 65, 63,
|
||||
nil, 62, nil, 46, 43, 6, -11, 42, 37, nil,
|
||||
41, 23, -2, 5, nil, nil, nil, nil, nil, -5,
|
||||
20, 47, nil, 31, 39, 36, 43, 54, 35, nil,
|
||||
nil, 7, nil, nil, -3, nil, nil, nil, nil, nil,
|
||||
nil, nil, nil, nil, nil, 17, 0, -1, nil, nil,
|
||||
61, nil, nil, nil, nil, nil ]
|
||||
|
||||
racc_action_default = [
|
||||
-42, -42, -42, -6, -4, -2, -42, -42, -42, -42,
|
||||
66, -42, -9, -42, -29, -42, -42, -42, -42, -7,
|
||||
-42, -3, -42, -12, -38, -13, -30, -27, -26, -28,
|
||||
-41, -42, -18, -42, -42, -42, -42, -42, -42, -10,
|
||||
-23, -11, -5, -39, -42, -37, -34, -33, -31, -35,
|
||||
-32, -1, -40, -19, -16, -20, -21, -22, -17, -14,
|
||||
-42, -8, -24, -25, -36, -15 ]
|
||||
|
||||
racc_goto_table = [
|
||||
26, 5, 53, 37, 39, 41, 12, 53, 21, 31,
|
||||
36, 19, 38, 2, 51, 46, 30, 23, 55, 56,
|
||||
57, 7, 3, 29, 60, 48, nil, 62, nil, nil,
|
||||
64, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, 62, 62, 62 ]
|
||||
|
||||
racc_goto_check = [
|
||||
10, 6, 14, 10, 10, 11, 9, 14, 6, 13,
|
||||
13, 7, 8, 1, 5, 10, 4, 12, 11, 11,
|
||||
11, 3, 2, 15, 10, 16, nil, 10, nil, nil,
|
||||
10, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
nil, 10, 10, 10 ]
|
||||
|
||||
racc_goto_pointer = [
|
||||
nil, 13, 21, 18, 2, -16, 0, 4, -5, -1,
|
||||
-14, -15, 6, -6, -29, 9, -4 ]
|
||||
|
||||
racc_goto_default = [
|
||||
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
40, nil, nil, nil, 32, nil, nil ]
|
||||
|
||||
racc_token_table = {
|
||||
false => 0,
|
||||
Object.new => 1,
|
||||
:XCLASS => 2,
|
||||
:XRULE => 3,
|
||||
"<" => 4,
|
||||
:XSYMBOL => 5,
|
||||
":" => 6,
|
||||
:XCONV => 7,
|
||||
:XEND => 8,
|
||||
:XSTART => 9,
|
||||
:XTOKEN => 10,
|
||||
:XOPTION => 11,
|
||||
:XEXPECT => 12,
|
||||
:DIGIT => 13,
|
||||
:STRING => 14,
|
||||
:XPRECHIGH => 15,
|
||||
:XPRECLOW => 16,
|
||||
:XLEFT => 17,
|
||||
:XRIGHT => 18,
|
||||
:XNONASSOC => 19,
|
||||
"|" => 20,
|
||||
";" => 21,
|
||||
"=" => 22,
|
||||
:ACTION => 23 }
|
||||
|
||||
racc_use_result_var = true
|
||||
|
||||
racc_nt_base = 24
|
||||
|
||||
Racc_arg = [
|
||||
racc_action_table,
|
||||
racc_action_check,
|
||||
racc_action_default,
|
||||
racc_action_pointer,
|
||||
racc_goto_table,
|
||||
racc_goto_check,
|
||||
racc_goto_default,
|
||||
racc_goto_pointer,
|
||||
racc_nt_base,
|
||||
racc_reduce_table,
|
||||
racc_token_table,
|
||||
racc_shift_n,
|
||||
racc_reduce_n,
|
||||
racc_use_result_var ]
|
||||
|
||||
Racc_token_to_s_table = [
|
||||
'$end',
|
||||
'error',
|
||||
'XCLASS',
|
||||
'XRULE',
|
||||
'"<"',
|
||||
'XSYMBOL',
|
||||
'":"',
|
||||
'XCONV',
|
||||
'XEND',
|
||||
'XSTART',
|
||||
'XTOKEN',
|
||||
'XOPTION',
|
||||
'XEXPECT',
|
||||
'DIGIT',
|
||||
'STRING',
|
||||
'XPRECHIGH',
|
||||
'XPRECLOW',
|
||||
'XLEFT',
|
||||
'XRIGHT',
|
||||
'XNONASSOC',
|
||||
'"|"',
|
||||
'";"',
|
||||
'"="',
|
||||
'ACTION',
|
||||
'$start',
|
||||
'xclass',
|
||||
'class',
|
||||
'params',
|
||||
'rules',
|
||||
'opt_end',
|
||||
'rubyconst',
|
||||
'param_seg',
|
||||
'convdefs',
|
||||
'xprec',
|
||||
'symbol',
|
||||
'symbol_list',
|
||||
'bare_symlist',
|
||||
'preclines',
|
||||
'precline',
|
||||
'rules_core',
|
||||
'rule_item']
|
||||
|
||||
Racc_debug_parser = false
|
||||
|
||||
##### racc system variables end #####
|
||||
|
||||
# reduce 0 omitted
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 88
|
||||
def _reduce_1( val, _values, result )
|
||||
@ruletable.end_register_rule
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 93
|
||||
def _reduce_2( val, _values, result )
|
||||
@class_name = val[0]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 98
|
||||
def _reduce_3( val, _values, result )
|
||||
@class_name = val[0]
|
||||
@super_class = val[2]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 103
|
||||
def _reduce_4( val, _values, result )
|
||||
result = result.id2name
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 107
|
||||
def _reduce_5( val, _values, result )
|
||||
result << '::' << val[3].id2name
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
# reduce 6 omitted
|
||||
|
||||
# reduce 7 omitted
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 115
|
||||
def _reduce_8( val, _values, result )
|
||||
@symboltable.end_register_conv
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
# reduce 9 omitted
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 120
|
||||
def _reduce_10( val, _values, result )
|
||||
@ruletable.register_start val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 124
|
||||
def _reduce_11( val, _values, result )
|
||||
@symboltable.register_token val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 130
|
||||
def _reduce_12( val, _values, result )
|
||||
val[1].each do |s|
|
||||
@ruletable.register_option s.to_s
|
||||
end
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 134
|
||||
def _reduce_13( val, _values, result )
|
||||
@ruletable.expect val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 139
|
||||
def _reduce_14( val, _values, result )
|
||||
@symboltable.register_conv val[0], val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 143
|
||||
def _reduce_15( val, _values, result )
|
||||
@symboltable.register_conv val[1], val[2]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 148
|
||||
def _reduce_16( val, _values, result )
|
||||
@symboltable.end_register_prec true
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 152
|
||||
def _reduce_17( val, _values, result )
|
||||
@symboltable.end_register_prec false
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
# reduce 18 omitted
|
||||
|
||||
# reduce 19 omitted
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 160
|
||||
def _reduce_20( val, _values, result )
|
||||
@symboltable.register_prec :Left, val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 164
|
||||
def _reduce_21( val, _values, result )
|
||||
@symboltable.register_prec :Right, val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 168
|
||||
def _reduce_22( val, _values, result )
|
||||
@symboltable.register_prec :Nonassoc, val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 173
|
||||
def _reduce_23( val, _values, result )
|
||||
result = val
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 177
|
||||
def _reduce_24( val, _values, result )
|
||||
result.push val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
# reduce 25 omitted
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 183
|
||||
def _reduce_26( val, _values, result )
|
||||
result = @symboltable.get(result)
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 187
|
||||
def _reduce_27( val, _values, result )
|
||||
result = @symboltable.get(eval(%Q<"#{result}">))
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 194
|
||||
def _reduce_28( val, _values, result )
|
||||
unless result.empty?
|
||||
@ruletable.register_rule_from_array result
|
||||
end
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
# reduce 29 omitted
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 200
|
||||
def _reduce_30( val, _values, result )
|
||||
result = val
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 204
|
||||
def _reduce_31( val, _values, result )
|
||||
result.push val[1]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 211
|
||||
def _reduce_32( val, _values, result )
|
||||
unless result.empty?
|
||||
@ruletable.register_rule_from_array result
|
||||
end
|
||||
result.clear
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 219
|
||||
def _reduce_33( val, _values, result )
|
||||
pre = result.pop
|
||||
unless result.empty?
|
||||
@ruletable.register_rule_from_array result
|
||||
end
|
||||
result = [pre]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
# reduce 34 omitted
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 225
|
||||
def _reduce_35( val, _values, result )
|
||||
result = OrMark.new(@scanner.lineno)
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 229
|
||||
def _reduce_36( val, _values, result )
|
||||
result = Prec.new(val[1], @scanner.lineno)
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 233
|
||||
def _reduce_37( val, _values, result )
|
||||
result = UserAction.new(*result)
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 238
|
||||
def _reduce_38( val, _values, result )
|
||||
result = [ result.id2name ]
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
module_eval <<'.,.,', '(boot.rb)', 242
|
||||
def _reduce_39( val, _values, result )
|
||||
result.push val[1].id2name
|
||||
result
|
||||
end
|
||||
.,.,
|
||||
|
||||
# reduce 40 omitted
|
||||
|
||||
# reduce 41 omitted
|
||||
|
||||
def _reduce_none( val, _values, result )
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end # module Racc
|
||||
@ -0,0 +1,300 @@
|
||||
#
|
||||
# grammarfilescanner.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
module Racc
|
||||
|
||||
class ScanError < StandardError; end
|
||||
|
||||
|
||||
class GrammarFileScanner
|
||||
|
||||
def initialize( str )
|
||||
@lines = str.split(/\n|\r\n|\r/)
|
||||
@lineno = -1
|
||||
@line_head = true
|
||||
@in_rule_blk = false
|
||||
@in_conv_blk = false
|
||||
@in_block = nil
|
||||
@debug = false
|
||||
|
||||
next_line
|
||||
end
|
||||
|
||||
def lineno
|
||||
@lineno + 1
|
||||
end
|
||||
|
||||
attr_accessor :debug
|
||||
|
||||
def scan
|
||||
result = do_scan()
|
||||
if @debug
|
||||
$stderr.printf "%7d %-10s %s\n",
|
||||
lineno(), result[0].inspect, result[1].inspect
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def do_scan
|
||||
begin
|
||||
until @line.empty?
|
||||
@line.sub!(/\A\s+/, '')
|
||||
|
||||
if /\A\#/ === @line
|
||||
break
|
||||
|
||||
elsif /\A\/\*/ === @line
|
||||
skip_comment
|
||||
|
||||
elsif s = reads(/\A[a-zA-Z_]\w*/)
|
||||
return check_atom(s)
|
||||
|
||||
elsif s = reads(/\A\d+/)
|
||||
return :DIGIT, s.to_i
|
||||
|
||||
elsif ch = reads(/\A./)
|
||||
case ch
|
||||
when '"', "'"
|
||||
return :STRING, eval(scan_quoted(ch))
|
||||
when '{'
|
||||
return :ACTION, [scan_action(), lineno()]
|
||||
else
|
||||
if ch == '|'
|
||||
@line_head = false
|
||||
end
|
||||
return ch, ch
|
||||
end
|
||||
|
||||
else
|
||||
;
|
||||
end
|
||||
end
|
||||
end while next_line()
|
||||
|
||||
return false, '$'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def next_line
|
||||
@lineno += 1
|
||||
@line = @lines[@lineno]
|
||||
|
||||
if not @line or /\A----/ === @line
|
||||
@lines.clear
|
||||
@line = nil
|
||||
if @in_block
|
||||
@lineno -= 1
|
||||
scan_error! sprintf('unterminated %s', @in_block)
|
||||
end
|
||||
|
||||
false
|
||||
else
|
||||
@line.sub!(/(?:\n|\r\n|\r)\z/, '')
|
||||
@line_head = true
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
ReservedWord = {
|
||||
'right' => :XRIGHT,
|
||||
'left' => :XLEFT,
|
||||
'nonassoc' => :XNONASSOC,
|
||||
'preclow' => :XPRECLOW,
|
||||
'prechigh' => :XPRECHIGH,
|
||||
'token' => :XTOKEN,
|
||||
'convert' => :XCONV,
|
||||
'options' => :XOPTION,
|
||||
'start' => :XSTART,
|
||||
'expect' => :XEXPECT,
|
||||
'class' => :XCLASS,
|
||||
'rule' => :XRULE,
|
||||
'end' => :XEND
|
||||
}
|
||||
|
||||
def check_atom( cur )
|
||||
if cur == 'end'
|
||||
symbol = :XEND
|
||||
@in_conv_blk = false
|
||||
@in_rule_blk = false
|
||||
else
|
||||
if @line_head and not @in_conv_blk and not @in_rule_blk
|
||||
symbol = ReservedWord[cur] || :XSYMBOL
|
||||
else
|
||||
symbol = :XSYMBOL
|
||||
end
|
||||
case symbol
|
||||
when :XRULE then @in_rule_blk = true
|
||||
when :XCONV then @in_conv_blk = true
|
||||
end
|
||||
end
|
||||
@line_head = false
|
||||
|
||||
[symbol, cur.intern]
|
||||
end
|
||||
|
||||
def skip_comment
|
||||
@in_block = 'comment'
|
||||
until m = /\*\//.match(@line)
|
||||
next_line
|
||||
end
|
||||
@line = m.post_match
|
||||
@in_block = nil
|
||||
end
|
||||
|
||||
def scan_action
|
||||
buf = ''
|
||||
nest = 1
|
||||
pre = nil
|
||||
|
||||
@in_block = 'action'
|
||||
|
||||
begin
|
||||
pre = nil
|
||||
if s = reads(/\A\s+/)
|
||||
# does not set 'pre'
|
||||
buf << s
|
||||
end
|
||||
|
||||
until @line.empty?
|
||||
if s = reads(/\A[^'"`{}%#\/\$]+/)
|
||||
buf << (pre = s)
|
||||
next
|
||||
end
|
||||
|
||||
case ch = read(1)
|
||||
when '{'
|
||||
nest += 1
|
||||
buf << (pre = ch)
|
||||
|
||||
when '}'
|
||||
nest -= 1
|
||||
if nest == 0
|
||||
@in_block = nil
|
||||
return buf
|
||||
end
|
||||
buf << (pre = ch)
|
||||
|
||||
when '#' # comment
|
||||
buf << ch << @line
|
||||
break
|
||||
|
||||
when "'", '"', '`'
|
||||
buf << (pre = scan_quoted(ch))
|
||||
|
||||
when '%'
|
||||
if literal_head? pre, @line
|
||||
# % string, regexp, array
|
||||
buf << ch
|
||||
case ch = read(1)
|
||||
when /[qQx]/n
|
||||
buf << ch << (pre = scan_quoted(read(1), '%string'))
|
||||
when /wW/n
|
||||
buf << ch << (pre = scan_quoted(read(1), '%array'))
|
||||
when /s/n
|
||||
buf << ch << (pre = scan_quoted(read(1), '%symbol'))
|
||||
when /r/n
|
||||
buf << ch << (pre = scan_quoted(read(1), '%regexp'))
|
||||
when /[a-zA-Z0-9= ]/n # does not include "_"
|
||||
scan_error! "unknown type of % literal '%#{ch}'"
|
||||
else
|
||||
buf << (pre = scan_quoted(ch, '%string'))
|
||||
end
|
||||
else
|
||||
# operator
|
||||
buf << '||op->' if $raccs_print_type
|
||||
buf << (pre = ch)
|
||||
end
|
||||
|
||||
when '/'
|
||||
if literal_head? pre, @line
|
||||
# regexp
|
||||
buf << (pre = scan_quoted(ch, 'regexp'))
|
||||
else
|
||||
# operator
|
||||
buf << '||op->' if $raccs_print_type
|
||||
buf << (pre = ch)
|
||||
end
|
||||
|
||||
when '$' # gvar
|
||||
buf << ch << (pre = read(1))
|
||||
|
||||
else
|
||||
raise 'Racc FATAL: did not match'
|
||||
end
|
||||
end
|
||||
|
||||
buf << "\n"
|
||||
end while next_line()
|
||||
|
||||
raise 'Racc FATAL: scan finished before parse finished'
|
||||
end
|
||||
|
||||
def literal_head?( pre, post )
|
||||
(not pre or not /[a-zA-Z_0-9]/n === pre[-1,1]) and
|
||||
not post.empty? and not /\A[\s\=]/n === post
|
||||
end
|
||||
|
||||
def read( len )
|
||||
s = @line[0, len]
|
||||
@line = @line[len .. -1]
|
||||
s
|
||||
end
|
||||
|
||||
def reads( re )
|
||||
m = re.match(@line) or return nil
|
||||
@line = m.post_match
|
||||
m[0]
|
||||
end
|
||||
|
||||
def scan_quoted( left, tag = 'string' )
|
||||
buf = left.dup
|
||||
buf = "||#{tag}->" + buf if $raccs_print_type
|
||||
re = get_quoted_re(left)
|
||||
|
||||
sv, @in_block = @in_block, tag
|
||||
begin
|
||||
if s = reads(re)
|
||||
buf << s
|
||||
break
|
||||
else
|
||||
buf << @line
|
||||
end
|
||||
end while next_line()
|
||||
@in_block = sv
|
||||
|
||||
buf << "<-#{tag}||" if $raccs_print_type
|
||||
buf
|
||||
end
|
||||
|
||||
LEFT_TO_RIGHT = {
|
||||
'(' => ')',
|
||||
'{' => '}',
|
||||
'[' => ']',
|
||||
'<' => '>'
|
||||
}
|
||||
|
||||
CACHE = {}
|
||||
|
||||
def get_quoted_re( left )
|
||||
term = Regexp.quote(LEFT_TO_RIGHT[left] || left)
|
||||
CACHE[left] ||= /\A[^#{term}\\]*(?:\\.[^\\#{term}]*)*#{term}/
|
||||
end
|
||||
|
||||
def scan_error!( msg )
|
||||
raise ScanError, "#{lineno()}: #{msg}"
|
||||
end
|
||||
|
||||
$raccs_print_type = false
|
||||
|
||||
end
|
||||
|
||||
end # module Racc
|
||||
@ -0,0 +1,15 @@
|
||||
#
|
||||
# info.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
module Racc
|
||||
Version = '1.4.4'
|
||||
Copyright = 'Copyright (c) 1999-2003 Minero Aoki'
|
||||
end
|
||||
@ -0,0 +1,98 @@
|
||||
#
|
||||
# iset.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
module Racc
|
||||
|
||||
#
|
||||
# ISet
|
||||
#
|
||||
# indexed set.
|
||||
# all items must respond to :ident
|
||||
#
|
||||
|
||||
class ISet
|
||||
|
||||
def initialize( a = [] )
|
||||
@set = a
|
||||
end
|
||||
|
||||
attr_reader :set
|
||||
|
||||
def add( i )
|
||||
@set[i.ident] = i
|
||||
end
|
||||
|
||||
def []( key )
|
||||
@set[key.ident]
|
||||
end
|
||||
|
||||
def []=( key, val )
|
||||
@set[key.ident] = val
|
||||
end
|
||||
|
||||
alias include? []
|
||||
alias key? []
|
||||
|
||||
def update( other )
|
||||
s = @set
|
||||
o = other.set
|
||||
o.each_index do |idx|
|
||||
if t = o[idx]
|
||||
s[idx] = t
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update_a( a )
|
||||
s = @set
|
||||
i = nil
|
||||
a.each {|i| s[i.ident] = i }
|
||||
end
|
||||
|
||||
def delete( key )
|
||||
i = @set[key.ident]
|
||||
@set[key.ident] = nil
|
||||
i
|
||||
end
|
||||
|
||||
def each( &block )
|
||||
@set.compact.each(&block)
|
||||
end
|
||||
|
||||
def to_a
|
||||
@set.compact
|
||||
end
|
||||
|
||||
def to_s
|
||||
"[#{@set.compact.join(' ')}]"
|
||||
end
|
||||
|
||||
alias inspect to_s
|
||||
|
||||
def size
|
||||
@set.nitems
|
||||
end
|
||||
|
||||
def empty?
|
||||
@set.nitems == 0
|
||||
end
|
||||
|
||||
def clear
|
||||
@set.clear
|
||||
end
|
||||
|
||||
def dup
|
||||
ISet.new(@set.dup)
|
||||
end
|
||||
|
||||
end # class ISet
|
||||
|
||||
end # module Racc
|
||||
@ -0,0 +1,645 @@
|
||||
#
|
||||
# output.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
require 'racc/compat'
|
||||
|
||||
|
||||
module Racc
|
||||
|
||||
class Formatter
|
||||
|
||||
def initialize( racc )
|
||||
@ruletable = racc.ruletable
|
||||
@symboltable = racc.symboltable
|
||||
@statetable = racc.statetable
|
||||
@actions = racc.statetable.actions
|
||||
|
||||
@fname = racc.filename
|
||||
@debug = racc.debug ? true : false
|
||||
@dsrc = racc.debug_parser ? true : false
|
||||
@line = racc.convert_line ? true : false
|
||||
@omit = racc.omit_action ? true : false
|
||||
@result = racc.result_var ? true : false
|
||||
@showall = racc.d_la || racc.d_state
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class CodeGenerator < Formatter
|
||||
|
||||
def output( out )
|
||||
out.print "\n##### racc #{Racc::Version} generates ###\n\n"
|
||||
output_reduce_table out
|
||||
output_action_table out
|
||||
output_goto_table out
|
||||
output_token_table out
|
||||
output_other out
|
||||
out.puts '##### racc system variables end #####'
|
||||
output_actions out
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def output_reduce_table( out )
|
||||
out << "racc_reduce_table = [\n"
|
||||
out << " 0, 0, :racc_error,"
|
||||
sep = "\n"
|
||||
sep_rest = ",\n"
|
||||
@ruletable.each_with_index do |rl, i|
|
||||
next if i == 0
|
||||
out.print sep; sep = sep_rest
|
||||
out.printf ' %d, %d, :_reduce_%s',
|
||||
rl.size,
|
||||
rl.target.ident,
|
||||
(@omit and not rl.action) ? 'none' : i.to_s
|
||||
end
|
||||
out << " ]\n\n"
|
||||
out << "racc_reduce_n = #{@actions.reduce_n}\n\n"
|
||||
out << "racc_shift_n = #{@actions.shift_n}\n\n"
|
||||
end
|
||||
|
||||
def output_action_table( out )
|
||||
tbl = [] # yytable
|
||||
chk = [] # yycheck
|
||||
defa = [] # yydefact
|
||||
ptr = [] # yypact
|
||||
state = tmp = min = max = i = nil
|
||||
e1 = []
|
||||
e2 = []
|
||||
|
||||
@statetable.each do |state|
|
||||
defa.push act2actid(state.defact)
|
||||
|
||||
if state.action.empty?
|
||||
ptr.push nil
|
||||
next
|
||||
end
|
||||
tmp = []
|
||||
state.action.each do |tok, act|
|
||||
tmp[tok.ident] = act2actid(act)
|
||||
end
|
||||
addent e1, e2, tmp, state.ident, ptr
|
||||
end
|
||||
set_table e1, e2, tbl, chk, ptr
|
||||
|
||||
output_table out, tbl, 'racc_action_table'
|
||||
output_table out, chk, 'racc_action_check'
|
||||
output_table out, ptr, 'racc_action_pointer'
|
||||
output_table out, defa, 'racc_action_default'
|
||||
end
|
||||
|
||||
def output_goto_table( out )
|
||||
tbl = [] # yytable (2)
|
||||
chk = [] # yycheck (2)
|
||||
ptr = [] # yypgoto
|
||||
defg = [] # yydefgoto
|
||||
state = dflt = tmp = freq = min = max = i = nil
|
||||
e1 = []
|
||||
e2 = []
|
||||
|
||||
@symboltable.each_nonterm do |tok|
|
||||
tmp = []
|
||||
|
||||
#
|
||||
# decide default
|
||||
#
|
||||
freq = Array.new(@statetable.size, 0)
|
||||
@statetable.each do |state|
|
||||
st = state.goto_table[tok]
|
||||
if st
|
||||
st = st.ident
|
||||
freq[st] += 1
|
||||
end
|
||||
tmp[state.ident] = st
|
||||
end
|
||||
max = freq.max
|
||||
if max > 1
|
||||
dflt = freq.index( max )
|
||||
tmp.map! {|i| dflt == i ? nil : i }
|
||||
else
|
||||
dflt = nil
|
||||
end
|
||||
|
||||
# default
|
||||
defg.push dflt
|
||||
|
||||
#
|
||||
# delete default value
|
||||
#
|
||||
tmp.pop until tmp[-1] or tmp.empty?
|
||||
if tmp.compact.empty?
|
||||
# only default
|
||||
ptr.push nil
|
||||
next
|
||||
end
|
||||
|
||||
addent e1, e2, tmp, (tok.ident - @symboltable.nt_base), ptr
|
||||
end
|
||||
set_table e1, e2, tbl, chk, ptr
|
||||
|
||||
output_table out, tbl, 'racc_goto_table'
|
||||
output_table out, chk, 'racc_goto_check'
|
||||
output_table out, ptr, 'racc_goto_pointer'
|
||||
output_table out, defg, 'racc_goto_default'
|
||||
end
|
||||
|
||||
def addent( all, dummy, arr, chkval, ptr )
|
||||
max = arr.size
|
||||
min = nil
|
||||
item = idx = nil
|
||||
arr.each_with_index do |item,idx|
|
||||
if item
|
||||
min ||= idx
|
||||
end
|
||||
end
|
||||
ptr.push(-7777) # mark
|
||||
|
||||
arr = arr[min...max]
|
||||
ent = [ arr, chkval, mkmapexp(arr), min, ptr.size - 1 ]
|
||||
all.push ent
|
||||
end
|
||||
|
||||
unless defined? RegexpError
|
||||
RegexpError = RegxpError
|
||||
end
|
||||
begin
|
||||
tmp = 2 ** 16
|
||||
begin
|
||||
Regexp.new("a{#{tmp}}")
|
||||
RE_DUP_MAX = tmp
|
||||
rescue RegexpError
|
||||
tmp /= 2
|
||||
retry
|
||||
end
|
||||
raise ArgumentError, 'dummy error to clear ruby_errinfo'
|
||||
rescue ArgumentError
|
||||
;
|
||||
end
|
||||
|
||||
def mkmapexp( arr )
|
||||
i = ii = 0
|
||||
as = arr.size
|
||||
map = ''
|
||||
maxdup = RE_DUP_MAX
|
||||
curr = nil
|
||||
|
||||
while i < as
|
||||
ii = i + 1
|
||||
if arr[i]
|
||||
ii += 1 while ii < as and arr[ii]
|
||||
curr = '-'
|
||||
else
|
||||
ii += 1 while ii < as and not arr[ii]
|
||||
curr = '.'
|
||||
end
|
||||
|
||||
offset = ii - i
|
||||
if offset == 1
|
||||
map << curr
|
||||
else
|
||||
while offset > maxdup
|
||||
map << "#{curr}{#{maxdup}}"
|
||||
offset -= maxdup
|
||||
end
|
||||
map << "#{curr}{#{offset}}" if offset > 1
|
||||
end
|
||||
i = ii
|
||||
end
|
||||
|
||||
Regexp.compile(map, 'n')
|
||||
end
|
||||
|
||||
def set_table( entries, dummy, tbl, chk, ptr )
|
||||
upper = 0
|
||||
map = '-' * 10240
|
||||
|
||||
# sort long to short
|
||||
entries.sort! {|a,b| b[0].size <=> a[0].size }
|
||||
|
||||
entries.each do |arr, chkval, expr, min, ptri|
|
||||
if upper + arr.size > map.size
|
||||
map << '-' * (arr.size + 1024)
|
||||
end
|
||||
idx = map.index(expr)
|
||||
ptr[ptri] = idx - min
|
||||
arr.each_with_index do |item, i|
|
||||
if item
|
||||
i += idx
|
||||
tbl[i] = item
|
||||
chk[i] = chkval
|
||||
map[i] = ?o
|
||||
end
|
||||
end
|
||||
upper = idx + arr.size
|
||||
end
|
||||
end
|
||||
|
||||
def act2actid( act )
|
||||
case act
|
||||
when Shift then act.goto_id
|
||||
when Reduce then -act.ruleid
|
||||
when Accept then @actions.shift_n
|
||||
when Error then @actions.reduce_n * -1
|
||||
else
|
||||
raise "Racc FATAL: wrong act type #{act.class} in action table"
|
||||
end
|
||||
end
|
||||
|
||||
def output_table( out, tab, label )
|
||||
if tab.size > 2000
|
||||
#
|
||||
# compressed table
|
||||
#
|
||||
output_table_c out, tab, label
|
||||
else
|
||||
#
|
||||
# normal array
|
||||
#
|
||||
output_table_s out, tab, label
|
||||
end
|
||||
end
|
||||
|
||||
def output_table_c( out, tab, label )
|
||||
sep = "\n"
|
||||
nsep = ",\n"
|
||||
buf = ''
|
||||
com = ''
|
||||
ncom = ','
|
||||
co = com
|
||||
|
||||
out.print 'clist = ['
|
||||
tab.each do |i|
|
||||
buf << co << i.to_s; co = ncom
|
||||
if buf.size > 66
|
||||
out.print sep; sep = nsep
|
||||
out.print "'", buf, "'"
|
||||
buf = ''
|
||||
co = com
|
||||
end
|
||||
end
|
||||
unless buf.empty?
|
||||
out.print sep
|
||||
out.print "'", buf, "'"
|
||||
end
|
||||
out.puts ' ]'
|
||||
|
||||
out.print(<<EOS)
|
||||
#{label} = arr = Array.new(#{tab.size}, nil)
|
||||
str = a = i = nil
|
||||
idx = 0
|
||||
clist.each do |str|
|
||||
str.split(',', -1).each do |i|
|
||||
arr[idx] = i.to_i unless i.empty?
|
||||
idx += 1
|
||||
end
|
||||
end
|
||||
|
||||
EOS
|
||||
end
|
||||
|
||||
def output_table_s( out, tab, label )
|
||||
sep = ''
|
||||
nsep = ','
|
||||
buf = ''
|
||||
i = 0
|
||||
|
||||
out.puts "#{label} = ["
|
||||
tab.each do |t|
|
||||
buf << sep ; sep = nsep
|
||||
if i == 10
|
||||
i = 0
|
||||
buf << "\n"
|
||||
out << buf
|
||||
buf = ''
|
||||
end
|
||||
buf << (t ? sprintf('%6d', t) : ' nil')
|
||||
i += 1
|
||||
end
|
||||
out << buf unless buf.empty?
|
||||
out.print " ]\n\n"
|
||||
end
|
||||
|
||||
def output_token_table( out )
|
||||
sep = "\n"
|
||||
sep_rest = ",\n"
|
||||
out << "racc_token_table = {"
|
||||
@symboltable.each do |tok|
|
||||
if tok.terminal?
|
||||
out.print sep; sep = sep_rest
|
||||
out.printf " %s => %d", tok.uneval, tok.ident
|
||||
end
|
||||
end
|
||||
out << " }\n\n"
|
||||
end
|
||||
|
||||
def output_other( out )
|
||||
out << "racc_use_result_var = #{@result}\n\n"
|
||||
out.print(<<EOS)
|
||||
racc_nt_base = #{@symboltable.nt_base}
|
||||
|
||||
Racc_arg = [
|
||||
racc_action_table,
|
||||
racc_action_check,
|
||||
racc_action_default,
|
||||
racc_action_pointer,
|
||||
racc_goto_table,
|
||||
racc_goto_check,
|
||||
racc_goto_default,
|
||||
racc_goto_pointer,
|
||||
racc_nt_base,
|
||||
racc_reduce_table,
|
||||
racc_token_table,
|
||||
racc_shift_n,
|
||||
racc_reduce_n,
|
||||
racc_use_result_var ]
|
||||
|
||||
EOS
|
||||
out << "Racc_token_to_s_table = [\n"
|
||||
out << @symboltable.map {|tok|
|
||||
"'" + tok.to_s.gsub(/'/, '\\\'') + "'" }.join(",\n")
|
||||
out << "]\n\n"
|
||||
out << "Racc_debug_parser = #{@dsrc}\n\n"
|
||||
end
|
||||
|
||||
def output_actions( out )
|
||||
rl = act = nil
|
||||
|
||||
if @result
|
||||
result1 = ', result '
|
||||
result2 = "\n result"
|
||||
defact = ''
|
||||
else
|
||||
result1 = result2 = ''
|
||||
defact = ' val[0]'
|
||||
end
|
||||
result = @result ? ', result ' : ''
|
||||
if @line
|
||||
src = <<'--'
|
||||
|
||||
module_eval <<'.,.,', '%s', %d
|
||||
def _reduce_%d( val, _values%s)
|
||||
%s%s
|
||||
end
|
||||
%s
|
||||
--
|
||||
else
|
||||
src = <<'--'
|
||||
|
||||
def _reduce_%d( val, _values%s)
|
||||
%s%s
|
||||
end
|
||||
--
|
||||
end
|
||||
|
||||
@ruletable.each_rule do |rl|
|
||||
act = rl.action
|
||||
if not act and @omit
|
||||
out.printf "\n # reduce %d omitted\n",
|
||||
rl.ident
|
||||
else
|
||||
act ||= defact
|
||||
act.sub!(/\s+\z/, '')
|
||||
if @line
|
||||
i = rl.lineno
|
||||
while m = /\A[ \t\f]*(?:\n|\r\n|\r)/.match(act)
|
||||
act = m.post_match
|
||||
i += 1
|
||||
end
|
||||
delim = '.,.,'
|
||||
while act.index(delim)
|
||||
delim *= 2
|
||||
end
|
||||
out.printf src, @fname, i - 1, rl.ident,
|
||||
result1, act, result2, delim
|
||||
else
|
||||
act.sub!(/\A\s*(?:\n|\r\n|\r)/, '')
|
||||
out.printf src, rl.ident,
|
||||
result1, act, result2
|
||||
end
|
||||
end
|
||||
end
|
||||
out.printf <<'--', result, (@result ? 'result' : 'val[0]')
|
||||
|
||||
def _reduce_none( val, _values%s)
|
||||
%s
|
||||
end
|
||||
--
|
||||
out.puts
|
||||
end
|
||||
|
||||
end # class CodeGenerator
|
||||
|
||||
###
|
||||
###
|
||||
###
|
||||
|
||||
class VerboseOutputter < Formatter
|
||||
|
||||
def output( out )
|
||||
output_conflict out; out.puts
|
||||
output_useless out; out.puts
|
||||
output_rule out; out.puts
|
||||
output_token out; out.puts
|
||||
output_state out
|
||||
end
|
||||
|
||||
#
|
||||
# Warnings
|
||||
#
|
||||
|
||||
def output_conflict( out )
|
||||
@statetable.each do |state|
|
||||
if state.srconf
|
||||
out.printf "state %d contains %d shift/reduce conflicts\n",
|
||||
state.stateid, state.srconf.size
|
||||
end
|
||||
if state.rrconf
|
||||
out.printf "state %d contains %d reduce/reduce conflicts\n",
|
||||
state.stateid, state.rrconf.size
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def output_useless( out )
|
||||
rl = t = nil
|
||||
used = []
|
||||
@ruletable.each do |rl|
|
||||
if rl.useless?
|
||||
out.printf "rule %d (%s) never reduced\n",
|
||||
rl.ident, rl.target.to_s
|
||||
end
|
||||
end
|
||||
@symboltable.each_nonterm do |t|
|
||||
if t.useless?
|
||||
out.printf "useless nonterminal %s\n", t.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# States
|
||||
#
|
||||
|
||||
def output_state( out )
|
||||
ptr = nil
|
||||
out << "--------- State ---------\n"
|
||||
|
||||
@statetable.each do |state|
|
||||
out << "\nstate #{state.ident}\n\n"
|
||||
|
||||
(@showall ? state.closure : state.core).each do |ptr|
|
||||
pointer_out(out, ptr) if ptr.rule.ident != 0 or @showall
|
||||
end
|
||||
out << "\n"
|
||||
|
||||
action_out out, state
|
||||
end
|
||||
end
|
||||
|
||||
def pointer_out( out, ptr )
|
||||
buf = sprintf("%4d) %s :", ptr.rule.ident, ptr.rule.target.to_s)
|
||||
ptr.rule.symbols.each_with_index do |tok, idx|
|
||||
buf << ' _' if idx == ptr.index
|
||||
buf << ' ' << tok.to_s
|
||||
end
|
||||
buf << ' _' if ptr.reduce?
|
||||
out.puts buf
|
||||
end
|
||||
|
||||
def action_out( f, state )
|
||||
r = ''
|
||||
e = ''
|
||||
sr = state.srconf && state.srconf.dup
|
||||
rr = state.rrconf && state.rrconf.dup
|
||||
acts = state.action
|
||||
keys = acts.keys
|
||||
keys.sort! {|a,b| a.ident <=> b.ident }
|
||||
|
||||
[ Shift, Reduce, Error, Accept ].each do |type|
|
||||
keys.delete_if do |tok|
|
||||
act = acts[tok]
|
||||
if type === act
|
||||
outact f, tok, act
|
||||
if sr and c = sr.delete(tok)
|
||||
outsrconf f, c
|
||||
end
|
||||
if rr and c = rr.delete(tok)
|
||||
outrrconf f, c
|
||||
end
|
||||
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
sr.each {|tok, c| outsrconf f, c } if sr
|
||||
rr.each {|tok, c| outrrconf f, c } if rr
|
||||
|
||||
act = state.defact
|
||||
if not Error === act or @debug
|
||||
outact f, '$default', act
|
||||
end
|
||||
|
||||
f.puts
|
||||
state.goto_table.each do |t, st|
|
||||
if t.nonterminal?
|
||||
f.printf " %-12s go to state %d\n", t.to_s, st.ident
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def outact( f, t, act )
|
||||
case act
|
||||
when Shift
|
||||
f.printf " %-12s shift, and go to state %d\n",
|
||||
t.to_s, act.goto_id
|
||||
when Reduce
|
||||
f.printf " %-12s reduce using rule %d (%s)\n",
|
||||
t.to_s, act.ruleid, act.rule.target.to_s
|
||||
when Accept
|
||||
f.printf " %-12s accept\n", t.to_s
|
||||
when Error
|
||||
f.printf " %-12s error\n", t.to_s
|
||||
else
|
||||
raise "Racc FATAL: wrong act for outact: act=#{act}(#{act.class})"
|
||||
end
|
||||
end
|
||||
|
||||
def outsrconf( f, confs )
|
||||
confs.each do |c|
|
||||
r = c.reduce
|
||||
f.printf " %-12s [reduce using rule %d (%s)]\n",
|
||||
c.shift.to_s, r.ident, r.target.to_s
|
||||
end
|
||||
end
|
||||
|
||||
def outrrconf( f, confs )
|
||||
confs.each do |c|
|
||||
r = c.low_prec
|
||||
f.printf " %-12s [reduce using rule %d (%s)]\n",
|
||||
c.token.to_s, r.ident, r.target.to_s
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Rules
|
||||
#
|
||||
|
||||
def output_rule( out )
|
||||
out.print "-------- Grammar --------\n\n"
|
||||
@ruletable.each_rule do |rl|
|
||||
if @debug or rl.ident != 0
|
||||
out.printf "rule %d %s: %s\n",
|
||||
rl.ident, rl.target.to_s, rl.symbols.join(' ')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Tokens
|
||||
#
|
||||
|
||||
def output_token( out )
|
||||
out.print "------- Symbols -------\n\n"
|
||||
|
||||
out.print "**Nonterminals, with rules where they appear\n\n"
|
||||
@symboltable.each_nonterm do |t|
|
||||
tmp = <<SRC
|
||||
%s (%d)
|
||||
on right: %s
|
||||
on left : %s
|
||||
SRC
|
||||
out.printf tmp, t.to_s, t.ident,
|
||||
locatestr(t.locate), locatestr(t.heads)
|
||||
end
|
||||
|
||||
out.print "\n**Terminals, with rules where they appear\n\n"
|
||||
@symboltable.each_terminal do |t|
|
||||
out.printf " %s (%d) %s\n",
|
||||
t.to_s, t.ident, locatestr(t.locate)
|
||||
end
|
||||
end
|
||||
|
||||
def locatestr( ptrs )
|
||||
list = ptrs.map {|ptr|
|
||||
i = ptr.rule.ident
|
||||
(i == 0) ? nil : i
|
||||
}
|
||||
list.compact!
|
||||
list.uniq!
|
||||
list.join(' ')
|
||||
end
|
||||
|
||||
end # class VerboseOutputter
|
||||
|
||||
end
|
||||
@ -0,0 +1,468 @@
|
||||
#
|
||||
# parser.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the same terms of ruby.
|
||||
#
|
||||
# As a special exception, when this code is copied by Racc
|
||||
# into a Racc output file, you may use that output file
|
||||
# without restriction.
|
||||
#
|
||||
# $Id: parser.rb,v 1.1 2003/10/12 06:10:49 aamine Exp $
|
||||
#
|
||||
|
||||
unless defined?(NotImplementedError)
|
||||
NotImplementedError = NotImplementError
|
||||
end
|
||||
|
||||
|
||||
module Racc
|
||||
class ParseError < StandardError; end
|
||||
end
|
||||
unless defined?(::ParseError)
|
||||
ParseError = Racc::ParseError
|
||||
end
|
||||
|
||||
|
||||
module Racc
|
||||
|
||||
unless defined?(Racc_No_Extentions)
|
||||
Racc_No_Extentions = false
|
||||
end
|
||||
|
||||
class Parser
|
||||
|
||||
Racc_Runtime_Version = '1.4.3'
|
||||
Racc_Runtime_Revision = '$Revision: 1.1 $'.split(/\s+/)[1]
|
||||
|
||||
Racc_Runtime_Core_Version_R = '1.4.3'
|
||||
Racc_Runtime_Core_Revision_R = '$Revision: 1.1 $'.split(/\s+/)[1]
|
||||
begin
|
||||
require 'racc/cparse'
|
||||
# Racc_Runtime_Core_Version_C = (defined in extention)
|
||||
Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split(/\s+/)[2]
|
||||
unless new.respond_to?(:_racc_do_parse_c, true)
|
||||
raise LoadError, 'old cparse.so'
|
||||
end
|
||||
if Racc_No_Extentions
|
||||
raise LoadError, 'selecting ruby version of racc runtime core'
|
||||
end
|
||||
|
||||
Racc_Main_Parsing_Routine = :_racc_do_parse_c
|
||||
Racc_YY_Parse_Method = :_racc_yyparse_c
|
||||
Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C
|
||||
Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C
|
||||
Racc_Runtime_Type = 'c'
|
||||
rescue LoadError
|
||||
Racc_Main_Parsing_Routine = :_racc_do_parse_rb
|
||||
Racc_YY_Parse_Method = :_racc_yyparse_rb
|
||||
Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R
|
||||
Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R
|
||||
Racc_Runtime_Type = 'ruby'
|
||||
end
|
||||
|
||||
def Parser.racc_runtime_type
|
||||
Racc_Runtime_Type
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _racc_setup
|
||||
@yydebug = false unless self.class::Racc_debug_parser
|
||||
@yydebug = false unless defined? @yydebug
|
||||
if @yydebug
|
||||
@racc_debug_out = $stderr unless defined? @racc_debug_out
|
||||
@racc_debug_out ||= $stderr
|
||||
end
|
||||
arg = self.class::Racc_arg
|
||||
arg[13] = true if arg.size < 14
|
||||
arg
|
||||
end
|
||||
|
||||
def _racc_init_sysvars
|
||||
@racc_state = [0]
|
||||
@racc_tstack = []
|
||||
@racc_vstack = []
|
||||
|
||||
@racc_t = nil
|
||||
@racc_val = nil
|
||||
|
||||
@racc_read_next = true
|
||||
|
||||
@racc_user_yyerror = false
|
||||
@racc_error_status = 0
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### do_parse
|
||||
###
|
||||
|
||||
def do_parse
|
||||
__send__ Racc_Main_Parsing_Routine, _racc_setup(), false
|
||||
end
|
||||
|
||||
def next_token
|
||||
raise NotImplementedError, "#{self.class}\#next_token is not defined"
|
||||
end
|
||||
|
||||
def _racc_do_parse_rb( arg, in_debug )
|
||||
action_table, action_check, action_default, action_pointer,
|
||||
goto_table, goto_check, goto_default, goto_pointer,
|
||||
nt_base, reduce_table, token_table, shift_n,
|
||||
reduce_n, use_result, * = arg
|
||||
|
||||
_racc_init_sysvars
|
||||
tok = act = i = nil
|
||||
nerr = 0
|
||||
|
||||
catch(:racc_end_parse) {
|
||||
while true
|
||||
if i = action_pointer[@racc_state[-1]]
|
||||
if @racc_read_next
|
||||
if @racc_t != 0 # not EOF
|
||||
tok, @racc_val = next_token()
|
||||
unless tok # EOF
|
||||
@racc_t = 0
|
||||
else
|
||||
@racc_t = (token_table[tok] or 1) # error token
|
||||
end
|
||||
racc_read_token(@racc_t, tok, @racc_val) if @yydebug
|
||||
@racc_read_next = false
|
||||
end
|
||||
end
|
||||
i += @racc_t
|
||||
if i >= 0 and
|
||||
act = action_table[i] and
|
||||
action_check[i] == @racc_state[-1]
|
||||
;
|
||||
else
|
||||
act = action_default[@racc_state[-1]]
|
||||
end
|
||||
else
|
||||
act = action_default[@racc_state[-1]]
|
||||
end
|
||||
while act = _racc_evalact(act, arg)
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
###
|
||||
### yyparse
|
||||
###
|
||||
|
||||
def yyparse( recv, mid )
|
||||
__send__ Racc_YY_Parse_Method, recv, mid, _racc_setup(), true
|
||||
end
|
||||
|
||||
def _racc_yyparse_rb( recv, mid, arg, c_debug )
|
||||
action_table, action_check, action_default, action_pointer,
|
||||
goto_table, goto_check, goto_default, goto_pointer,
|
||||
nt_base, reduce_table, token_table, shift_n,
|
||||
reduce_n, use_result, * = arg
|
||||
|
||||
_racc_init_sysvars
|
||||
tok = nil
|
||||
act = nil
|
||||
i = nil
|
||||
nerr = 0
|
||||
|
||||
|
||||
catch(:racc_end_parse) {
|
||||
until i = action_pointer[@racc_state[-1]]
|
||||
while act = _racc_evalact(action_default[@racc_state[-1]], arg)
|
||||
end
|
||||
end
|
||||
|
||||
recv.__send__(mid) do |tok, val|
|
||||
# $stderr.puts "rd: tok=#{tok}, val=#{val}"
|
||||
unless tok
|
||||
@racc_t = 0
|
||||
else
|
||||
@racc_t = (token_table[tok] or 1) # error token
|
||||
end
|
||||
@racc_val = val
|
||||
@racc_read_next = false
|
||||
|
||||
i += @racc_t
|
||||
if i >= 0 and
|
||||
act = action_table[i] and
|
||||
action_check[i] == @racc_state[-1]
|
||||
;
|
||||
# $stderr.puts "01: act=#{act}"
|
||||
else
|
||||
act = action_default[@racc_state[-1]]
|
||||
# $stderr.puts "02: act=#{act}"
|
||||
# $stderr.puts "curstate=#{@racc_state[-1]}"
|
||||
end
|
||||
|
||||
while act = _racc_evalact(act, arg)
|
||||
end
|
||||
|
||||
while not (i = action_pointer[@racc_state[-1]]) or
|
||||
not @racc_read_next or
|
||||
@racc_t == 0 # $
|
||||
if i and i += @racc_t and
|
||||
i >= 0 and
|
||||
act = action_table[i] and
|
||||
action_check[i] == @racc_state[-1]
|
||||
;
|
||||
# $stderr.puts "03: act=#{act}"
|
||||
else
|
||||
# $stderr.puts "04: act=#{act}"
|
||||
act = action_default[@racc_state[-1]]
|
||||
end
|
||||
|
||||
while act = _racc_evalact(act, arg)
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
###
|
||||
### common
|
||||
###
|
||||
|
||||
def _racc_evalact( act, arg )
|
||||
# $stderr.puts "ea: act=#{act}"
|
||||
action_table, action_check, action_default, action_pointer,
|
||||
goto_table, goto_check, goto_default, goto_pointer,
|
||||
nt_base, reduce_table, token_table, shift_n,
|
||||
reduce_n, use_result, * = arg
|
||||
nerr = 0 # tmp
|
||||
|
||||
if act > 0 and act < shift_n
|
||||
#
|
||||
# shift
|
||||
#
|
||||
|
||||
if @racc_error_status > 0
|
||||
@racc_error_status -= 1 unless @racc_t == 1 # error token
|
||||
end
|
||||
|
||||
@racc_vstack.push @racc_val
|
||||
@racc_state.push act
|
||||
@racc_read_next = true
|
||||
|
||||
if @yydebug
|
||||
@racc_tstack.push @racc_t
|
||||
racc_shift @racc_t, @racc_tstack, @racc_vstack
|
||||
end
|
||||
|
||||
elsif act < 0 and act > -reduce_n
|
||||
#
|
||||
# reduce
|
||||
#
|
||||
|
||||
code = catch(:racc_jump) {
|
||||
@racc_state.push _racc_do_reduce(arg, act)
|
||||
false
|
||||
}
|
||||
if code
|
||||
case code
|
||||
when 1 # yyerror
|
||||
@racc_user_yyerror = true # user_yyerror
|
||||
return -reduce_n
|
||||
when 2 # yyaccept
|
||||
return shift_n
|
||||
else
|
||||
raise RuntimeError, '[Racc Bug] unknown jump code'
|
||||
end
|
||||
end
|
||||
|
||||
elsif act == shift_n
|
||||
#
|
||||
# accept
|
||||
#
|
||||
|
||||
racc_accept if @yydebug
|
||||
throw :racc_end_parse, @racc_vstack[0]
|
||||
|
||||
elsif act == -reduce_n
|
||||
#
|
||||
# error
|
||||
#
|
||||
|
||||
case @racc_error_status
|
||||
when 0
|
||||
unless arg[21] # user_yyerror
|
||||
nerr += 1
|
||||
on_error @racc_t, @racc_val, @racc_vstack
|
||||
end
|
||||
when 3
|
||||
if @racc_t == 0 # is $
|
||||
throw :racc_end_parse, nil
|
||||
end
|
||||
@racc_read_next = true
|
||||
end
|
||||
@racc_user_yyerror = false
|
||||
@racc_error_status = 3
|
||||
|
||||
while true
|
||||
if i = action_pointer[@racc_state[-1]]
|
||||
i += 1 # error token
|
||||
if i >= 0 and
|
||||
(act = action_table[i]) and
|
||||
action_check[i] == @racc_state[-1]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
throw :racc_end_parse, nil if @racc_state.size < 2
|
||||
@racc_state.pop
|
||||
@racc_vstack.pop
|
||||
if @yydebug
|
||||
@racc_tstack.pop
|
||||
racc_e_pop @racc_state, @racc_tstack, @racc_vstack
|
||||
end
|
||||
end
|
||||
|
||||
return act
|
||||
|
||||
else
|
||||
raise RuntimeError, "[Racc Bug] unknown action #{act.inspect}"
|
||||
end
|
||||
|
||||
racc_next_state(@racc_state[-1], @racc_state) if @yydebug
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def _racc_do_reduce( arg, act )
|
||||
action_table, action_check, action_default, action_pointer,
|
||||
goto_table, goto_check, goto_default, goto_pointer,
|
||||
nt_base, reduce_table, token_table, shift_n,
|
||||
reduce_n, use_result, * = arg
|
||||
state = @racc_state
|
||||
vstack = @racc_vstack
|
||||
tstack = @racc_tstack
|
||||
|
||||
i = act * -3
|
||||
len = reduce_table[i]
|
||||
reduce_to = reduce_table[i+1]
|
||||
method_id = reduce_table[i+2]
|
||||
void_array = []
|
||||
|
||||
tmp_t = tstack[-len, len] if @yydebug
|
||||
tmp_v = vstack[-len, len]
|
||||
tstack[-len, len] = void_array if @yydebug
|
||||
vstack[-len, len] = void_array
|
||||
state[-len, len] = void_array
|
||||
|
||||
# tstack must be updated AFTER method call
|
||||
if use_result
|
||||
vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0])
|
||||
else
|
||||
vstack.push __send__(method_id, tmp_v, vstack)
|
||||
end
|
||||
tstack.push reduce_to
|
||||
|
||||
racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug
|
||||
|
||||
k1 = reduce_to - nt_base
|
||||
if i = goto_pointer[k1]
|
||||
i += state[-1]
|
||||
if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1
|
||||
return curstate
|
||||
end
|
||||
end
|
||||
goto_default[k1]
|
||||
end
|
||||
|
||||
def on_error( t, val, vstack )
|
||||
raise ParseError, sprintf("\nparse error on value %s (%s)",
|
||||
val.inspect, token_to_str(t) || '?')
|
||||
end
|
||||
|
||||
def yyerror
|
||||
throw :racc_jump, 1
|
||||
end
|
||||
|
||||
def yyaccept
|
||||
throw :racc_jump, 2
|
||||
end
|
||||
|
||||
def yyerrok
|
||||
@racc_error_status = 0
|
||||
end
|
||||
|
||||
|
||||
# for debugging output
|
||||
|
||||
def racc_read_token( t, tok, val )
|
||||
@racc_debug_out.print 'read '
|
||||
@racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') '
|
||||
@racc_debug_out.puts val.inspect
|
||||
@racc_debug_out.puts
|
||||
end
|
||||
|
||||
def racc_shift( tok, tstack, vstack )
|
||||
@racc_debug_out.puts "shift #{racc_token2str tok}"
|
||||
racc_print_stacks tstack, vstack
|
||||
@racc_debug_out.puts
|
||||
end
|
||||
|
||||
def racc_reduce( toks, sim, tstack, vstack )
|
||||
out = @racc_debug_out
|
||||
out.print 'reduce '
|
||||
if toks.empty?
|
||||
out.print ' <none>'
|
||||
else
|
||||
toks.each {|t| out.print ' ', racc_token2str(t) }
|
||||
end
|
||||
out.puts " --> #{racc_token2str(sim)}"
|
||||
|
||||
racc_print_stacks tstack, vstack
|
||||
@racc_debug_out.puts
|
||||
end
|
||||
|
||||
def racc_accept
|
||||
@racc_debug_out.puts 'accept'
|
||||
@racc_debug_out.puts
|
||||
end
|
||||
|
||||
def racc_e_pop( state, tstack, vstack )
|
||||
@racc_debug_out.puts 'error recovering mode: pop token'
|
||||
racc_print_states state
|
||||
racc_print_stacks tstack, vstack
|
||||
@racc_debug_out.puts
|
||||
end
|
||||
|
||||
def racc_next_state( curstate, state )
|
||||
@racc_debug_out.puts "goto #{curstate}"
|
||||
racc_print_states state
|
||||
@racc_debug_out.puts
|
||||
end
|
||||
|
||||
def racc_print_stacks( t, v )
|
||||
out = @racc_debug_out
|
||||
out.print ' ['
|
||||
t.each_index do |i|
|
||||
out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')'
|
||||
end
|
||||
out.puts ' ]'
|
||||
end
|
||||
|
||||
def racc_print_states( s )
|
||||
out = @racc_debug_out
|
||||
out.print ' ['
|
||||
s.each {|st| out.print ' ', st }
|
||||
out.puts ' ]'
|
||||
end
|
||||
|
||||
def racc_token2str( tok )
|
||||
self.class::Racc_token_to_s_table[tok] or
|
||||
raise RuntimeError, "[Racc Bug] can't convert token #{tok} to string"
|
||||
end
|
||||
|
||||
def token_to_str( t )
|
||||
self.class::Racc_token_to_s_table[t]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@ -0,0 +1,631 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# racc
|
||||
#
|
||||
# Copyright (c) 1999-2002 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU Lesser General Public License version 2 or later.
|
||||
#
|
||||
|
||||
|
||||
##### main -----------------------------------------------------
|
||||
|
||||
def racc_main
|
||||
opt = get_options()
|
||||
require opt['-R'] || 'racc/compiler'
|
||||
srcfn = ARGV[0]
|
||||
|
||||
racc = Racc::Compiler.new
|
||||
begin
|
||||
racc_main0 racc, srcfn, opt
|
||||
rescue Racc::ParseError, Racc::ScanError, Racc::RaccError, Errno::ENOENT
|
||||
raise if racc.debug
|
||||
msg = $!.to_s
|
||||
unless /\A\d/ === msg
|
||||
msg[0,0] = ' '
|
||||
end
|
||||
$stderr.puts "#{File.basename $0}:#{srcfn}:" + msg
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def racc_main0( racc, srcfn, opt )
|
||||
srcstr = nil
|
||||
File.open(srcfn, 'r') {|f| srcstr = f.read }
|
||||
|
||||
set_flags__before_parse racc, opt
|
||||
if opt['-P']
|
||||
prof = pcompile(racc, srcstr, srcfn) {
|
||||
set_flags__after_parse racc, opt
|
||||
}
|
||||
else
|
||||
racc.parse srcstr, srcfn
|
||||
if opt['--check-only']
|
||||
$stderr.puts 'syntax ok'
|
||||
exit 0
|
||||
end
|
||||
set_flags__after_parse racc, opt
|
||||
racc.compile
|
||||
end
|
||||
|
||||
write_table_file racc, srcfn, opt
|
||||
|
||||
if prof
|
||||
report_profile prof
|
||||
end
|
||||
|
||||
if opt['--verbose']
|
||||
output_fn = opt['--log-file'] ||
|
||||
make_filename(opt['--output'] || srcfn, '.output')
|
||||
File.open(output_fn, 'w') {|f|
|
||||
racc.output f
|
||||
}
|
||||
end
|
||||
|
||||
report_conflict racc, opt
|
||||
report_useless racc, opt
|
||||
end
|
||||
|
||||
|
||||
|
||||
##### parse arg ------------------------------------------------
|
||||
|
||||
require 'getoptlong'
|
||||
require 'racc/info'
|
||||
|
||||
|
||||
Racc_Options = <<S
|
||||
|
||||
o -g --debug - output parser for user level debugging
|
||||
o -o --output-file <outfile> file name of output [<fname>.tab.rb]
|
||||
o -e --executable <rubypath> insert #! line in output ('ruby' to default)
|
||||
o -E --embedded - output file which don't need runtime
|
||||
o -l --no-line-convert - never convert line numbers (for ruby<=1.4.3)
|
||||
o -c --line-convert-all - convert line numbers also header and footer
|
||||
x -s --super <super> use <super> instead of Racc::Parser
|
||||
x -r --runtime <file> use <file> instead of 'racc/parser'
|
||||
o -a --no-omit-actions - never omit actions
|
||||
|
||||
o -v --verbose - create <filename>.output file
|
||||
o -O --log-file <fname> file name of verbose output [<fname>.output]
|
||||
|
||||
o -C --check-only - syntax check only
|
||||
o -S --output-status - output status time to time
|
||||
o - --no-extentions - run without any ruby extentions
|
||||
o -h --help - print this message and quit
|
||||
o - --version - print version and quit
|
||||
o - --runtime-version - print runtime version and quit
|
||||
o - --copyright - print copyright and quit
|
||||
|
||||
x -P - - report profile
|
||||
x -R - <req> require <req> instead of 'racc/libracc'
|
||||
x -D - <flags> set (racc's) debug flags
|
||||
S
|
||||
|
||||
module Racc
|
||||
end
|
||||
|
||||
def get_options
|
||||
tmp = Racc_Options.collect {|line|
|
||||
next if /\A\s*\z/ === line
|
||||
disp, sopt, lopt, takearg, doc = line.strip.split(/\s+/, 5)
|
||||
a = []
|
||||
a.push lopt unless lopt == '-'
|
||||
a.push sopt unless sopt == '-'
|
||||
a.push takearg == '-' ?
|
||||
GetoptLong::NO_ARGUMENT : GetoptLong::REQUIRED_ARGUMENT
|
||||
a
|
||||
}
|
||||
getopt = GetoptLong.new(*tmp.compact)
|
||||
getopt.quiet = true
|
||||
|
||||
opt = {}
|
||||
begin
|
||||
getopt.each do |name, arg|
|
||||
raise GetoptLong::InvalidOption,
|
||||
"#{File.basename $0}: #{name} given twice" if opt.key? name
|
||||
opt[name] = arg.empty? ? true : arg
|
||||
end
|
||||
rescue GetoptLong::AmbigousOption, GetoptLong::InvalidOption,
|
||||
GetoptLong::MissingArgument, GetoptLong::NeedlessArgument
|
||||
usage 1, $!.message
|
||||
end
|
||||
|
||||
usage 0 if opt['--help']
|
||||
|
||||
if opt['--version']
|
||||
puts "racc version #{Racc::Version}"
|
||||
exit 0
|
||||
end
|
||||
Racc.const_set :Racc_No_Extentions, opt['--no-extentions']
|
||||
if opt['--runtime-version']
|
||||
require 'racc/parser'
|
||||
printf "racc runtime version %s (rev. %s); %s\n",
|
||||
Racc::Parser::Racc_Runtime_Version,
|
||||
Racc::Parser::Racc_Runtime_Revision,
|
||||
if Racc::Parser.racc_runtime_type == 'ruby'
|
||||
sprintf('ruby core version %s (rev. %s)',
|
||||
Racc::Parser::Racc_Runtime_Core_Version_R,
|
||||
Racc::Parser::Racc_Runtime_Core_Revision_R)
|
||||
else
|
||||
sprintf('c core version %s (rev. %s)',
|
||||
Racc::Parser::Racc_Runtime_Core_Version_C,
|
||||
Racc::Parser::Racc_Runtime_Core_Revision_C)
|
||||
end
|
||||
exit 0
|
||||
end
|
||||
if opt['--copyright']
|
||||
puts "racc version #{Racc::Version}"
|
||||
puts "#{Racc::Copyright} <aamine@loveruby.net>"
|
||||
exit 0
|
||||
end
|
||||
|
||||
usage(1, 'no grammar file given') if ARGV.empty?
|
||||
usage(1, 'too many grammar files given') if ARGV.size > 1
|
||||
|
||||
opt['--line-convert'] = true
|
||||
if opt['--no-line-convert']
|
||||
opt['--line-convert'] = opt['--line-convert-all'] = false
|
||||
end
|
||||
|
||||
opt['--omit-action'] = true
|
||||
if opt['--no-omit-action']
|
||||
opt['--omit-action'] = false
|
||||
end
|
||||
|
||||
opt
|
||||
end
|
||||
|
||||
|
||||
def usage( status, msg = nil )
|
||||
f = (status == 0 ? $stdout : $stderr)
|
||||
f.puts "#{File.basename $0}: #{msg}" if msg
|
||||
f.print(<<EOS)
|
||||
|
||||
Usage: racc [options] <grammar file>
|
||||
|
||||
Options:
|
||||
EOS
|
||||
|
||||
Racc_Options.each do |line|
|
||||
if /\A\s*\z/ === line
|
||||
f.puts
|
||||
next
|
||||
end
|
||||
|
||||
disp, sopt, lopt, takearg, doc = line.strip.split(/\s+/, 5)
|
||||
if disp == 'o'
|
||||
sopt = nil if sopt == '-'
|
||||
lopt = nil if lopt == '-'
|
||||
opt = [sopt, lopt].compact.join(',')
|
||||
|
||||
takearg = nil if takearg == '-'
|
||||
opt = [opt, takearg].compact.join(' ')
|
||||
|
||||
f.printf "%-27s %s\n", opt, doc
|
||||
end
|
||||
end
|
||||
|
||||
exit status
|
||||
end
|
||||
|
||||
|
||||
|
||||
##### compile ----------------------------------------------
|
||||
|
||||
def set_flags__before_parse( racc, opt )
|
||||
racc.verbose = opt['--output-status']
|
||||
|
||||
if opt['-D'] and /p/ === opt['-D']
|
||||
racc.d_parse = true
|
||||
end
|
||||
end
|
||||
|
||||
def set_flags__after_parse( racc, opt )
|
||||
# overwrite source's
|
||||
racc.debug_parser = opt['--debug']
|
||||
racc.convert_line = opt['--line-convert']
|
||||
racc.omit_action = opt['--omit-action']
|
||||
|
||||
if opt['-D'] or $DEBUG
|
||||
optd = opt['-D'] || ''
|
||||
$stdout.sync = true
|
||||
racc.debug = true
|
||||
racc.d_rule = true if /r/ === optd
|
||||
racc.d_token = true if /t/ === optd
|
||||
racc.d_state = true if /s/ === optd
|
||||
racc.d_la = true if /l/ === optd
|
||||
racc.d_prec = true if /c/ === optd
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##### profile
|
||||
|
||||
def pcompile( racc, srcstr, srcfn )
|
||||
times = []
|
||||
times.push [ 'parse', get_lap{ racc.parse(srcstr, srcfn) } ]
|
||||
yield
|
||||
times.push [ 'state', get_lap{ racc.nfa } ]
|
||||
times.push [ 'resolve', get_lap{ racc.dfa } ]
|
||||
times
|
||||
end
|
||||
|
||||
def get_lap
|
||||
begt = Time.times.utime
|
||||
yield
|
||||
endt = Time.times.utime
|
||||
endt - begt
|
||||
end
|
||||
|
||||
def report_profile( prof )
|
||||
out = $stderr
|
||||
|
||||
whole = 0
|
||||
prof.each do |arr|
|
||||
whole += arr[1]
|
||||
end
|
||||
whole = 0.01 if whole == 0
|
||||
|
||||
out.puts '--task-----------+--sec------+---%-'
|
||||
|
||||
prof.each do |arr|
|
||||
name, time = arr
|
||||
out.printf("%-19s %s %3d%%\n",
|
||||
name, pjust(time,4,4), (time/whole * 100).to_i)
|
||||
end
|
||||
|
||||
out.puts '-----------------+-----------+-----'
|
||||
out.printf("%-20s%s\n",
|
||||
'total', pjust(whole,4,4))
|
||||
end
|
||||
|
||||
def pjust( num, i, j )
|
||||
m = /(\d+)(\.\d+)?/.match(num.to_s)
|
||||
str = m[1].rjust(i)
|
||||
if m[2]
|
||||
str << m[2].ljust(j+1)[0,j+1]
|
||||
end
|
||||
|
||||
str
|
||||
end
|
||||
|
||||
|
||||
|
||||
##### output -----------------------------------------------
|
||||
|
||||
require 'racc/rubyloader'
|
||||
|
||||
|
||||
def write_table_file( racc, srcfn, opt )
|
||||
tabfn = opt['--output-file'] || make_filename(srcfn, '.tab.rb')
|
||||
|
||||
RaccTableFile.new(tabfn, srcfn, opt['--line-convert']) {|f|
|
||||
f.shebang opt['--executable'] if opt['--executable']
|
||||
f.notice
|
||||
f.require opt['--embedded'], opt['--runtime'] || 'racc/parser'
|
||||
f.header opt['--line-convert-all']
|
||||
f.parser_class(racc.parser.class_name,
|
||||
opt['--super'] || racc.parser.super_class || 'Racc::Parser') {
|
||||
f.inner
|
||||
racc.source f.file
|
||||
}
|
||||
f.footer opt['--line-convert-all']
|
||||
}
|
||||
|
||||
if opt['--executable']
|
||||
File.chmod 0755, tabfn
|
||||
else
|
||||
File.chmod 0644, tabfn
|
||||
end
|
||||
end
|
||||
|
||||
def make_filename( fname, suffix )
|
||||
fname.sub(/(?:\..*?)?\z/, suffix)
|
||||
end
|
||||
|
||||
|
||||
class RaccTableFile
|
||||
|
||||
def initialize( tabfn, srcfn, c )
|
||||
@tabfn = tabfn
|
||||
@srcfn = srcfn
|
||||
@convline = c
|
||||
|
||||
@header_labels = %w( header prepare )
|
||||
@inner_labels = %w( inner )
|
||||
@footer_labels = %w( footer driver )
|
||||
|
||||
@is_top = false
|
||||
@uniq = {}
|
||||
|
||||
init_user_code
|
||||
|
||||
File.open(tabfn, 'w') {|f|
|
||||
@f = f
|
||||
yield self
|
||||
}
|
||||
end
|
||||
|
||||
def file
|
||||
@f
|
||||
end
|
||||
|
||||
|
||||
RUBY_PATH = ::Config::CONFIG['bindir'] + '/' +
|
||||
::Config::CONFIG['ruby_install_name']
|
||||
|
||||
def shebang( path )
|
||||
@f.print "#!#{path == 'ruby' ? RUBY_PATH : path}\n"
|
||||
end
|
||||
|
||||
|
||||
def notice
|
||||
@f.print <<EOS
|
||||
#
|
||||
# DO NOT MODIFY!!!!
|
||||
# This file is automatically generated by racc #{Racc::Version}
|
||||
# from racc grammer file "#{@srcfn}".
|
||||
#
|
||||
EOS
|
||||
end
|
||||
|
||||
|
||||
def require( embed_p, parser_rb )
|
||||
if embed_p
|
||||
@f.print <<EOS
|
||||
#
|
||||
# #{@tabfn}: generated by racc (runtime embedded)
|
||||
#
|
||||
|
||||
EOS
|
||||
is_top {
|
||||
embed 'racc/parser.rb'
|
||||
}
|
||||
@f.puts
|
||||
else
|
||||
@f.puts
|
||||
@f.puts "require '#{parser_rb}'"
|
||||
@f.puts
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def parser_class( classname, superclass )
|
||||
@f.puts
|
||||
|
||||
mods = classname.split('::')
|
||||
real = mods.pop
|
||||
mods.each_with_index do |m,i|
|
||||
@f.puts "#{' ' * i}module #{m}"
|
||||
@f.puts
|
||||
end
|
||||
@f.puts "#{' ' * mods.size}class #{real} < #{superclass}"
|
||||
|
||||
yield
|
||||
|
||||
@f.puts "#{' ' * mods.size}end \# class #{real}"
|
||||
mods.reverse.each_with_index do |m,i|
|
||||
@f.puts
|
||||
@f.puts "#{' ' * (mods.size - i - 1)}end \# module #{m}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def header( conv )
|
||||
is_top {
|
||||
add_part conv, @header_labels
|
||||
}
|
||||
end
|
||||
|
||||
def inner
|
||||
add_part @convline, @inner_labels
|
||||
end
|
||||
|
||||
def footer( conv )
|
||||
is_top {
|
||||
add_part conv, @footer_labels
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
###
|
||||
### init
|
||||
###
|
||||
|
||||
def init_user_code
|
||||
@usercode = Racc::GrammarFileParser.get_usercode(@srcfn)
|
||||
check_dup_ucode
|
||||
end
|
||||
|
||||
def check_dup_ucode
|
||||
[ @header_labels, @inner_labels, @footer_labels ].each do |names|
|
||||
a = names.select {|n| @usercode[n] }
|
||||
if a.size > 1
|
||||
raise Racc::RaccError,
|
||||
"'#{a.join %<' and '>}' used at same time; must be only one"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### embed
|
||||
###
|
||||
|
||||
def embed( rbfile )
|
||||
@f.print <<EOS
|
||||
###### #{rbfile}
|
||||
|
||||
unless $".index '#{rbfile}'
|
||||
$".push '#{rbfile}'
|
||||
EOS
|
||||
add_file RubyLoader.find_feature(rbfile)
|
||||
@f.puts "end # end of #{rbfile}"
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### part
|
||||
###
|
||||
|
||||
def add_part( convp, names )
|
||||
str, lineno, fnames = getent(names)
|
||||
convert_line(convp) {
|
||||
add str, @srcfn, lineno if str and not str.strip.empty?
|
||||
}
|
||||
fnames.each {|n| add_file n } if fnames
|
||||
end
|
||||
|
||||
def getent( names )
|
||||
names.each do |n|
|
||||
return @usercode[n] if @usercode[n]
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def convert_line( b )
|
||||
save, @convline = @convline, b
|
||||
yield
|
||||
@convline = save
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
### low level code
|
||||
###
|
||||
|
||||
def add_file( fname )
|
||||
File.open(fname) {|f|
|
||||
add f.read, fname, 1
|
||||
}
|
||||
end
|
||||
|
||||
def add( str, fn, lineno )
|
||||
@f.puts
|
||||
if @convline
|
||||
surrounding_by_eval(fn, str, lineno) {
|
||||
@f.puts str
|
||||
}
|
||||
else
|
||||
@f.puts str
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def surrounding_by_eval( nm, str, lineno )
|
||||
sep = makesep(nm, str)
|
||||
@f.print 'self.class.' if toplevel?
|
||||
@f.puts "module_eval <<'#{sep}', '#{nm}', #{lineno}"
|
||||
yield
|
||||
@f.puts sep
|
||||
end
|
||||
|
||||
def is_top
|
||||
@is_top = true
|
||||
yield
|
||||
@is_top = false
|
||||
end
|
||||
|
||||
def toplevel?
|
||||
@is_top
|
||||
end
|
||||
|
||||
def makesep( nm, str )
|
||||
sep = uniqlabel(nm)
|
||||
sep *= 2 while str.index(sep)
|
||||
sep
|
||||
end
|
||||
|
||||
def uniqlabel( nm )
|
||||
ret = "..end #{nm} modeval..id"
|
||||
srand
|
||||
5.times do
|
||||
ret << sprintf('%02x', rand(255))
|
||||
end
|
||||
ret << sprintf('%02x', rand(255)) while @uniq[ret]
|
||||
@uniq[ret] = true
|
||||
ret
|
||||
end
|
||||
|
||||
end # class RaccTableFile
|
||||
|
||||
|
||||
|
||||
##### report -----------------------------------------------
|
||||
|
||||
def report_conflict( racc, opt )
|
||||
sr = 0
|
||||
rr = 0
|
||||
racc.statetable.each do |st|
|
||||
sr += st.srconf.size if st.srconf
|
||||
rr += st.rrconf.size if st.rrconf
|
||||
end
|
||||
|
||||
if opt['-D'] and /o/ === opt['-D']
|
||||
debugout {|f|
|
||||
f.print "ex#{racc.ruletable.expect}\n"
|
||||
f.print "sr#{sr}\n" if sr > 0
|
||||
f.print "rr#{rr}\n" if rr > 0
|
||||
}
|
||||
return
|
||||
end
|
||||
|
||||
ex = racc.ruletable.expect
|
||||
if (sr > 0 or ex) and sr != ex
|
||||
$stderr.puts "#{sr} shift/reduce conflicts"
|
||||
end
|
||||
if rr > 0
|
||||
$stderr.puts "#{rr} reduce/reduce conflicts"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def report_useless( racc, opt )
|
||||
nt = 0
|
||||
rl = 0
|
||||
racc.symboltable.each_nonterm do |t|
|
||||
if t.useless?
|
||||
nt += 1
|
||||
end
|
||||
end
|
||||
racc.ruletable.each do |r|
|
||||
if r.useless?
|
||||
rl += 1
|
||||
end
|
||||
end
|
||||
|
||||
if opt['-D'] and /o/ === opt['-D']
|
||||
debugout('a') {|f|
|
||||
f.print "un#{nt}\n" if nt > 0
|
||||
f.print "ur#{rl}\n" if rl > 0
|
||||
}
|
||||
return
|
||||
end
|
||||
|
||||
if nt > 0 or rl > 0
|
||||
$stderr.printf "%s%s%s\n",
|
||||
nt > 0 ? "#{nt} useless nonterminals" : '',
|
||||
((nt > 0) && (rl > 0)) ? ' and ' : '',
|
||||
rl > 0 ? "#{rl} useless rules" : ''
|
||||
end
|
||||
|
||||
if racc.ruletable.start.useless?
|
||||
$stderr.puts 'fatal: start symbol does not derive any sentence'
|
||||
end
|
||||
end
|
||||
|
||||
def debugout( flag = 'w', &block )
|
||||
File.open("log/#{File.basename(ARGV[0])}", flag, &block)
|
||||
end
|
||||
|
||||
|
||||
##### entry point ------------------------------------------
|
||||
|
||||
racc_main
|
||||
@ -0,0 +1,55 @@
|
||||
#
|
||||
# rubyloader.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
# $ amstd Id: rubyloader.rb,v 1.5 2003/05/26 14:14:57 aamine Exp $
|
||||
#
|
||||
|
||||
require 'rbconfig'
|
||||
|
||||
|
||||
module RubyLoader
|
||||
|
||||
module_function
|
||||
|
||||
def find_feature( feature )
|
||||
with_ext(feature) do |fname|
|
||||
$LOAD_PATH.each do |dir|
|
||||
path = dir + '/' + fname
|
||||
return path if File.file? path
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def provided?( feature )
|
||||
with_ext(feature) do |filename|
|
||||
return true if $".index(filename)
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
alias required? provided?
|
||||
|
||||
def provide( feature )
|
||||
$".push feature
|
||||
end
|
||||
|
||||
def with_ext( feature )
|
||||
if /\.(?:rb|#{Config::CONFIG['DLEXT']})\z/o === feature
|
||||
yield feature
|
||||
else
|
||||
[ 'rb', Config::CONFIG['DLEXT'] ].each do |ext|
|
||||
yield feature + '.' + ext
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@ -0,0 +1,985 @@
|
||||
#
|
||||
# state.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
require 'racc/iset'
|
||||
|
||||
|
||||
module Racc
|
||||
|
||||
class RaccError < StandardError; end
|
||||
|
||||
#
|
||||
# StateTable
|
||||
#
|
||||
# the table of lalr states.
|
||||
#
|
||||
|
||||
class StateTable
|
||||
|
||||
def initialize( racc )
|
||||
@ruletable = racc.ruletable
|
||||
@symboltable = racc.symboltable
|
||||
|
||||
@d_state = racc.d_state
|
||||
@d_la = racc.d_la
|
||||
@d_prec = racc.d_prec
|
||||
|
||||
@states = []
|
||||
@statecache = {}
|
||||
|
||||
@actions = ActionTable.new(@ruletable, self)
|
||||
end
|
||||
|
||||
attr_reader :actions
|
||||
|
||||
def size
|
||||
@states.size
|
||||
end
|
||||
|
||||
def inspect
|
||||
'#<state table>'
|
||||
end
|
||||
|
||||
alias to_s inspect
|
||||
|
||||
def []( i )
|
||||
@states[i]
|
||||
end
|
||||
|
||||
def each_state( &block )
|
||||
@states.each(&block)
|
||||
end
|
||||
|
||||
alias each each_state
|
||||
|
||||
def each_index( &block )
|
||||
@states.each_index(&block)
|
||||
end
|
||||
|
||||
###
|
||||
### nfa
|
||||
###
|
||||
|
||||
def init
|
||||
# add state 0
|
||||
core_to_state [ @ruletable[0].ptrs[0] ]
|
||||
|
||||
cur = 0
|
||||
@gotos = []
|
||||
while cur < @states.size
|
||||
generate_states @states[cur] # state is added here
|
||||
cur += 1
|
||||
end
|
||||
|
||||
@actions.init
|
||||
end
|
||||
|
||||
def generate_states( state )
|
||||
puts "dstate: #{state}" if @d_state
|
||||
|
||||
table = {}
|
||||
ptr = pt = s = g = nil
|
||||
|
||||
state.closure.each do |ptr|
|
||||
if sym = ptr.dereference
|
||||
addsym table, sym, ptr.next
|
||||
end
|
||||
end
|
||||
|
||||
table.each do |sym, core|
|
||||
puts "dstate: sym=#{sym} ncore=#{core}" if @d_state
|
||||
|
||||
dest = core_to_state(core.to_a)
|
||||
state.goto_table[sym] = dest
|
||||
id = sym.nonterminal?() ? @gotos.size : nil
|
||||
g = Goto.new(id, sym, state, dest)
|
||||
@gotos.push g if sym.nonterminal?
|
||||
state.gotos[sym] = g
|
||||
puts "dstate: #{state.ident} --#{sym}--> #{dest.ident}" if @d_state
|
||||
|
||||
# check infinite recursion
|
||||
if state.ident == dest.ident and state.closure.size == 1
|
||||
raise RaccError, sprintf("Infinite recursion: state %d, with rule %d",
|
||||
state.ident, state.ptrs[0].rule.ident)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def addsym( table, sym, ptr )
|
||||
unless s = table[sym]
|
||||
table[sym] = s = ISet.new
|
||||
end
|
||||
s.add ptr
|
||||
end
|
||||
|
||||
def core_to_state( core )
|
||||
#
|
||||
# convert CORE to a State object.
|
||||
# If matching state does not exist, create it and add to the table.
|
||||
#
|
||||
|
||||
k = fingerprint(core)
|
||||
unless dest = @statecache[k]
|
||||
# not registered yet
|
||||
dest = State.new(@states.size, core)
|
||||
@states.push dest
|
||||
|
||||
@statecache[k] = dest
|
||||
|
||||
puts "core_to_state: create state ID #{dest.ident}" if @d_state
|
||||
else
|
||||
if @d_state
|
||||
puts "core_to_state: dest is cached ID #{dest.ident}"
|
||||
puts "core_to_state: dest core #{dest.core.join(' ')}"
|
||||
end
|
||||
end
|
||||
|
||||
dest
|
||||
end
|
||||
|
||||
def fingerprint( arr )
|
||||
arr.map {|i| i.ident }.pack('L*')
|
||||
end
|
||||
|
||||
###
|
||||
### dfa
|
||||
###
|
||||
|
||||
def determine
|
||||
la = lookahead
|
||||
@states.each do |state|
|
||||
state.set_la la
|
||||
resolve state
|
||||
end
|
||||
|
||||
set_accept
|
||||
@states.each do |state|
|
||||
pack state
|
||||
end
|
||||
check_useless
|
||||
end
|
||||
|
||||
#
|
||||
# lookahead
|
||||
#
|
||||
|
||||
def lookahead
|
||||
#
|
||||
# lookahead algorithm ver.3 -- from bison 1.26
|
||||
#
|
||||
state = goto = arr = ptr = st = rl = i = a = t = g = nil
|
||||
|
||||
gotos = @gotos
|
||||
if @d_la
|
||||
puts "\n--- goto ---"
|
||||
gotos.each_with_index {|g,i| print i, ' '; p g }
|
||||
end
|
||||
|
||||
### initialize_LA()
|
||||
### set_goto_map()
|
||||
la_rules = []
|
||||
@states.each do |state|
|
||||
state.check_la la_rules
|
||||
end
|
||||
|
||||
|
||||
### initialize_F()
|
||||
f = create_tmap(gotos.size)
|
||||
reads = []
|
||||
edge = []
|
||||
gotos.each do |goto|
|
||||
goto.to_state.goto_table.each do |t, st|
|
||||
if t.terminal?
|
||||
f[goto.ident] |= (1 << t.ident)
|
||||
elsif t.nullable?
|
||||
edge.push goto.to_state.gotos[t].ident
|
||||
end
|
||||
end
|
||||
if edge.empty?
|
||||
reads.push nil
|
||||
else
|
||||
reads.push edge
|
||||
edge = []
|
||||
end
|
||||
end
|
||||
digraph f, reads
|
||||
if @d_la
|
||||
puts "\n--- F1 (reads) ---"
|
||||
print_tab gotos, reads, f
|
||||
end
|
||||
|
||||
|
||||
### build_relations()
|
||||
### compute_FOLLOWS
|
||||
path = nil
|
||||
edge = []
|
||||
lookback = Array.new(la_rules.size, nil)
|
||||
includes = []
|
||||
gotos.each do |goto|
|
||||
goto.symbol.heads.each do |ptr|
|
||||
path = record_path(goto.from_state, ptr.rule)
|
||||
g = path[-1]
|
||||
st = g ? g.to_state : goto.from_state
|
||||
if st.conflict?
|
||||
addrel lookback, st.rruleid(ptr.rule), goto
|
||||
end
|
||||
path.reverse_each do |g|
|
||||
break if g.symbol.terminal?
|
||||
edge.push g.ident
|
||||
break unless g.symbol.nullable?
|
||||
end
|
||||
end
|
||||
if edge.empty?
|
||||
includes.push nil
|
||||
else
|
||||
includes.push edge
|
||||
edge = []
|
||||
end
|
||||
end
|
||||
includes = transpose(includes)
|
||||
digraph f, includes
|
||||
if @d_la
|
||||
puts "\n--- F2 (includes) ---"
|
||||
print_tab gotos, includes, f
|
||||
end
|
||||
|
||||
|
||||
### compute_lookaheads
|
||||
la = create_tmap(la_rules.size)
|
||||
lookback.each_with_index do |arr, i|
|
||||
if arr
|
||||
arr.each do |g|
|
||||
la[i] |= f[g.ident]
|
||||
end
|
||||
end
|
||||
end
|
||||
if @d_la
|
||||
puts "\n--- LA (lookback) ---"
|
||||
print_tab la_rules, lookback, la
|
||||
end
|
||||
|
||||
la
|
||||
end
|
||||
|
||||
def create_tmap( size )
|
||||
Array.new(size, 0) # use Integer as bitmap
|
||||
end
|
||||
|
||||
def addrel( tbl, i, item )
|
||||
if a = tbl[i]
|
||||
a.push item
|
||||
else
|
||||
tbl[i] = [item]
|
||||
end
|
||||
end
|
||||
|
||||
def record_path( begst, rule )
|
||||
st = begst
|
||||
path = []
|
||||
rule.symbols.each do |t|
|
||||
goto = st.gotos[t]
|
||||
path.push goto
|
||||
st = goto.to_state
|
||||
end
|
||||
path
|
||||
end
|
||||
|
||||
def transpose( rel )
|
||||
new = Array.new(rel.size, nil)
|
||||
rel.each_with_index do |arr, idx|
|
||||
if arr
|
||||
arr.each do |i|
|
||||
addrel new, i, idx
|
||||
end
|
||||
end
|
||||
end
|
||||
new
|
||||
end
|
||||
|
||||
def digraph( map, relation )
|
||||
n = relation.size
|
||||
index = Array.new(n, nil)
|
||||
vertices = []
|
||||
@infinity = n + 2
|
||||
|
||||
i = nil
|
||||
index.each_index do |i|
|
||||
if not index[i] and relation[i]
|
||||
traverse i, index, vertices, map, relation
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def traverse( i, index, vertices, map, relation )
|
||||
vertices.push i
|
||||
index[i] = height = vertices.size
|
||||
|
||||
proci = nil
|
||||
if rp = relation[i]
|
||||
rp.each do |proci|
|
||||
unless index[proci]
|
||||
traverse proci, index, vertices, map, relation
|
||||
end
|
||||
if index[i] > index[proci]
|
||||
# circulative recursion !!!
|
||||
index[i] = index[proci]
|
||||
end
|
||||
map[i] |= map[proci]
|
||||
end
|
||||
end
|
||||
|
||||
if index[i] == height
|
||||
while true
|
||||
proci = vertices.pop
|
||||
index[proci] = @infinity
|
||||
break if i == proci
|
||||
|
||||
map[proci] |= map[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
|
||||
# debug method
|
||||
def print_atab( idx, tab )
|
||||
tab.each_with_index do |i,ii|
|
||||
printf '%-20s', idx[ii].inspect
|
||||
p i
|
||||
end
|
||||
end
|
||||
|
||||
def print_tab( idx, rel, tab )
|
||||
tab.each_with_index do |bin,i|
|
||||
print i, ' ', idx[i].inspect, ' << '; p rel[i]
|
||||
print ' '
|
||||
each_t(@symboltable, bin) {|t| print ' ', t }
|
||||
puts
|
||||
end
|
||||
end
|
||||
|
||||
# debug method
|
||||
def print_tab_i( idx, rel, tab, i )
|
||||
bin = tab[i]
|
||||
print i, ' ', idx[i].inspect, ' << '; p rel[i]
|
||||
print ' '
|
||||
each_t(@symboltable, bin) {|t| print ' ', t }
|
||||
end
|
||||
|
||||
# debug method
|
||||
def printb( i )
|
||||
each_t(@symboltable, i) do |t|
|
||||
print t, ' '
|
||||
end
|
||||
puts
|
||||
end
|
||||
|
||||
def each_t( tbl, set )
|
||||
i = ii = idx = nil
|
||||
0.upto( set.size ) do |i|
|
||||
(0..7).each do |ii|
|
||||
if set[idx = i * 8 + ii] == 1
|
||||
yield tbl[idx]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# resolve
|
||||
#
|
||||
|
||||
def resolve( state )
|
||||
if state.conflict?
|
||||
resolve_rr state, state.ritems
|
||||
resolve_sr state, state.stokens
|
||||
else
|
||||
if state.rrules.empty?
|
||||
# shift
|
||||
state.stokens.each do |t|
|
||||
state.action[t] = @actions.shift(state.goto_table[t])
|
||||
end
|
||||
else
|
||||
# reduce
|
||||
state.defact = @actions.reduce(state.rrules[0])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_rr( state, r )
|
||||
pt = t = act = item = nil
|
||||
|
||||
r.each do |item|
|
||||
item.each_la(@symboltable) do |t|
|
||||
act = state.action[t]
|
||||
if act
|
||||
Reduce === act or raise "Racc FATAL: #{act.class} in action table"
|
||||
#
|
||||
# can't resolve R/R conflict (on t).
|
||||
# reduce with upper rule as default
|
||||
#
|
||||
state.rr_conflict act.rule, item.rule, t
|
||||
else
|
||||
# not conflict
|
||||
state.action[t] = @actions.reduce(item.rule)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_sr( state, s )
|
||||
stok = rtok = goto = act = nil
|
||||
|
||||
s.each do |stok|
|
||||
goto = state.goto_table[stok]
|
||||
act = state.action[stok]
|
||||
|
||||
unless act
|
||||
# no conflict
|
||||
state.action[stok] = @actions.shift(goto)
|
||||
else
|
||||
unless Reduce === act
|
||||
puts 'DEBUG -------------------------------'
|
||||
p stok
|
||||
p act
|
||||
state.action.each do |k,v|
|
||||
print k.inspect, ' ', v.inspect, "\n"
|
||||
end
|
||||
raise "Racc FATAL: #{act.class} in action table"
|
||||
end
|
||||
|
||||
# conflict on stok
|
||||
|
||||
rtok = act.rule.prec
|
||||
case do_resolve_sr(stok, rtok)
|
||||
when :Reduce
|
||||
# action is already set
|
||||
|
||||
when :Shift
|
||||
# overwrite
|
||||
act.decref
|
||||
state.action[stok] = @actions.shift(goto)
|
||||
|
||||
when :Error
|
||||
act.decref
|
||||
state.action[stok] = @actions.error
|
||||
|
||||
when :CantResolve
|
||||
# shift as default
|
||||
act.decref
|
||||
state.action[stok] = @actions.shift(goto)
|
||||
state.sr_conflict stok, act.rule
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ASSOC = {
|
||||
:Left => :Reduce,
|
||||
:Right => :Shift,
|
||||
:Nonassoc => :Error
|
||||
}
|
||||
|
||||
def do_resolve_sr( stok, rtok )
|
||||
puts "resolve_sr: s/r conflict: rtok=#{rtok}, stok=#{stok}" if @d_prec
|
||||
|
||||
unless rtok and rtok.prec
|
||||
puts "resolve_sr: no prec for #{rtok}(R)" if @d_prec
|
||||
return :CantResolve
|
||||
end
|
||||
rprec = rtok.prec
|
||||
|
||||
unless stok and stok.prec
|
||||
puts "resolve_sr: no prec for #{stok}(S)" if @d_prec
|
||||
return :CantResolve
|
||||
end
|
||||
sprec = stok.prec
|
||||
|
||||
ret = if rprec == sprec
|
||||
ASSOC[rtok.assoc] or
|
||||
raise "Racc FATAL: #{rtok}.assoc is not Left/Right/Nonassoc"
|
||||
else
|
||||
(rprec > sprec) ? (:Reduce) : (:Shift)
|
||||
end
|
||||
|
||||
puts "resolve_sr: resolved as #{ret.id2name}" if @d_prec
|
||||
ret
|
||||
end
|
||||
|
||||
#
|
||||
# complete
|
||||
#
|
||||
|
||||
def set_accept
|
||||
anch = @symboltable.anchor
|
||||
init_state = @states[0].goto_table[@ruletable.start]
|
||||
targ_state = init_state.action[anch].goto_state
|
||||
acc_state = targ_state.action[anch].goto_state
|
||||
|
||||
acc_state.action.clear
|
||||
acc_state.goto_table.clear
|
||||
acc_state.defact = @actions.accept
|
||||
end
|
||||
|
||||
def pack( state )
|
||||
### find most frequently used reduce rule
|
||||
act = state.action
|
||||
arr = Array.new(@ruletable.size, 0)
|
||||
t = a = nil
|
||||
act.each do |t,a|
|
||||
if Reduce === a
|
||||
arr[a.ruleid] += 1
|
||||
end
|
||||
end
|
||||
i = arr.max
|
||||
s = i>0 ? arr.index(i) : nil
|
||||
|
||||
### set & delete default action
|
||||
if s
|
||||
r = @actions.reduce(s)
|
||||
if not state.defact or state.defact == r
|
||||
act.delete_if {|t,a| a == r }
|
||||
state.defact = r
|
||||
end
|
||||
else
|
||||
state.defact ||= @actions.error
|
||||
end
|
||||
end
|
||||
|
||||
def check_useless
|
||||
act = nil
|
||||
used = []
|
||||
@actions.each_reduce do |act|
|
||||
if not act or act.refn == 0
|
||||
act.rule.useless = true
|
||||
else
|
||||
t = act.rule.target
|
||||
used[t.ident] = t
|
||||
end
|
||||
end
|
||||
@symboltable.nt_base.upto(@symboltable.nt_max - 1) do |n|
|
||||
unless used[n]
|
||||
@symboltable[n].useless = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end # class StateTable
|
||||
|
||||
|
||||
#
|
||||
# State
|
||||
#
|
||||
# represents a LALR state.
|
||||
#
|
||||
|
||||
class State
|
||||
|
||||
def initialize( ident, core )
|
||||
@ident = ident
|
||||
@core = core
|
||||
|
||||
@goto_table = {}
|
||||
@gotos = {}
|
||||
|
||||
@stokens = nil
|
||||
@ritems = nil
|
||||
|
||||
@action = {}
|
||||
@defact = nil
|
||||
|
||||
@rrconf = nil
|
||||
@srconf = nil
|
||||
|
||||
###
|
||||
|
||||
@closure = make_closure(@core)
|
||||
end
|
||||
|
||||
attr_reader :ident
|
||||
alias stateid ident
|
||||
alias hash ident
|
||||
|
||||
attr_reader :core
|
||||
attr_reader :closure
|
||||
|
||||
attr_reader :goto_table
|
||||
attr_reader :gotos
|
||||
|
||||
attr_reader :stokens
|
||||
attr_reader :ritems
|
||||
attr_reader :rrules
|
||||
|
||||
attr_reader :action
|
||||
attr_accessor :defact # default action
|
||||
|
||||
attr_reader :rrconf
|
||||
attr_reader :srconf
|
||||
|
||||
def inspect
|
||||
"<state #{@ident}>"
|
||||
end
|
||||
|
||||
alias to_s inspect
|
||||
|
||||
def ==( oth )
|
||||
@ident == oth.ident
|
||||
end
|
||||
|
||||
alias eql? ==
|
||||
|
||||
def make_closure( core )
|
||||
set = ISet.new
|
||||
core.each do |ptr|
|
||||
set.add ptr
|
||||
if t = ptr.dereference and t.nonterminal?
|
||||
set.update_a t.expand
|
||||
end
|
||||
end
|
||||
set.to_a
|
||||
end
|
||||
|
||||
def check_la( la_rules )
|
||||
@conflict = false
|
||||
s = []
|
||||
r = []
|
||||
@closure.each do |ptr|
|
||||
if t = ptr.dereference
|
||||
if t.terminal?
|
||||
s[t.ident] = t
|
||||
if t.ident == 1 # $error
|
||||
@conflict = true
|
||||
end
|
||||
end
|
||||
else
|
||||
r.push ptr.rule
|
||||
end
|
||||
end
|
||||
unless r.empty?
|
||||
if not s.empty? or r.size > 1
|
||||
@conflict = true
|
||||
end
|
||||
end
|
||||
s.compact!
|
||||
@stokens = s
|
||||
@rrules = r
|
||||
|
||||
if @conflict
|
||||
@la_rules_i = la_rules.size
|
||||
@la_rules = r.map {|i| i.ident }
|
||||
la_rules.concat r
|
||||
else
|
||||
@la_rules_i = @la_rules = nil
|
||||
end
|
||||
end
|
||||
|
||||
def conflict?
|
||||
@conflict
|
||||
end
|
||||
|
||||
def rruleid( rule )
|
||||
if i = @la_rules.index(rule.ident)
|
||||
@la_rules_i + i
|
||||
else
|
||||
puts '/// rruleid'
|
||||
p self
|
||||
p rule
|
||||
p @rrules
|
||||
p @la_rules_i
|
||||
raise 'Racc FATAL: cannot get reduce rule id'
|
||||
end
|
||||
end
|
||||
|
||||
def set_la( la )
|
||||
return unless @conflict
|
||||
|
||||
i = @la_rules_i
|
||||
@ritems = r = []
|
||||
@rrules.each do |rule|
|
||||
r.push Item.new(rule, la[i])
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
def rr_conflict( high, low, ctok )
|
||||
c = RRconflict.new(@ident, high, low, ctok)
|
||||
|
||||
@rrconf ||= {}
|
||||
if a = @rrconf[ctok]
|
||||
a.push c
|
||||
else
|
||||
@rrconf[ctok] = [c]
|
||||
end
|
||||
end
|
||||
|
||||
def sr_conflict( shift, reduce )
|
||||
c = SRconflict.new(@ident, shift, reduce)
|
||||
|
||||
@srconf ||= {}
|
||||
if a = @srconf[shift]
|
||||
a.push c
|
||||
else
|
||||
@srconf[shift] = [c]
|
||||
end
|
||||
end
|
||||
|
||||
end # State
|
||||
|
||||
|
||||
#
|
||||
# Goto
|
||||
#
|
||||
# represents a transition on the grammar.
|
||||
# REAL GOTO means transition by nonterminal,
|
||||
# but this class treats also terminal's.
|
||||
# If one is a terminal transition, .ident returns nil.
|
||||
#
|
||||
|
||||
class Goto
|
||||
|
||||
def initialize( ident, sym, from, to )
|
||||
@ident = ident
|
||||
@symbol = sym
|
||||
@from_state = from
|
||||
@to_state = to
|
||||
end
|
||||
|
||||
attr_reader :ident
|
||||
attr_reader :symbol
|
||||
attr_reader :from_state
|
||||
attr_reader :to_state
|
||||
|
||||
def inspect
|
||||
"(#{@from_state.ident}-#{@symbol}->#{@to_state.ident})"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Item
|
||||
#
|
||||
# a LALR item. A set of rule and its lookahead tokens.
|
||||
#
|
||||
|
||||
class Item
|
||||
|
||||
def initialize( rule, la )
|
||||
@rule = rule
|
||||
@la = la
|
||||
end
|
||||
|
||||
attr_reader :rule
|
||||
attr_reader :la
|
||||
|
||||
def each_la( tbl )
|
||||
la = @la
|
||||
i = ii = idx = nil
|
||||
0.upto(la.size - 1) do |i|
|
||||
(0..7).each do |ii|
|
||||
if la[idx = i * 8 + ii] == 1
|
||||
yield tbl[idx]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# ActionTable
|
||||
#
|
||||
# The table of LALR actions. Actions are either of
|
||||
# Shift, Reduce, Accept and Error.
|
||||
#
|
||||
|
||||
class ActionTable
|
||||
|
||||
def initialize( rt, st )
|
||||
@ruletable = rt
|
||||
@statetable = st
|
||||
|
||||
@reduce = []
|
||||
@shift = []
|
||||
@accept = nil
|
||||
@error = nil
|
||||
end
|
||||
|
||||
def init
|
||||
@ruletable.each do |rule|
|
||||
@reduce.push Reduce.new(rule)
|
||||
end
|
||||
@statetable.each do |state|
|
||||
@shift.push Shift.new(state)
|
||||
end
|
||||
@accept = Accept.new
|
||||
@error = Error.new
|
||||
end
|
||||
|
||||
def reduce_n
|
||||
@reduce.size
|
||||
end
|
||||
|
||||
def reduce( i )
|
||||
case i
|
||||
when Rule then i = i.ident
|
||||
when Integer then ;
|
||||
else
|
||||
raise "Racc FATAL: wrong class #{i.class} for reduce"
|
||||
end
|
||||
|
||||
r = @reduce[i] or raise "Racc FATAL: reduce action #{i.inspect} not exist"
|
||||
r.incref
|
||||
r
|
||||
end
|
||||
|
||||
def each_reduce( &block )
|
||||
@reduce.each(&block)
|
||||
end
|
||||
|
||||
def shift_n
|
||||
@shift.size
|
||||
end
|
||||
|
||||
def shift( i )
|
||||
case i
|
||||
when State then i = i.ident
|
||||
when Integer then ;
|
||||
else
|
||||
raise "Racc FATAL: wrong class #{i.class} for shift"
|
||||
end
|
||||
|
||||
@shift[i] or raise "Racc FATAL: shift action #{i} not exist"
|
||||
end
|
||||
|
||||
def each_shift( &block )
|
||||
@shift.each(&block)
|
||||
end
|
||||
|
||||
attr_reader :accept
|
||||
attr_reader :error
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Shift
|
||||
|
||||
def initialize( goto )
|
||||
@goto_state = goto
|
||||
end
|
||||
|
||||
attr_reader :goto_state
|
||||
|
||||
def goto_id
|
||||
@goto_state.ident
|
||||
end
|
||||
|
||||
def inspect
|
||||
"<shift #{@goto_state.ident}>"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Reduce
|
||||
|
||||
def initialize( rule )
|
||||
@rule = rule
|
||||
@refn = 0
|
||||
end
|
||||
|
||||
attr_reader :rule
|
||||
attr_reader :refn
|
||||
|
||||
def ruleid
|
||||
@rule.ident
|
||||
end
|
||||
|
||||
def inspect
|
||||
"<reduce #{@rule.ident}>"
|
||||
end
|
||||
|
||||
def incref
|
||||
@refn += 1
|
||||
end
|
||||
|
||||
def decref
|
||||
@refn -= 1
|
||||
bug! 'act.refn < 0' if @refn < 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Accept
|
||||
|
||||
def inspect
|
||||
"<accept>"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Error
|
||||
|
||||
def inspect
|
||||
"<error>"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Conflicts
|
||||
#
|
||||
|
||||
class SRconflict
|
||||
|
||||
def initialize( sid, shift, reduce )
|
||||
@stateid = sid
|
||||
@shift = shift
|
||||
@reduce = reduce
|
||||
end
|
||||
|
||||
attr_reader :stateid
|
||||
attr_reader :shift
|
||||
attr_reader :reduce
|
||||
|
||||
def to_s
|
||||
sprintf('state %d: S/R conflict rule %d reduce and shift %s',
|
||||
@stateid, @reduce.ruleid, @shift.to_s)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class RRconflict
|
||||
|
||||
def initialize( sid, high, low, tok )
|
||||
@stateid = sid
|
||||
@high_prec = high
|
||||
@low_prec = low
|
||||
@token = tok
|
||||
end
|
||||
|
||||
attr_reader :stateid
|
||||
attr_reader :high_prec
|
||||
attr_reader :low_prec
|
||||
attr_reader :token
|
||||
|
||||
def to_s
|
||||
sprintf('state %d: R/R conflict with rule %d and %d on %s',
|
||||
@stateid, @high_prec.ident, @low_prec.ident, @token.to_s)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@ -0,0 +1,40 @@
|
||||
#
|
||||
# usercodeparser.rb
|
||||
#
|
||||
# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net>
|
||||
#
|
||||
# This program is free software.
|
||||
# You can distribute/modify this program under the terms of
|
||||
# the GNU LGPL, Lesser General Public License version 2.
|
||||
# For details of the GNU LGPL, see the file "COPYING".
|
||||
#
|
||||
|
||||
module Racc
|
||||
|
||||
class GrammarFileParser < Parser
|
||||
|
||||
def GrammarFileParser.get_usercode( fname )
|
||||
ret = {}
|
||||
re = /\A----+\s*(header|inner|footer|prepare|driver)\s*(=)?/i
|
||||
str = nil
|
||||
lineno = 0
|
||||
|
||||
File.foreach(fname) do |line|
|
||||
lineno += 1
|
||||
if m = re.match(line)
|
||||
ret[m[1].downcase] = [
|
||||
str = '',
|
||||
lineno + 1,
|
||||
(m[2] && !m[2].empty?) ? m.post_match.strip.split(/\s+/) : nil
|
||||
]
|
||||
else
|
||||
str << line if str
|
||||
end
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@ -0,0 +1,595 @@
|
||||
|
||||
module Translator
|
||||
|
||||
class SymbolTable
|
||||
|
||||
def initialize
|
||||
super
|
||||
@prepared = false
|
||||
@table = {}
|
||||
@shortcuts = {}
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
@table.each_value(&block)
|
||||
end
|
||||
|
||||
def dump
|
||||
@table.each { |key, symbol|
|
||||
puts "#{symbol.inspect}"
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
#removes a symbol completely from symbol table
|
||||
#used when compiling incremental
|
||||
def remove(symbol)
|
||||
check = @table.delete([symbol.identifier, symbol.class, symbol.scope])
|
||||
throw InternalError.new unless check == symbol
|
||||
|
||||
@shortcuts[symbol.identifier] -= [symbol]
|
||||
end
|
||||
|
||||
def get(identifier, symbol_class, scope = nil, &block)
|
||||
|
||||
symbol = @table[[identifier, symbol_class, scope]]
|
||||
if symbol.nil? && !block.nil?
|
||||
symbol = block.call
|
||||
end
|
||||
|
||||
return symbol
|
||||
end
|
||||
|
||||
def get_all_regexp(regexp)
|
||||
result = []
|
||||
|
||||
@table.each { |key, value|
|
||||
result << value if key[0] =~ regexp
|
||||
}
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
# function to intercept domain symbol information for shortcut generation.
|
||||
def set_domain_symbol(symbol, domain_symbol)
|
||||
|
||||
raise InternalError.new unless symbol.class <= DomainValueSymbol
|
||||
|
||||
symbol.domain_symbol = domain_symbol
|
||||
symbol.enum_domain = domain_symbol if symbol.class <= EnumTypeSymbol
|
||||
|
||||
shortcut = symbol.shortcut
|
||||
symbols = @shortcuts[shortcut]
|
||||
if symbols.nil?
|
||||
@shortcuts[shortcut] = [symbol]
|
||||
else
|
||||
symbols << symbol unless symbols.include?(symbol)
|
||||
end
|
||||
end
|
||||
|
||||
# returns array of shortcut symbols for given identifier.
|
||||
def get_shortcuts(identifier)
|
||||
result = @shortcuts[identifier]
|
||||
return [] if result.nil?
|
||||
return Array.new(result)
|
||||
end
|
||||
|
||||
# declares and returns a symbol with given identifier and requested class and scope.
|
||||
# scope is (only) used to disabiguate state symbols and should be set to the corresponding option symbol.
|
||||
# otherwise scope is nil.
|
||||
# yields block on symbol redefinition
|
||||
def declare(identifier, symbol_class, scope = nil, &block)
|
||||
|
||||
key = [identifier, symbol_class, scope]
|
||||
|
||||
symbol = @table[key]
|
||||
|
||||
if symbol.nil?
|
||||
symbol = symbol_class.new(identifier, scope)
|
||||
@table[key] = symbol
|
||||
|
||||
symbols = @shortcuts[identifier]
|
||||
if symbols.nil?
|
||||
@shortcuts[identifier] = [symbol]
|
||||
else
|
||||
symbols << symbol unless symbols.include?(symbol)
|
||||
end
|
||||
else
|
||||
block.call unless block.nil?
|
||||
end
|
||||
return symbol
|
||||
end
|
||||
|
||||
# checks symbol table and returns array of error messages.
|
||||
def errors
|
||||
result = []
|
||||
@table.each do |key, symbol|
|
||||
result << InternalError.new("no domain symbol set on #{key.inspect}") if symbol.class <= DomainValueSymbol && symbol.domain_symbol.nil?
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
#uesd by SymbolContext to validate the function parameters in xtc code
|
||||
class DomainParameterContext
|
||||
|
||||
attr_reader :domain_symbol
|
||||
attr_reader :used_value_symbols
|
||||
attr_reader :compiler_context
|
||||
|
||||
def initialize(domain_symbol, compiler_context)
|
||||
super()
|
||||
|
||||
@domain_symbol = domain_symbol
|
||||
@compiler_context = compiler_context
|
||||
@used_value_symbols = []
|
||||
end
|
||||
|
||||
|
||||
def use_value_symbol(symbol, token)
|
||||
|
||||
if used_value_symbols.include?(symbol)
|
||||
compiler_context.eh.error ParameterMultipleSetting.new(@compiler_context, token)
|
||||
end
|
||||
|
||||
unless symbol.class <= DomainValueSymbol
|
||||
compiler_context.eh.error DomainSymbolExpected.new(@compiler_context, token)
|
||||
end
|
||||
|
||||
unless symbol.domain_symbol == domain_symbol
|
||||
compiler_context.eh.error MismatchingDomain.new(@compiler_context, token)
|
||||
end
|
||||
|
||||
# mark symbol as used for MissingParameter warning
|
||||
@used_value_symbols << symbol
|
||||
end
|
||||
|
||||
# issue a MissingParameter warning on unused domain value symbols.
|
||||
def check_used_value_symbols(token)
|
||||
if used_value_symbols.size < @domain_symbol.value_symbols.size
|
||||
(@domain_symbol.value_symbols - used_value_symbols).each {|symbol|
|
||||
compiler_context.eh.error ParameterMissing.new(compiler_context, token, symbol)
|
||||
}
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# class provides short access methods to members of compiler context.
|
||||
class CompilerContextWorker
|
||||
def initialize(compiler_context)
|
||||
@compiler_context = compiler_context
|
||||
end
|
||||
|
||||
def cc
|
||||
return @compiler_context
|
||||
end
|
||||
|
||||
def cu
|
||||
return @compiler_context.compilation_unit
|
||||
end
|
||||
|
||||
def st
|
||||
return @compiler_context.symbol_table
|
||||
end
|
||||
|
||||
def sc
|
||||
return @compiler_context.symbol_context
|
||||
end
|
||||
|
||||
def tz
|
||||
return @compiler_context.tokenizer
|
||||
end
|
||||
|
||||
def pc
|
||||
return @compiler_context.parser_context
|
||||
end
|
||||
|
||||
def bc
|
||||
return @compiler_context.builder_context
|
||||
end
|
||||
|
||||
def eh
|
||||
return @compiler_context.error_handler
|
||||
end
|
||||
end
|
||||
|
||||
class CompilerContext < CompilerContextWorker
|
||||
|
||||
attr_reader :compilation_unit
|
||||
attr_reader :symbol_table
|
||||
attr_reader :tokenizer
|
||||
attr_reader :parser_context
|
||||
attr_reader :symbol_context
|
||||
attr_reader :builder_context
|
||||
attr_reader :error_handler
|
||||
|
||||
def initialize(compilation_unit, symbol_table)
|
||||
|
||||
super(self)
|
||||
@compilation_unit = compilation_unit
|
||||
@symbol_table = symbol_table
|
||||
@tokenizer = Tokenizer.new(self)
|
||||
@parser_context = ParserContext.new(self)
|
||||
@symbol_context = SymbolContext.new(self)
|
||||
@builder_context = BuilderContext.new(self)
|
||||
@error_handler = ErrorHandler.new(self)
|
||||
end
|
||||
|
||||
def id
|
||||
return File.expand_path(@compilation_unit.src_filename)
|
||||
end
|
||||
|
||||
def warnings?
|
||||
eh.messages.each do |message|
|
||||
return true if message.class <= CompilerWarning
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def errors?
|
||||
eh.messages.each do |message|
|
||||
return true if message.class <= CompilerError
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
class CompilationUnit
|
||||
attr_reader :src_fullname
|
||||
attr_reader :src_filename
|
||||
attr_reader :src_dir
|
||||
attr_reader :src_mtime
|
||||
attr_reader :dest_fullname
|
||||
attr_reader :dest_filename
|
||||
attr_reader :dest_dir
|
||||
|
||||
def initialize()
|
||||
end
|
||||
|
||||
def set_src(working_directory, filename)
|
||||
@src_filename = filename
|
||||
@src_dir = working_directory
|
||||
@src_fullname = File.join(@src_dir, @src_filename)
|
||||
update_src_mtime
|
||||
end
|
||||
|
||||
def update_src_mtime
|
||||
@src_mtime = File.stat(@src_fullname).mtime
|
||||
end
|
||||
|
||||
def set_dest(working_directory, filename = nil)
|
||||
|
||||
if filename.nil?
|
||||
case @src_filename
|
||||
|
||||
when /^(.*)\.[xy]absl$/
|
||||
@dest_filename = "#{$1}.xml"
|
||||
when /^(.*)\.xml$/
|
||||
@dest_filename = "#{$1}.xabsl"
|
||||
else
|
||||
raise InternalError.new
|
||||
end
|
||||
else
|
||||
@dest_filename = filename
|
||||
end
|
||||
|
||||
@dest_dir = working_directory unless working_directory.nil?
|
||||
@dest_fullname = File.join(@dest_dir, @dest_filename)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class BuilderContext < CompilerContextWorker
|
||||
|
||||
def start_generate_code(le, out)
|
||||
@stack = []
|
||||
@out = out
|
||||
generate_code(le)
|
||||
end
|
||||
|
||||
def generate_code(le)
|
||||
@stack.push le
|
||||
le.to_code(cc, @out)
|
||||
@stack.pop
|
||||
end
|
||||
|
||||
#convinience method
|
||||
def[](attribute_name)
|
||||
return sc.to_code(@stack.last.attr[attribute_name])
|
||||
end
|
||||
end
|
||||
|
||||
class SymbolContext < CompilerContextWorker
|
||||
|
||||
attr_reader :from_code_declaration_count
|
||||
attr_reader :from_code_usage_count
|
||||
attr_reader :from_code_namespace_symbol_usage_count
|
||||
|
||||
def initialize(cc)
|
||||
super
|
||||
@from_code_declaration_count = Hash.new(0)
|
||||
@from_code_usage_count = Hash.new(0)
|
||||
@from_code_namespace_symbol_usage_count = Hash.new(0)
|
||||
end
|
||||
|
||||
#transforms symbol to xtc identifier
|
||||
def to_code(symbol, at_prefix_on_option_parameter = true)
|
||||
return SymbolContext.to_code(symbol, at_prefix_on_option_parameter)
|
||||
end
|
||||
|
||||
|
||||
def SymbolContext.to_code(symbol, at_prefix_on_option_parameter = true)
|
||||
|
||||
identifier = symbol.identifier
|
||||
if symbol.class <= DomainValueSymbol
|
||||
if symbol.class == OptionParameterSymbol && at_prefix_on_option_parameter
|
||||
subst = '@'
|
||||
else
|
||||
subst = ''
|
||||
end
|
||||
|
||||
raise InternalError.new if symbol.domain_symbol.nil?
|
||||
identifier = identifier.sub(/^#{Regexp.escape(symbol.domain_symbol.identifier)}\./ , subst) if symbol.qualified?
|
||||
end
|
||||
|
||||
return identifier
|
||||
end
|
||||
|
||||
|
||||
def from_code_declare(token, symbol_class, domain_symbol = nil, identifier = nil, qualified = true)
|
||||
raise InternalError.new if symbol_class <= DomainValueSymbol && domain_symbol.nil?
|
||||
symbol = nil
|
||||
|
||||
identifier = token.to_s if identifier.nil?
|
||||
|
||||
#cut away the @prefix
|
||||
if symbol_class == OptionParameterSymbol
|
||||
raise InternalError.new if domain_symbol.nil?
|
||||
#option parameter symbols *have* to be marked as qualified
|
||||
raise InternalError.new unless qualified
|
||||
identifier = identifier.sub(/^@/, "#{domain_symbol.identifier}.")
|
||||
elsif [InputSymbolParameterSymbol, BasicBehaviorParameterSymbol].include?(symbol_class)
|
||||
raise InternalError.new if domain_symbol.nil?
|
||||
identifier = "#{domain_symbol.identifier}.#{identifier}" if qualified
|
||||
elsif [EnumSymbolValueSymbol].include?(symbol_class)
|
||||
raise InternalError.new if domain_symbol.nil?
|
||||
identifier = "#{domain_symbol.identifier}.#{identifier}" if qualified
|
||||
|
||||
elsif symbol_class <= DomainValueSymbol
|
||||
# this code does not yet support declaration of DomainValueSymbols,
|
||||
# because of the prefix handling
|
||||
# raise InternalError.new
|
||||
raise InternalError.new if domain_symbol.nil?
|
||||
identifier = "#{domain_symbol.identifier}.#{identifier}" if qualified
|
||||
end
|
||||
|
||||
|
||||
#StateSymbols get the option_symbol as scope
|
||||
scope = nil
|
||||
if symbol_class == StateSymbol
|
||||
raise InternalError.new if pc.option_symbol.nil?
|
||||
scope = pc.option_symbol
|
||||
end
|
||||
symbol = st.declare(identifier, symbol_class, scope) do
|
||||
cc.eh.error MultipleDefinitions.new(cc, token)
|
||||
end
|
||||
|
||||
unless domain_symbol.nil?
|
||||
st.set_domain_symbol(symbol, domain_symbol)
|
||||
end
|
||||
|
||||
#current symbol is declared within namespace
|
||||
unless pc.namespace_symbol.nil?
|
||||
symbol.namespace_symbol = pc.namespace_symbol
|
||||
@from_code_namespace_symbol_usage_count[symbol.namespace_symbol] += 1
|
||||
end
|
||||
|
||||
@from_code_usage_count[symbol] += 1
|
||||
@from_code_declaration_count[symbol] += 1
|
||||
if @from_code_declaration_count[symbol] > 1
|
||||
eh.error MultipleDefinitions.new(cc, token)
|
||||
end
|
||||
|
||||
return symbol
|
||||
end
|
||||
|
||||
#used to track used namespace symbols for entity list generation
|
||||
def used_namespace_symbols
|
||||
return @from_code_namespace_symbol_usage_count.keys
|
||||
end
|
||||
|
||||
|
||||
|
||||
#returns symbol from identifier
|
||||
#
|
||||
#returned symbol is subclasses of at least one element of symbol_classes
|
||||
#if !domain_symbol.nil? the returned symbol is a DomainValueSymbol with this domain symbol
|
||||
def from_code(token, symbol_classes, domain_symbol = nil, &block)
|
||||
|
||||
identifier = token.to_s
|
||||
|
||||
#separate-sausage for option parameters
|
||||
if identifier =~ /^@/
|
||||
|
||||
raise InternalError.new if pc.option_symbol.nil?
|
||||
identifier = identifier.sub(/^@/, "#{pc.option_symbol.identifier}.")
|
||||
return st.get(identifier, OptionParameterSymbol) {
|
||||
eh.error NoMatchingSymbolFound.new(cc, token, domain_symbol, symbol_classes)
|
||||
from_code_declare(token, OptionParameterSymbol, pc.option_symbol, identifier)
|
||||
}
|
||||
end
|
||||
|
||||
symbol_classes = [symbol_classes] unless symbol_classes.class <= Array
|
||||
symbols = get_fuzzy_fast(identifier, symbol_classes, domain_symbol)
|
||||
|
||||
#if we found exactly one symbol the world is in perfect order
|
||||
#otherwise give error message
|
||||
symbol = nil
|
||||
case symbols.size
|
||||
when 1:
|
||||
symbol = symbols[0]
|
||||
when 0:
|
||||
if !block.nil?
|
||||
return block.call
|
||||
else
|
||||
#declare symbol to prevent stopping the compile process
|
||||
#SENSE?
|
||||
eh.error NoMatchingSymbolFound.new(cc, token, domain_symbol, symbol_classes)
|
||||
symbol = from_code_declare(token, symbol_classes[0], domain_symbol)
|
||||
end
|
||||
else
|
||||
#return the first symbol to get on with compiling
|
||||
#SENSE?
|
||||
eh.error MultipleMatchingSymbolsFound.new(cc, token, domain_symbol, symbol_classes, symbols)
|
||||
symbol = symbols[0]
|
||||
end
|
||||
|
||||
@from_code_usage_count[symbol] += 1
|
||||
@from_code_namespace_symbol_usage_count[symbol.namespace_symbol] += 1 unless symbol.namespace_symbol.nil?
|
||||
symbol.usage_count += 1
|
||||
return symbol
|
||||
end
|
||||
|
||||
|
||||
def get_fuzzy_fast(identifier, symbol_classes, domain_symbol)
|
||||
|
||||
symbols = st.get_shortcuts(identifier)
|
||||
#delete symbols with wrong symbol class
|
||||
symbols.delete_if { |symbol|
|
||||
result = true
|
||||
|
||||
symbol_classes.each {|symbol_class|
|
||||
if symbol.class <= symbol_class
|
||||
result = false
|
||||
end
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#delete symbols out of scope
|
||||
symbols.delete_if { |symbol|
|
||||
!symbol.scope.nil? && symbol.scope != pc.option_symbol
|
||||
}
|
||||
|
||||
#delete symbols with wrong domain_symbol
|
||||
unless domain_symbol.nil?
|
||||
symbols.delete_if {|symbol|
|
||||
(not symbol.class <= DomainValueSymbol) || symbol.domain_symbol != domain_symbol
|
||||
}
|
||||
else
|
||||
symbols.delete_if {|symbol|
|
||||
symbol.class <= DomainValueSymbol
|
||||
}
|
||||
end
|
||||
|
||||
return symbols
|
||||
end
|
||||
|
||||
|
||||
#very imperformant due to regular expressions and speed >=O(#symbols)
|
||||
def get_fuzzy(identifier, symbol_classes, domain_symbol)
|
||||
|
||||
regexp = /(^|\.)#{Regexp.escape(identifier)}$/
|
||||
symbols = st.get_all_regexp(regexp)
|
||||
|
||||
#delete symbols with wrong symbol class
|
||||
symbols.delete_if { |symbol|
|
||||
result = true
|
||||
|
||||
symbol_classes.each {|symbol_class|
|
||||
if symbol.class <= symbol_class
|
||||
result = false
|
||||
end
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#delete symbols out of scope
|
||||
symbols.delete_if { |symbol|
|
||||
!symbol.scope.nil? && symbol.scope != pc.option_symbol
|
||||
}
|
||||
|
||||
#delete symbols with wrong domain_symbol
|
||||
unless domain_symbol.nil?
|
||||
symbols.delete_if {|symbol|
|
||||
symbol.domain_symbol != domain_symbol
|
||||
}
|
||||
end
|
||||
|
||||
#double check by domain_value substitution or identity
|
||||
result = []
|
||||
symbols.each {|symbol|
|
||||
if symbol.identifier == identifier
|
||||
result << symbol
|
||||
elsif symbol.class <= DomainValueSymbol
|
||||
result << symbol if symbol.identifier == "#{symbol.domain_symbol.identifier}.#{identifier}"
|
||||
end
|
||||
}
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
# represents a the location in code where a symbol occurs
|
||||
# and is used to resolve symbol abbrevs. and ambiguities
|
||||
# performs semantic checking
|
||||
class ParserContext < CompilerContextWorker
|
||||
|
||||
attr_accessor :option_root
|
||||
attr_accessor :agent_collection_root
|
||||
attr_accessor :namespace_root
|
||||
attr_accessor :option_definitions_temp
|
||||
|
||||
attr_accessor :option_definitions_by_symbol
|
||||
|
||||
attr_accessor :option_symbol
|
||||
attr_accessor :state_symbol
|
||||
attr_accessor :input_symbol
|
||||
attr_accessor :initial_state_symbol
|
||||
|
||||
attr_accessor :namespace_symbol
|
||||
attr_accessor :behavior_symbol
|
||||
|
||||
attr_reader :function_dpcs
|
||||
attr_reader :subsequent_dpc
|
||||
attr_reader :subsequent_type
|
||||
attr_reader :includes
|
||||
|
||||
attr_accessor :option_declared
|
||||
attr_accessor :agent_declared
|
||||
attr_accessor :namespace_declared
|
||||
|
||||
attr_accessor :enum_domains
|
||||
|
||||
attr_accessor :has_common_decision_tree
|
||||
|
||||
def initialize(compiler_context)
|
||||
super
|
||||
@function_dpcs = []
|
||||
@enum_domains = []
|
||||
@option_definitions_by_symbol = {}
|
||||
@includes = []
|
||||
@option_declared = false
|
||||
@agent_declared = false
|
||||
@namespace_declared = false
|
||||
@has_common_decision_tree = false
|
||||
end
|
||||
|
||||
def set_subsequent(dpc, type)
|
||||
|
||||
raise InternalError.new unless [:option, :behavior, nil].include?(type)
|
||||
|
||||
@subsequent_dpc = dpc
|
||||
@subsequent_type = type
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,158 @@
|
||||
module Translator
|
||||
|
||||
|
||||
#identifers are unique across one class of symbols
|
||||
#with the exception of states
|
||||
class Symbol
|
||||
|
||||
attr_reader :identifier
|
||||
attr_reader :scope
|
||||
attr_accessor :namespace_symbol
|
||||
attr_accessor :usage_count
|
||||
|
||||
def initialize(identifier, scope)
|
||||
super()
|
||||
@identifier = identifier
|
||||
@scope = scope
|
||||
@usage_count = 0
|
||||
|
||||
throw "trying to instantiate an abstract class" if self.class == Symbol
|
||||
end
|
||||
|
||||
def inspect
|
||||
scope_identifier = ''
|
||||
scope_identifier = ", @scope=#{@scope.identifier}>" unless @scope.nil?
|
||||
return "#{self.class.name}<@identifier=#{@identifier}#{scope_identifier}>"
|
||||
end
|
||||
|
||||
#for sorting by identifier
|
||||
def <=>(symbol)
|
||||
return self.identifier <=> symbol.identifier
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class DomainValueSymbol < Symbol
|
||||
|
||||
attr_reader :domain_symbol
|
||||
attr_reader :shortcut
|
||||
|
||||
def qualified?
|
||||
return identifier != shortcut
|
||||
end
|
||||
|
||||
|
||||
def domain_symbol=(symbol)
|
||||
|
||||
return if symbol.nil?
|
||||
return if @domain_symbol == symbol
|
||||
|
||||
if @domain_symbol.nil?
|
||||
@domain_symbol = symbol
|
||||
@domain_symbol.value_symbols << self
|
||||
else
|
||||
$stderr.puts "redeclaration mismatch on #{self.inspect}: old ds #{@domain_symbol.inspect} new ds #{symbol.inspect}"
|
||||
raise InternalError.new
|
||||
end
|
||||
|
||||
@shortcut = identifier.sub(/^#{Regexp.escape(@domain_symbol.identifier)}\./ , '')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class NamespaceSymbol < Symbol
|
||||
attr_reader :namespace_type
|
||||
|
||||
|
||||
#set the type of the namespace, allowed values for type are :symbols or :behaviors
|
||||
def namespace_type=(type)
|
||||
return if @namespace_type == type
|
||||
raise InternalError.new unless @namespace_type.nil?
|
||||
raise InternalError.new unless [:symbols, :behaviors].include?(type)
|
||||
@namespace_type = type
|
||||
end
|
||||
end
|
||||
|
||||
class AgentSymbol < Symbol
|
||||
end
|
||||
|
||||
class StateSymbol < Symbol
|
||||
end
|
||||
|
||||
class DomainSymbol < Symbol
|
||||
|
||||
attr_reader :value_symbols
|
||||
|
||||
def initialize(identifier, scope)
|
||||
super
|
||||
@value_symbols = []
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module EnumTypeSymbol
|
||||
attr_accessor :enum_domain
|
||||
end
|
||||
|
||||
class ParameterSymbol < DomainValueSymbol
|
||||
attr_accessor :type
|
||||
include EnumTypeSymbol
|
||||
end
|
||||
|
||||
class DecimalInputSymbol < DomainSymbol
|
||||
end
|
||||
|
||||
class InputSymbolParameterSymbol < ParameterSymbol
|
||||
end
|
||||
|
||||
class BooleanInputSymbol < DomainSymbol
|
||||
end
|
||||
|
||||
class ConstantSymbol < Symbol
|
||||
attr_accessor :value
|
||||
end
|
||||
|
||||
|
||||
class EnumInputSymbol < DomainSymbol
|
||||
include EnumTypeSymbol
|
||||
end
|
||||
|
||||
class DecimalOutputSymbol < Symbol
|
||||
attr_accessor :internal
|
||||
end
|
||||
|
||||
class BooleanOutputSymbol < Symbol
|
||||
attr_accessor :internal
|
||||
end
|
||||
|
||||
class EnumOutputSymbol < Symbol
|
||||
include EnumTypeSymbol
|
||||
attr_accessor :internal
|
||||
end
|
||||
|
||||
|
||||
class EnumSymbol < DomainSymbol
|
||||
attr_accessor :internal
|
||||
end
|
||||
|
||||
class EnumSymbolValueSymbol < DomainValueSymbol
|
||||
include EnumTypeSymbol
|
||||
end
|
||||
|
||||
|
||||
class OptionSymbol < DomainSymbol
|
||||
end
|
||||
|
||||
class OptionParameterSymbol < ParameterSymbol
|
||||
end
|
||||
|
||||
|
||||
class BasicBehaviorSymbol < DomainSymbol
|
||||
end
|
||||
|
||||
class BasicBehaviorParameterSymbol < ParameterSymbol
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,303 @@
|
||||
module Translator
|
||||
|
||||
class Token
|
||||
|
||||
attr_reader :token_type;
|
||||
attr_reader :line_nr;
|
||||
|
||||
def initialize(token_type, token_string, line_nr)
|
||||
@token_type = token_type
|
||||
@token_string = token_string
|
||||
@line_nr = line_nr
|
||||
end
|
||||
|
||||
def raw_string
|
||||
return @token_string
|
||||
end
|
||||
|
||||
def to_s
|
||||
|
||||
#cut away inverted commas und square backets
|
||||
if token_type == :STRING || token_type == :RANGE
|
||||
return @token_string[1..-2]
|
||||
end
|
||||
|
||||
return @token_string
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Tokenizer < CompilerContextWorker
|
||||
|
||||
attr_reader :keywords
|
||||
|
||||
@@keywords = nil
|
||||
|
||||
def Tokenizer.keywords
|
||||
return @@keywords unless @@keywords.nil?
|
||||
|
||||
@@keywords = {}
|
||||
@@keywords[TOKEN_TRUE] = :TRUE
|
||||
@@keywords[TOKEN_FALSE] = :FALSE
|
||||
@@keywords[TOKEN_OPTION] = :OPTION
|
||||
@@keywords[TOKEN_ACTION] = :ACTION
|
||||
@@keywords[TOKEN_INITIAL] = :INITIAL
|
||||
@@keywords[TOKEN_TARGET] = :TARGET
|
||||
@@keywords[TOKEN_STATE] = :STATE
|
||||
@@keywords[TOKEN_COMMON] = :COMMON
|
||||
@@keywords[TOKEN_DECISION] = :DECISION
|
||||
@@keywords[TOKEN_TTS] = :TTS
|
||||
@@keywords[TOKEN_IF] = :IF
|
||||
@@keywords[TOKEN_ELSE] = :ELSE
|
||||
@@keywords[TOKEN_TOOX] = :TOOX
|
||||
@@keywords[TOKEN_TOSX] = :TOSX
|
||||
@@keywords[TOKEN_SORTS] = :SORTS
|
||||
@@keywords[TOKEN_AGENT] = :AGENT
|
||||
@@keywords[TOKEN_FUNCTION] = :FUNCTION
|
||||
@@keywords[TOKEN_ENUM] = :ENUM
|
||||
@@keywords[TOKEN_INPUT] = :INPUT
|
||||
@@keywords[TOKEN_OUTPUT] = :OUTPUT
|
||||
@@keywords[TOKEN_BOOL] = :BOOL
|
||||
@@keywords[TOKEN_FLOAT] = :FLOAT
|
||||
@@keywords[TOKEN_CONST] = :CONST
|
||||
@@keywords[TOKEN_NAMESPACE] = :NAMESPACE
|
||||
@@keywords[TOKEN_BEHAVIOR] = :BEHAVIOR
|
||||
@@keywords[TOKEN_INCLUDE] = :INCLUDE
|
||||
@@keywords[TOKEN_STAY] = :STAY
|
||||
@@keywords[TOKEN_INTERNAL] = :INTERNAL
|
||||
@@keywords[TOKEN_CAPACITY] = :CAPACITY
|
||||
@@keywords[TOKEN_SYNCHRONIZED] = :SYNCHRONIZED
|
||||
@@keywords[TOKEN_CONFLICT] = :CONFLICT
|
||||
|
||||
return @@keywords
|
||||
end
|
||||
|
||||
def initialize(compiler_context)
|
||||
super
|
||||
@token_index = 0
|
||||
@token_counter = 0
|
||||
end
|
||||
|
||||
def rewind
|
||||
@token_index = 0
|
||||
end
|
||||
|
||||
def next_token
|
||||
token = @stream[@token_index]
|
||||
@token_index += 1
|
||||
return token
|
||||
end
|
||||
|
||||
def dump
|
||||
@stream.each do |token|
|
||||
p token.raw_string
|
||||
end
|
||||
end
|
||||
|
||||
def get_code_line(line_nr)
|
||||
return @lines[line_nr]
|
||||
end
|
||||
|
||||
def get_code_context(token, size)
|
||||
|
||||
line_tokens = Array.new(@stream) #copy token stream
|
||||
line_tokens.delete_if do |t|
|
||||
t.line_nr != token.line_nr
|
||||
end
|
||||
|
||||
index = line_tokens.index(token)
|
||||
regexp = "("
|
||||
(0..index-1).each do |i|
|
||||
regexp += Regexp.escape(line_tokens[i].raw_string)
|
||||
regexp += "\\s*(/\\*.*?\\*/\\s*)*"
|
||||
end
|
||||
regexp += ")(#{Regexp.escape(line_tokens[index].raw_string)})("
|
||||
(index+1..line_tokens.size-1).each do |i|
|
||||
regexp += "\\s*(/\\*.*?\\*/\\s*)*"
|
||||
regexp += Regexp.escape(line_tokens[i].raw_string)
|
||||
end
|
||||
regexp += ")"
|
||||
|
||||
regexp = Regexp.new(regexp)
|
||||
match = regexp.match(@lines[token.line_nr])
|
||||
|
||||
|
||||
r = ''
|
||||
m = ''
|
||||
l = ''
|
||||
unless match.nil?
|
||||
l = match[1].to_s
|
||||
r = match[index+3].to_s
|
||||
m = match[index+2].to_s
|
||||
end
|
||||
|
||||
#rest size for left and right part
|
||||
size -= m.size
|
||||
if(size <= 0)
|
||||
l = ''
|
||||
r = ''
|
||||
else
|
||||
if size > l.size
|
||||
|
||||
size -= l.size
|
||||
r = r[0..[r.size, size].min - 1]
|
||||
|
||||
else
|
||||
l = l[-size..-1]
|
||||
r = ''
|
||||
end
|
||||
end
|
||||
|
||||
return ["#{l}#{m}#{r}","#{' '*l.length}#{'^'*m.length}#{' '*r.length}"]
|
||||
|
||||
end
|
||||
|
||||
def push(token_type, token_string)
|
||||
token = Token.new(token_type, token_string, @line_nr)
|
||||
@token_counter[token_type] += 1
|
||||
@stream.push token
|
||||
end
|
||||
|
||||
def pop
|
||||
token = @stream.pop
|
||||
@token_counter[token.token_type] -= 1
|
||||
return token
|
||||
end
|
||||
|
||||
def tokenized?
|
||||
return !@stream.nil?
|
||||
end
|
||||
|
||||
def tokenize( str )
|
||||
|
||||
comment_mode = :no_comment
|
||||
|
||||
@token_counter = Hash.new(0)
|
||||
@stream = []
|
||||
@lines = []
|
||||
@line_nr = 1
|
||||
|
||||
until str.empty? do
|
||||
|
||||
#if we are within a comment...
|
||||
unless comment_mode == :no_comment
|
||||
case str
|
||||
when /\A((.|\n|\r)*?)(\*\/)/
|
||||
|
||||
case comment_mode
|
||||
when :doc_comment:
|
||||
push(:DOC_COMMENT, $1.strip)
|
||||
when :initial_comment:
|
||||
push(:INITIAL_COMMENT, $1.strip)
|
||||
end
|
||||
str = $'
|
||||
|
||||
#count newlines
|
||||
@line_nr += $1.count("\n")
|
||||
if @lines[@line_nr].nil?
|
||||
str =~ /^(.*)$/
|
||||
@lines[@line_nr] = $1.chomp
|
||||
end
|
||||
|
||||
comment_mode = :no_comment
|
||||
else
|
||||
|
||||
raise ClosingCommentMissingError.new(cc, @line_nr)
|
||||
end
|
||||
else
|
||||
|
||||
#consume whitespaces between tokens until end-of-line
|
||||
while str =~ /\A([\s]+|\/\/.*?[\r\n]|[\r\n])/
|
||||
str = $'
|
||||
|
||||
@line_nr += $1.count("\n")
|
||||
if @lines[@line_nr].nil?
|
||||
str =~ /^(.*)$/
|
||||
@lines[@line_nr] = $1.chomp
|
||||
end
|
||||
end
|
||||
|
||||
#check for keywords
|
||||
if str =~ /\A[a-zA-Z_][a-zA-Z0-9_\.\-]*/
|
||||
keyword_symbol = Tokenizer.keywords[$&]
|
||||
unless keyword_symbol.nil?
|
||||
|
||||
token_match = $&
|
||||
push(keyword_symbol, token_match)
|
||||
str = $'
|
||||
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
case str
|
||||
when ''
|
||||
#do nothing
|
||||
when /\A[0-9]+(\.[0-9]*)?|^[1-9]\.[0-9]*E(\+|-)?[0-9]+/
|
||||
push(:NUMBER, $&)
|
||||
str = $'
|
||||
when /\A[@]?[a-zA-Z_][a-zA-Z0-9_\.]*/
|
||||
push(:IDENTIFIER, $&)
|
||||
str = $'
|
||||
when /\A("[^"]*")/
|
||||
push(:STRING, $1.to_s)
|
||||
str = $'
|
||||
when /\A\/\*\*\*/
|
||||
str = $'
|
||||
comment_mode = :initial_comment
|
||||
when /\A\/\*\*/
|
||||
str = $'
|
||||
comment_mode = :doc_comment
|
||||
when /\A\/\*/
|
||||
str = $'
|
||||
comment_mode = :comment
|
||||
when /\A(\[[^\]]*\])/
|
||||
push(:RANGE, $1.to_s)
|
||||
str = $'
|
||||
when /\A\*\//
|
||||
raise ClosingCommentError.new(cc, @line_nr)
|
||||
else
|
||||
|
||||
b = str[0,2]
|
||||
c = str[0,1]
|
||||
|
||||
case b
|
||||
when '<='
|
||||
push(:LE, b)
|
||||
str = str[2..-1]
|
||||
when '>='
|
||||
push(:GE, b)
|
||||
str = str[2..-1]
|
||||
when '=='
|
||||
push(:EQ, b)
|
||||
str = str[2..-1]
|
||||
when '!='
|
||||
push(:NEQ, b)
|
||||
str = str[2..-1]
|
||||
when '&&'
|
||||
push(:AND, b)
|
||||
str = str[2..-1]
|
||||
when '||'
|
||||
push(:OR, b)
|
||||
str = str[2..-1]
|
||||
else
|
||||
if '%!<>[]{}();|+-*/=,?:'.index(c)
|
||||
push(c, c)
|
||||
str = str[1..-1]
|
||||
else
|
||||
dump if LOG.debug?
|
||||
raise TokenizerError.new(cc, @line_nr, str[0..[30, str.length].min])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#raise ParenthesisError.new(cc, '(', @token_counter['('], ')', @token_counter[')']) unless @token_counter['('] == @token_counter[')']
|
||||
#raise ParenthesisError.new(cc, '{', @token_counter['{'], '}', @token_counter['}']) unless @token_counter['{'] == @token_counter['}']
|
||||
#raise UnevenStringDelimiterError.new(cc, '"') unless (@token_counter['"'] % 2) == 0
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,10 @@
|
||||
require "rexml/document"
|
||||
require "rexml/streamlistener"
|
||||
require 'constants'
|
||||
require 'translator_base'
|
||||
require 'language_elements'
|
||||
require 'xml_parser'
|
||||
require 'symbols'
|
||||
require 'symbol_table'
|
||||
require 'tokenizer'
|
||||
require 'errors'
|
||||
@ -0,0 +1,142 @@
|
||||
require 'translator'
|
||||
|
||||
module Translator
|
||||
|
||||
def Translator.stopwatch(message)
|
||||
LOG.info "#{message}"
|
||||
start_time = Time.now
|
||||
yield
|
||||
elapsed_time = Time.now - start_time
|
||||
LOG.info "#{message} [#{elapsed_time}s]"
|
||||
return elapsed_time
|
||||
end
|
||||
|
||||
class Profiler
|
||||
|
||||
attr_accessor :count
|
||||
attr_reader :elapsed_time
|
||||
|
||||
def initialize(clazz, modulename, classname , methodname)
|
||||
@count = 0
|
||||
@elapsed_time = 0.0
|
||||
@name = "#{clazz.name}.#{methodname}(...)"
|
||||
|
||||
clazz.class_eval "
|
||||
def #{classname}.profiler
|
||||
return @profiler
|
||||
end
|
||||
|
||||
def #{classname}.profiler=(pr)
|
||||
@profiler = pr
|
||||
end
|
||||
|
||||
alias profiled_#{methodname} #{methodname}
|
||||
def #{methodname}(*args, &block)
|
||||
|
||||
start_time = Time.now
|
||||
result = self.profiled_#{methodname}(*args, &block)
|
||||
#{classname}.profiler.add(Time.now - start_time)
|
||||
|
||||
result
|
||||
end
|
||||
"
|
||||
|
||||
clazz.profiler = self
|
||||
end
|
||||
|
||||
def add(time)
|
||||
@elapsed_time += time
|
||||
@count += 1
|
||||
end
|
||||
|
||||
def log
|
||||
LOG.info "#{@name} #{@count} times called, #{@elapsed_time}s in total"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Out
|
||||
|
||||
attr_accessor :indent_string
|
||||
attr_accessor :verbose
|
||||
|
||||
def initialize(out)
|
||||
@out = out
|
||||
@indent = 0
|
||||
@indent_string = " "
|
||||
@verbose = false
|
||||
end
|
||||
|
||||
#for printing indents
|
||||
def pindent(delta = 0)
|
||||
result = ''
|
||||
@indent += delta if delta < 0
|
||||
@indent.times {
|
||||
result << @indent_string
|
||||
}
|
||||
@indent += delta if delta > 0
|
||||
return result
|
||||
end
|
||||
|
||||
def <<(something)
|
||||
@out << something
|
||||
return self
|
||||
end
|
||||
|
||||
#suggested line break
|
||||
#vaporware
|
||||
def |(something)
|
||||
self << ENDL << something
|
||||
end
|
||||
|
||||
#print with indent
|
||||
def %(something)
|
||||
self << pindent << something
|
||||
end
|
||||
|
||||
#print and increase indent
|
||||
def >(something)
|
||||
self << pindent(1) << something
|
||||
end
|
||||
|
||||
#print and decrease indent
|
||||
def <(something)
|
||||
self << pindent(-1) << something
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class RecodeOut < Out
|
||||
def <<(something)
|
||||
#recode utf8 strings to native charset
|
||||
@out << something.unpack("U*").pack("C*")
|
||||
return self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class << File
|
||||
|
||||
def relative_path(path, reference_path)
|
||||
|
||||
path = File.expand_path(path).sub(/^([A-Za-z]):/, '/cygdrive/\1').split(/[\\\/]+/)
|
||||
reference_path = File.expand_path(reference_path).sub(/^([A-Za-z]):/, '/cygdrive/\1').split(/[\\\/]+/)
|
||||
|
||||
equal_index = 0
|
||||
while(path[equal_index] == reference_path[equal_index])
|
||||
equal_index += 1
|
||||
end
|
||||
|
||||
relative_path = []
|
||||
(reference_path.size - equal_index).times do
|
||||
relative_path << ".."
|
||||
end
|
||||
|
||||
((equal_index)..(path.size-1)).each do |index|
|
||||
relative_path << path[index]
|
||||
end
|
||||
return File.join(*relative_path)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@ -0,0 +1,133 @@
|
||||
|
||||
|
||||
module Translator
|
||||
|
||||
class Node
|
||||
|
||||
attr_accessor :name
|
||||
attr_reader :children
|
||||
attr_accessor :type
|
||||
attr_accessor :relative_name
|
||||
|
||||
def initialize
|
||||
@children = []
|
||||
@type = nil
|
||||
end
|
||||
|
||||
def get_or_create(child_name)
|
||||
@children.each do |child|
|
||||
return child if child.name == child_name
|
||||
end
|
||||
|
||||
new_child = Node.new
|
||||
new_child.name = child_name
|
||||
@children << new_child
|
||||
|
||||
return new_child
|
||||
end
|
||||
|
||||
def sort!
|
||||
@children.sort! do |a, b|
|
||||
result = nil
|
||||
result = 1 if a.type == :file && b.type == :folder
|
||||
result = -1 if a.type == :folder && b.type == :file
|
||||
if a.type == :file && b.type == :file
|
||||
|
||||
result = File.basename(a.relative_name).downcase <=> File.basename(b.relative_name).downcase
|
||||
end
|
||||
result = a.name.downcase <=> b.name.downcase if a.type == :folder && b.type == :folder
|
||||
result
|
||||
end
|
||||
@children.each do |child|
|
||||
child.sort!
|
||||
end
|
||||
end
|
||||
|
||||
def print(out)
|
||||
|
||||
case type
|
||||
when :file
|
||||
out << "<File RelativePath=\"#{relative_name.gsub(/\//,'\\')}\">\r\n"
|
||||
out << "</File>\r\n"
|
||||
|
||||
when :folder
|
||||
|
||||
unless name.nil?
|
||||
out << "<Filter\r\n"
|
||||
out << "Name=\"#{name}\"\r\n"
|
||||
out << "Filter=\"\">\r\n"
|
||||
end
|
||||
children.each do |child|
|
||||
child.print(out)
|
||||
end
|
||||
out << "</Filter>\r\n" unless name.nil?
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
class VCProj
|
||||
|
||||
def VCProj.readMiddle(filename,root)
|
||||
File.open(filename, 'ab')
|
||||
input = IO.readlines(filename)
|
||||
input.each do |line|
|
||||
if (line =~ /RelativePath/)
|
||||
line = line.gsub('\\','/')
|
||||
path = line[line.index('/Src/')..line.rindex('l"')]
|
||||
relative_name = path.sub(/^.*\/Src\//, '../Src/')
|
||||
folder_names = path.sub(/^.*\/Modules\//, '').split('/')
|
||||
current = root
|
||||
while folder_names.size > 0
|
||||
folder_name = folder_names.shift
|
||||
current = current.get_or_create(folder_name)
|
||||
if folder_names.size == 0 #was last
|
||||
current.type = :file
|
||||
current.relative_name = relative_name
|
||||
else
|
||||
current.type = :folder
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def VCProj.generate_vcproj(filename, ccs)
|
||||
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
root = Node.new
|
||||
root.type = :folder
|
||||
VCProj.readMiddle(filename,root)
|
||||
|
||||
ccs.each do |cc|
|
||||
path = File.expand_path(cc.cu.src_fullname)
|
||||
if(path =~ /^.*\/Src\// && path =~ /^.*\/Modules\//)
|
||||
relative_name = path.sub(/^.*\/Src\//, '../Src/')
|
||||
folder_names = path.sub(/^.*\/Modules\//, '').split('/')
|
||||
|
||||
current = root
|
||||
while folder_names.size > 0
|
||||
folder_name = folder_names.shift
|
||||
current = current.get_or_create(folder_name)
|
||||
if folder_names.size == 0 #was last
|
||||
current.type = :file
|
||||
current.relative_name = relative_name
|
||||
else
|
||||
current.type = :folder
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
root.sort!
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
File.open(filename, "w") do |file|
|
||||
root.print(file)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,887 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
#make the script run from any location and workaround for cygwin ruby and windows style dirs
|
||||
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
||||
$LOAD_PATH << File.expand_path(File.dirname(__FILE__)).sub(/^([A-Za-z]):/, '/cygdrive/\1')
|
||||
|
||||
require 'logger'
|
||||
require 'optparse'
|
||||
require 'translator'
|
||||
require 'xabsl_parser.tab'
|
||||
require 'fileutils'
|
||||
require 'vcproj'
|
||||
require 'ftools'
|
||||
|
||||
module Translator
|
||||
|
||||
class XabslCompiler
|
||||
|
||||
def initialize
|
||||
super
|
||||
|
||||
@fp_stb = FirstPassSyntaxTreeBuilder.new
|
||||
@sp_stb = SecondPassSyntaxTreeBuilder.new
|
||||
@tp_stb = ThirdPassSyntaxTreeBuilder.new
|
||||
@parser = XabslParser.new
|
||||
@errors = false
|
||||
end
|
||||
|
||||
def prepare_cc(cc)
|
||||
|
||||
cc.pc.option_root = RootLanguageElement.new
|
||||
cc.pc.option_root.doctype = "<!DOCTYPE #{DTD_INCLUDE_ENTITY} SYSTEM \"../#{DTD_INCLUDE_FILE}\">"
|
||||
cc.pc.namespace_root = RootLanguageElement.new
|
||||
|
||||
cc.pc.option_definitions_temp = RootLanguageElement.new
|
||||
|
||||
ac_tag = AgentCollectionTag.new
|
||||
ac_tag.attr[ATTR_XMLNS] = "http://www.xabsl.de"
|
||||
ac_tag.attr[ATTR_XMLNS_XSI] = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
ac_tag.attr[ATTR_XMLNS_XI] = "http://www.w3.org/2003/XInclude"
|
||||
ac_tag.add_child(TitleTag.new)
|
||||
ac_tag.add_child(PlatformTag.new)
|
||||
ac_tag.add_child(SoftwareEnvironmentTag.new)
|
||||
|
||||
cc.pc.agent_collection_root = RootLanguageElement.new
|
||||
cc.pc.agent_collection_root.doctype = "<!DOCTYPE options [" << ENDL << " <!ENTITY #{OPTION_DEFINITIONS_ENTITY} SYSTEM \"#{OPTION_DEFINITIONS_FILE}\">" << ENDL << "]>"
|
||||
cc.pc.agent_collection_root.add_child(ac_tag)
|
||||
end
|
||||
|
||||
def pass(cc, stb)
|
||||
begin
|
||||
LOG.info "#{stb.class} #{cc.cu.src_filename}"
|
||||
@parser.parse(cc, stb)
|
||||
|
||||
rescue InternalError => error
|
||||
#if there are errors, the internal error is most likely caused by them
|
||||
unless errors?
|
||||
$stderr << cc.eh.visual_studio_format(error)
|
||||
|
||||
$stderr.print(error.class.name + ENDL)
|
||||
error.backtrace.each do |trace|
|
||||
$stderr.print trace
|
||||
$stderr.print ENDL
|
||||
end
|
||||
exit 1
|
||||
end
|
||||
rescue CompilerFatal => message
|
||||
$stderr << cc.eh.visual_studio_format(message)
|
||||
exit 100
|
||||
rescue CompilerMessage => message
|
||||
cc.eh.error message
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def write_xabsl(output_path, cc)
|
||||
|
||||
filename = File.join(output_path, cc.cu.dest_fullname)
|
||||
|
||||
if File.file?(filename) && File.stat(filename).mtime > cc.cu.src_mtime
|
||||
return 0
|
||||
end
|
||||
|
||||
#generate XML output
|
||||
LOG.info "writing #{filename}"
|
||||
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
File.open(filename, 'wb') do |dest|
|
||||
root = nil
|
||||
if cc.pc.option_declared
|
||||
root = cc.pc.option_root
|
||||
elsif cc.pc.namespace_declared
|
||||
root = cc.pc.namespace_root
|
||||
elsif cc.pc.agent_declared
|
||||
root = cc.pc.agent_collection_root
|
||||
else
|
||||
raise InternalError.new
|
||||
end
|
||||
|
||||
root.to_xml Out.new(dest)
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
def write_intermediate_code(ccs, agent_cc, filename)
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
LOG.info "writing #{filename}"
|
||||
|
||||
option_symbols_order = []
|
||||
|
||||
#gather option symbols from compilation contexts
|
||||
#and remember order
|
||||
ccs.each do |cc|
|
||||
|
||||
next unless cc.pc.option_declared
|
||||
option_symbol = cc.pc.option_root.child(OptionTag).attr[ATTR_NAME]
|
||||
option_symbols_order << [cc, option_symbol]
|
||||
end
|
||||
|
||||
option_symbols_order.sort! do |a,b|
|
||||
a[1].identifier.downcase <=> b[1].identifier.downcase
|
||||
end
|
||||
|
||||
File.open(filename, 'wb') do |file|
|
||||
out = Out.new(file)
|
||||
title = agent_cc.pc.agent_collection_root.child(AgentCollectionTag).child(TitleTag).string
|
||||
|
||||
out << "// Intermediate code for the agents of #{title}" << ENDL
|
||||
out << ENDL
|
||||
|
||||
#process internal symbols
|
||||
internal_output_symbols = []
|
||||
internal_enum_symbols = []
|
||||
agent_cc.st.each do |symbol|
|
||||
case symbol
|
||||
when BooleanOutputSymbol, DecimalOutputSymbol, EnumOutputSymbol:
|
||||
if symbol.internal
|
||||
internal_output_symbols << symbol
|
||||
end
|
||||
when EnumSymbol:
|
||||
if symbol.internal
|
||||
internal_enum_symbols << symbol
|
||||
end
|
||||
end
|
||||
end
|
||||
out << "// number of internal enumerations:" << ENDL if out.verbose
|
||||
out << "#{internal_enum_symbols.size}" << ENDL
|
||||
out << "// (enumeration number-of-elements (element)*)+" << ENDL if out.verbose
|
||||
internal_enum_symbols.sort! do |a,b|
|
||||
a.identifier.downcase <=> b.identifier.downcase
|
||||
end
|
||||
internal_enum_symbols.each do |symbol|
|
||||
out << "#{symbol.identifier}"
|
||||
out << " #{symbol.value_symbols.size}"
|
||||
symbol.value_symbols.each do |symbol|
|
||||
out << " #{symbol.identifier}"
|
||||
end
|
||||
out << ENDL
|
||||
end
|
||||
out << "// number of internal output symbols" << ENDL if out.verbose
|
||||
out << "#{internal_output_symbols.size}" << ENDL
|
||||
out << "// (d decimal-input-symbol | b boolean-input-symbol | e enum enumerated-input-symbol)+" << ENDL if out.verbose
|
||||
internal_output_symbols.sort! do |a,b|
|
||||
a.identifier.downcase <=> b.identifier.downcase
|
||||
end
|
||||
internal_output_symbols.each do |symbol|
|
||||
case symbol
|
||||
when BooleanOutputSymbol:
|
||||
out << "b "
|
||||
when DecimalOutputSymbol:
|
||||
out << "d "
|
||||
when EnumOutputSymbol:
|
||||
out << "e #{symbol.enum_domain.identifier} "
|
||||
else
|
||||
raise InternalError.new
|
||||
end
|
||||
out << "#{symbol.identifier}"
|
||||
out << ENDL
|
||||
end
|
||||
out << ENDL
|
||||
|
||||
#process options
|
||||
out << '// number of options' << ENDL if out.verbose
|
||||
out << "#{option_symbols_order.size}" << ENDL
|
||||
out << '// names, number of parameters, parameters for all options' << ENDL if out.verbose
|
||||
|
||||
option_symbols_order.each do |cc, option_symbol|
|
||||
out << "#{option_symbol.identifier} #{option_symbol.value_symbols.size}"
|
||||
option_symbol.value_symbols.each do |parameter_symbol|
|
||||
case parameter_symbol.type
|
||||
when :decimal:
|
||||
out << " d"
|
||||
when :boolean:
|
||||
out << " b"
|
||||
when :enum:
|
||||
out << " e #{parameter_symbol.enum_domain.identifier}"
|
||||
else
|
||||
raise InternalError.new
|
||||
end
|
||||
out << " #{parameter_symbol.identifier}"
|
||||
end
|
||||
out << ENDL
|
||||
end
|
||||
out << ENDL
|
||||
|
||||
option_symbols_order.each do |cc, option_symbol|
|
||||
cc.pc.option_root.child(OptionTag).to_ic(out)
|
||||
end
|
||||
|
||||
#process agents
|
||||
agent_tags = Array.new(agent_cc.pc.agent_collection_root.child(AgentCollectionTag).children)
|
||||
agent_tags.delete_if do |tag|
|
||||
tag.class != AgentTag
|
||||
end
|
||||
out << "// number of agents:" << ENDL if out.verbose
|
||||
out << "#{agent_tags.size}" << ENDL
|
||||
out << "// agents: (name initial-option)+" << ENDL if out.verbose
|
||||
first = true
|
||||
agent_tags.each do |tag|
|
||||
out << " " unless first
|
||||
out << "#{tag.attr[ATTR_ID].identifier} #{tag.attr[ATTR_ROOT_OPTION].identifier}"
|
||||
first = false
|
||||
end
|
||||
out << ENDL
|
||||
end
|
||||
end
|
||||
|
||||
def gather_incremental(st, all_ccs)
|
||||
changed_ccs = []
|
||||
all_ccs.each do |cc|
|
||||
|
||||
unless FileTest.readable?(cc.cu.src_fullname)
|
||||
LOG.info "file not readable #{cc.cu.src_filename}, switching to non-incremental mode"
|
||||
throw :non_incremental
|
||||
end
|
||||
|
||||
if cc.cu.src_mtime != File.stat(cc.cu.src_fullname).mtime
|
||||
changed_ccs << cc
|
||||
LOG.info "#{cc.cu.src_filename} modified"
|
||||
end
|
||||
end
|
||||
if changed_ccs.empty?
|
||||
LOG.info "nothing to do -- should proceed to output"
|
||||
end
|
||||
|
||||
#now gather symbols defined in changed_ccs
|
||||
symbols = []
|
||||
changed_ccs.each do |cc|
|
||||
symbols += cc.sc.from_code_declaration_count.keys
|
||||
end
|
||||
|
||||
symbols.uniq!
|
||||
symbols.each do |symbol|
|
||||
LOG.info "uses symbol #{symbol.identifier}"
|
||||
end
|
||||
|
||||
#now gather ccs again that use these symbols
|
||||
all_ccs.each do |cc|
|
||||
symbols.each do |symbol|
|
||||
if cc.sc.from_code_usage_count[symbol] > 0
|
||||
changed_ccs << cc
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
changed_ccs.uniq!
|
||||
|
||||
changed_ccs.each do |cc|
|
||||
cc.sc.from_code_declaration_count.keys.each do |symbol|
|
||||
symbols << symbol
|
||||
end
|
||||
LOG.info "used by #{cc.cu.src_filename}"
|
||||
|
||||
if cc.pc.includes.size > 0
|
||||
LOG.info "includes detected: switching to non-incremental mode"
|
||||
throw :non_incremental
|
||||
end
|
||||
end
|
||||
|
||||
symbols.uniq!
|
||||
symbols.each do |symbol|
|
||||
LOG.info "undeclaring symbol #{symbol.identifier}"
|
||||
st.remove symbol
|
||||
end
|
||||
|
||||
#generate new CompilerContexts for files that need recompiling
|
||||
all_ccs = all_ccs - changed_ccs
|
||||
ccs = []
|
||||
changed_ccs.each do |cc|
|
||||
ccs << CompilerContext.new(cc.cu, st)
|
||||
cc.cu.update_src_mtime
|
||||
end
|
||||
all_ccs += ccs
|
||||
|
||||
return [all_ccs, ccs]
|
||||
end
|
||||
|
||||
def errors?
|
||||
@error_ccs.each do |cc|
|
||||
return true if cc.errors?
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def translate(hash_value, compilation_units, write)
|
||||
@error_ccs = []
|
||||
|
||||
dump_filename = File.join(write[:inc], "xabsl.#{hash_value}.dump") if write[:inc]
|
||||
|
||||
agent_cc = nil
|
||||
message_count = Hash.new(0)
|
||||
st = nil
|
||||
marshalled_dump = nil
|
||||
options_tag = OptionsTag.new
|
||||
option_defintions_tag = ODSTag.new
|
||||
|
||||
ods_tag = ODSTag.new
|
||||
ods_tag.attr[ATTR_XMLNS] = "http://www.xabsl.de"
|
||||
ods_tag.attr[ATTR_XMLNS_XSI] = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
|
||||
option_definitions_root = RootLanguageElement.new
|
||||
option_definitions_root.add_child ods_tag
|
||||
|
||||
|
||||
build_ccs = nil
|
||||
all_ccs = nil
|
||||
incremental = false
|
||||
files_written = 0
|
||||
|
||||
if compilation_units.size > 1
|
||||
$stderr.puts "please give only one filename on command line"
|
||||
exit(1)
|
||||
end
|
||||
main_cu = compilation_units[0]
|
||||
|
||||
elapsed_time = Translator.stopwatch("whole compilation run") do
|
||||
|
||||
catch :non_incremental do
|
||||
if write[:inc]
|
||||
loaded = nil
|
||||
|
||||
unless FileTest.exists?(dump_filename)
|
||||
LOG.info "no dump file: switching to non-incremental mode"
|
||||
throw :non_incremental
|
||||
end
|
||||
|
||||
idle_run = true
|
||||
File.open(dump_filename, 'rb') do |file|
|
||||
precheck_cus = nil
|
||||
begin
|
||||
precheck_cus = Marshal.load(file)
|
||||
rescue EOFError
|
||||
throw :non_incremental
|
||||
end
|
||||
begin
|
||||
precheck_cus.each do |cu|
|
||||
#here only input files are checked as (shared) output files can be generated more than once
|
||||
idle_run = idle_run && (cu.src_mtime == File.stat(cu.src_fullname).mtime)
|
||||
end
|
||||
rescue Errno::ENOENT
|
||||
idle_run = false
|
||||
end
|
||||
|
||||
loaded = Marshal.load(file)
|
||||
end
|
||||
|
||||
#just to be sure
|
||||
if loaded[0] != hash_value
|
||||
LOG.info "mismatching hash_value: switching to non-incremental mode"
|
||||
throw :non_incremental
|
||||
end
|
||||
|
||||
hash_value, st, ccs = loaded
|
||||
#absolutely nothing changed
|
||||
if idle_run
|
||||
LOG.info "ultimate shortcut. none of the input files has changed."
|
||||
(1..rand(4)+1).each do
|
||||
$stdout.print "Z"
|
||||
(2..rand(5)+2).each do
|
||||
$stdout.print "z"
|
||||
end
|
||||
$stdout.print " "
|
||||
end
|
||||
$stdout.puts
|
||||
all_ccs = ccs
|
||||
build_ccs = []
|
||||
else
|
||||
all_ccs, build_ccs = gather_incremental(st, ccs)
|
||||
end
|
||||
incremental = true
|
||||
end
|
||||
end
|
||||
|
||||
#stuff for non-incremental use
|
||||
unless incremental
|
||||
|
||||
# create symbol table
|
||||
st = SymbolTable.new
|
||||
|
||||
#create compiler_contexts
|
||||
build_ccs = []
|
||||
all_ccs = []
|
||||
compilation_units.each do |cu|
|
||||
build_ccs << CompilerContext.new(cu, st)
|
||||
end
|
||||
end
|
||||
|
||||
@error_ccs = Array.new(build_ccs + all_ccs).uniq
|
||||
|
||||
#prepare and first pass
|
||||
processed_ccs = {}
|
||||
included_ccs = {}
|
||||
double_include = false
|
||||
while !build_ccs.empty?
|
||||
|
||||
cc = build_ccs.shift
|
||||
processed_ccs[cc.cu.src_fullname] = cc
|
||||
|
||||
prepare_cc(cc)
|
||||
next if cc.errors?
|
||||
pass(cc, @fp_stb)
|
||||
|
||||
|
||||
#keep in mind: if there are includes in the file, incremental build is disabled
|
||||
processed_filenames = {}
|
||||
cc.pc.includes.each do |filename|
|
||||
src_fullname = File.join(File.dirname(cc.cu.src_fullname), filename)
|
||||
dest_fullname = File.join(File.dirname(cc.cu.dest_fullname), filename)
|
||||
matched = 0
|
||||
cc.pc.includes.each do |filename2|
|
||||
if filename == filename2
|
||||
matched += 1
|
||||
end
|
||||
if matched > 1 && processed_filenames[filename].nil?
|
||||
processed_filenames[filename] = filename2
|
||||
cc.eh.error DoubleIncludeError.new(cc, src_fullname)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
unless File.basename(src_fullname) =~ /^(.*)\.[xy]absl$/
|
||||
cc.eh.error FileTypeError.new(cc, src_fullname)
|
||||
next
|
||||
end
|
||||
if processed_ccs[src_fullname].nil? && included_ccs[src_fullname].nil?
|
||||
if FileTest.file?(src_fullname)
|
||||
cu_new = CompilationUnit.new
|
||||
cu_new.set_src(File.dirname(src_fullname), File.basename(src_fullname))
|
||||
|
||||
# set default destination, for any file containing valid information this will be overwritten by SyntaxTreeBuilder
|
||||
cu_new.set_dest(".")
|
||||
|
||||
cc_new = CompilerContext.new(cu_new, st)
|
||||
included_ccs[src_fullname] = cc_new
|
||||
build_ccs << cc_new
|
||||
@error_ccs = Array.new(build_ccs + all_ccs).uniq
|
||||
else
|
||||
cc.eh.error FileOpenError.new(cc, src_fullname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
build_ccs = processed_ccs.values
|
||||
all_ccs = (all_ccs + build_ccs).uniq
|
||||
@error_ccs = Array.new(build_ccs + all_ccs).uniq
|
||||
|
||||
#dump .vcproj on command
|
||||
if write[:vcproj]
|
||||
VCProj.generate_vcproj(write[:vcproj], all_ccs)
|
||||
files_written+=1
|
||||
end
|
||||
|
||||
|
||||
#second pass
|
||||
build_ccs.each do |cc|
|
||||
#unless cc.errors?
|
||||
if (not cc.errors?) || write[:force]
|
||||
pass(cc, @sp_stb)
|
||||
end
|
||||
end
|
||||
|
||||
#third pass
|
||||
build_ccs.each do |cc|
|
||||
#unless cc.errors?
|
||||
if (not cc.errors?) || write[:force]
|
||||
pass(cc, @tp_stb)
|
||||
end
|
||||
end
|
||||
|
||||
#generate messages for unused symbols
|
||||
st.each do |symbol|
|
||||
unless (symbol.class <= AgentSymbol || symbol.class <= NamespaceSymbol)
|
||||
if (symbol.usage_count <= 1)
|
||||
message = "#{symbol.class.name} '#{symbol.identifier}' "
|
||||
message += "in #{symbol.domain_symbol.class.name} '#{symbol.domain_symbol.identifier}' " if symbol.class <= DomainValueSymbol
|
||||
message += "(#{symbol.namespace_symbol.identifier}) " if symbol.namespace_symbol.class <= NamespaceSymbol
|
||||
message += "is defined but never used"
|
||||
LOG.info message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#postprocessing
|
||||
build_ccs.each do |cc|
|
||||
unless errors?
|
||||
#postprocessing: generate entities for each fresh compiled option
|
||||
if cc.pc.option_declared
|
||||
cc.pc.option_root.child(OptionTag).entities += cc.sc.used_namespace_symbols
|
||||
end
|
||||
end
|
||||
|
||||
#misc: count errors and warnings
|
||||
cc.eh.messages.each do |message|
|
||||
message_count[CompilerError] +=1 if message.class <= CompilerError
|
||||
message_count[CompilerWarning] +=1 if message.class <= CompilerWarning
|
||||
end
|
||||
end
|
||||
|
||||
#print and count errors from symbol table
|
||||
st.errors.each do |message|
|
||||
|
||||
if write[:vs]
|
||||
$stderr.puts cc.eh.visual_studio_format(message)
|
||||
else
|
||||
$stderr.puts cc.eh.format(message)
|
||||
end
|
||||
|
||||
message_count[CompilerError] +=1 if message.class <= CompilerError
|
||||
message_count[CompilerWarning] +=1 if message.class <= CompilerWarning
|
||||
end
|
||||
|
||||
# marshal everything if there were no errors
|
||||
# the trick to do this *here* is: we are going to modify the syntax trees below for output generation
|
||||
# but we want unmodified trees for incremental compiling
|
||||
if write[:inc] && message_count[CompilerError] == 0
|
||||
marshalled_dump = Marshal.dump([hash_value, st, all_ccs])
|
||||
end
|
||||
|
||||
#prepare options tag for agents tag, find agents_cc
|
||||
file_entities = {}
|
||||
|
||||
unless errors?
|
||||
all_ccs.each do |cc|
|
||||
next if cc.errors?
|
||||
|
||||
root = nil
|
||||
root_counter = 0
|
||||
if cc.pc.option_declared
|
||||
root_counter += 1
|
||||
root = cc.pc.option_root
|
||||
|
||||
#add xincludes to options files
|
||||
xinclude_tag = XIncludeTag.new
|
||||
xinclude_tag.attr[ATTR_HREF] = File.relative_path(cc.cu.dest_fullname, main_cu.dest_dir)
|
||||
options_tag.add_child(xinclude_tag)
|
||||
|
||||
raise InternalError.new if cc.pc.option_definitions_temp.children.size != 1
|
||||
odTag = cc.pc.option_definitions_temp.child(ODTag)
|
||||
cc.pc.option_definitions_temp.remove_child odTag
|
||||
ods_tag.add_child(odTag)
|
||||
|
||||
option_symbol = cc.pc.option_root.child(OptionTag).attr[ATTR_NAME]
|
||||
file_entities[option_symbol] = File.relative_path(cc.cu.dest_fullname, main_cu.dest_dir)
|
||||
end
|
||||
if cc.pc.namespace_declared
|
||||
root_counter += 1
|
||||
root = cc.pc.namespace_root
|
||||
|
||||
#get symbols oder basic-behaviors tag and the id of this tag
|
||||
symbol = root.children[0].attr[ATTR_ID]
|
||||
|
||||
file_entities[symbol] = File.relative_path(cc.cu.dest_fullname, main_cu.dest_dir)
|
||||
end
|
||||
if cc.pc.agent_declared
|
||||
root_counter += 1
|
||||
root = cc.pc.agent_collection_root
|
||||
|
||||
#identified agent cc
|
||||
raise InternalError.new('multiple agent files encountered. i cannot handle this.') unless agent_cc.nil?
|
||||
agent_cc = cc
|
||||
|
||||
|
||||
ac_tag = cc.pc.agent_collection_root.child(AgentCollectionTag)
|
||||
ac_tag.child(TitleTag).string = ac_tag.title
|
||||
ac_tag.child(PlatformTag).string = ac_tag.platform
|
||||
ac_tag.child(SoftwareEnvironmentTag).string = ac_tag.software_environment
|
||||
ac_tag.add_child(options_tag)
|
||||
end
|
||||
|
||||
#check that other roots are really empty and the roots contain exactly 1 le
|
||||
raise InternalError.new if root_counter != 1
|
||||
raise InternalError.new if root.children.size != 1
|
||||
end
|
||||
|
||||
raise InternalError.new('agent file is not on command line.') if agent_cc.nil?
|
||||
#ab hier ist agents_cc != nil
|
||||
#main__cu sollte das gleiche sein
|
||||
end
|
||||
|
||||
all_ccs.each do |cc|
|
||||
#print errors and warnings
|
||||
cc.eh.messages.each_index do |index|
|
||||
#break if index >= 1
|
||||
message = cc.eh.messages[index]
|
||||
if write[:vs]
|
||||
$stderr.puts cc.eh.visual_studio_format(message)
|
||||
else
|
||||
$stderr.puts cc.eh.format(message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if write[:xabsl]
|
||||
all_ccs.each do |cc|
|
||||
|
||||
#generate a relative filename
|
||||
dtd_relative_filename = File.relative_path(DTD_INCLUDE_FILE, cc.cu.dest_dir)
|
||||
|
||||
#set doctype for options (we don't care whether it's actually an option file)
|
||||
cc.pc.option_root.doctype = "<!DOCTYPE #{DTD_INCLUDE_ENTITY} SYSTEM \"#{dtd_relative_filename}\">"
|
||||
|
||||
#only produce output if there were no errors
|
||||
if (write[:force] ||(!agent_cc.nil? && message_count[CompilerError] == 0))
|
||||
if cc == agent_cc
|
||||
#sort agent option by filename
|
||||
options_tag.children.sort! do |a,b|
|
||||
a.attr[ATTR_HREF] =~ /^(.*)\.xml$/
|
||||
x = $1.to_s
|
||||
b.attr[ATTR_HREF] =~ /^(.*)\.xml$/
|
||||
x <=> $1.to_s
|
||||
end
|
||||
end
|
||||
|
||||
files_written += write_xabsl(write[:xabsl], cc)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if message_count[CompilerError] == 0
|
||||
|
||||
if write[:xabsl]
|
||||
|
||||
|
||||
#generate option-defintions-file
|
||||
option_definitions_root.child(ODSTag).children.sort! do |a,b|
|
||||
a.attr[ATTR_NAME] <=> b.attr[ATTR_NAME]
|
||||
end
|
||||
|
||||
filename = File.join(write[:xabsl], OPTION_DEFINITIONS_FILE)
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
LOG.info "writing #{filename}"
|
||||
File.open(filename+".new", 'wb') do |dest|
|
||||
option_definitions_root.to_xml Out.new(dest)
|
||||
end
|
||||
if File.file?(filename) && File.cmp(filename+".new",filename)
|
||||
File.delete(filename+".new")
|
||||
else
|
||||
File.delete(filename) if File.file?(filename)
|
||||
File.rename(filename+".new",filename)
|
||||
files_written+=1
|
||||
end
|
||||
|
||||
#generate dtd-file
|
||||
file_entities[OPTION_DEFINITIONS_ENTITY] = OPTION_DEFINITIONS_FILE
|
||||
filename = File.join(write[:xabsl], DTD_INCLUDE_FILE)
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
|
||||
LOG.info "writing #{filename}"
|
||||
File.open(filename+".new", 'wb') do |dest|
|
||||
DTDEntityWriter.new.write(file_entities, dest)
|
||||
end
|
||||
if File.file?(filename) && File.cmp(filename+".new",filename)
|
||||
File.delete(filename+".new")
|
||||
else
|
||||
File.delete(filename) if File.file?(filename)
|
||||
File.rename(filename+".new",filename)
|
||||
files_written+=1
|
||||
end
|
||||
end
|
||||
|
||||
if write[:ic]
|
||||
raise InternalError.new if agent_cc.nil?
|
||||
write_intermediate_code(all_ccs, agent_cc, write[:ic]) if write[:ic]
|
||||
files_written+=1
|
||||
end
|
||||
|
||||
if write[:api]
|
||||
filename = write[:api]
|
||||
keywords = []
|
||||
if FileTest.exists?(filename)
|
||||
File.open(filename, 'rb') do |file|
|
||||
file.each do |line|
|
||||
keywords << line.chomp unless line =~ /^\s*$/ #keine leerzeilen
|
||||
end
|
||||
end
|
||||
end
|
||||
st.each do |symbol|
|
||||
next if [AgentSymbol, NamespaceSymbol].include?(symbol.class)
|
||||
|
||||
if [DecimalInputSymbol, BooleanInputSymbol, EnumInputSymbol, OptionSymbol, BasicBehaviorSymbol].include?(symbol.class)
|
||||
keyword = "#{SymbolContext.to_code(symbol, false)}("
|
||||
first = true
|
||||
symbol.value_symbols.each do |value_symbol|
|
||||
keyword += ", " unless first
|
||||
keyword += "#{SymbolContext.to_code(value_symbol, false)} = "
|
||||
first = false
|
||||
end
|
||||
|
||||
keyword += ")"
|
||||
keywords << keyword
|
||||
else
|
||||
keywords << SymbolContext.to_code(symbol, false)
|
||||
end
|
||||
end
|
||||
|
||||
Tokenizer.keywords.each do |key, value|
|
||||
keywords << key
|
||||
end
|
||||
|
||||
keywords.uniq!
|
||||
keywords.sort! do |x,y|
|
||||
x.downcase <=> y.downcase
|
||||
end
|
||||
|
||||
LOG.info "writing #{filename}"
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
File.open(filename, 'wb') do |file|
|
||||
keywords.each do |keyword|
|
||||
file.puts keyword
|
||||
end
|
||||
end
|
||||
|
||||
files_written+=1
|
||||
end
|
||||
|
||||
#dump updated cus here
|
||||
if write[:inc]
|
||||
FileUtils.mkdir_p(File.dirname(dump_filename))
|
||||
File.open(dump_filename, 'wb') do |file|
|
||||
dump_cus = []
|
||||
all_ccs.each do |cc|
|
||||
dump_cus << cc.cu
|
||||
end
|
||||
file.write Marshal.dump(dump_cus)
|
||||
file.write marshalled_dump
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
$stdout.puts "#{build_ccs.size} compiled, #{files_written} written, #{message_count[CompilerError]} error(s), #{message_count[CompilerWarning]} warning(s), elapsed time #{elapsed_time}s"
|
||||
$stdout.puts
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##################################################
|
||||
|
||||
#profiler = Translator::Profiler.new(Translator::SymbolContext, "Translator", "SymbolContext", "from_code")
|
||||
|
||||
|
||||
LOG = Logger.new(STDOUT)
|
||||
LOG.datetime_format = ""
|
||||
LOG.level = Logger::WARN
|
||||
|
||||
help = false
|
||||
output_path = nil
|
||||
write = Hash.new(false)
|
||||
opts = OptionParser.new do |opts|
|
||||
|
||||
opts.banner = "XABSL compiler" << ENDL << ENDL
|
||||
opts.banner += "usage: #{opts.program_name} [options] file(s)"
|
||||
opts.separator ""
|
||||
opts.separator "options:"
|
||||
|
||||
|
||||
opts.on("-q", "--quiet", "suppresses almost any output") do
|
||||
LOG.level = Logger::FATAL
|
||||
end
|
||||
|
||||
opts.on("-v", "--verbose", "run verbosely") do
|
||||
case LOG.level
|
||||
when Logger::INFO
|
||||
LOG.level = Logger::DEBUG
|
||||
when Logger::WARN
|
||||
LOG.level = Logger::INFO
|
||||
else
|
||||
LOG.level = Logger::WARN
|
||||
end
|
||||
end
|
||||
|
||||
opts.on("-x", "--xml path", "generate xml at <path>") do |path|
|
||||
write[:xabsl] = File.expand_path(path)
|
||||
end
|
||||
|
||||
opts.on("-i", "--intermediate-code filename", "generate intermediate code") do |filename|
|
||||
write[:ic] = filename
|
||||
end
|
||||
|
||||
opts.on("-a", "--api-file filename", "create .api file and copy it to scite/VisualStudio locations") do |filename|
|
||||
write[:api] = filename
|
||||
end
|
||||
|
||||
opts.on("-m", "--vcproj filename", "create .vcproj middle file") do |filename|
|
||||
write[:vcproj] = filename
|
||||
end
|
||||
|
||||
opts.on("-I", "--incremental directory", "incremental compiling, put dumpfiles to given directory") do |directory|
|
||||
write[:inc] = directory
|
||||
end
|
||||
|
||||
opts.on("-C", "--comments", "insert additional comments into generated files") do
|
||||
write[:comments] = true
|
||||
end
|
||||
|
||||
opts.on("-V", "--vs-error-message-style", "produce visual studio compliant error messages") do
|
||||
write[:vs] = true
|
||||
end
|
||||
opts.on("-f", "--force-output", "will force output even if errors occured (useful when working with single files") do
|
||||
write[:force] = true
|
||||
LOG.warn "using option 'force output' - please notice that some displayed errors may be important some not"
|
||||
end
|
||||
|
||||
opts.on_tail("-h", "--help", "show this message") do
|
||||
help = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#print help if requested or no filenames are supplied
|
||||
filenames = opts.parse!
|
||||
if help || filenames.empty?
|
||||
puts opts
|
||||
exit
|
||||
end
|
||||
|
||||
#check file existence and readablity
|
||||
errors = false
|
||||
compilation_units = []
|
||||
filenames.each do |src_filename|
|
||||
|
||||
unless src_filename =~ /^(.*)\.[xy]absl$/
|
||||
LOG.error "file '#{src_filename}' doesn't have extension .xabsl"
|
||||
errors = true
|
||||
next
|
||||
end
|
||||
dest_filename = "#{$1.to_s}.xml"
|
||||
|
||||
unless FileTest.file?(src_filename) && FileTest.readable?(src_filename)
|
||||
LOG.error "unable to read from file '#{src_filename}'"
|
||||
errors = true
|
||||
next
|
||||
end
|
||||
|
||||
cu = Translator::CompilationUnit.new
|
||||
cu.set_src(File.dirname(src_filename), File.basename(src_filename))
|
||||
cu.set_dest(".")
|
||||
compilation_units << cu
|
||||
|
||||
end
|
||||
exit 1 if errors
|
||||
|
||||
#hmmm put this elsewhere
|
||||
unless write.empty?
|
||||
|
||||
timestamp_mtime = File.stat(TIMESTAMP_FILE).mtime
|
||||
|
||||
Dir.foreach('.') do |entry|
|
||||
if entry =~ /xabsl\.[0-9A-Fa-f]+\.dump/ && FileTest.file?(entry) && File.stat(entry).mtime <= timestamp_mtime
|
||||
LOG.info "removing #{entry} because compiler timestamp is newer"
|
||||
FileUtils.rm(entry)
|
||||
end
|
||||
end
|
||||
|
||||
hash_value = "%8.8X" % [filenames.join.hash]
|
||||
translator = Translator::XabslCompiler.new
|
||||
translator.translate(hash_value, compilation_units, write)
|
||||
end
|
||||
|
||||
|
||||
#profiler.log
|
||||
LOG.close
|
||||
|
||||
exit 1 if translator.errors?
|
||||
|
||||
end
|
||||
@ -0,0 +1,604 @@
|
||||
class Translator::XabslParser
|
||||
|
||||
prechigh
|
||||
nonassoc UMINUS '!'
|
||||
left '*' '/' '%'
|
||||
left '+' '-'
|
||||
nonassoc '<' '>' LE GE EQ NEQ
|
||||
left AND
|
||||
left OR
|
||||
nonassoc '?' ':'
|
||||
preclow
|
||||
|
||||
|
||||
token
|
||||
LE
|
||||
GE
|
||||
EQ
|
||||
NEQ
|
||||
AND
|
||||
OR
|
||||
ACTION
|
||||
NUMBER
|
||||
TRUE
|
||||
FALSE
|
||||
STRING
|
||||
RANGE
|
||||
INTERNAL
|
||||
IDENTIFIER
|
||||
DOC_COMMENT
|
||||
INITIAL_COMMENT
|
||||
OPTION
|
||||
STATE
|
||||
COMMON
|
||||
DECISION
|
||||
TTS
|
||||
STAY
|
||||
DT
|
||||
CDT
|
||||
UMINUS
|
||||
IF
|
||||
ELSE
|
||||
TOOX
|
||||
TOSX
|
||||
SORTS
|
||||
INITIAL
|
||||
TARGET
|
||||
AGENT
|
||||
FUNCTION
|
||||
ENUM
|
||||
INPUT
|
||||
OUTPUT
|
||||
BOOL
|
||||
FLOAT
|
||||
CONST
|
||||
NAMESPACE
|
||||
BEHAVIOR
|
||||
INCLUDE
|
||||
SYNCHRONIZED
|
||||
CAPACITY
|
||||
CONFLICT
|
||||
'{' '}'
|
||||
'(' ')'
|
||||
'|' ',' ';'
|
||||
'+' '-'
|
||||
'*' '/'
|
||||
'<' '<=' '>' '>=' '==' '!'
|
||||
':' '?'
|
||||
|
||||
rule
|
||||
|
||||
xtc:
|
||||
__initial_comment
|
||||
__top_level
|
||||
{@stb.comments(val)}
|
||||
;
|
||||
|
||||
__initial_comment:
|
||||
INITIAL_COMMENT
|
||||
|
|
||||
;
|
||||
|
||||
__top_level:
|
||||
include
|
||||
__top_level
|
||||
|
|
||||
option
|
||||
|
|
||||
agents
|
||||
|
|
||||
namespace
|
||||
|
|
||||
;
|
||||
|
||||
agents:
|
||||
agent
|
||||
agents
|
||||
|
|
||||
agent
|
||||
;
|
||||
|
||||
include:
|
||||
INCLUDE STRING ';'
|
||||
{return @stb.include(val)}
|
||||
;
|
||||
|
||||
namespace:
|
||||
__doc_comment
|
||||
NAMESPACE IDENTIFIER '(' STRING ')' '{'
|
||||
{@stb.namespace_early(_values)}
|
||||
__inner_namespace
|
||||
'}'
|
||||
{return @stb.namespace(val)}
|
||||
;
|
||||
|
||||
__inner_namespace:
|
||||
__inner_namespace
|
||||
const
|
||||
{ return val[0] + [val[1]] }
|
||||
|
|
||||
__inner_namespace
|
||||
symbol_declaration
|
||||
{ return val[0] + [val[1]] }
|
||||
|
|
||||
__inner_namespace
|
||||
enum_symbol_declaration
|
||||
{ return val[0] + [val[1]] }
|
||||
|
|
||||
__inner_namespace
|
||||
behavior_declaration
|
||||
{ return val[0] + [val[1]] }
|
||||
|
|
||||
{ return [] }
|
||||
;
|
||||
|
||||
|
||||
behavior_declaration:
|
||||
__doc_comment
|
||||
BEHAVIOR IDENTIFIER '{'
|
||||
{@stb.behavior_declaration_early(_values)}
|
||||
__parameter_declarations
|
||||
'}'
|
||||
{ return @stb.behavior_declaration(val) }
|
||||
;
|
||||
|
||||
symbol_declaration:
|
||||
__doc_comment
|
||||
bool_or_float_or_enum __input_output_internal IDENTIFIER __range __measure
|
||||
{@stb.symbol_declaration_early(_values)}
|
||||
symbol_parameter_declarations
|
||||
';'
|
||||
{return @stb.symbol_declaration(val)}
|
||||
;
|
||||
|
||||
__input_output_internal:
|
||||
INPUT
|
||||
|
|
||||
OUTPUT
|
||||
|
|
||||
INTERNAL
|
||||
|
|
||||
;
|
||||
|
||||
enum_symbol_declaration:
|
||||
__doc_comment
|
||||
bool_or_float_or_enum __input_output_internal
|
||||
'{'
|
||||
enum_elements
|
||||
'}'
|
||||
';'
|
||||
{ return @stb.enum_symbol_declaration(val) }
|
||||
;
|
||||
|
||||
enum_elements:
|
||||
IDENTIFIER
|
||||
__enum_elements
|
||||
{ return [val[0]] + val[1] }
|
||||
;
|
||||
|
||||
__enum_elements:
|
||||
__enum_elements
|
||||
',' IDENTIFIER
|
||||
{ return val[0] + [val[2]] }
|
||||
|
|
||||
{ return [] }
|
||||
;
|
||||
|
||||
__minus:
|
||||
'-'
|
||||
|
|
||||
;
|
||||
|
||||
bool_or_float_or_enum:
|
||||
BOOL
|
||||
|
|
||||
FLOAT
|
||||
|
|
||||
ENUM IDENTIFIER
|
||||
{
|
||||
return val[1]
|
||||
}
|
||||
|
|
||||
;
|
||||
|
||||
const:
|
||||
__doc_comment
|
||||
__float CONST IDENTIFIER '=' __minus NUMBER __measure ';'
|
||||
{return @stb.const(val)}
|
||||
;
|
||||
|
||||
__float:
|
||||
FLOAT
|
||||
|
|
||||
;
|
||||
|
||||
agent:
|
||||
__doc_comment
|
||||
AGENT IDENTIFIER '(' STRING ',' IDENTIFIER ')' ';'
|
||||
{return @stb.agent(val)}
|
||||
;
|
||||
|
||||
option:
|
||||
__doc_comment
|
||||
OPTION IDENTIFIER '{'
|
||||
{@stb.option_early(_values)}
|
||||
__parameter_declarations
|
||||
__common_declarations
|
||||
state_declarations
|
||||
'}'
|
||||
{return @stb.option(val)}
|
||||
;
|
||||
|
||||
symbol_parameter_declarations:
|
||||
'('
|
||||
__parameter_declarations
|
||||
')'
|
||||
{ return val[1] }
|
||||
|
|
||||
;
|
||||
|
||||
__parameter_declarations:
|
||||
__parameter_declarations
|
||||
parameter_declaration
|
||||
{ return [] + val[0] + [val[1]] }
|
||||
|
|
||||
{ return [] };
|
||||
|
||||
parameter_declaration:
|
||||
__doc_comment
|
||||
bool_or_float_or_enum IDENTIFIER __range __measure ';'
|
||||
{return @stb.parameter_declaration(val)}
|
||||
;
|
||||
|
||||
__range:
|
||||
RANGE
|
||||
|
|
||||
;
|
||||
|
||||
__measure:
|
||||
STRING
|
||||
|
|
||||
;
|
||||
|
||||
state_declarations:
|
||||
state_declaration
|
||||
__state_declarations
|
||||
{ return [val[0]] + val[1] }
|
||||
;
|
||||
|
||||
__state_declarations:
|
||||
__state_declarations
|
||||
state_declaration
|
||||
{ return [] + val[0] + [val[1]] }
|
||||
|
|
||||
{ return [] };
|
||||
|
||||
state_declaration:
|
||||
__initial __target STATE IDENTIFIER cooperative '{'
|
||||
{@stb.state_declaration_early(_values)}
|
||||
decision_tree
|
||||
ACTION '{'
|
||||
__output_symbol_assignments_or_subsequent_declarations
|
||||
'}'
|
||||
'}'
|
||||
{ return @stb.state_declaration(val) };
|
||||
|
||||
cooperative:
|
||||
CAPACITY NUMBER
|
||||
{ return [val[0], val[1]] }
|
||||
|
|
||||
SYNCHRONIZED NUMBER
|
||||
{ return [val[0], val[1]] }
|
||||
|
|
||||
SYNCHRONIZED
|
||||
{ return [val[0]] }
|
||||
|;
|
||||
|
||||
__output_symbol_assignments_or_subsequent_declarations:
|
||||
__output_symbol_assignments_or_subsequent_declarations
|
||||
output_symbol_assignment
|
||||
{ return val[0] + [val[1]] }
|
||||
|
|
||||
__output_symbol_assignments_or_subsequent_declarations
|
||||
subsequent_declaration
|
||||
{ return val[0] + [val[1]] }
|
||||
|
|
||||
{ return [] };
|
||||
|
||||
output_symbol_assignment:
|
||||
IDENTIFIER
|
||||
{@stb.output_symbol_assignment_early(_values)}
|
||||
'=' exp ';'
|
||||
{ return @stb.output_symbol_assignment(val) };
|
||||
|
||||
#handled in state_declaration
|
||||
__doc_comment:
|
||||
DOC_COMMENT
|
||||
|;
|
||||
|
||||
#handled in state_declaration
|
||||
__initial:
|
||||
INITIAL
|
||||
|;
|
||||
|
||||
#handled in state_declaration
|
||||
__target:
|
||||
TARGET
|
||||
|;
|
||||
|
||||
subsequent_declaration:
|
||||
IDENTIFIER __option_or_behavior '('
|
||||
{@stb.subsequent_declaration_early(_values)}
|
||||
__set_parameter_list ')' ';'
|
||||
{return @stb.subsequent_declaration(val)};
|
||||
|
||||
__option_or_behavior:
|
||||
OPTION
|
||||
|
|
||||
BEHAVIOR
|
||||
|
|
||||
;
|
||||
|
||||
__set_parameter_list:
|
||||
set_parameter __set_parameter_list_end
|
||||
{return [val[0]] + val[1]}
|
||||
|
|
||||
{return []}
|
||||
;
|
||||
|
||||
__set_parameter_list_end:
|
||||
',' __set_parameter_list
|
||||
{return val[1]}
|
||||
|
|
||||
{return []}
|
||||
;
|
||||
|
||||
set_parameter:
|
||||
IDENTIFIER
|
||||
{@stb.set_parameter_early(_values)}
|
||||
'=' exp
|
||||
{return @stb.set_parameter(val)}
|
||||
;
|
||||
|
||||
__with_parameter_list:
|
||||
with_parameter __with_parameter_list_end
|
||||
{return [val[0]] + val[1]}
|
||||
|
|
||||
{return []}
|
||||
;
|
||||
|
||||
__with_parameter_list_end:
|
||||
',' __with_parameter_list
|
||||
{return val[1]}
|
||||
|
|
||||
{return []}
|
||||
;
|
||||
|
||||
with_parameter:
|
||||
IDENTIFIER
|
||||
{@stb.with_parameter_early(_values)}
|
||||
'=' exp
|
||||
{return @stb.with_parameter(val)}
|
||||
;
|
||||
|
||||
exp:
|
||||
'!' exp
|
||||
{return @stb.exp_unary(val)}
|
||||
|
|
||||
exp '+' {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp '-' {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp '*' {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp '/' {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp '%' {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp NEQ {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp EQ {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp '<' {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp LE {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp '>' {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp GE {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp AND {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp OR {@stb.exp_binary_early(_values)} exp
|
||||
{return @stb.exp_binary(val)}
|
||||
|
|
||||
exp '?' exp ':' exp
|
||||
{return @stb.conditional_expression(val)}
|
||||
|
|
||||
'(' exp ')'
|
||||
{return val[1]}
|
||||
|
|
||||
'-' exp = UMINUS
|
||||
{return @stb.exp_unary(val)}
|
||||
|
|
||||
NUMBER
|
||||
{return @stb.exp_number(val)}
|
||||
|
|
||||
TRUE
|
||||
{return @stb.exp_boolean(val)}
|
||||
|
|
||||
FALSE
|
||||
{return @stb.exp_boolean(val)}
|
||||
|
|
||||
function
|
||||
|
|
||||
IDENTIFIER
|
||||
{return @stb.exp_identifier(val)}
|
||||
|
|
||||
TOSX
|
||||
{return TOSXTag.new}
|
||||
|
|
||||
TOOX
|
||||
{return TOOXTag.new}
|
||||
|
|
||||
SORTS
|
||||
{return SORTSTag.new}
|
||||
|
|
||||
CONFLICT
|
||||
{return ConflictTag.new}
|
||||
;
|
||||
|
||||
|
||||
function:
|
||||
IDENTIFIER
|
||||
{@stb.function_early(_values)}
|
||||
'(' __with_parameter_list ')'
|
||||
{return @stb.function(val)}
|
||||
;
|
||||
|
||||
__common_declarations:
|
||||
COMMON DECISION
|
||||
__common_decision_tree
|
||||
COMMON ACTION
|
||||
__common_action
|
||||
{return [val[2], val[5]]}
|
||||
|
|
||||
COMMON DECISION
|
||||
__common_decision_tree
|
||||
{return [val[2]]}
|
||||
|
|
||||
COMMON ACTION
|
||||
__common_action
|
||||
{return [val[2]]}
|
||||
|;
|
||||
|
||||
__common_action:
|
||||
'{'
|
||||
__output_symbol_assignments_or_subsequent_declarations
|
||||
'}'
|
||||
{return @stb.common_action(val)}
|
||||
|;
|
||||
|
||||
#CDT stuff
|
||||
__common_decision_tree:
|
||||
'{' cdtree '}'
|
||||
{return @stb.common_decision_tree(val)}
|
||||
|;
|
||||
|
||||
#rule with IF and optional ELSEIF
|
||||
cdtree:
|
||||
'{'
|
||||
cdtree
|
||||
'}'
|
||||
{return val[1]}
|
||||
|
|
||||
__doc_comment
|
||||
IF '(' exp ')' dtree
|
||||
__cdtree_elseif_decisions
|
||||
{return @stb.cdtree(val)};
|
||||
|
||||
__cdtree_elseif_decisions:
|
||||
__doc_comment
|
||||
ELSE cdtree
|
||||
{return @stb.cdtree_elseif_decision(val)}
|
||||
|
|
||||
{return nil};
|
||||
|
||||
#DT stuff
|
||||
decision_tree:
|
||||
DECISION '{' dtree '}'
|
||||
{return @stb.decision_tree(val)}
|
||||
|
|
||||
DECISION '{' __doc_comment ELSE dtree '}'
|
||||
{return @stb.decision_tree(val)}
|
||||
|
|
||||
{return @stb.decision_tree(val)}
|
||||
;
|
||||
|
||||
#rule with transition or (IF and ELSE)
|
||||
dtree:
|
||||
'{'
|
||||
dtree
|
||||
'}'
|
||||
{return val[1]}
|
||||
|
|
||||
transition
|
||||
{return [val[0]]}
|
||||
|
|
||||
__doc_comment
|
||||
IF '(' exp ')' dtree
|
||||
__doc_comment
|
||||
ELSE dtree
|
||||
{return @stb.dtree(val)}
|
||||
;
|
||||
|
||||
|
||||
transition:
|
||||
TTS IDENTIFIER ';'
|
||||
{return @stb.transition(val)}
|
||||
|
|
||||
STAY ';'
|
||||
{return @stb.transition(val)}
|
||||
;
|
||||
|
||||
end
|
||||
|
||||
---- header
|
||||
|
||||
require 'translator'
|
||||
require 'syntax_tree_builder'
|
||||
|
||||
---- inner
|
||||
|
||||
def initialize
|
||||
super
|
||||
end
|
||||
|
||||
#start the parsing, use stb as SyntaxTreeBuilder, tokenize and rewind on demand
|
||||
def parse(cc, stb)
|
||||
@cc = cc
|
||||
@stb = stb
|
||||
@stb.compiler_context = cc
|
||||
if @cc.tz.tokenized?
|
||||
@cc.tz.rewind
|
||||
else
|
||||
File.open(cc.cu.src_fullname, 'rb') do |src|
|
||||
@cc.tz.tokenize(src.read)
|
||||
end
|
||||
end
|
||||
do_parse
|
||||
@cc = nil
|
||||
@stb.compiler_context = nil
|
||||
@stb = nil
|
||||
end
|
||||
|
||||
#return a token in the format the parser understands
|
||||
def next_token
|
||||
token = @cc.tz.next_token
|
||||
return nil if token.nil?
|
||||
return [token.token_type, token]
|
||||
end
|
||||
|
||||
def on_error(error_token_id, error_value, value_stack)
|
||||
if error_value == '$'
|
||||
raise UnexpectedEndOfFile.new(@cc)
|
||||
else
|
||||
error = SyntaxError.new(@cc)
|
||||
error.token = error_value if error_value.class <= Token
|
||||
raise error
|
||||
end
|
||||
end
|
||||
|
||||
---- footer
|
||||
@ -0,0 +1,179 @@
|
||||
module Translator
|
||||
|
||||
# parser callback with a stack of open tags.
|
||||
class StackParserCallback
|
||||
|
||||
include REXML::StreamListener
|
||||
|
||||
attr_reader :le_classes_by_tag
|
||||
attr_reader :root
|
||||
attr_reader :symbol_table
|
||||
|
||||
def initialize
|
||||
super
|
||||
@stack = nil
|
||||
@root = nil
|
||||
@symbol_table = nil
|
||||
@le_classes_by_tags = {}
|
||||
end
|
||||
|
||||
# sets root, symbol_tables and clears parser stack.
|
||||
def prepare(root, symbol_table)
|
||||
@root = root
|
||||
@symbol_table = symbol_table
|
||||
@stack = [@root]
|
||||
end
|
||||
|
||||
# registers an expected language element class for xml parsing.
|
||||
def add_le_class le_class
|
||||
@le_classes_by_tags[le_class.tag] = le_class
|
||||
end
|
||||
|
||||
# when a new tag starts: creates a new language elmement with attributes and pushes it onto the stack
|
||||
def tag_start(name, attributes)
|
||||
|
||||
@current = @stack.last
|
||||
|
||||
le_class = @le_classes_by_tags[name]
|
||||
if le_class.nil?
|
||||
le = UnknownLanguageElement.new(name)
|
||||
else
|
||||
le = le_class.new
|
||||
end
|
||||
@stack.push le
|
||||
|
||||
#then put it into the tree
|
||||
@current.add_child(le)
|
||||
|
||||
#and after that import attributes
|
||||
le.import(attributes, @symbol_table)
|
||||
end
|
||||
|
||||
# when tag ends: pops of a language element from the stack
|
||||
def tag_end(name)
|
||||
@current = @stack.pop
|
||||
end
|
||||
|
||||
# when text is encountered: send text to language element.
|
||||
# used for platform, software environment, title tags
|
||||
def text(text)
|
||||
@stack.last.text = text unless @current.nil? || text =~ /\A\s*\z/
|
||||
end
|
||||
|
||||
# REXML::StreamListener provided a function stub with only 2 parameters which caused an error
|
||||
def entitydecl a,b,c
|
||||
end
|
||||
end
|
||||
|
||||
# this parser callback cares for XML entities found and is used for agents.xml.
|
||||
class AgentCollectionParserCallback < StackParserCallback
|
||||
attr_reader :entities
|
||||
|
||||
def prepare(root, symbol_table)
|
||||
super
|
||||
@entities = {}
|
||||
end
|
||||
|
||||
def entitydecl(a, b, c)
|
||||
@entities[a] = c
|
||||
end
|
||||
|
||||
#hack for REXML. in some versions entitydecl is delivered as notationdecl
|
||||
def notationdecl(n)
|
||||
entitydecl(*n)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# parser callback implementation for parsing option-definitions files
|
||||
# creates an mapping between ODTags and OptionSymbols
|
||||
class OptionDefinitonsParserCallback < StackParserCallback
|
||||
|
||||
attr_reader :option_definitions_by_symbol
|
||||
|
||||
def initialize
|
||||
super
|
||||
@option_definitions_by_symbol = {}
|
||||
end
|
||||
|
||||
def tag_start(name, attributes)
|
||||
super
|
||||
|
||||
last = @stack.last
|
||||
if (last.class <= ODTag)
|
||||
@option_definitions_by_symbol[last.attr[ATTR_NAME]] = last
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# small parser for dtd files.
|
||||
class DTDEntityScanner
|
||||
|
||||
def scan(src)
|
||||
filename_by_entity = {}
|
||||
entity_by_filename = {}
|
||||
entity_order = []
|
||||
src.each do |line|
|
||||
if line =~ /<!ENTITY\s+([A-Za-z0-9_.\-]*)\s+SYSTEM\s+"([^"]*)">/
|
||||
filename = $2.to_s
|
||||
entity = $1.to_s
|
||||
filename_by_entity[entity] = filename
|
||||
entity_by_filename[filename] = entity
|
||||
entity_order << entity
|
||||
end
|
||||
end
|
||||
return [filename_by_entity , entity_by_filename, entity_order]
|
||||
end
|
||||
end
|
||||
|
||||
# the counterpart to the dtd scanner.
|
||||
class DTDEntityWriter
|
||||
|
||||
def initialize
|
||||
super
|
||||
end
|
||||
|
||||
def write(entities, dest)
|
||||
|
||||
dest.puts "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
|
||||
|
||||
symbols = []
|
||||
behaviors = []
|
||||
strings = []
|
||||
|
||||
keys = entities.keys
|
||||
keys.each do |key|
|
||||
symbols << key if key.class <= NamespaceSymbol && key.namespace_type == :symbols
|
||||
behaviors << key if key.class <= NamespaceSymbol && key.namespace_type == :behaviors
|
||||
strings << key if key.class <= String
|
||||
end
|
||||
|
||||
symbols.sort! do |a,b|
|
||||
a.identifier.downcase <=> b.identifier.downcase
|
||||
end
|
||||
behaviors.sort! do |a,b|
|
||||
a.identifier.downcase <=> b.identifier.downcase
|
||||
end
|
||||
strings.sort! do |a,b|
|
||||
a.downcase <=> b.downcase
|
||||
end
|
||||
|
||||
|
||||
symbols.each do |key|
|
||||
write_single(dest, key.identifier, entities[key])
|
||||
end
|
||||
behaviors.each do |key|
|
||||
write_single(dest, key.identifier, entities[key])
|
||||
end
|
||||
strings.each do |key|
|
||||
write_single(dest, key, entities[key])
|
||||
end
|
||||
end
|
||||
|
||||
def write_single(dest, a , b)
|
||||
dest.puts "<!ENTITY #{a} SYSTEM \"#{b}\">"
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,153 @@
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 10pt;
|
||||
margin-top: 0pt;
|
||||
}
|
||||
td {
|
||||
font-family: sans-serif;
|
||||
font-size: 10pt;
|
||||
vertical-align: top;
|
||||
}
|
||||
a:link {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #005A9C;
|
||||
}
|
||||
a:visited {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
color: #005A9C;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
color: #005A9C;
|
||||
}
|
||||
h1 {
|
||||
width: 100%;
|
||||
padding-top:10pt;
|
||||
font-size: 20pt;
|
||||
font-weight: bold;
|
||||
border-top: 1px none #FFFFFF;
|
||||
border-right: 1px none #FFFFFF;
|
||||
border-bottom: 2px solid #005A9C;
|
||||
border-left: 1px none #FFFFFF;
|
||||
color: #005A9C;
|
||||
}
|
||||
h2 {
|
||||
width: 100%;
|
||||
font-size: 15pt ;
|
||||
font-weight: bold;
|
||||
border-top: 1px none #FFFFFF;
|
||||
border-right: 1px none #FFFFFF;
|
||||
border-bottom: 1px solid #005A9C;
|
||||
border-left: 1px none #FFFFFF;
|
||||
color: #005A9C;
|
||||
}
|
||||
h3 {
|
||||
padding-bottom:0pt;
|
||||
font-size: 15pt;
|
||||
font-weight: normal;
|
||||
border-top: 1px none #FFFFFF;
|
||||
border-right: 1px none #FFFFFF;
|
||||
border-bottom: 1px none #005A9C;
|
||||
border-left: 1px none #FFFFFF;
|
||||
color: #005A9C;
|
||||
}
|
||||
|
||||
.frameline {
|
||||
background-color: #CCCCCC;
|
||||
}
|
||||
.bold { font-weight: bold; }
|
||||
.italic { font-style: italic; }
|
||||
.code {
|
||||
font-family: "Courier New", Courier, mono;
|
||||
font-size: 10pt;
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
background-color: #FFFFCC;
|
||||
}
|
||||
.tablehead{
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
color: #005A9C;
|
||||
border-bottom: 1px dotted #A0A0A0;
|
||||
}
|
||||
.menu-title{
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
.menu-item{
|
||||
font-size: 7pt;
|
||||
font-weight: normal;
|
||||
}
|
||||
.menu-cell{
|
||||
padding-right: 3pt;
|
||||
border-right: 1px dotted #BBBBFF;
|
||||
}
|
||||
.main-area{
|
||||
padding-left: 10pt;
|
||||
}
|
||||
.pseudo-code-frame{
|
||||
background-color:#F4F4F4;
|
||||
border-width:1;
|
||||
border-style:solid;
|
||||
border-color:#A0A0A0;
|
||||
width:100%;
|
||||
}
|
||||
.common-pseudo-code-frame{
|
||||
background-color:#FFFFFF;
|
||||
border-width:1;
|
||||
border-style:dashed;
|
||||
border-color:#A0A0A0;
|
||||
width:100%;
|
||||
}
|
||||
.pseudo-code-cell{
|
||||
padding-top:1;
|
||||
padding-bottom:1;
|
||||
padding-right:0;
|
||||
padding-left:0;
|
||||
font-family:monospace;
|
||||
}
|
||||
.nowrap{
|
||||
white-space:nowrap;
|
||||
}
|
||||
.pseudo-code-right-bracket{
|
||||
padding-top:1;
|
||||
padding-bottom:1;
|
||||
padding-right:0;
|
||||
padding-left:0;
|
||||
vertical-align:bottom;
|
||||
font-family:monospace;
|
||||
}
|
||||
.pseudo-code-left-bracket{
|
||||
padding-top:1;
|
||||
padding-bottom:1;
|
||||
padding-right:0;
|
||||
padding-left:0;
|
||||
vertical-align:top;
|
||||
font-family:monospace;
|
||||
}
|
||||
.xabsl-2-logo-big {
|
||||
padding-top:10;
|
||||
padding-bottom:0;
|
||||
padding-right:15;
|
||||
font-family:sans-serif;
|
||||
font-weight:bold;
|
||||
font-size:35pt;
|
||||
color:#000000;
|
||||
text-align:left;
|
||||
white-space:nowrap;
|
||||
background-color:#FFFFFF;
|
||||
}
|
||||
.xabsl-2-logo-small {
|
||||
padding-top:0;
|
||||
padding-bottom:0;
|
||||
font-family:sans-serif;
|
||||
font-weight:bold;
|
||||
font-size:12pt;
|
||||
color:#000000;
|
||||
text-align:left;
|
||||
white-space:nowrap;
|
||||
background-color:#FFFFFF;
|
||||
}
|
||||
@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de">
|
||||
<xsl:output method="text"/>
|
||||
<xsl:key name="basic-behaviors" match="xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:basic-behaviors/xabsl:basic-behavior" use="@name"/>
|
||||
<xsl:key name="output-symbols" match="xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:symbols/xabsl:decimal-output-symbol | xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:symbols/xabsl:boolean-output-symbol | xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:symbols/xabsl:enumerated-output-symbol" use="@name"/>
|
||||
<xsl:key name="input-symbols" match="xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:symbols/xabsl:decimal-input-symbol | xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:symbols/xabsl:boolean-input-symbol | xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:symbols/xabsl:enumerated-input-symbol" use="@name"/>
|
||||
<xsl:key name="enumerations" match="xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:symbols/xabsl:enumeration" use="@name"/>
|
||||
<xsl:variable name="space">
|
||||
<xsl:text> </xsl:text>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="line-break">
|
||||
<xsl:text>
|
||||
</xsl:text>
|
||||
</xsl:variable>
|
||||
<xsl:template match="xabsl:agent-collection">
|
||||
<xsl:text>// Debug Symbols for the agents of </xsl:text>
|
||||
<xsl:value-of select="xabsl:title"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// number of enumerations</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="count(xabsl:options/xabsl:option/xabsl:symbols/xabsl:*[local-name()='enumeration'][count(key('enumerations',@name)[1] | .)=1])"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// enumerations</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// (name number-of-elements (element)*)+</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:apply-templates select="xabsl:options/xabsl:option/xabsl:symbols/xabsl:enumeration"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// number of input symbols</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="count(xabsl:options/xabsl:option/xabsl:symbols/xabsl:*[local-name()='decimal-input-symbol' or local-name()='boolean-input-symbol' or local-name()='enumerated-input-symbol'][count(key('input-symbols',@name)[1] | .)=1])"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// input symbols</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// (d decimal-input-symbol | b boolean-input-symbol | e enum-name enumerated-input-symbol)+</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:apply-templates select="xabsl:options/xabsl:option/xabsl:symbols/xabsl:decimal-input-symbol | xabsl:options/xabsl:option/xabsl:symbols/xabsl:boolean-input-symbol | xabsl:options/xabsl:option/xabsl:symbols/xabsl:enumerated-input-symbol"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// number of output symbols</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="count(xabsl:options/xabsl:option/xabsl:symbols/xabsl:*[local-name()='decimal-output-symbol' or local-name()='boolean-output-symbol' or local-name()='enumerated-output-symbol'][count(key('output-symbols',@name)[1] | .)=1])"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// output symbols</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// (d decimal-output-symbol | b boolean-output-symbol | e enum-name enumerated-output-symbol)+</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:apply-templates select="xabsl:options/xabsl:option/xabsl:symbols/xabsl:decimal-output-symbol | xabsl:options/xabsl:option/xabsl:symbols/xabsl:boolean-output-symbol | xabsl:options/xabsl:option/xabsl:symbols/xabsl:enumerated-output-symbol"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// number of options</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="count(xabsl:options/xabsl:option)"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>//options: (name num-of-parameters (d decimal-parameter | b boolean_parameter | e enum-name enumerated-parameter)*)+</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:apply-templates select="xabsl:options/xabsl:option"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>// number of basic behaviors</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="count(xabsl:options/xabsl:option/xabsl:basic-behaviors/xabsl:basic-behavior[count(key('basic-behaviors',@name)[1] | .)=1])"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:text>//basic behaviors: (name num-of-parameters (d decimal-parameter | b boolean_parameter | e enum-name enumerated-parameter)*)+</xsl:text>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:apply-templates select="xabsl:options/xabsl:option/xabsl:basic-behaviors/xabsl:basic-behavior"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:option">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:value-of select="$name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="count(xabsl:option-definitions/xabsl:option-definition[@name=$name]/xabsl:*[local-name()='decimal-parameter' or local-name()='boolean-parameter' or local-name()='enumerated-parameter'])"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:apply-templates select="xabsl:option-definitions/xabsl:option-definition[@name=$name]/xabsl:*[local-name()='decimal-parameter' or local-name()='boolean-parameter' or local-name()='enumerated-parameter']"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:decimal-parameter">
|
||||
<xsl:text>d</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:boolean-parameter">
|
||||
<xsl:text>b</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumerated-parameter">
|
||||
<xsl:text>e</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@enumeration"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:basic-behavior">
|
||||
<xsl:if test="count(key('basic-behaviors',@name)[1] | .)=1">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:value-of select="$name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="count(xabsl:*[local-name()='decimal-parameter' or local-name()='boolean-parameter' or local-name()='enumerated-parameter'])"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:apply-templates select="xabsl:*[local-name()='decimal-parameter' or local-name()='boolean-parameter' or local-name()='enumerated-parameter']"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:decimal-input-symbol">
|
||||
<xsl:if test="count(key('input-symbols',@name)[1] | .)=1">
|
||||
<xsl:text>d</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:boolean-input-symbol">
|
||||
<xsl:if test="count(key('input-symbols',@name)[1] | .)=1">
|
||||
<xsl:text>b</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumerated-input-symbol">
|
||||
<xsl:if test="count(key('input-symbols',@name)[1] | .)=1">
|
||||
<xsl:text>e</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@enumeration"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:decimal-output-symbol">
|
||||
<xsl:if test="count(key('output-symbols',@name)[1] | .)=1">
|
||||
<xsl:text>d</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:boolean-output-symbol">
|
||||
<xsl:if test="count(key('output-symbols',@name)[1] | .)=1">
|
||||
<xsl:text>b</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumerated-output-symbol">
|
||||
<xsl:if test="count(key('output-symbols',@name)[1] | .)=1">
|
||||
<xsl:text>e</xsl:text>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@enumeration"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumeration">
|
||||
<xsl:if test="count(key('enumerations',@name)[1] | .)=1">
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:value-of select="count(xabsl:enum-element)"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
<xsl:for-each select="xabsl:enum-element">
|
||||
<xsl:value-of select="@name"/>
|
||||
<xsl:value-of select="$space"/>
|
||||
</xsl:for-each>
|
||||
<xsl:value-of select="$line-break"/>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="*"/>
|
||||
<xsl:template match="text()"/>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<xsl:import href="generate-documentation.option-tree.xsl"/>
|
||||
<xsl:import href="generate-documentation.menu.xsl"/>
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
<xsl:param name="option-tree-xml"/>
|
||||
<xsl:template match="xabsl:agent-collection">
|
||||
<html>
|
||||
<head>
|
||||
<title>XABSL Behavior Documentation: Agents</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<xsl:text> </xsl:text>
|
||||
</link>
|
||||
</head>
|
||||
<body>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="menu-cell">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<xsl:call-template name="menu-xabsl2-logo"/>
|
||||
<xsl:call-template name="menu-entry-index-linked"/>
|
||||
<xsl:call-template name="menu-entry-agents"/>
|
||||
<xsl:call-template name="menu-agents"/>
|
||||
<xsl:call-template name="menu-entry-symbols-linked"/>
|
||||
<xsl:call-template name="menu-entry-basic-behaviors-linked"/>
|
||||
<xsl:call-template name="menu-entry-options-linked"/>
|
||||
</table>
|
||||
</td>
|
||||
<td class="main-area">
|
||||
<h1>Agents</h1>
|
||||
<xsl:apply-templates select="xabsl:agent"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:agent">
|
||||
<h2 id="agent.{@id}">
|
||||
<xsl:value-of select="@title"/>
|
||||
</h2>
|
||||
<p>
|
||||
<xsl:value-of select="@description"/>
|
||||
</p>
|
||||
<p>Option Graph:<br/>
|
||||
<dotml:graph>
|
||||
<xsl:attribute name="file-name">svg/agent_<xsl:value-of select="@id"/></xsl:attribute>
|
||||
<xsl:call-template name="paint-option-tree">
|
||||
<xsl:with-param name="root-option" select="@root-option"/>
|
||||
<xsl:with-param name="option-tree-xml" select="$option-tree-xml"/>
|
||||
</xsl:call-template>
|
||||
</dotml:graph>
|
||||
</p>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<xsl:import href="generate-documentation.menu.xsl"/>
|
||||
<xsl:output method="html" indent="yes"/>
|
||||
<xsl:key name="basic-behaviors" match="xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:basic-behaviors" use="@id"/>
|
||||
<xsl:template match="xabsl:agent-collection">
|
||||
<html>
|
||||
<head>
|
||||
<title>XABSL Behavior Documentation: Basic Behaviors</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<xsl:text> </xsl:text>
|
||||
</link>
|
||||
</head>
|
||||
<body>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="menu-cell">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<xsl:call-template name="menu-xabsl2-logo"/>
|
||||
<xsl:call-template name="menu-entry-index-linked"/>
|
||||
<xsl:call-template name="menu-entry-agents-linked"/>
|
||||
<xsl:call-template name="menu-entry-symbols-linked"/>
|
||||
<xsl:call-template name="menu-entry-basic-behaviors"/>
|
||||
<xsl:call-template name="menu-basic-behaviors"/>
|
||||
<xsl:call-template name="menu-entry-options-linked"/>
|
||||
</table>
|
||||
</td>
|
||||
<td class="main-area">
|
||||
<h1>Basic Behaviors</h1>
|
||||
<table border="0" cellpadding="4" cellspacing="0">
|
||||
<xsl:for-each select="xabsl:options/xabsl:option/xabsl:basic-behaviors[count(key('basic-behaviors',@id)[1] | .)=1]">
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p> </p>
|
||||
<a href="basic-behaviors.{@id}.html" title="{@description}">
|
||||
<h3>
|
||||
<xsl:value-of select="@title"/>
|
||||
</h3>
|
||||
</a>
|
||||
<p>
|
||||
<xsl:value-of select="@description"/>
|
||||
</p>
|
||||
<p/>
|
||||
</td>
|
||||
</tr>
|
||||
<xsl:for-each select="xabsl:basic-behavior">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="basic-behaviors.{../@id}.html#{@name}" title="{@description}">
|
||||
<xsl:value-of select="@name"/>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de">
|
||||
<xsl:import href="generate-documentation.parameters.xsl"/>
|
||||
<xsl:import href="generate-documentation.menu.xsl"/>
|
||||
<xsl:output method="html" indent="yes"/>
|
||||
<xsl:template match="xabsl:basic-behaviors">
|
||||
<html>
|
||||
<head>
|
||||
<title>XABSL Behavior Documentation: <xsl:value-of select="@title"/>
|
||||
</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<xsl:text> </xsl:text>
|
||||
</link>
|
||||
</head>
|
||||
<body>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="menu-cell">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<xsl:call-template name="menu-xabsl2-logo"/>
|
||||
<xsl:call-template name="menu-entry-index-linked"/>
|
||||
<xsl:call-template name="menu-entry-agents-linked"/>
|
||||
<xsl:call-template name="menu-entry-symbols-linked"/>
|
||||
<xsl:call-template name="menu-entry-basic-behaviors-linked"/>
|
||||
<xsl:call-template name="menu-basic-behavior"/>
|
||||
<xsl:call-template name="menu-entry-options-linked"/>
|
||||
</table>
|
||||
</td>
|
||||
<td class="main-area">
|
||||
<h1>
|
||||
<xsl:value-of select="@title"/>
|
||||
</h1>
|
||||
<p>
|
||||
<xsl:value-of select="@description"/>
|
||||
</p>
|
||||
<xsl:for-each select="xabsl:basic-behavior">
|
||||
<h2 id="{@name}">Basic Behavior "<xsl:value-of select="@name"/>"</h2>
|
||||
<p>
|
||||
<xsl:value-of select="@description"/>
|
||||
</p>
|
||||
<xsl:call-template name="parameters"/>
|
||||
</xsl:for-each>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de">
|
||||
<xsl:import href="generate-documentation.menu.xsl"/>
|
||||
<xsl:output method="html" indent="yes"/>
|
||||
<xsl:template match="xabsl:agent-collection">
|
||||
<html>
|
||||
<head>
|
||||
<title>XABSL Behavior Documentation: <xsl:value-of select="xabsl:title"/>
|
||||
</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<xsl:text> </xsl:text>
|
||||
</link>
|
||||
</head>
|
||||
<body>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="menu-cell">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<xsl:call-template name="menu-xabsl2-logo"/>
|
||||
<xsl:call-template name="menu-entry-index"/>
|
||||
<xsl:call-template name="menu-entry-agents-linked"/>
|
||||
<xsl:call-template name="menu-entry-symbols-linked"/>
|
||||
<xsl:call-template name="menu-entry-basic-behaviors-linked"/>
|
||||
<xsl:call-template name="menu-entry-options-linked"/>
|
||||
</table>
|
||||
</td>
|
||||
<td class="main-area">
|
||||
<h1>
|
||||
<xsl:value-of select="xabsl:title"/>: Behavior Documentation</h1>
|
||||
<p>
|
||||
<div class="bold">Platform:</div>
|
||||
<xsl:value-of select="xabsl:platform"/>
|
||||
</p>
|
||||
<p>
|
||||
<div class="bold">Software Environment:</div>
|
||||
<xsl:value-of select="xabsl:software-environment"/>
|
||||
</p>
|
||||
<h2>Table Of Contents</h2>
|
||||
<table border="0" cellpadding="4" cellspacing="6">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="agents.html" title="Available agents">Agents</a>
|
||||
</td>
|
||||
<td>All agents of <xsl:value-of select="xabsl:title"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="symbols.html" title="Available symbols">Symbols</a>
|
||||
</td>
|
||||
<td>The symbols needed to run the behavior in the software environment</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="basic-behaviors.html" title="Available basic behaviors">Basic Behaviors</a>
|
||||
</td>
|
||||
<td>C++ written behaviors at the leaves of the option tree.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="options.html" title="Available options">Options</a>
|
||||
</td>
|
||||
<td>All options of all agents.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,283 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de">
|
||||
<xsl:output method="xml" indent="no"/>
|
||||
<xsl:template name="menu-xabsl2-logo">
|
||||
<tr>
|
||||
<td colspan="2" class="xabsl-2-logo-big">
|
||||
<a href="http://www.xabsl.de" title="The XABSL Web Site">>xabsl</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="xabsl-2-logo-small">Behavior Documentation</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-agents-linked">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">
|
||||
<a href="agents.html" title="All available agents">>Agents</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-agents">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">>Agents</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-index-linked">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-item">
|
||||
<br/>><a href="index.html" title="Start Page">Index</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-index">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-item">
|
||||
<br/>>Index</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-symbols-linked">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">
|
||||
<a href="symbols.html" title="All available symbols">>Symbols</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-symbols">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">>Symbols</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-basic-behaviors-linked">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">
|
||||
<a href="basic-behaviors.html" title="All available basic behaviors">>Basic Behaviors</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-basic-behaviors">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">>Basic Behaviors</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-options-linked">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">
|
||||
<a href="options.html" title="All available options">>Options</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-entry-options">
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">>Options</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-basic-behaviors">
|
||||
<xsl:for-each select="xabsl:options/xabsl:option/xabsl:basic-behaviors[count(key('basic-behaviors',@id)[1] | .)=1]">
|
||||
<xsl:sort select="@id"/>
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">   >>  <a href="basic-behaviors.{@id}.html" title="{@description}">
|
||||
<xsl:value-of select="@title"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<xsl:for-each select="xabsl:basic-behavior">
|
||||
<xsl:sort select="@name"/>
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">        >>>  <a href="basic-behaviors.{../@id}.html#{@name}" title="{@description}">
|
||||
<xsl:value-of select="@name"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-basic-behavior">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">   >>  <xsl:value-of select="@title"/>
|
||||
</td>
|
||||
</tr>
|
||||
<xsl:for-each select="xabsl:basic-behavior">
|
||||
<xsl:sort select="@name"/>
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">        >>>  <a href="basic-behaviors.{../@id}.html#{@name}" title="{@description}">
|
||||
<xsl:value-of select="@name"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-options">
|
||||
<xsl:for-each select="xabsl:option-definition">
|
||||
<xsl:sort select="@name"/>
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">   >>  <a href="option.{@name}.html" class="menu-item" title="{@description}">
|
||||
<xsl:value-of select="@name"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-symbols">
|
||||
<xsl:for-each select="xabsl:options/xabsl:option/xabsl:symbols[count(key('symbols',@id)[1] | .)=1]">
|
||||
<xsl:sort select="@id"/>
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">   >>  <a href="symbols.{@id}.html" title="{@description}">
|
||||
<xsl:value-of select="@title"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-agents">
|
||||
<xsl:for-each select="xabsl:agent">
|
||||
<xsl:sort select="@id"/>
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">   >>  <a href="agents.html#agent.{@id}" title="{@description}">
|
||||
<xsl:value-of select="@title"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-symbol">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">   >>  <xsl:value-of select="@title"/>
|
||||
</td>
|
||||
</tr>
|
||||
<xsl:if test="xabsl:decimal-input-symbol | xabsl:boolean-input-symbol | xabsl:enumerated-input-symbol">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">        >>>  <a href="symbols.{@id}.html#input-symbols" title="All available input symbols">Input Symbols</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="xabsl:decimal-input-function">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">        >>>  <a href="symbols.{@id}.html#input-functions" title="All available input functions">Input Functions</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="xabsl:enumerated-output-symbol">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">        >>>  <a href="symbols.{@id}.html#output-symbols" title="All available output symbols">Output Symbols</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="xabsl:constant">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">        >>>  <a href="symbols.{@id}.html#constants" title="All available constants">Constants</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template name="menu-option">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:for-each select="xabsl:option-definitions/xabsl:option-definition[@name = $name]">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">   >>  <xsl:value-of select="@name"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:state">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap" colspan="2">        >>>  <a href="option.{../@name}.html#state_{@name}" title="State {@name}">
|
||||
<xsl:value-of select="@name"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:agent-collection">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<!--<tr>
|
||||
<td colspan="2">
|
||||
<img src="Xabsl2Logo.gif"/>
|
||||
</td>
|
||||
</tr>-->
|
||||
<tr>
|
||||
<td colspan="2" class="xabsl-2-logo-big">>xabsl 2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="xabsl-2-logo-small">Behavior Documentation</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="menu-item">
|
||||
<br/>><a href="index.html" title="Start Page">Index</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">>Agents:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<xsl:for-each select="xabsl:agent">
|
||||
<xsl:sort select="@id"/>
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap">>></td>
|
||||
<td>
|
||||
<a href="agent.{@id}.html" class="menu-item" title="{@description}">
|
||||
<xsl:value-of select="@title"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">>Symbols:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<xsl:for-each select="xabsl:agent/xabsl:symbols">
|
||||
<xsl:sort select="@id"/>
|
||||
<xsl:variable name="title" select="@title"/>
|
||||
<xsl:if test="count(preceding::xabsl:symbols[@title=$title])=0">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap">>></td>
|
||||
<td>
|
||||
<a href="symbols.{@id}.html" class="menu-item" title="{@description}">
|
||||
<xsl:value-of select="@title"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">>Basic Behaviors:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<xsl:for-each select="xabsl:agent/xabsl:basic-behaviors">
|
||||
<xsl:sort select="@id"/>
|
||||
<xsl:variable name="title" select="@title"/>
|
||||
<xsl:if test="count(preceding::xabsl:basic-behaviors[@title=$title])=0">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap">>></td>
|
||||
<td>
|
||||
<a href="basic-behaviors.{@id}.html" class="menu-item" title="{@description}">
|
||||
<xsl:value-of select="@title"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="menu-title">>Options:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<xsl:for-each select="xabsl:agent/xabsl:option-definitions/xabsl:option-definition">
|
||||
<xsl:sort select="@name"/>
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:if test="count(preceding::xabsl:option-definition[@name=$name])=0">
|
||||
<tr>
|
||||
<td class="menu-item" nowrap="nowrap">>></td>
|
||||
<td>
|
||||
<a href="option.{@name}.html" class="menu-item" title="{@description}">
|
||||
<xsl:value-of select="@name"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</tr>
|
||||
</table>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<xsl:import href="generate-documentation.option-tree.xsl"/>
|
||||
<xsl:import href="generate-documentation.menu.xsl"/>
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
<xsl:param name="option-tree-xml"/>
|
||||
<xsl:template match="xabsl:option-definitions">
|
||||
<html>
|
||||
<head>
|
||||
<title>XABSL Behavior Documentation: Options</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<xsl:text> </xsl:text>
|
||||
</link>
|
||||
</head>
|
||||
<body>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="menu-cell">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<xsl:call-template name="menu-xabsl2-logo"/>
|
||||
<xsl:call-template name="menu-entry-index-linked"/>
|
||||
<xsl:call-template name="menu-entry-agents-linked"/>
|
||||
<xsl:call-template name="menu-entry-symbols-linked"/>
|
||||
<xsl:call-template name="menu-entry-basic-behaviors-linked"/>
|
||||
<xsl:call-template name="menu-entry-options"/>
|
||||
<xsl:call-template name="menu-options"/>
|
||||
</table>
|
||||
</td>
|
||||
<td class="main-area">
|
||||
<h1>Options</h1>
|
||||
<table border="0" cellpadding="4" cellspacing="0">
|
||||
<xsl:for-each select="xabsl:option-definition">
|
||||
<xsl:sort select="@name"/>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="option.{@name}.html" title="{@description}">
|
||||
<xsl:value-of select="@name"/>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
<p>Option Graph:<br/>
|
||||
<dotml:graph>
|
||||
<xsl:attribute name="file-name">svg/options</xsl:attribute>
|
||||
<xsl:call-template name="paint-complete-option-tree">
|
||||
<xsl:with-param name="option-tree-xml" select="$option-tree-xml"/>
|
||||
</xsl:call-template>
|
||||
</dotml:graph>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<xsl:import href="generate-documentation.string-functions.xsl"/>
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
<xsl:key name="options" match="xabsl:agent-collection/xabsl:options/xabsl:option" use="@name"/>
|
||||
<xsl:key name="basic-behaviors" match="xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:basic-behaviors/xabsl:basic-behavior" use="@name"/>
|
||||
<xsl:template match="xabsl:agent-collection">
|
||||
<xabsl:option-trees>
|
||||
<xsl:for-each select="xabsl:options/xabsl:option">
|
||||
<xabsl:option-tree root-option="{@name}">
|
||||
<xsl:call-template name="create-option-tree"/>
|
||||
</xabsl:option-tree>
|
||||
</xsl:for-each>
|
||||
</xabsl:option-trees>
|
||||
</xsl:template>
|
||||
<xsl:template name="create-option-tree">
|
||||
<xabsl:o-n name="{@name}">
|
||||
<xsl:for-each select="xabsl:common-action/xabsl:subsequent-option | xabsl:state/xabsl:subsequent-option">
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<xsl:if test="not(../preceding-sibling::xabsl:state/xabsl:subsequent-option[@ref=$ref])">
|
||||
<xabsl:e2o to="{@ref}"/>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:common-action/xabsl:subsequent-basic-behavior | xabsl:state/xabsl:subsequent-basic-behavior">
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<xsl:if test="not(../preceding-sibling::xabsl:state/xabsl:subsequent-basic-behavior[@ref=$ref])">
|
||||
<xabsl:e2b to="{@ref}"/>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xabsl:o-n>
|
||||
<xsl:for-each select="xabsl:common-action/xabsl:subsequent-option | xabsl:state/xabsl:subsequent-option">
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<xsl:if test="not(../preceding-sibling::xabsl:state/xabsl:subsequent-option[@ref=$ref])">
|
||||
<xsl:for-each select="key('options',@ref)[1]">
|
||||
<xsl:call-template name="create-option-tree"/>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:common-action/xabsl:subsequent-basic-behavior | xabsl:state/xabsl:subsequent-basic-behavior">
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<xsl:if test="not(../preceding-sibling::xabsl:state/xabsl:subsequent-basic-behavior[@ref=$ref])">
|
||||
<xabsl:b-n name="{@ref}" g="{key('basic-behaviors',@ref)[1]/../@id}"/>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
<xsl:template name="paint-option-tree">
|
||||
<xsl:param name="root-option"/>
|
||||
<xsl:param name="dont-paint-option"/>
|
||||
<xsl:param name="option-tree-xml"/>
|
||||
<xsl:for-each select="document($option-tree-xml)/xabsl:option-trees/xabsl:option-tree[@root-option=$root-option]">
|
||||
<xsl:for-each select="xabsl:o-n[@name!=$dont-paint-option]">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:if test="count(preceding-sibling::xabsl:o-n[@name=$name])=0">
|
||||
<dotml:node fontname="Arial" fontcolor="#005A9C" fontsize="9" shape="box" URL="option.{@name}.html" fillcolor="#FFFFFF" style="filled">
|
||||
<xsl:attribute name="id">option_<xsl:value-of select="@name"/></xsl:attribute>
|
||||
<xsl:attribute name="label"><xsl:call-template name="replace-in-string"><xsl:with-param name="original-string" select="@name"/><xsl:with-param name="replace">_</xsl:with-param><xsl:with-param name="with">\n</xsl:with-param></xsl:call-template></xsl:attribute>
|
||||
</dotml:node>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:b-n">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:if test="count(preceding-sibling::xabsl:b-n[@name=$name])=0">
|
||||
<dotml:node fontname="Arial" fontcolor="#005A9C" fontsize="9" URL="basic-behaviors.{@g}.html#{@name}" style="filled" fillcolor="#FFFFFF">
|
||||
<xsl:attribute name="id">basic_behavior_<xsl:value-of select="@name"/></xsl:attribute>
|
||||
<xsl:attribute name="label"><xsl:call-template name="replace-in-string"><xsl:with-param name="original-string" select="@name"/><xsl:with-param name="replace">_</xsl:with-param><xsl:with-param name="with">\n</xsl:with-param></xsl:call-template></xsl:attribute>
|
||||
</dotml:node>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:o-n[@name!=$dont-paint-option]">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:if test="count(preceding-sibling::xabsl:o-n[@name=$name])=0">
|
||||
<xsl:for-each select="xabsl:e2o">
|
||||
<dotml:edge arrowsize="0.8" color="#808080">
|
||||
<xsl:attribute name="from">option_<xsl:value-of select="../@name"/></xsl:attribute>
|
||||
<xsl:attribute name="to">option_<xsl:value-of select="@to"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:e2b">
|
||||
<dotml:edge arrowsize="0.8" color="#808080">
|
||||
<xsl:attribute name="from">option_<xsl:value-of select="../@name"/></xsl:attribute>
|
||||
<xsl:attribute name="to">basic_behavior_<xsl:value-of select="@to"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="paint-complete-option-tree">
|
||||
<xsl:param name="option-tree-xml"/>
|
||||
<xsl:for-each select="document($option-tree-xml)/xabsl:option-trees/xabsl:option-tree">
|
||||
<xsl:variable name="root-option" select="@root-option"/>
|
||||
<dotml:node fontname="Arial" fontcolor="#005A9C" fontsize="9" shape="box" URL="option.{$root-option}.html" fillcolor="#FFFFFF" style="filled">
|
||||
<xsl:attribute name="id">option_<xsl:value-of select="$root-option"/></xsl:attribute>
|
||||
<xsl:attribute name="label"><xsl:call-template name="replace-in-string"><xsl:with-param name="original-string" select="$root-option"/><xsl:with-param name="replace">_</xsl:with-param><xsl:with-param name="with">\n</xsl:with-param></xsl:call-template></xsl:attribute>
|
||||
</dotml:node>
|
||||
<xsl:for-each select="xabsl:b-n">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:if test="count(preceding-sibling::xabsl:b-n[@name=$name])=0">
|
||||
<dotml:node fontname="Arial" fontcolor="#005A9C" fontsize="9" URL="basic-behaviors.{@g}.html#{@name}" style="filled" fillcolor="#FFFFFF">
|
||||
<xsl:attribute name="id">basic_behavior_<xsl:value-of select="@name"/></xsl:attribute>
|
||||
<xsl:attribute name="label"><xsl:call-template name="replace-in-string"><xsl:with-param name="original-string" select="@name"/><xsl:with-param name="replace">_</xsl:with-param><xsl:with-param name="with">\n</xsl:with-param></xsl:call-template></xsl:attribute>
|
||||
</dotml:node>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="document($option-tree-xml)/xabsl:option-trees/xabsl:option-tree">
|
||||
<xsl:variable name="root-option" select="@root-option"/>
|
||||
<xsl:for-each select="xabsl:o-n[@name=$root-option]">
|
||||
<xsl:if test="count(preceding-sibling::xabsl:o-n[@name=$root-option])=0">
|
||||
<xsl:for-each select="xabsl:e2o">
|
||||
<dotml:edge arrowsize="0.8" color="#808080">
|
||||
<xsl:attribute name="from">option_<xsl:value-of select="$root-option"/></xsl:attribute>
|
||||
<xsl:attribute name="to">option_<xsl:value-of select="@to"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:e2b">
|
||||
<dotml:edge arrowsize="0.8" color="#808080">
|
||||
<xsl:attribute name="from">option_<xsl:value-of select="$root-option"/></xsl:attribute>
|
||||
<xsl:attribute name="to">basic_behavior_<xsl:value-of select="@to"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,457 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<xsl:import href="generate-documentation.option-tree.xsl"/>
|
||||
<xsl:import href="generate-documentation.parameters.xsl"/>
|
||||
<xsl:import href="generate-documentation.pseudo-code.xsl"/>
|
||||
<xsl:import href="generate-documentation.menu.xsl"/>
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
<xsl:param name="option-tree-xml"/>
|
||||
<xsl:key name="basic-behaviors" match="xabsl:option/xabsl:basic-behaviors/xabsl:basic-behavior" use="@name"/>
|
||||
<xsl:key name="option-definitions" match="xabsl:option/xabsl:option-definitions/xabsl:option-definition" use="@name"/>
|
||||
<xsl:key name="transitions" match="xabsl:option/descendant::xabsl:transition-to-state" use="@ref"/>
|
||||
<xsl:template match="xabsl:option">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<xsl:variable name="description" select="xabsl:option-definitions/xabsl:option-definition[@name=$name]/@description"/>
|
||||
<html>
|
||||
<head>
|
||||
<title>XABSL Behavior Documentation: Option <xsl:value-of select="@name"/>
|
||||
</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<xsl:text> </xsl:text>
|
||||
</link>
|
||||
</head>
|
||||
<body>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="menu-cell">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<xsl:call-template name="menu-xabsl2-logo"/>
|
||||
<xsl:call-template name="menu-entry-index-linked"/>
|
||||
<xsl:call-template name="menu-entry-agents-linked"/>
|
||||
<xsl:call-template name="menu-entry-symbols-linked"/>
|
||||
<xsl:call-template name="menu-entry-basic-behaviors-linked"/>
|
||||
<xsl:call-template name="menu-entry-options-linked"/>
|
||||
<xsl:call-template name="menu-option"/>
|
||||
</table>
|
||||
</td>
|
||||
<td class="main-area">
|
||||
<h1>Option <xsl:value-of select="@name"/>
|
||||
</h1>
|
||||
<p>
|
||||
<xsl:value-of select="$description"/>
|
||||
</p>
|
||||
<xsl:for-each select="key('option-definitions',@name)">
|
||||
<xsl:if test="xabsl:decimal-parameter | xabsl:boolean-parameter | xabsl:enumerated-parameter">
|
||||
<p>Parameters of that option:
|
||||
<xsl:call-template name="parameters"/>
|
||||
</p>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<h2>State Machine</h2>
|
||||
<dotml:graph file-name="svg/option_{$name}" ranksep="0.4" nodesep="0.3">
|
||||
<dotml:cluster id="option" label="option {$name}" fontname="Arial" fontcolor="#005A9C" fontsize="12" fillcolor="#F4F4F4" style="filled">
|
||||
<xsl:call-template name="state-machine"/>
|
||||
</dotml:cluster>
|
||||
<dotml:cluster id="option_tree" color="#FFFFFF">
|
||||
<xsl:call-template name="paint-option-tree">
|
||||
<xsl:with-param name="root-option" select="@name"/>
|
||||
<xsl:with-param name="dont-paint-option" select="@name"/>
|
||||
<xsl:with-param name="option-tree-xml" select="$option-tree-xml"/>
|
||||
</xsl:call-template>
|
||||
<xsl:for-each select="xabsl:common-action/xabsl:subsequent-basic-behavior">
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<xsl:for-each select="../../xabsl:state">
|
||||
<dotml:edge arrowsize="0.8" color="#808080" style="dashed" minlen="3">
|
||||
<xsl:attribute name="from">state_<xsl:value-of select="@name"/></xsl:attribute>
|
||||
<xsl:attribute name="to">basic_behavior_<xsl:value-of select="$ref"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:common-action/xabsl:subsequent-option">
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<xsl:for-each select="../../xabsl:state">
|
||||
<dotml:edge minlen="2" arrowsize="0.8" color="#808080" style="dashed">
|
||||
<xsl:attribute name="from">state_<xsl:value-of select="@name"/></xsl:attribute>
|
||||
<xsl:attribute name="to">option_<xsl:value-of select="$ref"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:state/xabsl:subsequent-basic-behavior">
|
||||
<dotml:edge arrowsize="0.8" color="#808080" style="dashed" minlen="3">
|
||||
<xsl:attribute name="from">state_<xsl:value-of select="../@name"/></xsl:attribute>
|
||||
<xsl:attribute name="to">basic_behavior_<xsl:value-of select="@ref"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:state/xabsl:subsequent-option">
|
||||
<dotml:edge minlen="2" arrowsize="0.8" color="#808080" style="dashed">
|
||||
<xsl:attribute name="from">state_<xsl:value-of select="../@name"/></xsl:attribute>
|
||||
<xsl:attribute name="to">option_<xsl:value-of select="@ref"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:for-each>
|
||||
</dotml:cluster>
|
||||
</dotml:graph>
|
||||
<xsl:apply-templates select="xabsl:state"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:state">
|
||||
<xsl:variable name="option-name" select="../@name"/>
|
||||
<xsl:variable name="current-state" select="@name"/>
|
||||
<h2 id="state_{@name}">State <xsl:value-of select="@name"/>
|
||||
</h2>
|
||||
<table cellpadding="0" cellspacing="5">
|
||||
<xsl:if test="@is-target-state='true'">
|
||||
<tr>
|
||||
<td colspan="5">This state is a target state.<br/>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="@synchronized">
|
||||
<tr>
|
||||
<td colspan="5">This state is synchronized. All cooperating agents that are executing this option will enter it at once.
|
||||
<xsl:if test="@synchronized > 0">
|
||||
Minimum number of agents required to enter the state is <xsl:value-of select="@synchronized"/>.
|
||||
</xsl:if>
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:if test="@capacity">
|
||||
<tr>
|
||||
<td colspan="5">This state has a capacity of <xsl:value-of select="@capacity"/>.
|
||||
Only <xsl:value-of select="@capacity"/> of the cooperating agents that are executing this option can enter it at the same time.
|
||||
<br/><br/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<tr>
|
||||
<td colspan="5">If that state is active, </td>
|
||||
</tr>
|
||||
<xsl:for-each select="../xabsl:common-action/xabsl:subsequent-option | ../xabsl:common-action/xabsl:subsequent-basic-behavior |
|
||||
../xabsl:common-action/xabsl:set-decimal-output-symbol | ../xabsl:common-action/xabsl:set-boolean-output-symbol | ../xabsl:common-action/xabsl:set-enumerated-output-symbol |
|
||||
xabsl:subsequent-option | xabsl:subsequent-basic-behavior |
|
||||
xabsl:set-decimal-output-symbol | xabsl:set-boolean-output-symbol | xabsl:set-enumerated-output-symbol">
|
||||
<xsl:choose>
|
||||
<xsl:when test="name()='subsequent-option'">
|
||||
<tr>
|
||||
<td nowrap="nowrap">
|
||||
<span class="bold"> > </span>
|
||||
</td>
|
||||
<td colspan="4">
|
||||
The option <a href="option.{@ref}.html" title="{key('option-definitions',@ref)/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a> is executed. <xsl:if test="xabsl:set-parameter">Parameters:</xsl:if>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:when>
|
||||
<xsl:when test="name()='subsequent-basic-behavior'">
|
||||
<tr>
|
||||
<td nowrap="nowrap">
|
||||
<span class="bold"> > </span>
|
||||
</td>
|
||||
<td colspan="4">
|
||||
The <xsl:variable name="ref" select="@ref"/> basic behavior <a href="basic-behaviors.{key('basic-behaviors',$ref)/../@id}.html#{$ref}" title="{key('basic-behaviors',$ref)/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a> is executed. <xsl:if test="xabsl:set-parameter">Parameters:</xsl:if>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:when>
|
||||
<xsl:when test="name()='set-decimal-output-symbol'">
|
||||
<tr>
|
||||
<td nowrap="nowrap">
|
||||
<span class="bold"> > </span>
|
||||
</td>
|
||||
<td colspan="4">This decimal output symbol is set:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<td nowrap="nowrap"> </td>
|
||||
<td nowrap="nowrap"> </td>
|
||||
<td class="pseudo-code-cell">
|
||||
<a href="symbols.{../../xabsl:symbols/xabsl:decimal-output-symbol[@name=$ref]/../@id}.html#symbols.{$ref}" title="{../../xabsl:symbols/xabsl:decimal-output-symbol[@name=$ref]/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</td>
|
||||
<td nowrap="nowrap" class="pseudo-code-cell"> = </td>
|
||||
<td>
|
||||
<xsl:call-template name="pseudo-code"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:when>
|
||||
<xsl:when test="name()='set-boolean-output-symbol'">
|
||||
<tr>
|
||||
<td nowrap="nowrap">
|
||||
<span class="bold"> > </span>
|
||||
</td>
|
||||
<td colspan="4">This boolean output symbol is set:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td class="pseudo-code-cell">
|
||||
<a href="symbols.{../../xabsl:symbols/xabsl:boolean-output-symbol[@name=$ref]/../@id}.html#symbols.{$ref}" title="{../../xabsl:symbols/xabsl:boolean-output-symbol[@name=$ref]/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</td>
|
||||
<td nowrap="nowrap" class="pseudo-code-cell"> = </td>
|
||||
<td>
|
||||
<xsl:call-template name="pseudo-code"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:when>
|
||||
<xsl:when test="name()='set-enumerated-output-symbol'">
|
||||
<tr>
|
||||
<td nowrap="nowrap">
|
||||
<span class="bold"> > </span>
|
||||
</td>
|
||||
<td colspan="4">This enumerated output symbol is set:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<td nowrap="nowrap"> </td>
|
||||
<td nowrap="nowrap"> </td>
|
||||
<td class="pseudo-code-cell">
|
||||
<a href="symbols.{../../xabsl:symbols/xabsl:enumerated-output-symbol[@name=$ref]/../@id}.html#symbols.{$ref}" title="{../../xabsl:symbols/xabsl:enumerated-output-symbol[@name=$ref]/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</td>
|
||||
<td nowrap="nowrap" class="pseudo-code-cell"> = </td>
|
||||
<td class="pseudo-code-cell">
|
||||
<xsl:call-template name="pseudo-code"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:if test="xabsl:set-parameter">
|
||||
<xsl:for-each select="xabsl:set-parameter">
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<xsl:variable name="subsequent" select="../@ref"/>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td class="pseudo-code-cell">
|
||||
<xsl:if test="../../xabsl:subsequent-option">
|
||||
<a href="option.{../@ref}.html" title="{key('option-definitions',$subsequent)/xabsl:parameter[@name=$ref]/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</xsl:if>
|
||||
<xsl:if test="../../xabsl:subsequent-basic-behavior">
|
||||
<a href="basic-behaviors.{key('basic-behaviors',$subsequent)/../@id}.html#{$subsequent}" title="{key('basic-behaviors',$subsequent)/xabsl:parameter[@name=$ref]/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</xsl:if>
|
||||
</td>
|
||||
<td nowrap="nowrap" class="pseudo-code-cell"> = </td>
|
||||
<td class="pseudo-code-cell">
|
||||
<xsl:apply-templates/>;
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<tr>
|
||||
<td colspan="5"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="5">The decision tree:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="4">
|
||||
<dotml:graph ranksep="0.4">
|
||||
<xsl:attribute name="file-name">svg/option_<xsl:value-of select="../@name"/>_state_<xsl:value-of select="@name"/></xsl:attribute>
|
||||
<dotml:cluster id="option" label="option {../@name}" fontname="Arial" fontcolor="#005A9C" fontsize="12" fillcolor="#F4F4F4" style="filled">
|
||||
<dotml:cluster id="states" style="filled" fillcolor="#F4F4F4" color="#F4F4F4">
|
||||
<xsl:for-each select=".//xabsl:transition-to-state | ../xabsl:common-decision-tree//xabsl:transition-to-state">
|
||||
<xsl:variable name="ref" select="@ref"/>
|
||||
<xsl:for-each select="ancestor::xabsl:option/xabsl:state[@name=$ref and @name!=$current-state]">
|
||||
<xsl:call-template name="paint-state-node">
|
||||
<xsl:with-param name="option-name" select="../@name"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="ancestor::xabsl:option/xabsl:state[@name=$ref and @name=$current-state]">
|
||||
<dotml:node label="{@name}" fontname="Arial" fontcolor="#005A9C" fontsize="9" style="dashed" fillcolor="#FFFFFF">
|
||||
<xsl:attribute name="id">state_<xsl:value-of select="@name"/></xsl:attribute>
|
||||
<xsl:attribute name="label"><xsl:call-template name="replace-in-string"><xsl:with-param name="original-string" select="@name"/><xsl:with-param name="replace">_</xsl:with-param><xsl:with-param name="with">\n</xsl:with-param></xsl:call-template></xsl:attribute>
|
||||
<xsl:attribute name="shape"><xsl:choose><xsl:when test="../@initial-state=@name">Mcircle</xsl:when><xsl:when test="@is-target-state='true'">doublecircle</xsl:when><xsl:otherwise>circle</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
</dotml:node>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
</dotml:cluster>
|
||||
<dotml:cluster id="decision_tree" label="state {@name}" fillcolor="#FFFFFF" fontname="Arial" fontcolor="#005A9C" fontsize="12" style="filled">
|
||||
<dotml:node id="start" shape="point"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="../xabsl:common-decision-tree">
|
||||
<xsl:for-each select="../xabsl:common-decision-tree">
|
||||
<xsl:call-template name="decision-tree">
|
||||
<xsl:with-param name="parent">start</xsl:with-param>
|
||||
<xsl:with-param name="id-string"></xsl:with-param>
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:for-each select="xabsl:decision-tree">
|
||||
<xsl:call-template name="decision-tree">
|
||||
<xsl:with-param name="parent">start</xsl:with-param>
|
||||
<xsl:with-param name="id-string"></xsl:with-param>
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</dotml:cluster>
|
||||
</dotml:cluster>
|
||||
</dotml:graph>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="5"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="5">Pseudo code of the decision tree:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="4">
|
||||
<xsl:choose>
|
||||
<xsl:when test="../xabsl:common-decision-tree">
|
||||
<xsl:for-each select="../xabsl:common-decision-tree">
|
||||
<xsl:call-template name="pseudo-code">
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string">state_<xsl:value-of select="$current-state"/>_pseudo-code</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:for-each select="xabsl:decision-tree">
|
||||
<xsl:call-template name="pseudo-code">
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string">state_<xsl:value-of select="$current-state"/>_pseudo-code</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</xsl:template>
|
||||
<xsl:template name="decision-tree">
|
||||
<xsl:param name="parent"/>
|
||||
<xsl:param name="id-string"/>
|
||||
<xsl:param name="current-state"/>
|
||||
<xsl:param name="taillabel"/>
|
||||
<xsl:variable name="pos_else" select="count(xabsl:else-if)+1"/>
|
||||
<xsl:if test="xabsl:if">
|
||||
<xsl:for-each select="xabsl:if | xabsl:else-if">
|
||||
<dotml:node id="{$id-string}_{position()-1}" shape="box" fontsize="9" style="filled" fillcolor="#FFFFFF">
|
||||
<xsl:attribute name="fontname"><xsl:choose><xsl:when test="ancestor-or-self::xabsl:common-decision-tree">Arial Italic</xsl:when><xsl:otherwise>Arial</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
<xsl:attribute name="label"><xsl:call-template name="add-line-breaks"><xsl:with-param name="original-string"><xsl:value-of select="xabsl:condition/@description"/></xsl:with-param><xsl:with-param name="min-length">5</xsl:with-param></xsl:call-template></xsl:attribute>
|
||||
<xsl:attribute name="URL">option.<xsl:value-of select="ancestor::xabsl:option/@name"/>.html#state_<xsl:value-of select="$current-state"/>_pseudo-code<xsl:value-of select="$id-string"/>_<xsl:value-of select="position()-1"/></xsl:attribute>
|
||||
</dotml:node>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:if | xabsl:else-if">
|
||||
<xsl:call-template name="decision-tree">
|
||||
<xsl:with-param name="parent">
|
||||
<xsl:value-of select="$id-string"/>_<xsl:value-of select="position()-1"/></xsl:with-param>
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string">
|
||||
<xsl:value-of select="$id-string"/>_<xsl:value-of select="position()-1"/></xsl:with-param>
|
||||
<xsl:with-param name="taillabel">1</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
<xsl:if test="position() < $pos_else">
|
||||
<dotml:edge from="{$id-string}_{position()-1}" to="{$id-string}_{position()}" label="" fontsize="9" taillabel="0">
|
||||
<xsl:attribute name="style"><xsl:choose><xsl:when test="ancestor-or-self::xabsl:common-decision-tree">dashed</xsl:when><xsl:otherwise>solid</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
<xsl:attribute name="fontname"><xsl:choose><xsl:when test="ancestor-or-self::xabsl:common-decision-tree">Arial Bold Italic</xsl:when><xsl:otherwise>Arial Bold</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
<dotml:edge from="{$parent}" to="{$id-string}_0" label="" fontsize="9" taillabel="{$taillabel}">
|
||||
<xsl:attribute name="style"><xsl:choose><xsl:when test="ancestor-or-self::xabsl:common-decision-tree">dashed</xsl:when><xsl:otherwise>solid</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
<xsl:attribute name="fontname"><xsl:choose><xsl:when test="ancestor-or-self::xabsl:common-decision-tree">Arial Bold Italic</xsl:when><xsl:otherwise>Arial Bold</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
</dotml:edge>
|
||||
<xsl:if test="ancestor-or-self::xabsl:common-decision-tree and count(xabsl:else)=0">
|
||||
<xsl:for-each select="ancestor::xabsl:option/xabsl:state[@name=$current-state]/xabsl:decision-tree">
|
||||
<xsl:call-template name="decision-tree">
|
||||
<xsl:with-param name="parent">
|
||||
<xsl:value-of select="$id-string"/>_<xsl:value-of select="$pos_else - 1"/></xsl:with-param>
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string">
|
||||
<xsl:value-of select="$id-string"/>_<xsl:value-of select="$pos_else"/></xsl:with-param>
|
||||
<xsl:with-param name="taillabel">0</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
<xsl:for-each select="xabsl:else">
|
||||
<xsl:call-template name="decision-tree">
|
||||
<xsl:with-param name="parent">
|
||||
<xsl:value-of select="$id-string"/>_<xsl:value-of select="$pos_else - 1"/>
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string">
|
||||
<xsl:value-of select="$id-string"/>_<xsl:value-of select="$pos_else"/>
|
||||
</xsl:with-param>
|
||||
<xsl:with-param name="taillabel">0</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
<xsl:if test="xabsl:transition-to-state">
|
||||
<dotml:edge from="{$parent}" minlen="2" label="" fontsize="9" taillabel="{$taillabel}">
|
||||
<xsl:variable name="ref" select="xabsl:transition-to-state/@ref"/>
|
||||
<xsl:attribute name="style"><xsl:choose><xsl:when test="ancestor-or-self::xabsl:common-decision-tree">dashed</xsl:when><xsl:otherwise>solid</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
<xsl:attribute name="to">state_<xsl:value-of select="$ref"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template name="paint-state-node">
|
||||
<xsl:param name="option-name"/>
|
||||
<dotml:node fontcolor="#005A9C" fontsize="9" style="filled" fillcolor="#FFFFFF" fontname="Arial" URL="option.{$option-name}.html#state_{@name}">
|
||||
<xsl:attribute name="id">state_<xsl:value-of select="@name"/></xsl:attribute>
|
||||
<xsl:attribute name="label"><xsl:call-template name="replace-in-string"><xsl:with-param name="original-string" select="@name"/><xsl:with-param name="replace">_</xsl:with-param><xsl:with-param name="with">\n</xsl:with-param></xsl:call-template></xsl:attribute>
|
||||
<xsl:attribute name="shape"><xsl:choose><xsl:when test="../@initial-state=@name">Mcircle</xsl:when><xsl:when test="@is-target-state='true'">doublecircle</xsl:when><xsl:otherwise>circle</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
</dotml:node>
|
||||
</xsl:template>
|
||||
<xsl:template name="state-machine">
|
||||
<xsl:variable name="name" select="@name"/>
|
||||
<dotml:sub-graph rank="same">
|
||||
<xsl:for-each select="xabsl:state[1]">
|
||||
<xsl:call-template name="paint-state-node">
|
||||
<xsl:with-param name="option-name" select="$name"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</dotml:sub-graph>
|
||||
<xsl:for-each select="xabsl:state[position() mod 3 = 2]">
|
||||
<dotml:sub-graph rank="same">
|
||||
<xsl:call-template name="paint-state-node">
|
||||
<xsl:with-param name="option-name" select="$name"/>
|
||||
</xsl:call-template>
|
||||
<xsl:for-each select="following-sibling::xabsl:state[1]">
|
||||
<xsl:call-template name="paint-state-node">
|
||||
<xsl:with-param name="option-name" select="$name"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="following-sibling::xabsl:state[2]">
|
||||
<xsl:call-template name="paint-state-node">
|
||||
<xsl:with-param name="option-name" select="$name"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</dotml:sub-graph>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:state">
|
||||
<xsl:variable name="name2" select="@name"/>
|
||||
<xsl:for-each select="descendant::xabsl:transition-to-state | ../xabsl:common-decision-tree/descendant::xabsl:transition-to-state">
|
||||
<xsl:if test="count(key('transitions',@ref)[ancestor::xabsl:state[@name=$name2] or ancestor::xabsl:common-decision-tree][1] | .) = 1">
|
||||
<dotml:edge>
|
||||
<xsl:attribute name="from">state_<xsl:value-of select="$name2"/></xsl:attribute>
|
||||
<xsl:attribute name="to">state_<xsl:value-of select="@ref"/></xsl:attribute>
|
||||
</dotml:edge>
|
||||
</xsl:if>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de">
|
||||
<xsl:template name="parameters">
|
||||
<xsl:if test="xabsl:decimal-parameter | xabsl:boolean-parameter | xabsl:enumerated-parameter">
|
||||
<table border="0" cellspacing="6" cellpadding="0">
|
||||
<tr>
|
||||
<td class="tablehead">Parameter</td>
|
||||
<td class="tablehead">Type</td>
|
||||
<td class="tablehead">Measure</td>
|
||||
<td class="tablehead">Range</td>
|
||||
<td class="tablehead">Description</td>
|
||||
</tr>
|
||||
<xsl:for-each select="xabsl:decimal-parameter">
|
||||
<tr>
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>decimal</td>
|
||||
<td class="italic">
|
||||
<xsl:value-of select="@measure"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@range"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:boolean-parameter">
|
||||
<tr>
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>boolean</td>
|
||||
<td class="italic">true/ false</td>
|
||||
<td/>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="xabsl:enumerated-parameter">
|
||||
<tr>
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>enumerated</td>
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@enumeration"/>
|
||||
</td>
|
||||
<td/>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,427 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<xsl:key name="decimal-input-symbols" match="//xabsl:decimal-input-symbol" use="@name"/>
|
||||
<xsl:key name="boolean-input-symbols" match="//xabsl:boolean-input-symbol" use="@name"/>
|
||||
<xsl:key name="enumerated-input-symbols" match="//xabsl:enumerated-input-symbol" use="@name"/>
|
||||
<xsl:key name="decimal-output-symbols" match="//xabsl:decimal-output-symbol" use="@name"/>
|
||||
<xsl:key name="boolean-output-symbols" match="//xabsl:boolean-output-symbol" use="@name"/>
|
||||
<xsl:key name="enumerated-output-symbols" match="//xabsl:enumerated-output-symbol" use="@name"/>
|
||||
<xsl:key name="constants" match="//xabsl:constant" use="@name"/>
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
<xsl:template name="pseudo-code">
|
||||
<xsl:param name="current-state"/>
|
||||
<xsl:param name="id-string"/>
|
||||
<table>
|
||||
<xsl:attribute name="class"><xsl:choose><xsl:when test="ancestor-or-self::xabsl:common-decision-tree">common-pseudo-code-frame</xsl:when><xsl:otherwise>pseudo-code-frame</xsl:otherwise></xsl:choose></xsl:attribute>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<xsl:choose>
|
||||
<xsl:when test="local-name(xabsl:*)='if' or local-name(xabsl:*)='else' or local-name(xabsl:*)='else-if'">
|
||||
<xsl:apply-templates>
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string" select="$id-string"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<tr>
|
||||
<xsl:for-each select="xabsl:*">
|
||||
<xsl:call-template name="apply-template-in-new-table-cell">
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</tr>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</xsl:template>
|
||||
<xsl:template name="apply-template-in-new-table-cell">
|
||||
<xsl:param name="current-state"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="local-name()='not' or local-name()='and' or local-name()='or'">
|
||||
<td>
|
||||
<xsl:apply-templates select=".">
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
</xsl:apply-templates>
|
||||
</td>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<td class="pseudo-code-cell">
|
||||
<xsl:apply-templates select=".">
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
</xsl:apply-templates>
|
||||
</td>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:else-if | xabsl:if">
|
||||
<xsl:param name="current-state"/>
|
||||
<xsl:param name="id-string"/>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr id="{$id-string}_{count(preceding-sibling::xabsl:else-if | preceding-sibling::xabsl:if)}">
|
||||
<td colspan="4" class="pseudo-code-cell">
|
||||
<xsl:for-each select="xabsl:condition">
|
||||
<span class="italic">/** <xsl:value-of select="@description"/> */</span>
|
||||
</xsl:for-each>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="pseudo-code-left-bracket" nowrap="nowrap">
|
||||
<span class="bold">
|
||||
<xsl:if test="local-name()='if'">if</xsl:if>
|
||||
<xsl:if test="local-name()='else-if'">else if</xsl:if>
|
||||
</span> (
|
||||
</td>
|
||||
<xsl:for-each select="xabsl:condition">
|
||||
<xsl:for-each select="xabsl:*">
|
||||
<xsl:call-template name="apply-template-in-new-table-cell">
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
<td class="pseudo-code-right-bracket">)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="4" class="pseudo-code-cell">{</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="pseudo-code-cell" nowrap="nowrap">  </td>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<xsl:apply-templates>
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string">
|
||||
<xsl:value-of select="$id-string"/>_<xsl:value-of select="count(preceding-sibling::xabsl:else-if | preceding-sibling::xabsl:if)"/>
|
||||
</xsl:with-param>
|
||||
</xsl:apply-templates>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="4" class="pseudo-code-cell">}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<xsl:if test="ancestor-or-self::xabsl:common-decision-tree and count(following-sibling::xabsl:*)=0">
|
||||
<xsl:variable name="index" select="count(preceding-sibling::xabsl:else-if | preceding-sibling::xabsl:if)+1"/>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="4" class="pseudo-code-cell">
|
||||
<span class="bold">else</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="4" class="pseudo-code-cell">{</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="pseudo-code-cell" nowrap="nowrap">  </td>
|
||||
<td>
|
||||
<xsl:for-each select="ancestor::xabsl:option/xabsl:state[@name=$current-state]/xabsl:decision-tree">
|
||||
<xsl:call-template name="pseudo-code">
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string"><xsl:value-of select="$id-string"/>_<xsl:value-of select="$index"/></xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:for-each>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="4" class="pseudo-code-cell">}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:else">
|
||||
<xsl:param name="current-state"/>
|
||||
<xsl:param name="id-string"/>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="4" class="pseudo-code-cell">
|
||||
<span class="bold">else</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="4" class="pseudo-code-cell">{</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="pseudo-code-cell" nowrap="nowrap">  </td>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<xsl:apply-templates>
|
||||
<xsl:with-param name="current-state" select="$current-state"/>
|
||||
<xsl:with-param name="id-string"><xsl:value-of select="$id-string"/>_<xsl:value-of select="count(preceding-sibling::xabsl:else-if | preceding-sibling::xabsl:if)"/></xsl:with-param>
|
||||
</xsl:apply-templates>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="4" class="pseudo-code-cell">}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:transition-to-state">
|
||||
<xsl:param name="current-state"/>
|
||||
<tr>
|
||||
<xsl:choose>
|
||||
<xsl:when test="not(ancestor-or-self::xabsl:common-decision-tree) and @ref=$current-state">
|
||||
<td class="pseudo-code-cell">stay;</td>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<td class="pseudo-code-cell">goto <a href="#state_{@ref}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>;
|
||||
</td>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:condition"/>
|
||||
<xsl:template match="xabsl:or | xabsl:and">
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="pseudo-code-left-bracket" nowrap="nowrap">(</td>
|
||||
<xsl:for-each select="xabsl:*[1]">
|
||||
<xsl:call-template name="apply-template-in-new-table-cell"/>
|
||||
</xsl:for-each>
|
||||
<td class="pseudo-code-right-bracket">)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<xsl:for-each select="xabsl:*[position()>1]">
|
||||
<tr>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td nowrap="nowrap" class="pseudo-code-cell">
|
||||
<xsl:choose>
|
||||
<xsl:when test="local-name(..)='or'">|| </xsl:when>
|
||||
<xsl:when test="local-name(..)='and'">&& </xsl:when>
|
||||
</xsl:choose>
|
||||
</td>
|
||||
<td>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="pseudo-code-left-bracket" nowrap="nowrap">(</td>
|
||||
<xsl:call-template name="apply-template-in-new-table-cell"/>
|
||||
<td valign="bottom" class="pseudo-code-right-bracket" nowrap="nowrap">)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:not">
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="pseudo-code-left-bracket" nowrap="nowrap">!(</td>
|
||||
<xsl:for-each select="xabsl:*[1]">
|
||||
<xsl:call-template name="apply-template-in-new-table-cell"/>
|
||||
</xsl:for-each>
|
||||
<td class="pseudo-code-right-bracket">)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:equal-to | xabsl:not-equal-to | xabsl:less-than | xabsl:less-than-or-equal-to | xabsl:greater-than | xabsl:greater-than-or-equal-to | xabsl:enumerated-input-symbol-comparison">
|
||||
<xsl:apply-templates select="xabsl:*[1]"/>
|
||||
<span class="nowrap">
|
||||
<xsl:choose>
|
||||
<xsl:when test="local-name()='equal-to'"> == </xsl:when>
|
||||
<xsl:when test="local-name()='not-equal-to'"> != </xsl:when>
|
||||
<xsl:when test="local-name()='less-than'"> < </xsl:when>
|
||||
<xsl:when test="local-name()='less-than-or-equal-to'"> < </xsl:when>
|
||||
<xsl:when test="local-name()='greater-than'"> > </xsl:when>
|
||||
<xsl:when test="local-name()='greater-than-or-equal-to'"> >= </xsl:when>
|
||||
<xsl:when test="local-name()='enumerated-input-symbol-comparison'"> == </xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:apply-templates select="xabsl:*[2]"/>
|
||||
</span>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:plus | xabsl:minus | xabsl:multiply | xabsl:divide | xabsl:mod">(<xsl:apply-templates select="xabsl:*[1]"/>
|
||||
<span class="nowrap">
|
||||
<xsl:choose>
|
||||
<xsl:when test="local-name()='plus'"> + </xsl:when>
|
||||
<xsl:when test="local-name()='minus'"> - </xsl:when>
|
||||
<xsl:when test="local-name()='multiply'"> * </xsl:when>
|
||||
<xsl:when test="local-name()='divide'"> / </xsl:when>
|
||||
<xsl:when test="local-name()='mod'"> % </xsl:when>
|
||||
</xsl:choose>
|
||||
<xsl:apply-templates select="xabsl:*[2]"/>)</span>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:decimal-input-symbol-ref">
|
||||
<a href="symbols.{key('decimal-input-symbols',@ref)/../@id}.html#{@ref}" title="{key('decimal-input-symbols',@ref)/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>(<xsl:for-each select="xabsl:with-parameter">
|
||||
<span class="nowrap">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:if test="count(following-sibling::xabsl:*)>0">, </xsl:if>
|
||||
</span>
|
||||
</xsl:for-each>)
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:boolean-input-symbol-ref">
|
||||
<a href="symbols.{key('boolean-input-symbols',@ref)/../@id}.html#{@ref}" title="{key('boolean-input-symbols',@ref)/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>(<xsl:for-each select="xabsl:with-parameter">
|
||||
<span class="nowrap">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:if test="count(following-sibling::xabsl:*)>0">, </xsl:if>
|
||||
</span>
|
||||
</xsl:for-each>)
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumerated-input-symbol-ref">
|
||||
<a href="symbols.{key('enumerated-input-symbols',@ref)/../@id}.html#{@ref}" title="{key('enumerated-input-symbols',@ref)/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>(<xsl:for-each select="xabsl:with-parameter">
|
||||
<span class="nowrap">
|
||||
<xsl:apply-templates/>
|
||||
<xsl:if test="count(following-sibling::xabsl:*)>0">, </xsl:if>
|
||||
</span>
|
||||
</xsl:for-each>)
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:decimal-output-symbol-ref">
|
||||
<a href="symbols.{key('decimal-output-symbols',@ref)/../@id}.html#{@ref}" title="{key('decimal-output-symbols',@ref)/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:boolean-output-symbol-ref">
|
||||
<a href="symbols.{key('boolean-output-symbols',@ref)/../@id}.html#{@ref}" title="{key('boolean-output-symbols',@ref)/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumerated-output-symbol-ref">
|
||||
<a href="symbols.{key('enumerated-output-symbols',@ref)/../@id}.html#{@ref}" title="{key('enumerated-output-symbols',@ref)/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:constant-ref">
|
||||
<a href="symbols.{key('constants',@ref)/../@id}.html#{@ref}" title="{key('constants',@ref)/@description} ({key('constants',@ref)/@value})">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:conditional-expression">(<xsl:for-each select="xabsl:condition">
|
||||
<xsl:apply-templates/>
|
||||
</xsl:for-each>?<xsl:for-each select="xabsl:expression1">
|
||||
<xsl:apply-templates/>
|
||||
</xsl:for-each>:<xsl:for-each select="xabsl:expression2">
|
||||
<xsl:apply-templates/>
|
||||
</xsl:for-each>)</xsl:template>
|
||||
<xsl:template match="xabsl:option-parameter-ref">
|
||||
<xsl:variable name="option-name" select="ancestor::xabsl:option/@name"/>
|
||||
<xsl:variable name="ref" select="@ref"/>@<a href="option.{ancestor::xabsl:option/@name}.html" title="Option parameter {@ref}: {ancestor::xabsl:option/xabsl:option-definitions/xabsl:option-definition[@name=$option-name]/xabsl:parameter[@name=$ref]/@description}">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</a>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:decimal-value">
|
||||
<xsl:value-of select="@value"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:boolean-value">
|
||||
<xsl:value-of select="@value"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enum-element-ref">
|
||||
<xsl:value-of select="@ref"/>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:subsequent-option-reached-target-state">action_done</xsl:template>
|
||||
<xsl:template match="xabsl:time-of-state-execution">state_time</xsl:template>
|
||||
<xsl:template match="xabsl:time-of-option-execution">option_time</xsl:template>
|
||||
<xsl:template match="xabsl:*" priority="-10000">
|
||||
<xsl:value-of select="local-name()"/>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de">
|
||||
<xsl:template name="replace-in-string">
|
||||
<!-- A nice template for "search and replace" on strings.
|
||||
Parameter original-string: the string to process
|
||||
Parameter replace: the expression to be replaced.
|
||||
Parameter with: the new string.
|
||||
|
||||
Example: original-string: "1+3+6=10", replace: "+", with: "-" returns "1-3-6=10". -->
|
||||
<xsl:param name="original-string"/>
|
||||
<xsl:param name="replace"/>
|
||||
<xsl:param name="with"/>
|
||||
<xsl:variable name="string-before-replace-pattern" select="substring-before($original-string,$replace)"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="string-length($string-before-replace-pattern)=0">
|
||||
<xsl:value-of select="$original-string"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$string-before-replace-pattern"/>
|
||||
<xsl:value-of select="$with"/>
|
||||
<xsl:call-template name="replace-in-string">
|
||||
<xsl:with-param name="original-string" select="substring-after($original-string,$replace)"/>
|
||||
<xsl:with-param name="replace" select="$replace"/>
|
||||
<xsl:with-param name="with" select="$with"/>
|
||||
</xsl:call-template>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
<xsl:template name="add-line-breaks">
|
||||
<!-- A template that adds "\n" line breaks to a string after a minimum length of characters.
|
||||
Parameter original-string: the string to process
|
||||
Parameter min-length: the minimum length after that a line break is inserted
|
||||
|
||||
Example: original-string: "Tom doesn't like to eat cats", min-length: "10" returns "Tom doesn't\nlike to eat\ncats."-->
|
||||
<xsl:param name="original-string"/>
|
||||
<xsl:param name="min-length"/>
|
||||
<xsl:variable name="first-sub-string" select="substring-before($original-string,substring($original-string,$min-length+1))"/>
|
||||
<xsl:if test="string-length($first-sub-string)=0">
|
||||
<xsl:value-of select="$original-string"/>
|
||||
</xsl:if>
|
||||
<xsl:if test="string-length($first-sub-string)>0">
|
||||
<xsl:variable name="second-sub-string" select="substring-before(substring($original-string,$min-length+1),' ')"/>
|
||||
<xsl:variable name="third-sub-string" select="substring-after(substring($original-string,$min-length+1),' ')"/>
|
||||
<xsl:if test="string-length($third-sub-string)=0">
|
||||
<xsl:value-of select="$original-string"/>
|
||||
</xsl:if>
|
||||
<xsl:if test="string-length($third-sub-string)>0">
|
||||
<xsl:value-of select="$first-sub-string"/>
|
||||
<xsl:value-of select="$second-sub-string"/>\n<xsl:call-template name="add-line-breaks">
|
||||
<xsl:with-param name="original-string" select="$third-sub-string"/>
|
||||
<xsl:with-param name="min-length" select="$min-length"/>
|
||||
</xsl:call-template>
|
||||
</xsl:if>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
|
||||
<xsl:import href="generate-documentation.menu.xsl"/>
|
||||
<xsl:output method="html" indent="yes"/>
|
||||
<xsl:key name="symbols" match="xabsl:agent-collection/xabsl:options/xabsl:option/xabsl:symbols" use="@id"/>
|
||||
<xsl:template match="xabsl:agent-collection">
|
||||
<html>
|
||||
<head>
|
||||
<title>XABSL Behavior Documentation: Symbols</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<xsl:text> </xsl:text>
|
||||
</link>
|
||||
</head>
|
||||
<body>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="menu-cell">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<xsl:call-template name="menu-xabsl2-logo"/>
|
||||
<xsl:call-template name="menu-entry-index-linked"/>
|
||||
<xsl:call-template name="menu-entry-agents-linked"/>
|
||||
<xsl:call-template name="menu-entry-symbols"/>
|
||||
<xsl:call-template name="menu-symbols"/>
|
||||
<xsl:call-template name="menu-entry-basic-behaviors-linked"/>
|
||||
<xsl:call-template name="menu-entry-options-linked"/>
|
||||
</table>
|
||||
</td>
|
||||
<td class="main-area">
|
||||
<h1>Symbols</h1>
|
||||
<table border="0" cellpadding="4" cellspacing="0">
|
||||
<xsl:for-each select="xabsl:options/xabsl:option/xabsl:symbols[count(key('symbols',@id)[1] | .)=1]">
|
||||
<tr>
|
||||
<td class="bold">
|
||||
<div class="nowrap">
|
||||
<a href="symbols.{@id}.html" title="{@description}">
|
||||
<xsl:value-of select="@title"/>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="menu-item">
|
||||
<xsl:for-each select="xabsl:*">
|
||||
<a href="symbols.{../@id}.html#{@name}" title="{@description}">
|
||||
<span class="nowrap">
|
||||
<xsl:value-of select="@name"/>
|
||||
</span>
|
||||
</a>    </xsl:for-each>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,238 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de">
|
||||
<xsl:import href="generate-documentation.parameters.xsl"/>
|
||||
<xsl:import href="generate-documentation.menu.xsl"/>
|
||||
<xsl:output method="html" indent="yes"/>
|
||||
<xsl:template match="xabsl:symbols">
|
||||
<html>
|
||||
<head>
|
||||
<title>XABSL Behavior Documentation: <xsl:value-of select="@title"/>
|
||||
</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<xsl:text> </xsl:text>
|
||||
</link>
|
||||
</head>
|
||||
<body>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="menu-cell">
|
||||
<table border="0" cellspacing="0" cellpadding="1">
|
||||
<xsl:call-template name="menu-xabsl2-logo"/>
|
||||
<xsl:call-template name="menu-entry-index-linked"/>
|
||||
<xsl:call-template name="menu-entry-agents-linked"/>
|
||||
<xsl:call-template name="menu-entry-symbols-linked"/>
|
||||
<xsl:call-template name="menu-symbol"/>
|
||||
<xsl:call-template name="menu-entry-basic-behaviors-linked"/>
|
||||
<xsl:call-template name="menu-entry-options-linked"/>
|
||||
</table>
|
||||
</td>
|
||||
<td class="main-area">
|
||||
<h1>
|
||||
<xsl:value-of select="@title"/>
|
||||
</h1>
|
||||
<p>
|
||||
<xsl:value-of select="@description"></xsl:value-of>
|
||||
</p>
|
||||
<p>The formalized behavior references a variety of input and output symbols, which can stand for variables or functions of the agent's software. Constants are constant decimal values.</p>
|
||||
<xsl:if test="xabsl:enumeration">
|
||||
<h2 id="enumerations">Enumerations</h2>
|
||||
<table border="0" cellpadding="0" cellspacing="6">
|
||||
<tr>
|
||||
<td class="tablehead">Name</td>
|
||||
<td class="tablehead">Elements</td>
|
||||
<td class="tablehead">Internal</td>
|
||||
<td class="tablehead">Description</td>
|
||||
</tr>
|
||||
<xsl:apply-templates select="xabsl:enumeration"/>
|
||||
</table>
|
||||
</xsl:if>
|
||||
<xsl:if test="xabsl:decimal-input-symbol | xabsl:boolean-input-symbol | xabsl:enumerated-input-symbol">
|
||||
|
||||
<h2 id="input-symbols">Input Symbols</h2>
|
||||
<table border="0" cellpadding="0" cellspacing="6">
|
||||
<tr>
|
||||
<td class="tablehead">Name</td>
|
||||
<td class="tablehead">Type</td>
|
||||
<td class="tablehead">Measure</td>
|
||||
<td class="tablehead">Description / Parameters</td>
|
||||
</tr>
|
||||
<xsl:apply-templates select="xabsl:decimal-input-symbol | xabsl:boolean-input-symbol | xabsl:enumerated-input-symbol"/>
|
||||
</table></xsl:if>
|
||||
<xsl:if test="xabsl:decimal-output-symbol | xabsl:boolean-output-symbol | xabsl:enumerated-output-symbol">
|
||||
|
||||
|
||||
<h2 id="output-symbols">Output Symbols</h2>
|
||||
<table border="0" cellpadding="0" cellspacing="6">
|
||||
<tr>
|
||||
<td class="tablehead">Name</td>
|
||||
<td class="tablehead">Type</td>
|
||||
<td class="tablehead">Measure</td>
|
||||
<td class="tablehead">Internal</td>
|
||||
<td class="tablehead">Description</td>
|
||||
</tr>
|
||||
<xsl:apply-templates select="xabsl:decimal-output-symbol | xabsl:boolean-output-symbol | xabsl:enumerated-output-symbol"/>
|
||||
</table>
|
||||
|
||||
</xsl:if>
|
||||
<xsl:if test="xabsl:constant">
|
||||
<h2 id="constants">Constants</h2>
|
||||
<table border="0" cellpadding="0" cellspacing="6">
|
||||
<tr>
|
||||
<td class="tablehead">Name</td>
|
||||
<td class="tablehead">Value</td>
|
||||
<td class="tablehead">Measure</td>
|
||||
<td class="tablehead">Description</td>
|
||||
</tr>
|
||||
<xsl:apply-templates select="xabsl:constant"/>
|
||||
</table>
|
||||
|
||||
</xsl:if>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumeration">
|
||||
<tr id="{@name}">
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td class="italic">
|
||||
<xsl:for-each select="xabsl:enum-element">
|
||||
<xsl:value-of select="@name"/>
|
||||
<br/>
|
||||
</xsl:for-each>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@internal"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:decimal-input-symbol">
|
||||
<tr id="{@name}">
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>decimal</td>
|
||||
<td class="italic">
|
||||
<xsl:value-of select="@measure"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"> </td>
|
||||
<td>
|
||||
<xsl:call-template name="parameters"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:boolean-input-symbol">
|
||||
<tr id="{@name}">
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>boolean</td>
|
||||
<td class="italic">true/ false</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"> </td>
|
||||
<td>
|
||||
<xsl:call-template name="parameters"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:decimal-output-symbol">
|
||||
<tr id="{@name}">
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>decimal</td>
|
||||
<td class="italic">
|
||||
<xsl:value-of select="@measure"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@internal"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:boolean-output-symbol">
|
||||
<tr id="{@name}">
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>boolean</td>
|
||||
<td class="italic">true/ false</td>
|
||||
<td>
|
||||
<xsl:value-of select="@internal"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumerated-input-symbol">
|
||||
<tr id="{@name}">
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>enumerated</td>
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@enumeration"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3"> </td>
|
||||
<td>
|
||||
<xsl:call-template name="parameters"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:enumerated-output-symbol">
|
||||
<tr id="{@name}">
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>enumerated</td>
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@enumeration"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@internal"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="xabsl:constant">
|
||||
<tr id="{@name}">
|
||||
<td class="bold">
|
||||
<xsl:value-of select="@name"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@value"/>
|
||||
</td>
|
||||
<td class="italic">
|
||||
<xsl:value-of select="@measure"/>
|
||||
</td>
|
||||
<td>
|
||||
<xsl:value-of select="@description"/>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xabsl="http://www.xabsl.de">
|
||||
<xsl:template match="*" priority="-1000">
|
||||
<xsl:copy>
|
||||
<xsl:copy-of select="./@*"/>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:copy>
|
||||
</xsl:template>
|
||||
<xsl:template match="text()" priority="-1000">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:template>
|
||||
<xsl:template match="comment()">
|
||||
<!-- the aim of this stylesheet is to remove all comments from a xml file and to reproduce the rest of it. -->
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@ -0,0 +1,84 @@
|
||||
/*===========================================================================
|
||||
|
||||
MyBasicBehaviors.h
|
||||
|
||||
Implementation of all basic behaviors.
|
||||
|
||||
author: Martin Lötzsch
|
||||
===========================================================================*/
|
||||
|
||||
#include "MyBasicBehaviors.h"
|
||||
|
||||
void BasicBehaviorGetBehindBall::execute()
|
||||
{
|
||||
int ballLocalDirection = worldState.getBallLocalDirection();
|
||||
|
||||
switch(ballLocalDirection)
|
||||
{
|
||||
case -1: action=worldState.ball_direction[worldState.activePlayerNumber]; break;
|
||||
case E:
|
||||
if (worldState.y[worldState.activePlayerNumber] < 11) action=SE;
|
||||
else action=NE;
|
||||
break;
|
||||
case SE: action=E; break;
|
||||
case NE: action=E; break;
|
||||
case N:
|
||||
if (worldState.local_area[NE][worldState.activePlayerNumber] == EMPTY) action=NE;
|
||||
else action = E;
|
||||
break;
|
||||
case S:
|
||||
if (worldState.local_area[SE][worldState.activePlayerNumber] == EMPTY) action=SE;
|
||||
else action = E;
|
||||
break;
|
||||
action=SE; break;
|
||||
case SW: action=S; break;
|
||||
case NW: action=N; break;
|
||||
case W: action=W; break;
|
||||
case PLAYER: action=E; break;
|
||||
}
|
||||
}
|
||||
|
||||
void BasicBehaviorGoTo::execute()
|
||||
{
|
||||
int _x=(int)x, _y=(int)y;
|
||||
|
||||
if (_x<1) _x=1; if (_x>78) _x=78; if (_y>21) _y=21; if (_y<1) _y=1;
|
||||
|
||||
if (_x<worldState.ball_x && _y==worldState.ball_y) if (_y <11) _y++; else _y--;
|
||||
|
||||
int dx = _x - worldState.x[worldState.activePlayerNumber], dy = _y - worldState.y[worldState.activePlayerNumber];
|
||||
|
||||
if (dy < 0)
|
||||
{
|
||||
if (dx >= 0 || abs(dx) < abs(dy)) action=NE;
|
||||
else action=NW;
|
||||
}
|
||||
else if (dy > 0)
|
||||
{
|
||||
if (dx >= 0 || abs(dx) < abs(dy)) action=SE;
|
||||
else action=SW;
|
||||
}
|
||||
else // dy == 0
|
||||
{
|
||||
if (dx>0) action = E;
|
||||
else if (dx<0) action = W;
|
||||
else action = DO_NOTHING;
|
||||
}
|
||||
|
||||
if (worldState.local_area[action][worldState.activePlayerNumber] != EMPTY)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case N: action=NE; break;
|
||||
case NE: action=E; break;
|
||||
case E: action=(worldState.y[worldState.activePlayerNumber]<11?SE:NE); break;
|
||||
case SE: action=E; break;
|
||||
case S: action=SE; break;
|
||||
case SW: action=S; break;
|
||||
case W: action=W; break;
|
||||
case NW: action=N; break;
|
||||
}
|
||||
}
|
||||
if (worldState.local_area[action][worldState.activePlayerNumber] != EMPTY) action=DO_NOTHING;
|
||||
}
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
/*===========================================================================
|
||||
|
||||
MyBasicBehaviors.h
|
||||
|
||||
Definition of all basic behaviors.
|
||||
|
||||
author: Martin Lötzsch
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef __MyBasicBehaviors_h_
|
||||
#define __MyBasicBehaviors_h_
|
||||
|
||||
#include "../Xabsl/XabslEngine/XabslBasicBehavior.h"
|
||||
#include "WorldState.h"
|
||||
#include "../ascii-soccer/soccer.h"
|
||||
|
||||
class BasicBehaviorGetBehindBall : public xabsl::BasicBehavior
|
||||
{
|
||||
public:
|
||||
BasicBehaviorGetBehindBall(xabsl::ErrorHandler& errorHandler,
|
||||
WorldState& worldState, int& action)
|
||||
: xabsl::BasicBehavior("get_behind_ball",errorHandler),
|
||||
worldState(worldState),
|
||||
action(action)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void execute();
|
||||
private:
|
||||
WorldState& worldState; // the world state on that the action is based
|
||||
int& action; // the action to be generated
|
||||
};
|
||||
|
||||
|
||||
class BasicBehaviorGoTo : public xabsl::BasicBehavior
|
||||
{
|
||||
public:
|
||||
double x,y; // the parameters of the basic behavior
|
||||
|
||||
BasicBehaviorGoTo(xabsl::ErrorHandler& errorHandler,
|
||||
WorldState& worldState, int& action)
|
||||
: xabsl::BasicBehavior("go_to",errorHandler),
|
||||
worldState(worldState),
|
||||
action(action)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void registerParameters()
|
||||
{
|
||||
// as basic behaviors are shared among engines for all players this is called more than once
|
||||
// register parameters only if they are not already registered
|
||||
if (!parameters->decimal.exists("go_to.x"))
|
||||
{
|
||||
parameters->registerDecimal("go_to.x",x);
|
||||
parameters->registerDecimal("go_to.y",y);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void execute();
|
||||
private:
|
||||
WorldState& worldState; // the world state on that the action is based
|
||||
int& action; // the action to be generated
|
||||
};
|
||||
|
||||
#endif //__MyBasicBehaviors_h_
|
||||
@ -0,0 +1,81 @@
|
||||
/*===========================================================================
|
||||
|
||||
Tools.h
|
||||
|
||||
Adapts the xabsl::Engine to the target platform.
|
||||
|
||||
author: Martin Lötzsch
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef __Tools_h_
|
||||
#define __Tools_h_
|
||||
|
||||
#include <fstream>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
// An error handling class derived from xabsl::ErrorHandler
|
||||
class MyErrorHandler : public xabsl::ErrorHandler
|
||||
{
|
||||
public:
|
||||
MyErrorHandler() { logfile.open("messages.log"); }
|
||||
|
||||
~MyErrorHandler() { logfile.close(); }
|
||||
|
||||
virtual void printError(const char* text)
|
||||
{logfile << "error: " << text << "\n"; logfile.flush();}
|
||||
|
||||
virtual void printMessage(const char* text)
|
||||
{logfile << text << "\n"; logfile.flush();}
|
||||
|
||||
private:
|
||||
std::ofstream logfile;
|
||||
};
|
||||
|
||||
// A file access class derived from xabsl::InputSource
|
||||
class MyFileInputSource : public xabsl::InputSource
|
||||
{
|
||||
public:
|
||||
MyFileInputSource(const char* fileName) : file(0), theChar(' ')
|
||||
{ strcpy(filename,fileName); }
|
||||
|
||||
~MyFileInputSource() {if (file!=0) delete file;}
|
||||
|
||||
virtual bool open() {file = new std::ifstream(filename); return(file!=0 && !file->fail());}
|
||||
virtual void close() {if (file!=0) delete file; file = 0;}
|
||||
|
||||
virtual double readValue()
|
||||
{ char buf[20]; readFromFile(buf); return atof(buf); }
|
||||
|
||||
virtual bool readString(char* destination, int maxLength)
|
||||
{ readFromFile(destination); return true; }
|
||||
|
||||
private:
|
||||
char filename[200]; // the file name
|
||||
std::ifstream* file; // the file to access
|
||||
char theChar; // the last character read
|
||||
|
||||
void readFromFile(char* value)
|
||||
{
|
||||
while(!file->eof() && isWhitespace())
|
||||
{
|
||||
if (theChar == '/') while(!file->eof() && theChar != '\n') file->read(&theChar,1);
|
||||
file->read(&theChar,1);
|
||||
}
|
||||
|
||||
while(!file->eof() && !isWhitespace())
|
||||
{ *value++ = theChar; if(!file->eof()) file->read(&theChar,1); }
|
||||
*value = 0;
|
||||
}
|
||||
|
||||
bool isWhitespace()
|
||||
{ return theChar == ' ' || theChar == '/' || theChar == '\n' || theChar == '\r' || theChar == '\t'; }
|
||||
};
|
||||
|
||||
// returns the current system time in milliseconds
|
||||
static unsigned getCurrentSystemTime() {
|
||||
timeb sysTime;
|
||||
ftime(&sysTime);
|
||||
return (sysTime.time * 1000 + sysTime.millitm);
|
||||
}
|
||||
|
||||
#endif //__Tools_h_
|
||||
@ -0,0 +1,224 @@
|
||||
/*===========================================================================
|
||||
|
||||
WorldState.cpp
|
||||
|
||||
The class WorldState represents the knowledge of an agent.
|
||||
|
||||
author: Martin Lötzsch
|
||||
===========================================================================*/
|
||||
|
||||
#include "WorldState.h"
|
||||
|
||||
WorldState* WorldState::theInstance = NULL;
|
||||
|
||||
WorldState::WorldState() : activePlayerNumber(0), ball_x(40), ball_y(10)
|
||||
{
|
||||
theInstance = this;
|
||||
}
|
||||
|
||||
void WorldState::update(int playerNumber, int _local_area[9], int _ball_direction, int _x, int _y)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
// set the active player
|
||||
activePlayerNumber = playerNumber;
|
||||
|
||||
// copy new values
|
||||
for (j=0; j<9; j++) local_area[j][activePlayerNumber] = _local_area[j];
|
||||
ball_direction[activePlayerNumber] = _ball_direction;
|
||||
x[activePlayerNumber] = _x; y[activePlayerNumber] = _y;
|
||||
|
||||
// estimate the ball position: fill "field" with the number of players that see the ball for each field element
|
||||
for (i=0;i<MAX_Y;i++) for (j=0;j<MAX_X;j++) field[j][i] = 0;
|
||||
|
||||
double temp_angle; int temp_dir;
|
||||
for (i=1;i<MAX_Y-1;i++) for (j=1;j<MAX_X-1;j++) for (k=3; k>=0; k--)
|
||||
{
|
||||
if ((j == x[k]) && (i == y[k])) temp_angle = 0;
|
||||
else temp_angle = atan2((j - x[k]), (i - y[k]));
|
||||
temp_angle += PI;
|
||||
temp_angle = 360.0*temp_angle/(2.0*PI);
|
||||
temp_dir = N;
|
||||
if (temp_angle > 22.5+0*45) temp_dir = NW;
|
||||
if (temp_angle > 22.5+1*45) temp_dir = W;
|
||||
if (temp_angle > 22.5+2*45) temp_dir = SW;
|
||||
if (temp_angle > 22.5+3*45) temp_dir = S;
|
||||
if (temp_angle > 22.5+4*45) temp_dir = SE;
|
||||
if (temp_angle > 22.5+5*45) temp_dir = E;
|
||||
if (temp_angle > 22.5+6*45) temp_dir = NE;
|
||||
if (temp_angle > 22.5+7*45) temp_dir = N;
|
||||
|
||||
if (temp_dir == ball_direction[k]) field[j][i] += 1;
|
||||
}
|
||||
|
||||
// estimate the ball position: search for peaks:
|
||||
int sum_x=0, sum_y=0, num_fields=0;
|
||||
|
||||
for (i=1;i<MAX_Y-1;i++) for (j=1;j<MAX_X-1;j++) if (field[j][i]==4) { sum_x += j; sum_y += i; num_fields++; }
|
||||
|
||||
if (num_fields!=0) { ball_x=sum_x / num_fields; ball_y=sum_y / num_fields; }
|
||||
else
|
||||
{
|
||||
for (i=1;i<MAX_Y-1;i++) for (j=1;j<MAX_X-1;j++) if (field[j][i]==3) { sum_x += j; sum_y += i; num_fields++;}
|
||||
if (num_fields!=0) { ball_x=sum_x / num_fields; ball_y=sum_y / num_fields; }
|
||||
}
|
||||
|
||||
// check if the ball is in the local area of a player
|
||||
for (i=3; i>=0; i--)
|
||||
{
|
||||
if (local_area[N][i] == BALL) { ball_x=x[i]; ball_y=y[i]-1; }
|
||||
if (local_area[NE][i] == BALL) { ball_x=x[i]+1; ball_y=y[i]-1; }
|
||||
if (local_area[E][i] == BALL) { ball_x=x[i]+1; ball_y=y[i]; }
|
||||
if (local_area[SE][i] == BALL) { ball_x=x[i]+1; ball_y=y[i]+1; }
|
||||
if (local_area[S][i] == BALL) { ball_x=x[i]; ball_y=y[i]+1; }
|
||||
if (local_area[SW][i] == BALL) { ball_x=x[i]-1; ball_y=y[i]+1; }
|
||||
if (local_area[W][i] == BALL) { ball_x=x[i]-1; ball_y=y[i]; }
|
||||
if (local_area[NW][i] == BALL) { ball_x=x[i]-1; ball_y=y[i]-1; }
|
||||
}
|
||||
}
|
||||
|
||||
void WorldState::computeRoles()
|
||||
{
|
||||
int i,j;
|
||||
double ball_distances[4];
|
||||
int min_dist = 0;
|
||||
int rank[4] = {0,1,2,3};
|
||||
|
||||
for (i=0;i<4;i++) ball_distances[i]=sqrt(pow(x[i] - ball_x,2) + pow(y[i] - ball_y,2));
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
if (ball_distances[i] < ball_distances[min_dist]) {
|
||||
min_dist = i;
|
||||
}
|
||||
}
|
||||
|
||||
int temp = rank[0];
|
||||
rank[0] = min_dist;
|
||||
rank[min_dist] = temp;
|
||||
for (i=1; i<3; i++) {
|
||||
for (j=i+1;j<4;j++) {
|
||||
if (x[rank[i]] < x[rank[j]]) {
|
||||
int temp = rank[i];
|
||||
rank[i] = rank[j];
|
||||
rank[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
playerRole[rank[0]] = WorldState::midfielder;
|
||||
playerRole[rank[1]] = WorldState::defender;
|
||||
playerRole[rank[2]] = WorldState::midfielder; // substitute by role 'runner'
|
||||
playerRole[rank[3]] = WorldState::striker;
|
||||
|
||||
for (i=0;i<4;i++) if (x[i] >73) playerRole[i]=WorldState::midfielder;
|
||||
}
|
||||
|
||||
double WorldState::getMostWesterlyTeammateX()
|
||||
{
|
||||
double minX=78;
|
||||
for (int player=1;player<4;player++) if (theInstance->x[player] < minX) minX = theInstance->x[player];
|
||||
return minX;
|
||||
}
|
||||
|
||||
double WorldState::getMostWesterlyTeammateY()
|
||||
{
|
||||
double minX=78;
|
||||
double Y=22;
|
||||
for (int player=1;player<4;player++) {
|
||||
if (theInstance->x[player] < minX) {
|
||||
minX = theInstance->x[player]; // x coordinate of most westerly team mate
|
||||
Y = theInstance->y[player]; // y coordinate of most westerly team mate
|
||||
}
|
||||
}
|
||||
return Y;
|
||||
}
|
||||
|
||||
int WorldState::getBallLocalDirection()
|
||||
{
|
||||
for (int i=0;i<10;i++) if (theInstance->local_area[i][theInstance->activePlayerNumber]==BALL) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
double WorldState::getBallDistance()
|
||||
{
|
||||
if (getBallLocalDirection()!=-1)
|
||||
return 1;
|
||||
else
|
||||
return sqrt(pow(theInstance->x[theInstance->activePlayerNumber] - theInstance->ball_x,2) + pow(theInstance->y[theInstance->activePlayerNumber] - theInstance->ball_y,2));
|
||||
}
|
||||
|
||||
int WorldState::getPlayerRole()
|
||||
{
|
||||
return theInstance->playerRole[theInstance->activePlayerNumber];
|
||||
}
|
||||
|
||||
void WorldState::printField(xabsl::ErrorHandler& errorHandler)
|
||||
{
|
||||
int i,j;
|
||||
field[(int)ball_x][(int)ball_y] = 5;
|
||||
for (i=0;i<4;i++)
|
||||
field[x[i]][y[i]] = playerRole[i] + ((i==activePlayerNumber) ? 6 : 10);
|
||||
errorHandler.message("===============================================================================");
|
||||
for (i=1;i<22;i++)
|
||||
{
|
||||
char line[80];
|
||||
for (j=1;j<=78;j++)
|
||||
{
|
||||
line[0]='|';
|
||||
char c;
|
||||
switch ((char)field[j][i])
|
||||
{
|
||||
case 0: c=' '; break;
|
||||
case 1: c='-'; break;
|
||||
case 2: c='='; break;
|
||||
case 3: c=':'; break;
|
||||
case 4: c='*'; break;
|
||||
case 5: c='o'; break;
|
||||
case 6: c='D'; break;
|
||||
case 7: c='M'; break;
|
||||
case 8: c='S'; break;
|
||||
case 9: c='R'; break;
|
||||
case 10: c='d'; break;
|
||||
case 11: c='m'; break;
|
||||
case 12: c='s'; break;
|
||||
case 13: c='r'; break;
|
||||
default: c='.'; break;
|
||||
}
|
||||
line[j]=c;
|
||||
}
|
||||
line[79]=0;
|
||||
errorHandler.message("%s",line);
|
||||
}
|
||||
errorHandler.message("===============================================================================");
|
||||
}
|
||||
|
||||
void WorldState::reset()
|
||||
{
|
||||
for(int i = 0; i <4; i++)
|
||||
{
|
||||
x[i] = 46;
|
||||
y[i] = 4+3*i;
|
||||
for (int j=0; j<9; j++) local_area[j][i] = EMPTY;
|
||||
ball_direction[i]=W;
|
||||
}
|
||||
}
|
||||
|
||||
double WorldState::getX()
|
||||
{
|
||||
return (double)theInstance->x[theInstance->activePlayerNumber];
|
||||
}
|
||||
|
||||
double WorldState::getY()
|
||||
{
|
||||
return (double)theInstance->y[theInstance->activePlayerNumber];
|
||||
}
|
||||
|
||||
double WorldState::getBallX()
|
||||
{
|
||||
return (double)theInstance->ball_x;
|
||||
}
|
||||
|
||||
double WorldState::getBallY()
|
||||
{
|
||||
return (double)theInstance->ball_y;
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
/*===========================================================================
|
||||
|
||||
WorldState.h
|
||||
|
||||
The class WorldState represents the knowledge of all agents.
|
||||
|
||||
author: Martin Lötzsch
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef __WorldState_h_
|
||||
#define __WorldState_h_
|
||||
|
||||
#include "../Xabsl/XabslEngine/XabslSymbols.h"
|
||||
#include "../ascii-soccer/soccer.h"
|
||||
|
||||
|
||||
class WorldState
|
||||
{
|
||||
public:
|
||||
WorldState();
|
||||
|
||||
// the player indexing works like a ring buffer.
|
||||
// E.g. x[0] is for the active player, x[1] for the previously active player etc.
|
||||
|
||||
/*
|
||||
local_area[] Reveals what's nearby. Indexed by
|
||||
N,NE,E,SE,S, etc. so that, for example,
|
||||
local_area[S] tells you what is in the
|
||||
cell to the south of the robot. Possible
|
||||
values include: BOUNDARY, OPPONENT, TEAMMATE,
|
||||
BALL and EMPTY. */
|
||||
int local_area[9][4];
|
||||
|
||||
/* ball_direction Compass heading to the ball: N, S, E, W, NE, etc. */
|
||||
int ball_direction[4];
|
||||
|
||||
/* x, y The robot's location. y varies from 1 to 22,
|
||||
x varies from 1 to 78. */
|
||||
int x[4];
|
||||
int y[4];
|
||||
|
||||
|
||||
// the position of the ball, estimated from observations by all four players.
|
||||
int ball_x, ball_y;
|
||||
|
||||
// the number of the active player (0..3)
|
||||
int activePlayerNumber;
|
||||
|
||||
/* updates the world state for a single player */
|
||||
void update(int playerNumber, int local_area[9], int ball_direction, int x, int y);
|
||||
|
||||
/* computes the dynamic roles */
|
||||
void computeRoles();
|
||||
|
||||
void reset(); // resets the positions
|
||||
|
||||
static WorldState* theInstance;
|
||||
|
||||
/* the dynamically assigned player role */
|
||||
enum PlayerRole { defender, midfielder, striker, runner } playerRole[4];
|
||||
|
||||
static double getX(); // a function for the symbol "x"
|
||||
static double getY(); // a function for the symbol "y"
|
||||
static double getBallX(); // a function for the symbol "ball.x"
|
||||
static double getBallY(); // a function for the symbol "ball.y"
|
||||
static double getBallDistance(); // a function for the symbol "ball.distance"
|
||||
static int getBallLocalDirection(); // a function for the symbol "ball.local.direction"
|
||||
static double getMostWesterlyTeammateX(); // a function for the symbol "most-westerly-teammate.x"
|
||||
static double getMostWesterlyTeammateY(); // a function for the symbol "most-westerly-teammate.y"
|
||||
static int getPlayerRole(); // a function for the symbol "player-role"
|
||||
|
||||
char field[MAX_X][MAX_Y]; // for debug output
|
||||
void printField(xabsl::ErrorHandler& errorHandler); // prints the field containing debug informations
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //__WorldState_h_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
/*===========================================================================
|
||||
|
||||
common.c
|
||||
|
||||
Put routines in here that don't need unique names. You might
|
||||
want to share these routines if your team is playing against
|
||||
itself. You may not need to put anything in this file.
|
||||
|
||||
Tucker Balch tucker@cc.gatech.edu
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
#include "players.h"
|
||||
|
||||
void dummyrandomname()
|
||||
{
|
||||
}
|
||||
|
||||
@ -0,0 +1,258 @@
|
||||
/*===========================================================================
|
||||
|
||||
main.cpp
|
||||
|
||||
Initializes and executes the four XABSL engines.
|
||||
|
||||
author: Martin Lötzsch
|
||||
===========================================================================*/
|
||||
|
||||
#include "players.h"
|
||||
#include "soccer.h"
|
||||
#include "WorldState.h"
|
||||
#include "MyBasicBehaviors.h"
|
||||
#include "Tools.h"
|
||||
#include "../Xabsl/XabslEngine/XabslEngine.h"
|
||||
|
||||
// an instance of the derived error handler
|
||||
MyErrorHandler myErrorHandler;
|
||||
|
||||
// the world state that is shared by all players
|
||||
WorldState worldState;
|
||||
|
||||
// the next action to be generated by the active agent
|
||||
int nextAction;
|
||||
|
||||
// an xabsl engine for each of the four players
|
||||
xabsl::Engine* pEngine[4];
|
||||
|
||||
// instances of the basic behaviors
|
||||
BasicBehaviorGetBehindBall basicBehaviorGetBehindBall(myErrorHandler, worldState, nextAction);
|
||||
BasicBehaviorGoTo basicBehaviorGoTo(myErrorHandler, worldState, nextAction);
|
||||
|
||||
void UN(initialize_game)()
|
||||
{
|
||||
// create four engines
|
||||
for (int i=0; i<4;i++)
|
||||
{
|
||||
// create the engine
|
||||
pEngine[i] = new xabsl::Engine(myErrorHandler, &getCurrentSystemTime);
|
||||
|
||||
// register basic behaviors
|
||||
pEngine[i]->registerBasicBehavior(basicBehaviorGetBehindBall);
|
||||
pEngine[i]->registerBasicBehavior(basicBehaviorGoTo);
|
||||
|
||||
// register the symbols
|
||||
pEngine[i]->registerEnumeratedInputSymbol("role", "role", &WorldState::getPlayerRole);
|
||||
pEngine[i]->registerEnumElement("role", "role.striker", WorldState::striker);
|
||||
pEngine[i]->registerEnumElement("role", "role.defender", WorldState::defender);
|
||||
pEngine[i]->registerEnumElement("role", "role.midfielder", WorldState::midfielder);
|
||||
pEngine[i]->registerEnumeratedOutputSymbol("next_action", "next_action", &nextAction);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.undefined", -1);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.NW", NW);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.N", N);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.NE", NE);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.E", E);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.SE", SE);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.S", S);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.SW", SW);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.W", W);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.kick", KICK);
|
||||
pEngine[i]->registerEnumElement("next_action", "next_action.do_nothing", DO_NOTHING);
|
||||
pEngine[i]->registerDecimalInputSymbol("x", &WorldState::getX);
|
||||
pEngine[i]->registerDecimalInputSymbol("y", &WorldState::getY);
|
||||
pEngine[i]->registerDecimalInputSymbol("ball.x", &WorldState::getBallX);
|
||||
pEngine[i]->registerDecimalInputSymbol("ball.y", &WorldState::getBallY);
|
||||
pEngine[i]->registerDecimalInputSymbol("ball.distance", &WorldState::getBallDistance);
|
||||
pEngine[i]->registerEnumeratedInputSymbol("ball.local.direction","next_action", &WorldState::getBallLocalDirection);
|
||||
pEngine[i]->registerDecimalInputSymbol("most_westerly_teammate.x", &WorldState::getMostWesterlyTeammateX);
|
||||
pEngine[i]->registerDecimalInputSymbol("most_westerly_teammate.y", &WorldState::getMostWesterlyTeammateY);
|
||||
|
||||
// parse the intermediate code
|
||||
MyFileInputSource input("intermediate-code.dat");
|
||||
pEngine[i]->createOptionGraph(input);
|
||||
}
|
||||
}
|
||||
|
||||
void printOptionActivationTree(xabsl::Engine& engine, xabsl::ErrorHandler& errorHandler);
|
||||
|
||||
int UN(player1)(int local_area[9], int ball_direction, int x, int y)
|
||||
{
|
||||
const char* actionStrings[] = {"NW","N","NE","W","","E","SW","S","SE","kick","do_nothing"};
|
||||
|
||||
if (!myErrorHandler.errorsOccurred)
|
||||
{
|
||||
worldState.update(0, local_area,ball_direction,x,y);
|
||||
worldState.computeRoles();
|
||||
|
||||
|
||||
pEngine[0]->execute();
|
||||
printOptionActivationTree(*pEngine[0],myErrorHandler);
|
||||
myErrorHandler.message("action = %s",actionStrings[nextAction]);
|
||||
worldState.printField(myErrorHandler);
|
||||
return nextAction;
|
||||
}
|
||||
else
|
||||
{
|
||||
return W;
|
||||
}
|
||||
}
|
||||
|
||||
int UN(player2)(int local_area[9], int ball_direction, int x, int y)
|
||||
{
|
||||
if (!myErrorHandler.errorsOccurred)
|
||||
{
|
||||
worldState.update(1, local_area,ball_direction,x,y);
|
||||
pEngine[1]->execute();
|
||||
return nextAction;
|
||||
}
|
||||
else
|
||||
{
|
||||
return W;
|
||||
}
|
||||
}
|
||||
|
||||
int UN(player3)(int local_area[9], int ball_direction, int x, int y)
|
||||
{
|
||||
if (!myErrorHandler.errorsOccurred)
|
||||
{
|
||||
worldState.update(2, local_area,ball_direction,x,y);
|
||||
pEngine[2]->execute();
|
||||
return nextAction;
|
||||
}
|
||||
else
|
||||
{
|
||||
return W;
|
||||
}
|
||||
}
|
||||
|
||||
int UN(player4)(int local_area[9], int ball_direction, int x, int y)
|
||||
{
|
||||
if (!myErrorHandler.errorsOccurred)
|
||||
{
|
||||
worldState.update(3, local_area,ball_direction,x,y);
|
||||
pEngine[3]->execute();
|
||||
return nextAction;
|
||||
}
|
||||
else
|
||||
{
|
||||
return W;
|
||||
}
|
||||
}
|
||||
|
||||
char *UN(team_name)()
|
||||
{
|
||||
char *s;
|
||||
/* "####################\0" <--- 20 characters */
|
||||
s = "XABSL Example Agents\0";
|
||||
return(s);
|
||||
}
|
||||
|
||||
void UN(initialize_point)()
|
||||
{
|
||||
worldState.reset();
|
||||
}
|
||||
|
||||
void UN(lost_point)()
|
||||
{
|
||||
myErrorHandler.message("lost point");
|
||||
}
|
||||
|
||||
void UN(won_point)()
|
||||
{
|
||||
myErrorHandler.message("won point");
|
||||
}
|
||||
|
||||
void UN(game_over)()
|
||||
{
|
||||
// delete the four engines
|
||||
for (int i=0; i<4;i++) if (pEngine[i]!=0) delete pEngine[i];
|
||||
}
|
||||
|
||||
void printOptionActivationSubTree(int depth, const xabsl::Action* action, xabsl::ErrorHandler& errorHandler)
|
||||
{
|
||||
char string[300]; int i;
|
||||
string[0]=0;
|
||||
|
||||
for (i=0;i<depth;i++) strcat(string," ");
|
||||
|
||||
if (const xabsl::Behavior* behavior = action->getBehavior())
|
||||
{
|
||||
strcat(string,behavior->n);
|
||||
strcat(string,"(");
|
||||
|
||||
bool first=true;
|
||||
for(i=0; i<action->getParameters()->decimalValues.getSize();i++)
|
||||
{
|
||||
if (!first) strcat(string,", ");
|
||||
first = false;
|
||||
sprintf(string+strlen(string),"%s=%.0f",action->getParameters()->decimalValues.getName(i), action->getParameters()->decimalValues[i]);
|
||||
}
|
||||
for(i=0; i<action->getParameters()->booleanValues.getSize();i++)
|
||||
{
|
||||
if (!first) strcat(string,", ");
|
||||
first = false;
|
||||
sprintf(string+strlen(string),"%s=%s",action->getParameters()->booleanValues.getName(i), action->getParameters()->booleanValues[i] ? "true" : "false");
|
||||
}
|
||||
for(i=0; i<action->getParameters()->enumeratedValues.getSize();i++)
|
||||
{
|
||||
if (!first) strcat(string,", ");
|
||||
first = false;
|
||||
strcat(string,action->getParameters()->enumeratedValues.getName(i));
|
||||
strcat(string,"=");
|
||||
|
||||
const xabsl::Enumeration* enumeration = action->getParameters()->enumeratedExpressions[i]->enumeration;
|
||||
|
||||
for (int j = 0; j < enumeration->enumElements.getSize(); j++)
|
||||
if (enumeration->enumElements[j]->v == action->getParameters()->enumeratedValues[i])
|
||||
{
|
||||
strcat(string, enumeration->enumElements[j]->n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strcat(string,")");
|
||||
}
|
||||
else if (const xabsl::DecimalOutputSymbol* decimalOutputSymbol = action->getDecimalOutputSymbol())
|
||||
{
|
||||
sprintf(string+strlen(string),"%s=%.0f",decimalOutputSymbol->n,action->getDecimalOutputSymbolValue());
|
||||
}
|
||||
else if (const xabsl::BooleanOutputSymbol* booleanOutputSymbol = action->getBooleanOutputSymbol())
|
||||
{
|
||||
sprintf(string+strlen(string),"%s=%s",booleanOutputSymbol->n,action->getBooleanOutputSymbolValue() ? "true" : "false");
|
||||
}
|
||||
else if (const xabsl::EnumeratedOutputSymbol* enumeratedOutputSymbol = action->getEnumeratedOutputSymbol())
|
||||
{
|
||||
strcat(string, enumeratedOutputSymbol->n);
|
||||
strcat(string, "=");
|
||||
|
||||
const xabsl::Enumeration* enumeration = enumeratedOutputSymbol->enumeration;
|
||||
|
||||
for (int j = 0; j < enumeration->enumElements.getSize(); j++)
|
||||
if (enumeration->enumElements[j]->v == action->getEnumeratedOutputSymbolValue())
|
||||
{
|
||||
strcat(string, enumeration->enumElements[j]->n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
errorHandler.message("%s",string);
|
||||
|
||||
if (const xabsl::Option* option = action->getOption())
|
||||
{
|
||||
const xabsl::Array<xabsl::Action*>& actions =
|
||||
option->activeState->actions;
|
||||
|
||||
for(i=0;i<actions.getSize();i++)
|
||||
printOptionActivationSubTree(depth + 1, actions[i], errorHandler);
|
||||
}
|
||||
}
|
||||
|
||||
void printOptionActivationTree(xabsl::Engine& engine, xabsl::ErrorHandler& errorHandler)
|
||||
{
|
||||
errorHandler.message("\n\n\n\n");
|
||||
|
||||
const xabsl::Action* action = engine.getRootAction(0);
|
||||
|
||||
printOptionActivationSubTree(0, action, errorHandler);
|
||||
}
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
XABSLFILES=$(shell echo `ls ../Xabsl/XabslEngine/ -c1 | grep .cpp` | sed "s%Xabsl%Build/Xabsl%g" | sed "s%\.cpp%.o%g")
|
||||
|
||||
all: Build/libeast.a Build/libcommon.a
|
||||
|
||||
Build/Xabsl%.o: ../Xabsl/XabslEngine/Xabsl%.cpp ../Xabsl/XabslEngine/Xabsl%.h
|
||||
@echo $@
|
||||
@if !(test -d Build); then mkdir Build; fi
|
||||
@g++ -c $< -o $@
|
||||
|
||||
Build/WorldState.o: WorldState.cpp WorldState.h
|
||||
@echo $@
|
||||
@if !(test -d Build); then mkdir Build; fi
|
||||
@g++ -c WorldState.cpp -o $@
|
||||
|
||||
Build/MyBasicBehaviors.o: MyBasicBehaviors.cpp MyBasicBehaviors.h
|
||||
@echo $@
|
||||
@if !(test -d Build); then mkdir Build; fi
|
||||
@g++ -c MyBasicBehaviors.cpp -o $@
|
||||
|
||||
Build/east.o: main.cpp WorldState.h MyBasicBehaviors.h Tools.h
|
||||
@echo $@
|
||||
@if !(test -d Build); then mkdir Build; fi
|
||||
@g++ -I../ascii-soccer -c -DEAST_TEAM main.cpp -o $@
|
||||
|
||||
Build/common.o: common.c
|
||||
@echo $@
|
||||
@if !(test -d Build); then mkdir Build; fi
|
||||
@g++ -I../ascii-soccer -c -DWEST_TEAM common.c -o $@
|
||||
|
||||
Build/libeast.a: Build/east.o Build/MyBasicBehaviors.o Build/WorldState.o $(XABSLFILES)
|
||||
@echo $@
|
||||
@if !(test -d Build); then mkdir Build; fi
|
||||
@ar rc $@ Build/east.o Build/MyBasicBehaviors.o Build/WorldState.o $(XABSLFILES)
|
||||
@ranlib $@
|
||||
|
||||
Build/libcommon.a: Build/common.o Build/east.o
|
||||
@echo $@
|
||||
@if !(test -d Build); then mkdir Build; fi
|
||||
@ar rc $@ Build/common.o
|
||||
@ranlib $@
|
||||
|
||||
|
||||
clean:
|
||||
@rm -rf Build
|
||||
@ -0,0 +1,23 @@
|
||||
|
||||
|
||||
XABSL_DIR = ../../Xabsl
|
||||
|
||||
XSLT = xsltproc #../../util/LibXML/xsltproc.exe --xinclude
|
||||
DOT = dot #util/dot-1.9.0/dot.exe
|
||||
DOTML_DIR = ../../util/dotml-1.2
|
||||
XABSL_COMPILER_DIR = $(XABSL_DIR)/compiler
|
||||
XABSL_XSL_DIR = $(XABSL_DIR)/xsl
|
||||
|
||||
XABSL_OUTPUT_DIR = ../../ascii-soccer
|
||||
INTERMEDIATE_CODE = intermediate-code.dat
|
||||
DEBUG_SYMBOLS = debug-symbols.dat
|
||||
DOC_OUTPUT_DIR = ../xabsl-doc
|
||||
XABSL_TEMP_DIR = .
|
||||
XML_OUTPUT_DIR = ../xabsl-xml
|
||||
XABSL_COMPILER_OPTIONS =
|
||||
|
||||
SOURCES = $(shell find . -name "*.xabsl")
|
||||
|
||||
AGENTS_FILE = agents.xabsl
|
||||
|
||||
include $(XABSL_DIR)/XabslMakefile
|
||||
@ -0,0 +1,35 @@
|
||||
/** Waits behind the ball */
|
||||
option defender {
|
||||
|
||||
initial state own_team_has_ball {
|
||||
decision {
|
||||
/** opponent team has ball */
|
||||
if (most_westerly_teammate.x() < ball.x()) {
|
||||
goto opponent_team_has_ball;
|
||||
}
|
||||
else {
|
||||
stay;
|
||||
}
|
||||
}
|
||||
action {
|
||||
go_to(x = ball.x() + 12, y = ball.y());
|
||||
}
|
||||
}
|
||||
|
||||
state opponent_team_has_ball {
|
||||
decision {
|
||||
/** own team has ball */
|
||||
if (most_westerly_teammate.x() >= ball.x()) {
|
||||
goto own_team_has_ball;
|
||||
}
|
||||
else {
|
||||
stay;
|
||||
}
|
||||
}
|
||||
action {
|
||||
go_to(x = ball.x() + 10, y = ball.y());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
/** Dribbles the ball without kicking */
|
||||
option dribble {
|
||||
|
||||
initial state behind_ball {
|
||||
decision {
|
||||
/** not behind ball */
|
||||
if (ball.local.direction() != W) {
|
||||
goto not_behind_ball;
|
||||
}
|
||||
else {
|
||||
/** near opponent goal */
|
||||
if (x() < 13) {
|
||||
goto behind_ball_near_opponent_goal;
|
||||
}
|
||||
else {
|
||||
stay;
|
||||
}
|
||||
}
|
||||
}
|
||||
action {
|
||||
next_action = W;
|
||||
}
|
||||
}
|
||||
|
||||
state behind_ball_near_opponent_goal {
|
||||
decision {
|
||||
goto behind_ball;
|
||||
}
|
||||
action {
|
||||
next_action = kick;
|
||||
}
|
||||
}
|
||||
|
||||
state not_behind_ball {
|
||||
decision {
|
||||
/** not behind ball */
|
||||
if (ball.local.direction() != W) {
|
||||
stay;
|
||||
}
|
||||
else {
|
||||
goto behind_ball;
|
||||
}
|
||||
}
|
||||
action {
|
||||
get_behind_ball();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
/** Handles the ball. */
|
||||
option midfielder {
|
||||
|
||||
initial state get_to_ball {
|
||||
decision {
|
||||
/** far from ball */
|
||||
if (ball.distance() > 3) {
|
||||
stay;
|
||||
}
|
||||
else {
|
||||
/** no teammate to the west */
|
||||
if (most_westerly_teammate.x() > ball.x() + 2) {
|
||||
goto dribble;
|
||||
}
|
||||
/** most westerly teammate north of ball */
|
||||
else if (most_westerly_teammate.y() < ball.y()){
|
||||
goto passNW;
|
||||
}
|
||||
/** most westerly teammate south of ball */
|
||||
else
|
||||
goto passSW;
|
||||
}
|
||||
}
|
||||
action {
|
||||
go_to(x = ball.x(), y = ball.y());
|
||||
}
|
||||
}
|
||||
|
||||
state passNW {
|
||||
decision {
|
||||
/** far from ball */
|
||||
if (ball.distance() > 3) {
|
||||
goto get_to_ball;
|
||||
}
|
||||
/** at desired position for pass to NW */
|
||||
else if (x == ball.x()+1 && y == ball.y()+1)
|
||||
goto pass;
|
||||
else {
|
||||
stay;
|
||||
}
|
||||
}
|
||||
action {
|
||||
// go to position SW of ball in order to pass in NW direction
|
||||
go_to(x = ball.x()+1, y = ball.y()+1);
|
||||
}
|
||||
}
|
||||
|
||||
state passSW {
|
||||
decision {
|
||||
/** far from ball */
|
||||
if (ball.distance() > 3) {
|
||||
goto get_to_ball;
|
||||
}
|
||||
/** at desired position for pass to SW */
|
||||
else if (x == ball.x()+1 && y == ball.y()-1)
|
||||
goto pass;
|
||||
else {
|
||||
stay;
|
||||
}
|
||||
}
|
||||
action {
|
||||
// go to position SW of ball in order to pass in NW direction
|
||||
go_to(x = ball.x()+1, y = ball.y()-1);
|
||||
}
|
||||
}
|
||||
|
||||
state pass {
|
||||
decision {
|
||||
if (ball.distance() > 3)
|
||||
goto get_to_ball;
|
||||
else
|
||||
stay;
|
||||
}
|
||||
action {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
|
||||
state dribble {
|
||||
decision {
|
||||
/** far from ball */
|
||||
if (ball.distance() > 3) {
|
||||
goto get_to_ball;
|
||||
}
|
||||
else {
|
||||
stay;
|
||||
}
|
||||
}
|
||||
action {
|
||||
dribble();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
/** Passes the ball to a teammate. */
|
||||
option pass {
|
||||
|
||||
initial state get_behind_ball {
|
||||
decision {
|
||||
/** at ball */
|
||||
if (ball.local.direction() == NW || ball.local.direction() == W || ball.local.direction() == SW) {
|
||||
goto kick;
|
||||
}
|
||||
else {
|
||||
stay;
|
||||
}
|
||||
}
|
||||
action {
|
||||
get_behind_ball();
|
||||
}
|
||||
}
|
||||
|
||||
state kick {
|
||||
decision {
|
||||
/** still behind ball */
|
||||
if (ball.local.direction() == N || ball.local.direction() == NW || ball.local.direction() == W || ball.local.direction() == SW || ball.local.direction() == S) {
|
||||
stay;
|
||||
}
|
||||
else {
|
||||
goto get_behind_ball;
|
||||
}
|
||||
}
|
||||
action {
|
||||
next_action = kick;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
/** The soccer root behavior */
|
||||
option play_soccer {
|
||||
|
||||
common decision {
|
||||
/** player role is striker */
|
||||
if (role() == striker) {
|
||||
goto striker;
|
||||
}
|
||||
/** player role is defender */
|
||||
else if (role() == defender) {
|
||||
goto defender;
|
||||
}
|
||||
/** player role is midfielder */
|
||||
else if (role() == midfielder) {
|
||||
goto midfielder;
|
||||
}
|
||||
}
|
||||
|
||||
state striker {
|
||||
action {
|
||||
striker();
|
||||
}
|
||||
}
|
||||
|
||||
initial state midfielder {
|
||||
action {
|
||||
midfielder();
|
||||
}
|
||||
}
|
||||
|
||||
state defender {
|
||||
action {
|
||||
defender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
/** Waits in front of the other players for a pass */
|
||||
option striker {
|
||||
|
||||
initial state __initial {
|
||||
action {
|
||||
go_to(x = ball.x() - 10, y = 11); //central position 10 units west of ball position
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
/***
|
||||
Title: XABSL Example Agent Team
|
||||
Platform: Soccer simulation.
|
||||
Software-Environment: The ascii-soccer environment (http://www-2.cs.cmu.edu/~trb/soccer/).
|
||||
*/
|
||||
|
||||
include "my-basic-behaviors.xabsl";
|
||||
include "my-symbols.xabsl";
|
||||
include "Options/play-soccer.xabsl";
|
||||
include "Options/midfielder.xabsl";
|
||||
include "Options/pass.xabsl";
|
||||
include "Options/dribble.xabsl";
|
||||
include "Options/defender.xabsl";
|
||||
include "Options/striker.xabsl";
|
||||
|
||||
/** A simple soccer agent behavior */
|
||||
agent soccer("Soccer", play_soccer);
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
/** My common basic behaviors */
|
||||
namespace my_basic_behaviors("My Basic Behaviors") {
|
||||
|
||||
/** Lets the agent move to a point */
|
||||
behavior go_to {
|
||||
/** X of destination position */
|
||||
float x [1..78] "px";
|
||||
/** Y of destination position */
|
||||
float y [1..22] "px";
|
||||
}
|
||||
|
||||
/** Approaches the ball and gets behind it */
|
||||
behavior get_behind_ball {
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
/** My most used symbols */
|
||||
namespace my_symbols("My Symbols") {
|
||||
|
||||
/** The possible roles of a player */
|
||||
enum role {
|
||||
defender,
|
||||
midfielder,
|
||||
striker
|
||||
};
|
||||
|
||||
/** The possible direction and actions */
|
||||
enum next_action {
|
||||
undefined,
|
||||
NW,
|
||||
N,
|
||||
NE,
|
||||
E,
|
||||
SE,
|
||||
S,
|
||||
SW,
|
||||
W,
|
||||
kick,
|
||||
do_nothing
|
||||
};
|
||||
|
||||
/** The next action to be performed */
|
||||
enum next_action output next_action;
|
||||
|
||||
/** The dynamically assigned role of the player */
|
||||
enum role input role;
|
||||
|
||||
/** The x position of the player */
|
||||
float input x;
|
||||
|
||||
/** The y position of the player */
|
||||
float input y;
|
||||
|
||||
/** The x position of the ball */
|
||||
float input ball.x;
|
||||
|
||||
/** The y position of the ball */
|
||||
float input ball.y;
|
||||
|
||||
/** The distance to the ball */
|
||||
float input ball.distance;
|
||||
|
||||
/** The direction of the ball if in the local area of the player. If the ball is not in the local area, undefined is returned */
|
||||
enum next_action input ball.local.direction;
|
||||
|
||||
/** The x position of the most westerly teammate */
|
||||
float input most_westerly_teammate.x;
|
||||
|
||||
/** The y position of the most westerly teammate */
|
||||
float input most_westerly_teammate.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
@ -0,0 +1,209 @@
|
||||
ASCII Soccer version 2.0
|
||||
========================
|
||||
|
||||
This program is a tool for investigating how groups of simple agents
|
||||
interact while playing a soccer-like game. You can develop your own
|
||||
team strategies and test them against others.
|
||||
|
||||
Two teams of players attempt to push a ball across the other team's
|
||||
goal. The game can be viewed on your screen using patented
|
||||
ASCII-animation(tm) technology.
|
||||
|
||||
Where to get it:
|
||||
|
||||
ASCII Soccer Homepage: http://www.cc.gatech.edu/grads/b/Tucker.Balch/soccer/
|
||||
Source code: ftp://ftp.cc.gatech.edu/pub/people/tucker/soccer.2.0.tar.Z
|
||||
|
||||
For a synopsis of what's new in version 2.0, see the NEW file.
|
||||
|
||||
|
||||
Compatibility
|
||||
=============
|
||||
|
||||
NOTE: this is AS IS unsupported software. It was developed on and runs
|
||||
on SunOS 4.1.3 and Linux systems, but it may compile on other systems.
|
||||
|
||||
To unpack the source code you will need uncompress and tar.
|
||||
To compile you will need make, g++, csh, and the curses and termcap libraries.
|
||||
|
||||
It seems that most incompatiblities arise from OLD versions of gcc/g++.
|
||||
I have compiled with versions of g++ as old as 2.5.8. To see which version
|
||||
you have, type g++ --version . Note that gcc and g++ are usually installed
|
||||
together.
|
||||
|
||||
To use the packteam and unpackteam you'll need tar, compress and uuencode.
|
||||
|
||||
|
||||
Quickstart
|
||||
==========
|
||||
|
||||
Get the source code off the web
|
||||
|
||||
http://www.cc.gatech.edu/grads/b/Tucker.Balch/soccer/
|
||||
|
||||
After you've uncompressed and untarred it, type:
|
||||
|
||||
contest example wall
|
||||
|
||||
This will set up a soccer match between the "example" team and the
|
||||
"wall" team, by compiling and linking teams in the directories teams/example
|
||||
and teams/wall. If it does not compile, you probably don't have all the
|
||||
software you need to compile it. See COMPATIBLIY above. Don't be too
|
||||
concerned about "warnings" but "errors" are bad! After the compilation
|
||||
is complete the teams will automatically start a game. The first team to
|
||||
7 points wins. To run another game, type "soccer"
|
||||
|
||||
Look in the "teams" directory for other teams to try.
|
||||
|
||||
|
||||
RULES
|
||||
=====
|
||||
|
||||
The teams consist of four players. Each team member is provided with
|
||||
sensors that tell it about the immediately adjoining 8 cells and a
|
||||
compass heading towards the ball, and their location on the field. Players
|
||||
can push the ball by trying to move to the cell it occupies, but they
|
||||
cannot move over one another or outside the boundaries. Players may also
|
||||
kick the ball if they are immediately next to it. A kicked ball travels
|
||||
10 cells at 8 times the speed of a player. When kicking the ball, the
|
||||
player also moves into the cell were the ball was previously.
|
||||
|
||||
A point is scored when the ball is pushed or kicked across a goal line.
|
||||
The game continues until the first team scores 7 points.
|
||||
|
||||
Occasionally, the ball gets "stuck" between two competitors. In that case
|
||||
the ball is automatically "nudged" up or down, so play can resume.
|
||||
|
||||
|
||||
Designing Your Own Team
|
||||
=======================
|
||||
|
||||
Take a look at teams/example/main.c as a start. There are several things to
|
||||
keep in mind as you write your code:
|
||||
|
||||
1) You MUST have the following functions:
|
||||
player1(), player2(), player3(), player4() and
|
||||
team_name(), initialize_point(), won_point(), lost_point(),
|
||||
initialize_game(), game_over(). Just use the example
|
||||
team as a shell and this will happen for you.
|
||||
2) Always assume you are the East Team: you start on the east
|
||||
side and you want to push the ball to the west. The
|
||||
program will automatically reverse things for you when
|
||||
you start on the other side.
|
||||
|
||||
The player() functions represent each player's strategy, the team_name
|
||||
function is used to print your team's name on the screen.
|
||||
|
||||
You will notice a macro called UN(). This is used to ensure that function
|
||||
and variable names are not duplicated between team's .c files.
|
||||
For instance, for the east team, UN(team_name)() will become EASTteam_name().
|
||||
This is necessary for the automatic compiling and linking of arbitrary teams
|
||||
for tournaments. It also allows the same team to play itself. Be sure to
|
||||
use the macro around all functions and global variables in your main.c file.
|
||||
|
||||
The players are actually functions player1() through player4(). Each
|
||||
function is passed 4 parameters. The incoming parameters are the robot's
|
||||
sensory information:
|
||||
|
||||
local_area[] Reveals what's nearby. Indexed by
|
||||
N,NE,E,SE,S, etc. so that, for example,
|
||||
local_area[S] tells you what is in the
|
||||
cell to the south of the robot. Possible
|
||||
values include: BOUNDARY, OPPONENT, TEAMMATE,
|
||||
BALL and EMPTY.
|
||||
|
||||
ball_direction Compass heading to the ball: N, S, E, W, NE, etc.
|
||||
|
||||
x, y The robot's location. y varies from 1 to 22,
|
||||
x varies from 1 to 78. +x is east, +y is south.
|
||||
0 and 79 are goal lines, so your players will never
|
||||
occupy those locations.
|
||||
|
||||
Each player function should return an integer indicating either a direction to
|
||||
move (N, NE, E, S, etc) or KICK to kick the ball.
|
||||
|
||||
|
||||
How the Compiling and Linking Works
|
||||
====================================
|
||||
|
||||
You don't have to read this section!
|
||||
|
||||
This is rather hairy mostly because we can link together any two arbitrary
|
||||
teams, and they can play on either side of the field. Fortunately, if you
|
||||
just copy everything from the teams/example directory to a new directory,
|
||||
and develop your team there, you shouldn't have to worry about this too much.
|
||||
|
||||
The default makefile assumes your team is coded in main.c .
|
||||
main.c is compiled into either west.o or east.o depending on whether your
|
||||
team will take the east or west side of the field. The symbols WEST_TEAM
|
||||
and EAST_TEAM are defined/not defined according to which side you're on.
|
||||
|
||||
The makefile also compiles common.c which is presumed to include functions
|
||||
and globals that do not have unique names and that might be shared if your
|
||||
team was playing itself. Even if you don't use common.c, don't remove it!
|
||||
the contest script and makefiles aren't smart enough not to use it. I found
|
||||
I needed this to make it easier to use some c++ classes I use for my
|
||||
learning team.
|
||||
|
||||
Finally, the .o files are grouped into libraries: libeast.a libwest.a
|
||||
and libcommon.a . The contest script copies the appropriate libraries
|
||||
up to the top directory, then links soccer.o with them to generate the
|
||||
final executable.
|
||||
|
||||
You can take advantage of this library approach now to design more complex
|
||||
teams composed of several separately compiled modules - but you don't have
|
||||
to! Just make sure your makefile correctly generates libeast.a libwest.a
|
||||
and libcommon.a .
|
||||
|
||||
|
||||
Advanced Techniques
|
||||
===================
|
||||
|
||||
There are some additional hooks for learning, etc. which you may choose
|
||||
to use. You will notice at the bottom of example.c there are several
|
||||
additional functions with no body. These functions are automatically
|
||||
called at various points in the game, as follows:
|
||||
|
||||
initialize_game() Called once per game before play begins.
|
||||
game_over() Called once per game at the end of the game.
|
||||
initialize_point() Called once per point before play begins.
|
||||
lost_point() Called if your team loses a point.
|
||||
won_point() Called if your team wins a point.
|
||||
|
||||
You may find these functions handy for initialization and learning strategies.
|
||||
|
||||
|
||||
Command-line Arguments
|
||||
======================
|
||||
|
||||
The soccer executable offers a few command-line arguments you may want
|
||||
to use:
|
||||
|
||||
-d Don't display the game on the screen.
|
||||
-s seed Use seed as the random seed for the game.
|
||||
time() is used otherwise.
|
||||
-p points Play to points instead of the default 7.
|
||||
|
||||
|
||||
packteam and unpackteam
|
||||
=======================
|
||||
|
||||
These two scipts will pack up or unpack a team for you so that they are more
|
||||
convenient to exchange by email. The command "packteam fred" will look for
|
||||
a team in the teams/fred directory and tar, compress and uuencode it. The
|
||||
resulting file fred.tar.Z.uu is plain ascii text. If someone sends you one
|
||||
of these files, or you download one you can unpack it with the command
|
||||
"unpackteam fred" Unpackteam will look for fred.tar.Z.uu, so make sure all
|
||||
the file extensions are there.
|
||||
|
||||
When you use either of these scripts make sure you cd to the top of your
|
||||
soccer directory structure.
|
||||
|
||||
|
||||
Bugs, Gripes, Complaints
|
||||
========================
|
||||
|
||||
I don't promise ANYTHING, but I am very glad to see your teams and hear
|
||||
about bugs. Especially if you have fixed them!!!!
|
||||
|
||||
Email: tucker@cc.gatech.edu
|
||||
@ -0,0 +1,54 @@
|
||||
#!/bin/sh -f
|
||||
|
||||
if test $2'x' = 'x'; then
|
||||
echo "usage: contest team1name team2name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "contest: Removing old stuff"
|
||||
rm -f *.a
|
||||
rm -f *.o
|
||||
rm -f soccer
|
||||
rm -f soccer.exe #if compiled under cygwin
|
||||
rm -f core
|
||||
|
||||
|
||||
if test $1 != $2; then
|
||||
echo "contest: Moving to ./teams/"$1" ."
|
||||
echo "contest: Compiling libraries for the " $1 " team."
|
||||
cd teams/$1
|
||||
make libwest.a
|
||||
cp libwest.a ../..
|
||||
make libcommon.a
|
||||
cp libcommon.a ../../libwestcommon.a
|
||||
echo "contest: Moving to ./teams/"$2" ."
|
||||
echo "contest: Compiling libraries for the " $2 " team."
|
||||
cd ../$2
|
||||
make libeast.a
|
||||
cp libeast.a ../..
|
||||
make libcommon.a
|
||||
cp libcommon.a ../../libeastcommon.a
|
||||
cd ../..
|
||||
echo "contest: Compiling and linking soccer."
|
||||
make soccer;
|
||||
else
|
||||
cd teams/$1
|
||||
echo "contest: This team will play against itself."
|
||||
echo "contest: WARNING some teams will fail to link in this case."
|
||||
echo "contest: Moving to ./teams/"$2" ."
|
||||
echo "contest: Compiling libraries for the " $1 " team."
|
||||
make libeast.a
|
||||
make libwest.a
|
||||
make libcommon.a
|
||||
cp libeast.a ../../libeast.a
|
||||
cp libwest.a ../../libwest.a
|
||||
cp libcommon.a ../../libcommon.a
|
||||
cd ../..
|
||||
echo "contest: Compiling and linking soccer."
|
||||
make soccerboth;
|
||||
fi
|
||||
|
||||
echo "contest: starting a game."
|
||||
./soccer -p 7
|
||||
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
soccer.o: soccer.c soccer.h players.h
|
||||
g++ -w -c soccer.c
|
||||
|
||||
soccer: soccer.o libeast.a libwest.a libeastcommon.a libwestcommon.a
|
||||
g++ -w soccer.o -o soccer -L./ -lncurses -lm \
|
||||
-least -leastcommon -lwest -lwestcommon
|
||||
|
||||
soccerboth: soccer.o libeast.a libwest.a libcommon.a
|
||||
g++ -w soccer.o -o soccer -L./ -lncurses -lm \
|
||||
-least -lcommon -lwest
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f *.a
|
||||
rm -f soccer
|
||||
rm -f core
|
||||
|
||||
reallyclean: clean
|
||||
cleanteams
|
||||
@ -0,0 +1,17 @@
|
||||
#include "soccer.h"
|
||||
#ifndef PLAYERS_H
|
||||
#define PLAYERS_H
|
||||
|
||||
#ifdef EAST_TEAM
|
||||
#define OPPONENT WEST_PLAYER
|
||||
#define TEAMMATE EAST_PLAYER
|
||||
#define UN(original_name) EAST ## original_name
|
||||
#endif
|
||||
|
||||
#ifdef WEST_TEAM
|
||||
#define OPPONENT EAST_PLAYER
|
||||
#define TEAMMATE WEST_PLAYER
|
||||
#define UN(original_name) WEST ## original_name
|
||||
#endif
|
||||
#define unique_name(a) UN(a)
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user