diff --git a/ws2011/CE/Folien/gms-03-col.pdf b/ws2011/CE/Folien/gms-03-col.pdf new file mode 100644 index 00000000..2c8a325f Binary files /dev/null and b/ws2011/CE/Folien/gms-03-col.pdf differ diff --git a/ws2011/CE/Probeklausur.pdf b/ws2011/CE/Probeklausur.pdf new file mode 100644 index 00000000..ee7fc05f Binary files /dev/null and b/ws2011/CE/Probeklausur.pdf differ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011.zip b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011.zip new file mode 100644 index 00000000..c7ee2e84 Binary files /dev/null and b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011.zip differ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Acknowledgements.txt b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Acknowledgements.txt new file mode 100644 index 00000000..a67e10c3 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Acknowledgements.txt @@ -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). + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAction.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAction.cpp new file mode 100644 index 00000000..df089b9f --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAction.cpp @@ -0,0 +1,348 @@ +/** +* @file XabslAction.cpp +* +* Implementation of class Action and helper classes +* +* @author Max Risler +*/ + + +#include "XabslAction.h" +#include "XabslOption.h" + +namespace xabsl +{ + +Action* Action::create( + InputSource& input, + NamedArray& options, + NamedArray& 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(behavior)) + { + action = new ActionOption(time); + static_cast(action)->option = option; + } + else if (BasicBehavior* basicBehavior = dynamic_cast(behavior)) + { + action = new ActionBasicBehavior(time); + static_cast(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(this)) + return action->getBehavior(); + else + return 0; +} + +Option* Action::getOption() +{ + if (ActionOption* action = dynamic_cast(this)) + return action->option; + else + return 0; +} + +BasicBehavior* Action::getBasicBehavior() +{ + if (ActionBasicBehavior* action = dynamic_cast(this)) + return action->basicBehavior; + else + return 0; +} + +const Behavior* Action::getBehavior() const +{ + if (const ActionBehavior* action = dynamic_cast(this)) + return action->getBehavior(); + else + return 0; +} + +const Option* Action::getOption() const +{ + if (const ActionOption* action = dynamic_cast(this)) + return action->option; + else + return 0; +} + +const BasicBehavior* Action::getBasicBehavior() const +{ + if (const ActionBasicBehavior* action = dynamic_cast(this)) + return action->basicBehavior; + else + return 0; +} + +ParameterAssignment* Action::getParameters() +{ + if (ActionBehavior* action = dynamic_cast(this)) + return action->parameters; + else + return 0; +} + +const ParameterAssignment* Action::getParameters() const +{ + if (const ActionBehavior* action = dynamic_cast(this)) + return action->parameters; + else + return 0; +} + +const DecimalOutputSymbol* Action::getDecimalOutputSymbol() const +{ + if (const ActionDecimalOutputSymbol* action = dynamic_cast(this)) + return action->decimalOutputSymbol; + else + return 0; +} + +const BooleanOutputSymbol* Action::getBooleanOutputSymbol() const +{ + if (const ActionBooleanOutputSymbol* action = dynamic_cast(this)) + return action->booleanOutputSymbol; + else + return 0; +} + +const EnumeratedOutputSymbol* Action::getEnumeratedOutputSymbol() const +{ + if (const ActionEnumeratedOutputSymbol* action = dynamic_cast(this)) + return action->enumeratedOutputSymbol; + else + return 0; +} + +double Action::getDecimalOutputSymbolValue() const +{ + if (const ActionDecimalOutputSymbol* action = dynamic_cast(this)) + return action->decimalOutputSymbolValue; + else + return 0; +} + +bool Action::getBooleanOutputSymbolValue() const +{ + if (const ActionBooleanOutputSymbol* action = dynamic_cast(this)) + return action->booleanOutputSymbolValue; + else + return false; +} + +int Action::getEnumeratedOutputSymbolValue() const +{ + if (const ActionEnumeratedOutputSymbol* action = dynamic_cast(this)) + return action->enumeratedOutputSymbolValue; + else + return 0; +} + +} // namespace diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAction.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAction.h new file mode 100644 index 00000000..e752db0c --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAction.h @@ -0,0 +1,317 @@ +/** +* @file XabslAction.h +* +* Definition of class Action and Helper classes +* +* @author Max Risler +*/ + +#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& options, + NamedArray& 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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAgent.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAgent.cpp new file mode 100644 index 00000000..d1164fa5 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAgent.cpp @@ -0,0 +1,27 @@ +/** +* @file XabslAgent.cpp +* +* Implementation of class Agent +* +* @author Martin Loetzsch +*/ + +#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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAgent.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAgent.h new file mode 100644 index 00000000..61c2cae4 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslAgent.h @@ -0,0 +1,54 @@ +/** +* @file XabslAgent.h +* +* Definition of class Agent +* +* @author Martin Loetzsch +*/ + +#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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslArray.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslArray.h new file mode 100644 index 00000000..3f37fbe1 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslArray.h @@ -0,0 +1,396 @@ +/** +* @file XabslArray.h +* +* Declaration and implementation of template class NamedArray +* +* @author Martin Loetzsch +* @author Matthias JŸngel +* @author Thomas Ršfer +*/ + + +#ifndef __XabslArray_h_ +#define __XabslArray_h_ + +#include +#include + +namespace xabsl +{ + +/** +* @class NamedItem +* A class that has a text label +* @author Martin Loetzsch +*/ +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 Martin Loetzsch +* @author Matthias JŸngel +* @author Thomas Ršfer +*/ +template 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 Martin Loetzsch +* @author Matthias JŸngel +* @author Thomas Ršfer +* @author Max Risler +*/ +template 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& operator=(const Array& 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& 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&() {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 Martin Loetzsch +* @author Matthias JŸngel +* @author Thomas Ršfer +*/ +template class NamedArray : public Array*> +{ + 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& operator=(const NamedArray& 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(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*>::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* 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*>::append(new NamedArrayElement(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_ + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBasicBehavior.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBasicBehavior.h new file mode 100644 index 00000000..c27b25cb --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBasicBehavior.h @@ -0,0 +1,59 @@ +/** +* @file XabslBasicBehavior.h +* +* Declaration class BasicBehavior +* +* @author Martin Loetzsch +* @author Max Risler +* @author Matthias JŸngel +*/ + +#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 Martin Loetzsch +* @author Max Risler +* @author Matthias JŸngel +*/ +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_ + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBehavior.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBehavior.h new file mode 100644 index 00000000..9b34617d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBehavior.h @@ -0,0 +1,72 @@ +/** +* @file XabslBehavior.h +* +* Definition of class Behavior +* +* @author Max Risler +*/ + +#ifndef __XabslBehavior_h_ +#define __XabslBehavior_h_ + +#include "XabslArray.h" +#include "XabslSymbols.h" + +namespace xabsl +{ + +/** +* @class Behavior +* +* Parent class for Option and BasicBehavior +* +* @author Max Risler +*/ +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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBooleanExpression.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBooleanExpression.cpp new file mode 100644 index 00000000..ea1458e4 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBooleanExpression.cpp @@ -0,0 +1,477 @@ +/** +* @file XabslBooleanExpression.cpp +* +* Implementation of BooleanExpression and derivates +* +* @author Martin Loetzsch +* @author Max Risler +*/ + +#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; iaddOperand(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; iaddOperand(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(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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBooleanExpression.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBooleanExpression.h new file mode 100644 index 00000000..fa21fc6c --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslBooleanExpression.h @@ -0,0 +1,495 @@ +/** +* @file XabslBooleanExpression.h +* +* Definition of BooleanExpression and derivates +* +* @author Martin Loetzsch +* @author Max Risler +*/ + +#ifndef __XabslBooleanExpression_h_ +#define __XabslBooleanExpression_h_ + +#include "XabslDecimalExpression.h" + +namespace xabsl +{ + +/** +* @class BooleanExpression +* +* Base class for all boolean expressions inside an option graph. +* +* @author Martin Loetzsch +* @author Max Risler +*/ +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 Max Risler +*/ +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 Max Risler +*/ +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 Martin Loetzsch +*/ +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 operands; +}; + +/** +* @class OrOperator +* +* Represents an 'or' element of the option graph +* +* @author Martin Loetzsch +*/ +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 operands; +}; + + +/** +* @class NotOperator +* +* Represents an 'not' element of the option graph +* +* @author Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Max Risler +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +class GreaterThanOrEqualToOperator : public RelationalAndEqualityOperator +{ +public: + /** Evaluates the boolean expression.*/ + virtual bool getValue() const; +}; + + +} // namespace + +#endif //__XabslBooleanExpression_h_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslCoopState.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslCoopState.h new file mode 100644 index 00000000..935efde5 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslCoopState.h @@ -0,0 +1,238 @@ +/** +* @file XabslCoopState.h +* +* Definition of class CoopState and Helper classes +* +* @author Max Risler +*/ + +#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 Max Risler +*/ +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 Max Risler +*/ +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 Max Risler +*/ +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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslDecimalExpression.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslDecimalExpression.cpp new file mode 100644 index 00000000..91874a50 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslDecimalExpression.cpp @@ -0,0 +1,342 @@ +/** +* @file XabslDecimalExpression.cpp +* +* Implementation of DecimalExpression and derivates +* +* @author Martin Loetzsch +* @author Max Risler +*/ + +#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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslDecimalExpression.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslDecimalExpression.h new file mode 100644 index 00000000..9fda3743 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslDecimalExpression.h @@ -0,0 +1,383 @@ +/** +* @file XabslDecimalExpression.h +* +* Definition of DecimalExpression and derivates +* +* @author Martin Loetzsch +* @author Max Risler +* @author Matthias JŸngel +*/ + +#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 Martin Loetzsch +* @author Max Risler +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +* @author Max Risler +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +*/ +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 Martin Loetzsch +* @author Max Risler +*/ +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 Max Risler +*/ +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 Martin Loetzsch +* @author Max Risler +*/ +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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEngine.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEngine.cpp new file mode 100644 index 00000000..14cef7e5 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEngine.cpp @@ -0,0 +1,552 @@ +/** +* @file XabslEngine.cpp +* +* Implementation of class Engine +* +* @author Martin Loetzsch +* @author Max Risler +* @author Matthias JŸngel +*/ + +#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;iwasActive = 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[i]->getRootOption())) + { + int size = countActions(option) + 1; + ActionBehavior** currentOptionPath = new ActionBehavior*[size]; + + currentOptionPath[0] = dynamic_cast(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;istates.getSize();j++) + if (CoopState* state = dynamic_cast(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; istates.getSize(); i++) + { + int newLength = currentLength; + + for (j=0; jstates[i]->actions.getSize(); j++) + { + if (ActionBehavior* nextAction = dynamic_cast(currentOption->states[i]->actions[j])) + { + for(k=0; kgetBehavior() == 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(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(actionToAdd)) + { + for (i=0; ioption->states.getSize(); i++) + { + for (j=0; joption->states[i]->actions.getSize(); j++) + { + if (ActionBehavior* nextAction = dynamic_cast(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; istates.getSize(); i++) + { + for (j=0; jstates[i]->actions.getSize(); j++) + { + if (ActionBehavior* nextAction = dynamic_cast(option->states[i]->actions[j])) + { + count++; + if (ActionOption* nextOption = dynamic_cast(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& Engine::getRootActions() const +{ + return rootActions; +} + +Array& 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; iprepareIncomingMessages(); + } +} + +void Engine::processIncomingMessage(const TeamMessage& message) +{ + for (int i=0; inumberOfAgentsExecuting++; + + for (int i=0; inumberOfAgentsEntering == 0 || + coopStates[message.coopStatesEntering[i]]->highestPriorityOfAgentsEntering < message.agentPriority) + coopStates[message.coopStatesEntering[i]]->highestPriorityOfAgentsEntering = message.agentPriority; + coopStates[message.coopStatesEntering[i]]->numberOfAgentsEntering++; + } + + for (int i=0; inumberOfAgentsInOption++; +} + +void Engine::generateOutgoingMessage(TeamMessage& message) +{ + message.reset(); + for (int i=0; ioptionIndex]->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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEngine.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEngine.h new file mode 100644 index 00000000..1d3d9e3d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEngine.h @@ -0,0 +1,248 @@ +/** +* @file XabslEngine.h +* +* Declaration class Engine +* +* @author Martin Loetzsch +* @author Max Risler +* @author Matthias JŸngel +*/ + +#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 Martin Loetzsch +* @author Max Risler +* @author Matthias JŸngel +*/ +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 agents; + + /** The selected agent */ + Agent* selectedAgent; + + /** The options of the engine */ + NamedArray options; + + /** The actions for the execution of the start of the option graph */ + Array rootActions; + + /** The registered basic behaviors of the engine */ + NamedArray 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 internalDecimalSymbols; + NamedArray internalBooleanSymbols; + NamedArray internalEnumeratedSymbols; + + /** Array of states which are used for cooperating agents */ + Array 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& getAgents() const {return agents;} + + /** Return the options of the engine */ + const NamedArray& getOptions() const {return options;} + + /** Returns the registered basic behaviors of the engine */ + const NamedArray& 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& getRootActions() const; + + /** Returns the selected root actions */ + Array& 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_ + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEnumeratedExpression.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEnumeratedExpression.cpp new file mode 100644 index 00000000..24de9b9b --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEnumeratedExpression.cpp @@ -0,0 +1,264 @@ +/** +* @file XabslEnumeratedExpression.cpp +* +* Implementation of EnumeratedExpression and derivates +* +* @author Max Risler +*/ + +#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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEnumeratedExpression.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEnumeratedExpression.h new file mode 100644 index 00000000..69e820cd --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslEnumeratedExpression.h @@ -0,0 +1,266 @@ +/** +* @file XabslEnumeratedExpression.h +* +* Definition of EnumeratedExpression and derivates +* +* @author Max Risler +*/ + +#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 Max Risler +*/ +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 Max Risler +*/ +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 Max Risler +*/ +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 Max Risler +* @author Martin Loetzsch +*/ +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 Martin Loetzsch +* @author Max Risler +*/ +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 Martin Loetzsch +* @author Max Risler +*/ +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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslOption.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslOption.cpp new file mode 100644 index 00000000..5a778623 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslOption.cpp @@ -0,0 +1,190 @@ +/** +* @file XabslOption.cpp +* +* Implementation of class Option and helper classes +* +* @author Martin Loetzsch +* @author Max Risler +*/ + +#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& options, + NamedArray& 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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslOption.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslOption.h new file mode 100644 index 00000000..abf0ff34 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslOption.h @@ -0,0 +1,124 @@ +/** +* @file XabslOption.h +* +* Definition of class Option and Helper classes +* +* @author Martin Loetzsch +* @author Max Risler +*/ + +#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 Martin Loetzsch +* @author Max Risler +*/ +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 Martin Loetzsch +* @author Max Risler +*/ +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& options, + NamedArray& 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 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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslParameters.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslParameters.cpp new file mode 100644 index 00000000..b880ad73 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslParameters.cpp @@ -0,0 +1,312 @@ +/** +* @file XabslParameters.cpp +* +* Implementation of class Parameters +* +* @author Max Risler +*/ + +#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; ienumElements[0]->v; +} + +void Parameters::registerEnumerations(NamedArray& 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; ienumeration != 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; igetValue()); + if (*decimal[i] != decimalValues[i]) + { + parametersChanged = true; + *decimal[i] = decimalValues[i]; + } + } + for (i=0; igetValue()); + if (*boolean[i] != booleanValues[i]) + { + parametersChanged = true; + *boolean[i] = booleanValues[i]; + } + } + for (i=0; igetValue()); + if (*enumerated[i] != enumeratedValues[i]) + { + parametersChanged = true; + *enumerated[i] = enumeratedValues[i]; + } + } + + return parametersChanged; +} + +} // namespace + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslParameters.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslParameters.h new file mode 100644 index 00000000..a52580ba --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslParameters.h @@ -0,0 +1,202 @@ +/** +* @file XabslParameters.h +* +* Definition of class Parameters +* +* @author Max Risler +*/ + +#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 decimal; + + /** The boolean parameters */ + NamedArray boolean; + + /** The enumerated parameters */ + NamedArray enumerated; + + /** The enumeration domain of the enumerated parameters */ + NamedArray enumerations; + + /** + * Registers a reference to the enumerations of the engine + * This is only required when registerEnumerated is called afterwards + */ + void registerEnumerations(NamedArray& 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* 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 decimalValues; + NamedArray booleanValues; + NamedArray enumeratedValues; + + /** Decimal expressions for the parameters */ + NamedArray decimalExpressions; + /** Boolean expressions for the parameters */ + NamedArray booleanExpressions; + /** Enumerated expressions for the parameters */ + NamedArray enumeratedExpressions; + + /** + * sets parameter variables to current expression values + * returns true when parameter values have been changed + */ + bool set(); +}; + +} // namespace + +#endif // __XabslParameters_h_ + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslState.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslState.cpp new file mode 100644 index 00000000..72e7cd13 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslState.cpp @@ -0,0 +1,112 @@ +/** +* @file XabslState.cpp +* +* Implementation of class State and helper classes +* +* @author Max Risler +*/ + +#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& options, + NamedArray& basicBehaviors, + NamedArray& 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(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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslState.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslState.h new file mode 100644 index 00000000..1c8c9854 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslState.h @@ -0,0 +1,124 @@ +/** +* @file XabslState.h +* +* Definition of class State and Helper classes +* +* @author Max Risler +*/ + +#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 Martin Loetzsch +*/ +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& options, + NamedArray& basicBehaviors, + NamedArray& 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 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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslStatement.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslStatement.cpp new file mode 100644 index 00000000..5f5ccd71 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslStatement.cpp @@ -0,0 +1,118 @@ +/** +* @file XabslStatement.cpp +* +* Implementation of class Statement and helper classes +* +* @author Max Risler +*/ + +#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; igetValue()) return ifStatement->getNextState(); + + for (int i=0; igetValue()) 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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslStatement.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslStatement.h new file mode 100644 index 00000000..70b47dff --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslStatement.h @@ -0,0 +1,131 @@ +/** +* @file XabslStatement.h +* +* Definition of class Statement and Helper classes +* +* @author Max Risler +*/ + +#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 Martin Loetzsch +* @author Max Risler +*/ +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 Martin Loetzsch +*/ +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 elseIfConditions; + + /** The statements that are executed if the else-if condition are true */ + NamedArray 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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslSymbols.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslSymbols.cpp new file mode 100644 index 00000000..8f908017 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslSymbols.cpp @@ -0,0 +1,464 @@ +/** +* @file XabslSymbols.cpp +* +* Implementation of class Symbols and helper classes +* +* @author Martin Loetzsch +* @author Max Risler +*/ + +#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;iactiveValueWasSet = false; + for (int i=0;iactiveValueWasSet = false; + for (int i=0;iactiveValueWasSet = false; +} + +} // namespace + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslSymbols.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslSymbols.h new file mode 100644 index 00000000..6f9913de --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslSymbols.h @@ -0,0 +1,635 @@ +/** +* @file XabslSymbols.h +* +* Definition of class Symbols and helper classes +* +* @author Martin Loetzsch +* @author Max Risler +*/ + +#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 Martin Loetzsch +*/ +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 enumElements; + + /** Index of the enumeration in array enumerations in corresponding engine */ + int index; +}; + +/** +* A Template for the input symbol classes +* @author Martin Loetzsch +*/ +template 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 Martin Loetzsch +*/ +class DecimalInputSymbol : public InputSymbol +{ +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(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(name, pFunction, errorHandler, index) {}; +}; + +/** +* @class BooleanInputSymbol +* +* Represents a boolean input symbol of the Engine +* +* @author Martin Loetzsch +*/ +class BooleanInputSymbol : public InputSymbol +{ +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(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(name, pFunction, errorHandler, index) {}; +}; + +/** +* @class EnumeratedInputSymbol +* +* Represents a enumerated input symbol of the Engine +* +* @author Martin Loetzsch +*/ +class EnumeratedInputSymbol : public InputSymbol +{ +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(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(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 Max Risler +*/ +template 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 Max Risler +*/ +class DecimalOutputSymbol : public OutputSymbol +{ +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(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(name, pSetFunction, pGetFunction, index) + {}; +}; + +/** +* @class BooleanOutputSymbol +* +* Represents a boolean output symbol of the Engine +* +* @author Max Risler +* +*/ +class BooleanOutputSymbol : public OutputSymbol +{ +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(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(name, pSetFunction, pGetFunction, index) + {}; +}; + +/** +* @class EnumeratedOutputSymbol +* +* Represents a enumerated output symbol of the Engine +* +* @author Martin Loetzsch +*/ +class EnumeratedOutputSymbol : public OutputSymbol +{ +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(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(name, pSetFunction, pGetFunction, index), enumeration(enumeration) + {}; + + /** Pointer to the list of enumeration elements */ + Enumeration* enumeration; +}; + +/** +* @class Symbols +* +* Handles the symbols of the Engine. +* +* @author Martin Loetzsch +* @author Max Risler +*/ +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 enumerations; + + /** The decimal input symbols */ + NamedArray decimalInputSymbols; + + /** The boolean input symbols */ + NamedArray booleanInputSymbols; + + /** The enumerated input symbols */ + NamedArray enumeratedInputSymbols; + + /** The decimal output symbols */ + NamedArray decimalOutputSymbols; + + /** The boolean output symbols */ + NamedArray booleanOutputSymbols; + + /** The enumerated output symbols */ + NamedArray enumeratedOutputSymbols; + +private: + /** Is invoked when errors occur */ + ErrorHandler& errorHandler; +}; + +} // namespace + +#endif //__XabslSymbols_h_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTeamMessage.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTeamMessage.h new file mode 100644 index 00000000..1b29029b --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTeamMessage.h @@ -0,0 +1,56 @@ +/** +* @file XabslTeamMessage.h +* +* Definition of class TeamMessage +* +* @author Max Risler +*/ + +#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 Max Risler +*/ +class TeamMessage +{ +public: + /** + * Constructor. + */ + TeamMessage() : agentPriority(0) + {}; + + /** An array containing indexes of currently executed cooperative states */ + Array coopStatesExecuted; + + /** An array containing indexes of cooperative states, currently trying to be executed but blocked due to cooperating agents */ + Array coopStatesEntering; + + /** An array containing indexes of cooperative states, whose corresponding option is being executed */ + Array 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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTools.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTools.cpp new file mode 100644 index 00000000..77d5917d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTools.cpp @@ -0,0 +1,49 @@ +/** +* @file XabslTools.cpp +* +* Implementation of several helper classes for the Engine. +* +* @author Martin Loetzsch +*/ + +#include "XabslTools.h" +#include +#include +#include + +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 + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTools.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTools.h new file mode 100644 index 00000000..f1c99899 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslEngine/XabslTools.h @@ -0,0 +1,110 @@ +/** +* @file XabslTools.h +* +* Definition of several helper classes for the Engine. +* +* @author Martin Loetzsch +* @author Max Risler +* @author Matthias Juengel +*/ + +#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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslMakefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslMakefile new file mode 100644 index 00000000..0a05ab8d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/XabslMakefile @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/Makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/Makefile new file mode 100644 index 00000000..c6955829 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/Makefile @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/constants.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/constants.rb new file mode 100644 index 00000000..6b73b561 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/constants.rb @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/errors.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/errors.rb new file mode 100644 index 00000000..99546257 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/errors.rb @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/language_elements.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/language_elements.rb new file mode 100644 index 00000000..2ea1e4b7 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/language_elements.rb @@ -0,0 +1,2584 @@ +require 'translator' + +module Translator + + #stores symbols and strings within language elements. + class AttributeHash + + def initialize + super + @storage = {} + @order = [] + @declarations = {} + end + + # returns value for key. + def [](key) + raise_on_undeclared(key) + return @storage[key] + end + + # sets value for key. + def []=(key, value) + raise_on_undeclared(key) + raise_on_value(key, value) + + return @storage.delete(key) if value.nil? + return @storage[key] = value + end + + def raise_on_undeclared(key) + if @declarations[key].nil? + LOG.error "undeclared xml attribute '#{key}' accessed" + raise InternalError.new + end + end + + def raise_on_value(key, value) + return if value.nil? + unless value.class <= @declarations[key] + LOG.error "class mismatch on xml attribute '#{key}'" + LOG.error "got #{value.class.name}" + LOG.error "expected #{@declarations[key].name}" + raise InternalError.new + end + end + + # imports from a string hash. + # declares symbols in symbol table if requested by declare(...). + def import(attributes_string_hash, symbol_table) + attributes_string_hash.each { |key, value| + + raise_on_undeclared(key) + decl = @declarations[key] + + if decl == String + @storage[key] = value + elsif decl <= Symbol + #simply ignore redeclarations + symbol = symbol_table.declare(value, decl) + @storage[key] = symbol + else + raise InternalError.new + end + } + end + + # returns array of keys. + def keys + return @storage.keys + end + + # iterates over keys in order of declaration. + def each + @order.each { |key| + yield(key, @storage[key]) if @storage.key?(key) + } + end + + # declares a key. klass can be String or a Symbol subclass. + # 'required' String values are initialized with an empty String. + def declare(key, klass = String, required = false) + @declarations[key] = klass + @order << key unless @order.include?(key) + @storage[key] = '' if klass == String && required + end + end + + # language elements are the XABSL tags + # base class for elements of the syntax tree(s). + class LanguageElement + + @in_type = :any + @out_type = :any + @tag = nil + class << LanguageElement #strange syntax, eeh? + attr_reader :in_type + attr_reader :out_type + attr_reader :tag + end + + #usually ignore text in XML files + def text=(text) + end + + def in_type + return self.class.in_type + end + + def out_type + return self.class.out_type + end + + def tag + return self.class.tag + end + + # AttributeHash for this language element + attr_reader :attr + + # array of child language elements + attr_reader :children + + # parent of this language element + attr_accessor :parent + + # for error handling + attr_reader :leftmost_token + attr_reader :rightmost_token + + def initialize + super + @attr = AttributeHash.new + @children = [] + @parent = nil + @leftmost_token = nil + @rightmost_token = nil + end + + + #set leftmost and rightmost token for a language element + def map_tokens(array) + array.each do |a| + if a.class <= Token + @leftmost_token = a if @leftmost_token.nil? + @rightmost_token = a + elsif a.class <= LanguageElement + @leftmost_token = a.leftmost_token if leftmost_token.nil? && !a.leftmost_token.nil? + @rightmost_token = a.rightmost_token unless a.rightmost_token.nil? + elsif a.class <= Array + map_tokens a + end + end + end + + + # adds le as a child to this language element + def add_child(le, cc=nil, &block) + if valid_child(le) + @children << le + le.parent = self + else + if !block.nil? + block.call(le) + elsif cc.nil? + $stderr << "invalid child '#{le.tag}' for '#{self.tag}'" + raise InternalError.new("invalid child '#{le.tag}' for '#{self.tag}'") + elsif le.leftmost_token.nil? && le.rightmost_token.nil? + $stderr << "invalid child '#{le.tag}' for '#{self.tag}'" + raise InternalError.new("invalid child '#{le.tag}' for '#{self.tag}'") + else + if le.leftmost_token.nil? + cc.eh.error UnexpectedLE.new(cc, le.rightmost_token, le, self) + else + cc.eh.error UnexpectedLE.new(cc, le.leftmost_token, le , self) + end + end + end + end + + #removes le as a child + def remove_child(le) + @children.delete le + le.parent = nil + end + + # method to return true if le can be added as a child + # default is no children allowed + def valid_child(le) + return false + end + + # returns true if this language elements has children. + def children? + return children.size > 0 + end + + # returns the first child with child.class == clazz + # raises InternalError on ambuigities or if no child is found + def child(clazz) + result = [] + children.each do |child| + if child.class <= clazz + result << child + end + end + + raise InternalError.new unless result.size == 1 + return result[0] + end + + # produces XML output for this language element. + # this implementation should be sufficent for almost all language elements. + def to_xml(out) + out << out.pindent(@children.empty? ? 0 : 1) + out << "<#{tag}" + + attr.each { |key, value| + out << " #{key}=\"#{value.class <= Symbol ? value.identifier : escape_xml(value) }\"" + } + + if(@children.empty?) + out << "/>#{ENDL}" + else + out << ">#{ENDL}" + + @children.each { |child| + child.to_xml(out) + } + + out < "#{ENDL}" + end + end + + SPECIALS = [ /&(?!#?[\w-]+;)/u, //u, /"/u ] + SUBSTITUTES = ['&', '<', '>', '"'] + + def escape_xml(string) + + copy = string.clone + copy.gsub!( SPECIALS[0], SUBSTITUTES[0] ) + copy.gsub!( SPECIALS[1], SUBSTITUTES[1] ) + copy.gsub!( SPECIALS[2], SUBSTITUTES[2] ) + copy.gsub!( SPECIALS[3], SUBSTITUTES[3] ) + + return copy + end + + # produces XTC code output for this language element. + # this method implementation differs between classes. + def to_code(cc, out) + raise InternalError.new("#{self.class.name}: to_code not implemented") + end + + # shortcut, often used in to_code(...) + def generate_children_code(cc, out) + @children.each { |child| + cc.bc.generate_code(child) + } + end + + # delegate call to AttributesHash. + # entry point for intercepting symbol declarations while XML parsing. + def import(attributes_string_hash, symbol_table) + attr.import(attributes_string_hash, symbol_table) + end + + def search_upwards(le_class) + current = self + while true + return current if current.class == le_class + return nil if current.class == RootLanguageElement + current = current.parent + end + end + end + + #class used during development to cope with yet unimplemented tags + class UnknownLanguageElement < LanguageElement + + attr_reader :debug_tag + + def initialize(debug_tag) + super() + @debug_tag = debug_tag + LOG.warn "UnknownLanguageElement created for tag #{debug_tag}" + end + + def to_code(cc, out) + out > "/* start dummy code for #{@debug_tag} tag */#{ENDL}" if VERBOSE + generate_children_code(cc, out) + out < "/* end dummy code for #{@debug_tag} tag */#{ENDL}" if VERBOSE + end + end + + #root language elements are the root element of the syntax trees + class RootLanguageElement < LanguageElement + + attr_accessor :doctype + + def initialize + super + end + + def valid_child le + return true + end + + def to_code(cc, out) + + generate_children_code(cc, out) + end + + def to_xml(out) + + out % '' << "#{ENDL}" + out % doctype << "#{ENDL}" unless doctype.nil? + + @children.each { |child| + child.to_xml(out) + } + end + end + + class OptionTag < LanguageElement + + attr_accessor :entities + @tag = TAG_OPTION + + def initialize + super + attr.declare(ATTR_XMLNS) + attr.declare(ATTR_XMLNS_XSI) + attr.declare(ATTR_XSI_SCHEMALOCATION) + attr.declare(ATTR_XMLNS_XI) + attr.declare(ATTR_NAME, OptionSymbol) + attr.declare(ATTR_INITIAL_STATE, StateSymbol) + + @entities = [] + end + + def valid_child(le) + return [StateTag, CDTTag, CommonActionTag].include?(le.class) + end + + def to_ic(out) + out << "// option #{attr[ATTR_NAME].identifier}#{ENDL}" if out.verbose + out << "// number of states#{ENDL}" if out.verbose + + state_count = 0 + children.each do |child| + state_count +=1 if child.class == StateTag + end + + out << "#{state_count}#{ENDL}" + out << "// The states#{ENDL}" if out.verbose + children.each do |child| + if (child.class == StateTag) + begin + out << "#{child.attr[ATTR_NAME].identifier} " + if (!child.attr[ATTR_CAPACITY].nil?) + out << "c #{child.attr[ATTR_CAPACITY]}#{ENDL}" + elsif (!child.attr[ATTR_SYNCHRONIZED].nil?) + out << "s #{child.attr[ATTR_SYNCHRONIZED]}#{ENDL}" + else + out << "n#{ENDL}" + end + end + end + end + out << "#{ENDL}" + + out << "// initial-state#{ENDL}" if out.verbose + out << "#{attr[ATTR_INITIAL_STATE].identifier}#{ENDL}" + children.each do |child| + child.to_ic(out) if child.class == StateTag + end + + out << "#{ENDL}#{ENDL}#{ENDL}" + end + + + def to_code(cc, out) + #TODO was machen mit dem comment, etc. + od = cc.pc.option_definitions_by_symbol[attr[ATTR_NAME]] + throw InternalError.new if od.nil? + + descr = od.attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out > "#{TOKEN_OPTION} #{cc.bc[ATTR_NAME]} {#{ENDL}#{ENDL}" + od.generate_children_code(cc, out) + out << "#{ENDL}" if od.children.size > 0 + + generate_children_code(cc, out) + + out < "}" + out << " /* #{TOKEN_OPTION} #{cc.bc[ATTR_NAME]} end */" if VERBOSE + out << "#{ENDL}#{ENDL}" + end + + def to_xml(out) + out > "<#{tag}" + + attr.each { |key, value| + out << " #{key}=\"#{value.class <= Symbol ? value.identifier : value}\"" + } + + out << ">#{ENDL}" + + symbols = [] + behaviors = [] + strings = [] + + entities.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 { |entity| + out % "&#{entity.identifier};#{ENDL}" + } + behaviors.each { |entity| + out % "&#{entity.identifier};#{ENDL}" + } + strings.each { |entity| + out % "&#{entity};#{ENDL}" + } + + @children.each { |child| + child.to_xml(out) + } + + + out < "#{ENDL}" + + end + + end + + class StateTag < LanguageElement + + @tag = TAG_STATE + + def initialize + super + attr.declare(ATTR_NAME, StateSymbol) + attr.declare(ATTR_IS_TARGET_STATE) + attr.declare(ATTR_CAPACITY) + attr.declare(ATTR_SYNCHRONIZED) + end + + def valid_child(le) + return [TAG_SDOS, TAG_SBOS, TAG_SEOS, TAG_SBB, TAG_SO, TAG_DT].include?(le.tag) + end + + def to_ic(out) + out << "// state #{attr[ATTR_NAME].identifier}#{ENDL}" if out.verbose + if attr[ATTR_IS_TARGET_STATE] == 'true' + out << "// is target state (1)#{ENDL}" if out.verbose + out << "1#{ENDL}" + else + out << "// not a target state (0)#{ENDL}" if out.verbose + out << "0#{ENDL}" + end + + out << "// number of subsequent behavior definitions and output symbol assignments#{ENDL}" if out.verbose + count = 0 + + #include common action here + search_upwards(OptionTag).children.each do |sibling| + count += sibling.children.size if sibling.class == CommonActionTag + end + + children.each do |child| + count += 1 if child.class <= SubTag || child.class <= SOSTag + end + out << "#{count}#{ENDL}" + + search_upwards(OptionTag).children.each do |sibling| + if sibling.class == CommonActionTag + sibling.children.each do |child| + child.to_ic(out) + end + end + end + + children.each do |child| + child.to_ic(out) if child.class <= SubTag || child.class <= SOSTag + end + + + children.each do |child| + child.to_ic(out) if child.class == DTTag + end + + end + + def to_code(cc, out) + + option = search_upwards(OptionTag) + keywords = [] + keywords << TOKEN_INITIAL if option.attr[ATTR_INITIAL_STATE] == attr[ATTR_NAME] + keywords << TOKEN_TARGET if attr[ATTR_IS_TARGET_STATE] == 'true' + keywords << TOKEN_STATE + + out > "#{keywords.join(' ')} #{cc.bc[ATTR_NAME]} {#{ENDL}" + + children.each do |child| + cc.bc.generate_code(child) if child.class == DTTag + end + + out > "#{TOKEN_ACTION} {#{ENDL}" + children.each do |child| + cc.bc.generate_code(child) if child.class <= SOSTag + end + + children.each do |child| + cc.bc.generate_code(child) if [SBBTag, SOTag].include?(child.class) + end + out < "}#{ENDL}" + + + out < "}" + out << " /* #{TOKEN_STATE} #{cc.bc[ATTR_NAME]} end */" if VERBOSE + out << "#{ENDL}#{ENDL}" + end + + end + + class CommonActionTag < LanguageElement + + @tag = TAG_COMMON_ACTION + + def valid_child(le) + return [TAG_SDOS, TAG_SBOS, TAG_SEOS, TAG_SBB, TAG_SO].include?(le.tag) + end + + def to_ic(out) + out << "// common action#{ENDL}" if out.verbose + + out << "// number of subsequent behavior definitions#{ENDL}" if out.verbose + count = 0 + children.each do |child| + count += 1 if child.class <= SubTag + end + out << "#{count}#{ENDL}" + + children.each do |child| + child.to_ic(out) if child.class <= SubTag + end + + out << "// number of set output symbols#{ENDL}" if out.verbose + count = 0 + children.each do |child| + count += 1 if child.class <= SOSTag + end + out << "#{count}#{ENDL}" + + children.each do |child| + child.to_ic(out) if child.class <= SOSTag + end + end + + def to_code(cc, out) + out > "#{TOKEN_COMMON} #{TOKEN_ACTION} {#{ENDL}" + children.each do |child| + cc.bc.generate_code(child) if child.class <= SOSTag + end + + children.each do |child| + cc.bc.generate_code(child) if [SBBTag, SOTag].include?(child.class) + end + out < "}#{ENDL}" + out << " /* #{TAG_COMMON_ACTION} end */" if VERBOSE + out << "#{ENDL}#{ENDL}" + end + + end + + class SubTag < LanguageElement + end + + class SBBTag < SubTag + + @tag = TAG_SBB + + def initialize + super + attr.declare(ATTR_REF, BasicBehaviorSymbol) + end + + def valid_child le + return le.class == SPTag + end + + def to_ic(out) + out << "// subsequent basic behavior (b)#{ENDL}" if out.verbose + out << "a #{attr[ATTR_REF].identifier}#{ENDL}" + out << "// number of set parameters#{ENDL}" if out.verbose + out << "#{children.size}#{ENDL}" + children.each do |child| + child.to_ic(out) unless children[0].nil? + end + end + + def to_code(cc, out) + + #does an option exist with the same identifier ? + out % "#{cc.bc[ATTR_REF]}" + out << " #{TOKEN_BEHAVIOR}" if cc.st.get(attr[ATTR_REF].identifier, OptionSymbol) + out <<"(" + + first = true + @children.each { |child| + out << ", " unless first + cc.bc.generate_code(child) + first = false + } + + out << ");#{ENDL}" + + end + end + + class SOTag < SubTag + + @tag = TAG_SO + + def initialize + super + attr.declare(ATTR_REF, OptionSymbol) + end + + def valid_child le + return SPTag == le.class + end + + def to_ic(out) + out << "// subsequent option (o)#{ENDL}" if out.verbose + out << "o #{attr[ATTR_REF].identifier}#{ENDL}" + out << "// number of set parameters#{ENDL}" if out.verbose + out << "#{children.size}#{ENDL}" + children.each do |child| + child.to_ic(out) unless children[0].nil? + end + end + + def to_code(cc, out) + #does an behavior exist with the same identifier ? + out % "#{cc.bc[ATTR_REF]}" + out << " #{TOKEN_OPTION}" if cc.st.get(attr[ATTR_REF].identifier, BasicBehaviorSymbol) + out << "(" + + first = true + @children.each { |child| + out << ", " unless first + cc.bc.generate_code(child) + first = false + } + + out << ");#{ENDL}" + + end + + end + + + class SPTag < LanguageElement + + @tag = TAG_SP + attr_accessor :in_type + + def initialize + super + @in_type = :any + attr.declare(ATTR_REF, DomainValueSymbol) + end + + def valid_child le + return @in_type == :any || le.out_type == :any || @in_type == le.out_type + end + + #late declaration dependant on parent class + def parent=(value) + super + + if parent.class == SBBTag + attr.declare(ATTR_REF, BasicBehaviorParameterSymbol) + elsif parent.class == SOTag + attr.declare(ATTR_REF, OptionParameterSymbol) + else + raise InternalError.new + end + end + + def to_ic(out) + out << "// set-parameter#{ENDL}" if out.verbose + case in_type + when :decimal + out << "d " + when :boolean + out << "b " + when :enum + out << "e #{attr[ATTR_REF].enum_domain.identifier} " + else + raise InternalError.new + end + out << "#{attr[ATTR_REF].identifier}#{ENDL}" + children[0].to_ic(out) + end + + def to_code(cc, out) + throw "only 1 child expected" unless @children.size == 1 + throw "parent should be SBBTag or SOTag but is #{parent.tag}" unless [SBBTag, SOTag].include?(parent.class) + + #skip output of prefixed '@' + out << "#{cc.sc.to_code(attr[ATTR_REF], false)} = " + + generate_children_code(cc, out) + end + end + + class OPRTag < LanguageElement + + @tag = TAG_OPR + attr_accessor :out_type + attr_accessor :enum_domain + + def initialize + super + @out_type = :any + attr.declare(ATTR_REF, OptionParameterSymbol) + end + + def to_ic(out) + out << "// option-parameter-ref#{ENDL}" if out.verbose + out << "p #{attr[ATTR_REF].identifier}#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + out << cc.bc[ATTR_REF] + out << " /* #{TAG_OPR} */" if VERBOSE + end + end + + class DVTag < LanguageElement + + @tag = TAG_DV + @out_type = :decimal + + def initialize + super + attr.declare(ATTR_VALUE) + end + + def valid_child le + return false + end + + def normalize + float = attr[ATTR_VALUE].to_f + int = float.to_i + + if (float == int.to_f) + attr[ATTR_VALUE] = int.to_s + else + attr[ATTR_VALUE] = float.to_s + end + end + + def to_ic(out) + normalize + out << "// decimal-value#{ENDL}" if out.verbose + out << "v #{attr[ATTR_VALUE]}#{ENDL}" + end + + def to_xml(out) + normalize + super + end + + def to_code(cc, out) + normalize + out << attr[ATTR_VALUE] + end + end + + class BVTag < LanguageElement + + @tag = TAG_BV + @out_type = :boolean + + def initialize + super + attr.declare(ATTR_VALUE) + end + + def valid_child le + return false + end + + def to_ic(out) + out << "// boolean-value#{ENDL}" if out.verbose + out << "v #{attr[ATTR_VALUE]}#{ENDL}" + end + + def to_code(cc, out) + out << attr[ATTR_VALUE] + end + end + + class StatementContainingTag < LanguageElement + + def condition_and_statement_to_ic(out) + + raise InternalError.new if children.size < 2 + raise InternalError.new unless children[0].class == CondTag + out << "// condition#{ENDL}" if out.verbose + children[0].to_ic(out) + statement_to_ic(out, children[1..-1]) + end + + def statement_to_ic(out, children = self.children) + + raise InternalError.new if children.size == 0 + + case children[0] + when TTSTag: + raise InternalError.new if children.size != 1 + children[0].to_ic(out) + when IfTag: + out << "// if/else block (i) #{ENDL}" if out.verbose + out << "i#{ENDL}" + children[0].to_ic(out) + else + p children[0].class.name + exit 1 + end + + children[1..-1].each do |child| + child.to_ic(out) + end + + + end + + + end + + class DTTag < StatementContainingTag + + @tag = TAG_DT + + def valid_child le + return [IfTag, ElseTag, TTSTag].include?(le.class) + end + + def to_ic(out) + #include common decision tree here + search_upwards(OptionTag).children.each do |child| + if child.class == CDTTag + child.to_ic(out) + break + end + end + + out << "// state decision tree:#{ENDL}" if out.verbose + statement_to_ic(out) + end + + def to_code(cc, out) + # exactly one child that is TTSTag and has a transition to self state. + return if children.size == 1 && children[0].class == TTSTag && parent.attr[ATTR_NAME] == children[0].attr[ATTR_REF] + + out > "#{TOKEN_DECISION} {#{ENDL}" + + #begin with else if there is a common decision tree + search_upwards(OptionTag).children.each do |child| + if child.class == CDTTag + out % "#{TOKEN_ELSE}#{ENDL}" + break + end + end + + generate_children_code(cc, out) + + out < "}" + out << " /* #{TAG_DT} end */" if VERBOSE + out << "#{ENDL}" + end + end + + + + class IfTag < StatementContainingTag + + @tag = TAG_IF + + def valid_child le + return [IfTag, ElseTag, CondTag, TTSTag].include?(le.class) + end + + def to_ic(out) + + out << "// if statement#{ENDL}" if out.verbose + condition_and_statement_to_ic(out) + + end + + def to_code(cc, out) + throw "child #1 is not #{TAG_COND}" unless @children[0].tag == TAG_COND + + #print description of condition tag + descr = @children[0].attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + + out > "#{TOKEN_IF} (" + cc.bc.generate_code(@children[0]) + out << ") {#{ENDL}" + (1..@children.size - 1).each { |i| + cc.bc.generate_code(@children[i]) + } + out < "}#{ENDL}" + end + end + + class ElseTag < StatementContainingTag + + @tag = TAG_ELSE + + def valid_child le + return [IfTag, ElseTag, TTSTag].include?(le.class) + end + + def to_ic(out) + out << "// else statement#{ENDL}" if out.verbose + statement_to_ic(out) + end + + def to_code(cc, out) + + out > "#{TOKEN_ELSE} {#{ENDL}" + generate_children_code(cc, out) + out < "}#{ENDL}" + end + + end + + class CondTag < LanguageElement + + @tag = TAG_COND + @in_type = :boolean + + def initialize + super + attr.declare(ATTR_DESCRIPTION, String) + end + + def valid_child le + return le.out_type == :any || in_type == le.out_type + end + + def to_ic(out) + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + generate_children_code(cc, out) + end + + #hack to suppress description attributes on CE children + #and to generate on all other even if empty + def to_xml(out) + if parent.class == CETag + attr[ATTR_DESCRIPTION] = nil + else + attr[ATTR_DESCRIPTION] = '' if attr[ATTR_DESCRIPTION].nil? + end + super + end + end + + class TTSTag < LanguageElement + + @tag = TAG_TTS + + def initialize + super + attr.declare(ATTR_REF, StateSymbol) + end + + def valid_child le + return false + end + + def to_ic(out) + out << "// transition to state (t) #{attr[ATTR_REF].identifier}#{ENDL}" if out.verbose + out << "t #{attr[ATTR_REF].identifier}#{ENDL}" + end + + def to_code(cc, out) + #current_state can be nil because of common-decision-trees + current_state = search_upwards(StateTag) + + if !current_state.nil? && current_state.attr[ATTR_NAME] == attr[ATTR_REF] + out % "#{TOKEN_STAY};#{ENDL}" + else + out % "#{TOKEN_TTS} #{cc.bc[ATTR_REF]};#{ENDL}" + end + end + end + + class BinaryOperator < LanguageElement + + attr_reader :operator + attr_reader :priority + attr_reader :associative + + def initialize(operator, priority, associative) + super() + @operator = operator + @priority = priority + @associative = associative + end + + def valid_child le + return in_type == :any || le.out_type == :any || in_type == le.out_type + end + + def to_code(cc, out) + + throw "child count is must be greater than 2" unless @children.size >= 2 + + braces = (@children[0].class <= BinaryOperator && @children[0].priority < self.priority) + out << "(" if braces + out << "/* braces needed */" if braces && VERBOSE + cc.bc.generate_code(@children[0]) + out << ")" if braces + + (1..@children.size-1).each {|i| + out << " #{operator} " + braces = (@children[i].class <= BinaryOperator && @children[i].priority < self.priority) + out << "(" if braces + out << "/* braces needed */" if braces && VERBOSE + cc.bc.generate_code(@children[i]) + out << ")" if braces + } + end + end + + + class OrTag < BinaryOperator + + @tag = TAG_OR + @in_type = :boolean + @out_type = :boolean + + def to_ic(out) + out << "// or (#{children.size})#{ENDL}" if out.verbose + out << "| #{children.size}#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('||', 1 , true) + end + end + + class AndTag < BinaryOperator + + @tag = TAG_AND + @in_type = :boolean + @out_type = :boolean + + def to_ic(out) + out << "// and (#{children.size})#{ENDL}" if out.verbose + out << "& #{children.size}#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('&&', 2, true) + end + end + + class LTTag < BinaryOperator + + @tag = TAG_LT + @in_type = :decimal + @out_type = :boolean + + def to_ic(out) + out << "// <#{ENDL}" if out.verbose + out << "<#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('<', 3, false) + end + end + + class GTTag < BinaryOperator + + @tag = TAG_GT + @in_type = :decimal + @out_type = :boolean + + def to_ic(out) + out << "// >#{ENDL}" if out.verbose + out << ">#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('>', 3, false) + end + end + + class GTEQTag < BinaryOperator + + @tag = TAG_GTEQ + @in_type = :decimal + @out_type = :boolean + + def to_ic(out) + out << "// >=#{ENDL}" if out.verbose + out << "g#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('>=', 3, false) + end + end + + class LTEQTag < BinaryOperator + + @tag = TAG_LTEQ + @in_type = :decimal + @out_type = :boolean + + def to_ic(out) + out << "// <=#{ENDL}" if out.verbose + out << "l#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('<=', 3, false) + end + end + + + class EISCTag < BinaryOperator + + @tag = TAG_EISC + @in_type = :enum + @out_type = :boolean + + def to_ic(out) + out << "// enumerated-input-symbol-comparison#{ENDL}" if out.verbose + out << "c#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('==', 0, false) + end + end + + class EQTag < BinaryOperator + + @tag = TAG_EQ + @in_type = :decimal + @out_type = :boolean + + def to_ic(out) + out << "// ==#{ENDL}" if out.verbose + out << "=#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('==', 3, false) + end + end + + class NEQTag < BinaryOperator + + @tag = TAG_NEQ + @in_type = :decimal + @out_type = :boolean + + def to_ic(out) + out << "// !=#{ENDL}" if out.verbose + out << "n#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('!=', 3, false) + end + end + + class PlusTag < BinaryOperator + + @tag = TAG_PLUS + @in_type = :decimal + @out_type = :decimal + + def to_ic(out) + out << "// plus#{ENDL}" if out.verbose + out << "+#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('+', 4, true) + end + end + + class MinusTag < BinaryOperator + + @tag = TAG_MINUS + @in_type = :decimal + @out_type = :decimal + + def to_ic(out) + out << "// minus#{ENDL}" if out.verbose + out << "-#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('-', 4, false) + end + end + + class MPLTag < BinaryOperator + + @tag = TAG_MPL + @in_type = :decimal + @out_type = :decimal + + def to_ic(out) + out << "// multiply#{ENDL}" if out.verbose + out << "*#{ENDL}" + + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('*', 5, true) + end + end + + + class DIVTag < BinaryOperator + + @tag = TAG_DIV + @in_type = :decimal + @out_type = :decimal + + def to_ic(out) + out << "// divide#{ENDL}" if out.verbose + out << "d#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('/', 5, false) + end + end + + + class MODTag < BinaryOperator + + @tag = TAG_MOD + @in_type = :decimal + @out_type = :decimal + + def to_ic(out) + out << "// modulo#{ENDL}" if out.verbose + out << "%#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def initialize + super('%', 5, false) + end + end + + class DOSRTag < LanguageElement + + @tag = TAG_DOSR + @out_type = :decimal + + def initialize + super + attr.declare(ATTR_REF, DecimalOutputSymbol) + end + + def to_ic(out) + out << "// decimal-output-symbol-ref#{ENDL}" if out.verbose + out << "o #{attr[ATTR_REF].identifier}#{ENDL}" + end + + def to_code(cc, out) + out << "#{cc.bc[ATTR_REF]}" + out << " /* #{TAG_DOSR} */" if VERBOSE + end + end + + class BOSRTag < LanguageElement + + @tag = TAG_BOSR + @out_type = :boolean + + def initialize + super + attr.declare(ATTR_REF, BooleanOutputSymbol) + end + + def to_ic(out) + out << "// boolean-output-symbol-ref#{ENDL}" if out.verbose + out << "o #{attr[ATTR_REF].identifier}#{ENDL}" + end + + def to_code(cc, out) + out << "#{cc.bc[ATTR_REF]}" + out << " /* #{TAG_BOSR} */" if VERBOSE + end + end + + class EOSRTag < LanguageElement + + @tag = TAG_EOSR + @out_type = :enum + attr_accessor :enum_domain + + def initialize + super + attr.declare(ATTR_REF, EnumOutputSymbol) + end + + def to_ic(out) + out << "// enumerated-output-symbol-ref#{ENDL}" if out.verbose + out << "o #{attr[ATTR_REF].identifier}#{ENDL}" + end + + def to_code(cc, out) + out << "#{cc.bc[ATTR_REF]}" + out << " /* #{TAG_EOSR} */" if VERBOSE + end + end + + class DISRTag < LanguageElement + + @tag = TAG_DISR + @out_type = :decimal + + def initialize + super + attr.declare(ATTR_REF, DecimalInputSymbol) + end + + def valid_child le + return le.class == WPTag + end + + def to_ic(out) + out << "// decimal-input-symbol-ref#{ENDL}" if out.verbose + out << "i #{attr[ATTR_REF].identifier}#{ENDL}" + out << "// number of with-parameter elements#{ENDL}" if out.verbose + out << "#{children.size}#{ENDL}" + + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + out << "#{cc.bc[ATTR_REF]}(" + first = true + @children.each { |child| + out << ", " unless first + cc.bc.generate_code(child) + first = false + } + out << ")" + out << " /* #{TAG_DISR} */" if VERBOSE + end + end + + class BISRTag < LanguageElement + + @tag = TAG_BISR + @out_type = :boolean + + def initialize + super + attr.declare(ATTR_REF, BooleanInputSymbol) + end + + def valid_child le + return le.class == WPTag + end + + def to_ic(out) + out << "// boolean-input-symbol-ref#{ENDL}" if out.verbose + out << "i #{attr[ATTR_REF].identifier}#{ENDL}" + out << "// number of with-parameter elements#{ENDL}" if out.verbose + out << "#{children.size}#{ENDL}" + + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + out << "#{cc.bc[ATTR_REF]}(" + first = true + @children.each { |child| + out << ", " unless first + cc.bc.generate_code(child) + first = false + } + out << ")" + out << " /* #{TAG_BISR} */" if VERBOSE + end + end + + class EISRTag < LanguageElement + + @tag = TAG_EISR + @out_type = :enum + attr_accessor :enum_domain + + def initialize + super + attr.declare(ATTR_REF, EnumInputSymbol) + end + + def valid_child le + return le.class == WPTag + end + + def to_ic(out) + out << "// enumerated-input-symbol-ref#{ENDL}" if out.verbose + out << "i #{attr[ATTR_REF].identifier}#{ENDL}" + out << "// number of with-parameter elements#{ENDL}" if out.verbose + out << "#{children.size}#{ENDL}" + + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + out << "#{cc.bc[ATTR_REF]}(" + first = true + @children.each { |child| + out << ", " unless first + cc.bc.generate_code(child) + first = false + } + out << ")" + out << " /* #{TAG_EISR} */" if VERBOSE + end + end + + class WPTag < LanguageElement + + @tag = TAG_WP + attr_accessor :in_type + + def initialize + super + @in_type = :any + attr.declare(ATTR_REF, InputSymbolParameterSymbol) + end + + def valid_child le + return @in_type == :any || le.out_type == :any || @in_type == le.out_type + end + + def to_ic(out) + raise "exactly 1 child expected" unless @children.size == 1 + raise "parent should be either DISRTag, BISRTag or EISRTag instead of #{parent.class.to_s}" unless (parent.class == DISRTag || parent.class == BISRTag || parent.class == EISRTag) + + out << "// with parameter #{attr[ATTR_REF].identifier}#{ENDL}" if out.verbose + case in_type + when :decimal + out << "d " + when :boolean + out << "b " + when :enum + out << "e #{attr[ATTR_REF].enum_domain.identifier} " + else + raise InternalError.new + end + out << "#{attr[ATTR_REF].identifier}#{ENDL}" + children[0].to_ic(out) + end + + def to_code(cc, out) + raise "exactly 1 child expected" unless @children.size == 1 + raise "parent should be either DISRTag, BISRTag or EISRTag instead of #{parent.class.to_s}" unless (parent.class == DISRTag || parent.class == BISRTag || parent.class == EISRTag) + + out << "#{cc.bc[ATTR_REF]} = " + cc.bc.generate_code(@children[0]) + end + end + + class CDTTag < StatementContainingTag + + @tag = TAG_CDT + + def valid_child le + return [IfTag, ElseTag].include?(le.class) + end + + def to_ic(out) + out << "// common decision tree:#{ENDL}" if out.verbose + statement_to_ic(out) + out << "// (else)#{ENDL}" if out.verbose + end + + def to_code(cc, out) + out > "#{TOKEN_COMMON} #{TOKEN_DECISION} {#{ENDL}" + + generate_children_code(cc, out) + + out < "}" + out << " /* #{TAG_CDT} end */" if VERBOSE + out << "#{ENDL}#{ENDL}" + end + end + + class CRTag < LanguageElement + + @tag = TAG_CR + @out_type = :decimal + + def initialize + super + attr.declare(ATTR_REF, ConstantSymbol) + end + + def to_ic(out) + out << "// constant-ref#{ENDL}" if out.verbose + out << "c #{attr[ATTR_REF].value}#{ENDL}" + end + + def to_code(cc, out) + out << "#{cc.bc[ATTR_REF]}" + out << " /* #{TAG_CR} */" if VERBOSE + end + end + + class TOSXTag < LanguageElement + + @tag = TAG_TOSX + @out_type = :decimal + + def initialize + super + end + + def to_ic(out) + out << "// time-of-state-execution#{ENDL}" if out.verbose + out << "s#{ENDL}" + end + + def to_code(cc, out) + out << TOKEN_TOSX + out << " /* #{TAG_TOSX} */" if VERBOSE + end + end + + class TOOXTag < LanguageElement + + @tag = TAG_TOOX + @out_type = :decimal + + def initialize + super + end + + def to_ic(out) + out << "// time-of-option-execution#{ENDL}" if out.verbose + out << "t#{ENDL}" + end + + def to_code(cc, out) + out << TOKEN_TOOX + out << " /* #{TAG_TOOX} */" if VERBOSE + end + end + + class SOSTag < LanguageElement + end + + class EVTag < LanguageElement + + @tag = TAG_EV + @out_type = :enum + attr_accessor :enum_domain + + def initialize + super + attr.declare(ATTR_REF, EnumSymbolValueSymbol) + end + + def valid_child le + return false + end + + def to_ic(out) + out << "// enum element#{ENDL}" if out.verbose + out << "v #{attr[ATTR_REF].identifier} #{ENDL}" + end + + def to_code(cc, out) + out << cc.bc[ATTR_REF] + end + end + + class SDOSTag < SOSTag + + @tag = TAG_SDOS + @in_type = :decimal + + def initialize + super + attr.declare(ATTR_REF, DecimalOutputSymbol) + end + + def valid_child le + return le.out_type == :any || in_type == le.out_type + end + + def to_ic(out) + out << "// set decimal output symbol#{ENDL}" if out.verbose + out << "d #{attr[ATTR_REF].identifier}#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + out % cc.bc[ATTR_REF] << " = " + generate_children_code(cc, out) + out << ";" + out << " /* #{TAG_SDOS} */" if VERBOSE + out << "#{ENDL}" + end + end + + class SBOSTag < SOSTag + + @tag = TAG_SBOS + @in_type = :boolean + + def initialize + super + attr.declare(ATTR_REF, BooleanOutputSymbol) + end + + def valid_child le + return le.out_type == :any || in_type == le.out_type + end + + def to_ic(out) + out << "// set boolean output symbol#{ENDL}" if out.verbose + out << "b #{attr[ATTR_REF].identifier}#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + out % cc.bc[ATTR_REF] << " = " + generate_children_code(cc, out) + out << ";" + out << " /* #{TAG_SBOS} */" if VERBOSE + out << "#{ENDL}" + end + end + + class SEOSTag < SOSTag + + @tag = TAG_SEOS + @in_type = :enum + + def initialize + super + attr.declare(ATTR_REF, EnumOutputSymbol) + end + + def valid_child le + return le.out_type == :any || in_type == le.out_type + end + + def to_ic(out) + out << "// set enumerated output symbol#{ENDL}" if out.verbose + out << "e #{attr[ATTR_REF].identifier}#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + out % cc.bc[ATTR_REF] << " = " + generate_children_code(cc, out) + out << ";" + out << " /* #{TAG_SEOS} */" if VERBOSE + out << "#{ENDL}" + end + end + + class NotTag < LanguageElement + + @tag = TAG_NOT + @in_type = :boolean + @out_type = :boolean + + def initialize + super + end + + def valid_child le + return le.out_type == :any || in_type == le.out_type + end + + def to_ic(out) + out << "// not#{ENDL}" if out.verbose + out << "!#{ENDL}" + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + throw "only 1 child expected" unless @children.size == 1 + + out << "!(" + cc.bc.generate_code(@children[0]) + out << ")" + end + end + + class SORTSTag < LanguageElement + + @tag = TAG_SORTS + @out_type = :boolean + + def initialize + super + end + + def to_ic(out) + out << "// subsequent-option-reached-target-state#{ENDL}" if out.verbose + out << "t#{ENDL}" + end + + def to_code(cc, out) + out << TOKEN_SORTS + out << " /* #{TAG_SORTS} */" if VERBOSE + end + end + + class ConflictTag < LanguageElement + + @tag = TAG_CONFLICT + @out_type = :boolean + + def initialize + super + end + + def to_ic(out) + out << "// conflict#{ENDL}" if out.verbose + out << "x#{ENDL}" + end + + def to_code(cc, out) + out << TOKEN_CONFLICT + out << " /* #{TAG_CONFLICT} */" if VERBOSE + end + end + + class CETag < LanguageElement + + @tag = TAG_CE + attr_accessor :out_type + attr_accessor :enum_domain + + def initialize + super + @out_type = :any + end + + def valid_child le + case @children.size + when 0: + return le.class == CondTag + when 1: + return le.class == EX1Tag && (self.out_type == :any || le.in_type == :any || self.out_type == le.in_type) + when 2: + return le.class == EX2Tag && (self.out_type == :any || le.in_type == :any || self.out_type == le.in_type) + end + + return false + end + + def to_ic(out) + out << "// conditional expression (question mark operator)#{ENDL}" if out.verbose + out << "q#{ENDL}" + out << "// conditional expression: condition#{ENDL}" if out.verbose + children[0].to_ic(out) + out << "// conditional expression: expression1#{ENDL}" if out.verbose + children[1].to_ic(out) + out << "// conditional expression: expression2#{ENDL}" if out.verbose + children[2].to_ic(out) + end + + def to_code(cc, out) + throw "exactly 3 children expected" unless @children.size == 3 + + out << "(" + cc.bc.generate_code(@children[0]) + out << " ? " + cc.bc.generate_code(@children[1]) + out << " : " + cc.bc.generate_code(@children[2]) + out << ")" + end + end + + + class EX1Tag < LanguageElement + + @tag = TAG_EX1 + attr_accessor :in_type + + def initialize + super + @in_type = :any + end + + def valid_child le + @in_type = le.out_type + return true + end + + def to_ic(out) + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + throw "exactly 1 child expected" unless @children.size == 1 + cc.bc.generate_code(@children[0]) + end + end + + class EX2Tag < LanguageElement + + @tag = TAG_EX2 + attr_accessor :in_type + + def initialize + super + @in_type = :any + end + + def valid_child le + @in_type = le.out_type + return true + end + + def to_ic(out) + children.each do |child| + child.to_ic(out) + end + end + + def to_code(cc, out) + throw "exactly 1 child expected" unless @children.size == 1 + cc.bc.generate_code(@children[0]) + end + end + + + class ODTag < LanguageElement + + @tag = TAG_OD + + def initialize + super + attr.declare(ATTR_NAME, OptionSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def valid_child le + return le.class == DParaTag || le.class == BParaTag || le.class == EParaTag + end + end + + class ODSTag < LanguageElement + + @tag = TAG_ODS + + def initialize + super + attr.declare(ATTR_XMLNS) + attr.declare(ATTR_XMLNS_XSI) + attr.declare(ATTR_XSI_SCHEMALOCATION) + end + + def valid_child le + return ODTag == le.class + end + end + + # declaration of decimal function or option parameters + class DParaTag < LanguageElement + + @tag = TAG_DPARA + + def initialize + super + attr.declare(ATTR_NAME, ParameterSymbol) + attr.declare(ATTR_MEASURE, String, true) + attr.declare(ATTR_RANGE, String, true) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def import(attributes_string_hash, symbol_table) + super + symbol_table.set_domain_symbol(attr[ATTR_NAME], parent.attr[ATTR_NAME]) + end + + #late declaration dependant on parent class + def parent=(value) + super + + if parent.class == DISTag || parent.class == BISTag || parent.class == EISTag + attr.declare(ATTR_NAME, InputSymbolParameterSymbol) + elsif parent.class == ODTag + attr.declare(ATTR_NAME, OptionParameterSymbol) + elsif parent.class == BBTag + attr.declare(ATTR_NAME, BasicBehaviorParameterSymbol) + else + raise InternalError.new("unexpected parent class #{parent.class.name}") + end + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "float " + out << cc.bc[ATTR_NAME] + out << " [#{attr[ATTR_RANGE]}]" unless attr[ATTR_RANGE] =~ /^\s*$/ + out << " \"#{attr[ATTR_MEASURE]}\"" unless attr[ATTR_MEASURE] =~ /^\s*$/ + out << ";#{ENDL}" + end + end + + # declaration of boolean function or option parameters + class BParaTag < LanguageElement + + @tag = TAG_BPARA + + def initialize + super + attr.declare(ATTR_NAME, ParameterSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def import(attributes_string_hash, symbol_table) + super + symbol_table.set_domain_symbol(attr[ATTR_NAME], parent.attr[ATTR_NAME]) + end + + #late declaration dependant on parent class + def parent=(value) + super + + if parent.class == DISTag || parent.class == BISTag || parent.class == EISTag + attr.declare(ATTR_NAME, InputSymbolParameterSymbol) + elsif parent.class == ODTag + attr.declare(ATTR_NAME, OptionParameterSymbol) + elsif parent.class == BBTag + attr.declare(ATTR_NAME, BasicBehaviorParameterSymbol) + else + raise InternalError.new("unexpected parent class #{parent.class.name}") + end + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "bool " + out << cc.bc[ATTR_NAME] + out << ";#{ENDL}" + end + end + + # declaration of function or option parameters + class EParaTag < LanguageElement + + @tag = TAG_EPARA + + def initialize + super + attr.declare(ATTR_NAME, ParameterSymbol) + attr.declare(ATTR_ENUM, EnumSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def import(attributes_string_hash, symbol_table) + super + symbol_table.set_domain_symbol(attr[ATTR_NAME], parent.attr[ATTR_NAME]) + end + + #late declaration dependant on parent class + def parent=(value) + super + + if parent.class == DISTag || parent.class == BISTag || parent.class == EISTag + attr.declare(ATTR_NAME, InputSymbolParameterSymbol) + elsif parent.class == ODTag + attr.declare(ATTR_NAME, OptionParameterSymbol) + elsif parent.class == BBTag + attr.declare(ATTR_NAME, BasicBehaviorParameterSymbol) + else + raise InternalError.new("unexpected parent class #{parent.class.name}") + end + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "enum " + out << cc.bc[ATTR_ENUM] + out << " " + out << cc.bc[ATTR_NAME] + out << ";#{ENDL}" + end + end + + class SymbolsTag < LanguageElement + + @tag = TAG_SYMBOLS + + def initialize + super + attr.declare(ATTR_XMLNS) + attr.declare(ATTR_XMLNS_XSI) + attr.declare(ATTR_XSI_SCHEMALOCATION) + attr.declare(ATTR_ID, NamespaceSymbol) + attr.declare(ATTR_TITLE) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def valid_child le + return [DISTag, DOSTag, ETag, EISTag, EOSTag, BISTag, BOSTag, ConstantTag].include?(le.class) + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out > "namespace #{cc.bc[ATTR_ID]}(\"#{attr[ATTR_TITLE]}\") {#{ENDL}#{ENDL}" + generate_children_code(cc, out) + out < "}#{ENDL}#{ENDL}" + end + end + + class DISTag < LanguageElement + + @tag = TAG_DIS + + def initialize + super + attr.declare(ATTR_NAME, DecimalInputSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + attr.declare(ATTR_MEASURE, String, true) + attr.declare(ATTR_RANGE, String, true) + end + + def valid_child le + return le.class == DParaTag || le.class == BParaTag || le.class == EParaTag + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "#{TOKEN_FLOAT} #{TOKEN_INPUT} #{cc.bc[ATTR_NAME]}" + out << " [#{attr[ATTR_RANGE]}]" unless (attr[ATTR_RANGE].nil? || attr[ATTR_RANGE].empty?) + out << " \"#{attr[ATTR_MEASURE]}\"" unless (attr[ATTR_MEASURE].nil? || attr[ATTR_MEASURE].empty?) + if children.size > 0 + out > "#{ENDL}(" + is_first = true + children.each do |child| + out << "," unless is_first + out << "#{ENDL}" + out % "" + cc.bc.generate_code(child) + is_first = false + end + out << "#{ENDL})" + out < ")" + end + out << ";#{ENDL}#{ENDL}" + end + end + + class DOSTag < LanguageElement + + @tag = TAG_DOS + + def initialize + super + attr.declare(ATTR_NAME, DecimalOutputSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + attr.declare(ATTR_MEASURE, String, true) + attr.declare(ATTR_RANGE, String, true) + attr.declare(ATTR_INTERNAL) + end + + def to_code(cc, out) + + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "#{TOKEN_FLOAT} " + out << "#{TOKEN_INTERNAL} " if attr[ATTR_INTERNAL] == 'true' + out << "#{TOKEN_OUTPUT} #{cc.bc[ATTR_NAME]}" + out << " [#{attr[ATTR_RANGE]}]" unless (attr[ATTR_RANGE].nil? || attr[ATTR_RANGE].empty?) + out << " \"#{attr[ATTR_MEASURE]}\"" unless (attr[ATTR_MEASURE].nil? || attr[ATTR_MEASURE].empty?) + out << ";#{ENDL}#{ENDL}" + end + end + + class EISTag < LanguageElement + + @tag = TAG_EIS + + def initialize + super + attr.declare(ATTR_NAME, EnumInputSymbol) + attr.declare(ATTR_ENUM, EnumSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def valid_child le + return le.class == DParaTag || le.class == BParaTag || le.class == EParaTag + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "#{TOKEN_ENUM} #{cc.bc[ATTR_ENUM]} #{TOKEN_INPUT} #{cc.bc[ATTR_NAME]}" + if children.size > 0 + out > "#{ENDL}(" + is_first = true + children.each do |child| + out << "," unless is_first + out << "#{ENDL}" + out % "" + cc.bc.generate_code(child) + is_first = false + end + out << "#{ENDL})" + out < ")" + end + out << ";#{ENDL}#{ENDL}" + end + + end + + class EnumTag < LanguageElement + + @tag = TAG_ENUM + + def initialize + super + attr.declare(ATTR_NAME, EnumSymbolValueSymbol) + end + + def to_code(cc, out) + out << cc.bc[ATTR_NAME] + end + + def import(attributes_string_hash, symbol_table) + super + symbol_table.set_domain_symbol(attr[ATTR_NAME], parent.attr[ATTR_NAME]) + end + end + + class EOSTag < LanguageElement + + @tag = TAG_EOS + + def initialize + super + attr.declare(ATTR_NAME, EnumOutputSymbol) + attr.declare(ATTR_ENUM, EnumSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + attr.declare(ATTR_INTERNAL) + end + + def valid_child le + return false + end + + def to_code(cc, out) + is_first = true + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "#{TOKEN_ENUM} #{cc.bc[ATTR_ENUM]} " + out << "#{TOKEN_INTERNAL} " if attr[ATTR_INTERNAL] == 'true' + out << "#{TOKEN_OUTPUT} #{cc.bc[ATTR_NAME]};#{ENDL}#{ENDL}" + end + end + + class ETag < LanguageElement + + @tag = TAG_E + + def initialize + super + attr.declare(ATTR_NAME, EnumSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + attr.declare(ATTR_INTERNAL) + end + + def valid_child le + return EnumTag == le.class + end + + def to_code(cc, out) + is_first = true + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out > "" + out << "#{TOKEN_INTERNAL} " if attr[ATTR_INTERNAL] == 'true' + our << "#{TOKEN_ENUM} #{cc.bc[ATTR_NAME]} {" + children.each do |child| + out << "," unless is_first + out << "#{ENDL}" + out % "" + cc.bc.generate_code(child) + is_first = false + end + out << "#{ENDL}" + out < "};#{ENDL}#{ENDL}" + end + end + + class BISTag < LanguageElement + + @tag = TAG_BIS + + def initialize + super + attr.declare(ATTR_NAME, BooleanInputSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def valid_child le + return le.class == DParaTag || le.class == BParaTag || le.class == EParaTag + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "#{TOKEN_BOOL} #{TOKEN_INPUT} #{cc.bc[ATTR_NAME]}" + if children.size > 0 + out > "#{ENDL}(" + is_first = true + children.each do |child| + out << "," unless is_first + out << "#{ENDL}" + out % "" + cc.bc.generate_code(child) + is_first = false + end + out << "#{ENDL})" + out < ")" + end + out << ";#{ENDL}#{ENDL}" + end + + end + + class BOSTag < LanguageElement + + @tag = TAG_BOS + + def initialize + super + attr.declare(ATTR_NAME, BooleanOutputSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + attr.declare(ATTR_INTERNAL) + end + + def to_code(cc, out) + + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "#{TOKEN_BOOL} " + out << "#{TOKEN_INTERNAL} " if attr[ATTR_INTERNAL] == 'true' + out << "#{TOKEN_OUTPUT} #{cc.bc[ATTR_NAME]};#{ENDL}#{ENDL}" + end + + end + + class ConstantTag < LanguageElement + + @tag = TAG_CONST + + def initialize + super + attr.declare(ATTR_NAME, ConstantSymbol) + attr.declare(ATTR_VALUE) + attr.declare(ATTR_MEASURE, String, true) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def import(attributes_string_hash, symbol_table) + super + #save constant value within symbol. this value is accessed while generating IC. + attr[ATTR_NAME].value = attr[ATTR_VALUE] + end + + def to_code(cc, out) + + descr = attr[ATTR_DESCRIPTION] + measure = attr[ATTR_MEASURE] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "#{TOKEN_FLOAT} #{TOKEN_CONST} #{cc.bc[ATTR_NAME]} = #{attr[ATTR_VALUE]}" + out << " \"#{measure}\"" unless (measure.nil? || measure.empty?) + out << ";#{ENDL}#{ENDL}" + end + + end + + class BBSTag < LanguageElement + + @tag = TAG_BBS + + def initialize + super + attr.declare(ATTR_XMLNS) + attr.declare(ATTR_XMLNS_XSI) + attr.declare(ATTR_XSI_SCHEMALOCATION) + attr.declare(ATTR_ID, NamespaceSymbol) + attr.declare(ATTR_TITLE) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def valid_child le + return BBTag == le.class + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out > "namespace #{cc.bc[ATTR_ID]}(\"#{attr[ATTR_TITLE]}\") {#{ENDL}#{ENDL}" + generate_children_code(cc, out) + out < "}#{ENDL}#{ENDL}" + end + end + + class BBTag < LanguageElement + + @tag = TAG_BB + + def initialize + super + attr.declare(ATTR_NAME, BasicBehaviorSymbol) + attr.declare(ATTR_DESCRIPTION, String, true) + end + + def valid_child le + return le.class == DParaTag || le.class == BParaTag || le.class == EParaTag + end + + def to_code(cc, out) + + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out > "#{TOKEN_BEHAVIOR} #{cc.bc[ATTR_NAME]} {#{ENDL}" + generate_children_code(cc, out) + out < "}#{ENDL}#{ENDL}" + end + end + + #TODO title, platform, software-environment tags + class AgentCollectionTag < LanguageElement + + @tag = TAG_AGENT_COLLECTION + attr_accessor :includes + attr_accessor :title + attr_accessor :platform + attr_accessor :software_environment + + def initialize + super + attr.declare(ATTR_XMLNS) + attr.declare(ATTR_XMLNS_XSI) + attr.declare(ATTR_XSI_SCHEMALOCATION) + attr.declare(ATTR_XMLNS_XI) + @includes = [] + end + + def to_code(cc, out) + unless @title.nil? || @platform.nil? || @software_environment.nil? + out > "/***#{ENDL}" + out % "Title: #{@title}#{ENDL}" unless @title.nil? + out % "Platform: #{@platform}#{ENDL}" unless @platform.nil? + out % "Software-Environment: #{@software_environment}#{ENDL}" unless @software_environment.nil? + out < "*/#{ENDL}#{ENDL}" + end + + @includes.each do |filename| + out % "include \"#{filename}\";#{ENDL}" + end + out << "#{ENDL}" unless @includes.empty? + + generate_children_code(cc, out) + end + + def valid_child le + return [AgentTag, OptionsTag, TitleTag, PlatformTag, SoftwareEnvironmentTag].include?(le.class) + end + + end + + class AgentTag < LanguageElement + + @tag = TAG_AGENT + + def initialize + super + attr.declare(ATTR_ID, AgentSymbol) + attr.declare(ATTR_TITLE) + attr.declare(ATTR_DESCRIPTION, String, true) + attr.declare(ATTR_ROOT_OPTION, OptionSymbol) + end + + def to_code(cc, out) + descr = attr[ATTR_DESCRIPTION] + out % "/** #{descr} */#{ENDL}" unless (descr.nil? || descr.empty?) + out % "#{TOKEN_AGENT} #{cc.bc[ATTR_ID]}(\"#{attr[ATTR_TITLE]}\", #{cc.bc[ATTR_ROOT_OPTION]});#{ENDL}" + out % "#{ENDL}" + end + end + + class OptionsTag < LanguageElement + @tag = TAG_OPTIONS + + def valid_child le + return le.class == XIncludeTag + end + + def to_xml(out) + out % "&options;#{ENDL}" + super + end + + def to_code(cc, out) + end + end + + class StringTag < LanguageElement + + attr_accessor :string + + def initialize(string = nil) + super() + @string = string + end + + def to_xml(out) + if @string.nil? || @string.empty? + out % "<#{tag}/>#{ENDL}" + else + out % "<#{tag}>#{@string}#{ENDL}" + end + end + + def to_code(cc, out) + end + end + + class TitleTag < StringTag + @tag = TAG_TITLE + + def text=(text) + @string = text + parent.title = text unless parent.nil? + end + + end + + class PlatformTag < StringTag + @tag = TAG_PLATFORM + + def text=(text) + @string = text + parent.platform = text unless parent.nil? + end + + + end + + class SoftwareEnvironmentTag < StringTag + @tag = TAG_SOFTWARE_ENVIRONMENT + + def text=(text) + @string = text + parent.software_environment = text unless parent.nil? + end + + + end + + class XIncludeTag < LanguageElement + @tag = TAG_XINCLUDE + + def initialize + super + attr.declare(ATTR_HREF) + end + end +end diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/compat.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/compat.rb new file mode 100644 index 00000000..09b5cefc --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/compat.rb @@ -0,0 +1,30 @@ +# +# compat.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/compiler.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/compiler.rb new file mode 100644 index 00000000..3cfc9871 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/compiler.rb @@ -0,0 +1,112 @@ +# +# compiler.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammar.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammar.rb new file mode 100644 index 00000000..f01e2ad1 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammar.rb @@ -0,0 +1,844 @@ +# +# grammar.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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, "'=' 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 + "" + 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 + "#" + 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 + '#' + 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammarfileparser.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammarfileparser.rb new file mode 100644 index 00000000..817b36aa --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammarfileparser.rb @@ -0,0 +1,521 @@ +# +# This file is automatically generated. DO NOT MODIFY!! +# +# grammerfileparser.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammarfilescanner.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammarfilescanner.rb new file mode 100644 index 00000000..c628864e --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/grammarfilescanner.rb @@ -0,0 +1,300 @@ +# +# grammarfilescanner.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/info.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/info.rb new file mode 100644 index 00000000..f78b8c92 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/info.rb @@ -0,0 +1,15 @@ +# +# info.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/iset.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/iset.rb new file mode 100644 index 00000000..fa0972f0 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/iset.rb @@ -0,0 +1,98 @@ +# +# iset.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/output.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/output.rb new file mode 100644 index 00000000..c2325e1b --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/output.rb @@ -0,0 +1,645 @@ +# +# output.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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(< %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(< 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 = < +# +# 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 ' ' + 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/racc b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/racc new file mode 100644 index 00000000..de8f1626 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/racc @@ -0,0 +1,631 @@ +#!/usr/bin/ruby +# +# racc +# +# Copyright (c) 1999-2002 Minero Aoki +# +# 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 = < file name of output [.tab.rb] +o -e --executable 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 use instead of Racc::Parser +x -r --runtime use instead of 'racc/parser' +o -a --no-omit-actions - never omit actions + +o -v --verbose - create .output file +o -O --log-file file name of verbose output [.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 - require instead of 'racc/libracc' +x -D - 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} " + 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(< + +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 < 1 + raise Racc::RaccError, + "'#{a.join %<' and '>}' used at same time; must be only one" + end + end + end + + + ### + ### embed + ### + + def embed( rbfile ) + @f.print < 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/rubyloader.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/rubyloader.rb new file mode 100644 index 00000000..8b7eace7 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/rubyloader.rb @@ -0,0 +1,55 @@ +# +# rubyloader.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/state.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/state.rb new file mode 100644 index 00000000..27f2c5fb --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/state.rb @@ -0,0 +1,985 @@ +# +# state.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 + '#' + 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 + "" + 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 + "" + 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 + "" + end + + def incref + @refn += 1 + end + + def decref + @refn -= 1 + bug! 'act.refn < 0' if @refn < 0 + end + + end + + + class Accept + + def inspect + "" + end + + end + + + class Error + + def inspect + "" + 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/usercodeparser.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/usercodeparser.rb new file mode 100644 index 00000000..022042c4 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/racc/usercodeparser.rb @@ -0,0 +1,40 @@ +# +# usercodeparser.rb +# +# Copyright (c) 1999-2003 Minero Aoki +# +# 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/symbol_table.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/symbol_table.rb new file mode 100644 index 00000000..959be025 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/symbol_table.rb @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/symbols.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/symbols.rb new file mode 100644 index 00000000..51e63ce7 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/symbols.rb @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/syntax_tree_builder.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/syntax_tree_builder.rb new file mode 100644 index 00000000..78637629 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/syntax_tree_builder.rb @@ -0,0 +1,1211 @@ +module Translator + + class SyntaxTreeBuilder < CompilerContextWorker + + def initialize + super(nil) + end + + def debug_val(val) + val.each_index do |i| + $stderr.puts "#{i} #{val[i]}" + end + exit + end + + def assume(val, expected) + + return unless PARANOIA + + val.each_index do |i| + v = val[i] + e = expected[i] + + unless expected[i].nil? + if v.class <= Token + if v.token_type != e + LOG.error "got token #{v.inspect}" + LOG.error "expected token type #{e.inspect}" + raise InternalError.new + end + elsif e.class <= Class + unless v.class <= e + LOG.error "got #{v.inspect}" + LOG.error "expected class #{e.name}" + raise InternalError.new + end + end + end + + end + end + + def compiler_context=(compiler_context) + @compiler_context = compiler_context + end + + def option val + end + + def option_early val + end + + def parameter_declaration val + end + + def state_declaration val + end + + def state_declaration_early val + end + + def subsequent_declaration_early val + end + + def subsequent_declaration val + end + + def output_symbol_assignment_early val + end + + def output_symbol_assignment val + end + + def exp_number(val) + end + + def exp_boolean(val) + end + + def exp_identifier val + end + + def decision_tree val + end + + def dtree val + end + + def gtree val + end + + def common_decision_tree val + end + + def common_action val + end + + def cdtree val + end + + def cdtree_elseif_decision val + end + + def transition val + end + + def exp_binary_early val + end + + def exp_binary val + end + + def set_parameter_early val + end + + def set_parameter val + end + + def with_parameter_early val + end + + def with_parameter val + end + + def comments val + end + + def function_early val + end + + def function val + end + + def conditional_expression val + end + + def exp_unary val + end + + def agent val + end + + def const val + end + + def symbol_declaration_early val + end + + def symbol_declaration val + end + + def enum_symbol_declaration val + end + + def behavior_declaration_early val + end + + def behavior_declaration val + end + + def namespace val + end + + def namespace_early val + end + + def include val + end + end + + class FirstPassSyntaxTreeBuilder < SyntaxTreeBuilder + + def initialize + super + end + + def include(val) + pc.includes << val[1].to_s + end + + def enum_symbol_declaration val + unless val[1].nil? || val[1].token_type == :FLOAT || val[1].token_type == :BOOL + symbol = cc.sc.from_code_declare(val[1], EnumSymbol) + else + error = SyntaxError.new(cc) + error.token = val[1] + eh.error error + end + end + end + + class SecondPassSyntaxTreeBuilder < SyntaxTreeBuilder + + def initialize + super + end + + def enum_symbol_declaration val + + unless val[1].nil? || val[1].token_type == :FLOAT || val[1].token_type == :BOOL + symbol = cc.sc.from_code(val[1], EnumSymbol) + end + + if [nil, :symbols].include?(pc.namespace_symbol.namespace_type) + pc.namespace_symbol.namespace_type = :symbols + else + eh.error NamespaceSeparation.new(cc, val[3], pc.namespace_symbol) + end + + tag = ETag.new + + tag.attr[ATTR_NAME] = symbol + tag.attr[ATTR_DESCRIPTION] = val[0].to_s unless val[0].nil? + + unless val[2].nil? + if val[2].token_type == :INTERNAL + tag.attr[ATTR_INTERNAL] = "true" + symbol.internal = true + else + error = SyntaxError.new(cc) + error.token = val[2] + eh.error error + end + end + + val[4].each do |token| + sub_tag = EnumTag.new + tag.add_child(sub_tag, cc) + sub_tag.attr[ATTR_NAME] = sc.from_code_declare(token, EnumSymbolValueSymbol, symbol, nil, true) + end + return tag + end + + def parameter_declaration val + + symbol = nil + if(!pc.option_symbol.nil?) + symbol = cc.sc.from_code_declare(val[2], OptionParameterSymbol, pc.option_symbol) + elsif(!pc.input_symbol.nil?) + symbol = cc.sc.from_code_declare(val[2], InputSymbolParameterSymbol, pc.input_symbol, nil, true) + elsif(!pc.behavior_symbol.nil?) + symbol = cc.sc.from_code_declare(val[2], BasicBehaviorParameterSymbol, pc.behavior_symbol, nil, true) + else + raise InternalError.new + end + + if val[1].nil? || val[1].token_type == :FLOAT + symbol.type = :decimal + tag = DParaTag.new + elsif val[1].token_type == :BOOL + symbol.type = :boolean + tag = BParaTag.new + else + symbol.type = :enum + symbol.enum_domain = cc.sc.from_code(val[1], EnumSymbol) + tag = EParaTag.new + tag.attr[ATTR_ENUM] = symbol.enum_domain + end + + tag.map_tokens val + + tag.attr[ATTR_DESCRIPTION] = val[0].to_s unless val[0].nil? + tag.attr[ATTR_NAME] = symbol + if symbol.type == :decimal + tag.attr[ATTR_RANGE] = val[3].to_s unless val[3].nil? + tag.attr[ATTR_MEASURE] = val[4].to_s unless val[4].nil? + else + unless val[3].nil? + error = SyntaxError.new(cc) + error.token = val[3] + error.message = "must not give range for boolean/enumerated parameter" + eh.error error + end + unless val[4].nil? + error = SyntaxError.new(cc) + error.token = val[4] + error.message = "must not give measure for boolean/enumerated parameter" + eh.error error + end + end + + return tag + end + + def option_early val + symbol = cc.sc.from_code_declare(val[-2], OptionSymbol) + + pc.option_symbol = symbol + pc.option_declared = true + symbol.namespace_symbol = OPTION_DEFINITIONS_ENTITY + end + + def option val + + odTag = ODTag.new + pc.option_definitions_temp.add_child(odTag, cc) + + odTag.attr[ATTR_DESCRIPTION] = val[0].to_s unless val[0].nil? + odTag.attr[ATTR_NAME] = pc.option_symbol + + #add ParaTags + val[5].each do |paraTag| + + odTag.add_child(paraTag, cc) + end + pc.option_symbol = nil + end + + def state_declaration_early val + sc.from_code_declare(val[-3], StateSymbol) + end + + def agent val + sc.from_code_declare(val[2], AgentSymbol) + pc.agent_declared = true + end + + def const val + + if [nil, :symbols].include?(pc.namespace_symbol.namespace_type) + pc.namespace_symbol.namespace_type = :symbols + else + eh.error NamespaceSeparation.new(cc, val[3], pc.namespace_symbol) + end + + symbol = sc.from_code_declare(val[3], ConstantSymbol) + tag = ConstantTag.new + tag.attr[ATTR_NAME] = symbol + tag.attr[ATTR_DESCRIPTION] = val[0].to_s unless val[0].nil? + tag.attr[ATTR_MEASURE] = val[7].to_s unless val[7].nil? + symbol.value = val[6].to_s + symbol.value = -symbol.value unless val[5].nil? + tag.attr[ATTR_VALUE] = symbol.value + return tag + end + + def symbol_declaration_early val + if val[-5].nil? || val[-5].token_type == :FLOAT + if val[-4].nil? || val[-4].token_type == :INPUT + pc.input_symbol = cc.sc.from_code_declare(val[-3], DecimalInputSymbol) + elsif val[-4].token_type == :OUTPUT || val[-4].token_type == :INTERNAL + pc.input_symbol = cc.sc.from_code_declare(val[-3], DecimalOutputSymbol) + else + raise InternalError.new + end + elsif val[-5].token_type == :BOOL + if val[-4].nil? || val[-4].token_type == :INPUT + pc.input_symbol = cc.sc.from_code_declare(val[-3], BooleanInputSymbol) + elsif val[-4].token_type == :OUTPUT || val[-4].token_type == :INTERNAL + pc.input_symbol = cc.sc.from_code_declare(val[-3], BooleanOutputSymbol) + else + raise InternalError.new + end + else + if val[-4].nil? || val[-4].token_type == :INPUT + pc.input_symbol = cc.sc.from_code_declare(val[-3], EnumInputSymbol) + elsif val[-4].token_type == :OUTPUT || val[-4].token_type == :INTERNAL + pc.input_symbol = cc.sc.from_code_declare(val[-3], EnumOutputSymbol) + else + raise InternalError.new + end + end + + if [nil, :symbols].include?(pc.namespace_symbol.namespace_type) + pc.namespace_symbol.namespace_type = :symbols + else + eh.error NamespaceSeparation.new(cc, val[-3], pc.namespace_symbol) + end + end + + def symbol_declaration val + tag = nil + if val[1].nil? || val[1].token_type == :FLOAT + if val[2].nil? || val[2].token_type == :INPUT + tag = DISTag.new + elsif val[2].token_type == :OUTPUT || val[2].token_type == :INTERNAL + tag = DOSTag.new + else + raise InternalError.new + end + symbol = pc.input_symbol + tag.attr[ATTR_RANGE] = val[4].to_s unless val[4].nil? + tag.attr[ATTR_MEASURE] = val[5].to_s unless val[5].nil? + pc.input_symbol = nil + elsif val[1].token_type == :BOOL + if val[2].nil? || val[2].token_type == :INPUT + tag = BISTag.new + elsif val[2].token_type == :OUTPUT || val[2].token_type == :INTERNAL + tag = BOSTag.new + else + raise InternalError.new + end + unless val[4].nil? + error = SyntaxError.new(cc) + error.token = val[4] + error.message = "must not give range for boolean symbol" + eh.error error + end + unless val[5].nil? + error = SyntaxError.new(cc) + error.token = val[5] + error.message = "must not give measure for boolean symbol" + eh.error error + end + symbol = pc.input_symbol + pc.input_symbol = nil + else + if val[2].nil? || val[2].token_type == :INPUT + tag = EISTag.new + elsif val[2].token_type == :OUTPUT || val[2].token_type == :INTERNAL + tag = EOSTag.new + else + raise InternalError.new + end + unless val[4].nil? + error = SyntaxError.new(cc) + error.token = val[4] + error.message = "must not give measure for enumerated symbol" + eh.error error + end + unless val[5].nil? + error = SyntaxError.new(cc) + error.token = val[5] + error.message = "must not give range for enumerated symbol" + eh.error error + end + symbol = pc.input_symbol + symbol.enum_domain = cc.sc.from_code(val[1], EnumSymbol) + tag.attr[ATTR_ENUM] = symbol.enum_domain + pc.input_symbol = nil + end + tag.attr[ATTR_NAME] = symbol + + if val[2].token_type == :INTERNAL + tag.attr[ATTR_INTERNAL] = "true" + symbol.internal = true + end + + unless val[7].nil? + if val[2].token_type == :INPUT + val[7].each do |sub_tag| + tag.add_child(sub_tag, cc) + end + else + error = SyntaxError.new(cc) + error.token = val[7] + eh.error error + end + end + tag.attr[ATTR_DESCRIPTION] = val[0].to_s unless val[0].nil? + return tag + end + + def namespace_early val + pc.namespace_symbol = cc.sc.from_code_declare(val[-5], NamespaceSymbol) + pc.namespace_declared = true + end + + def namespace val + tag = nil + dir = "" + case pc.namespace_symbol.namespace_type + when :symbols + tag = SymbolsTag.new + dir = "Symbols" + #tag.attr[ATTR_XSI_SCHEMALOCATION] = "http://www.xabsl.de" + when :behaviors + tag = BBSTag.new + dir = "BasicBehaviors" + #tag.attr[ATTR_XSI_SCHEMALOCATION] = "http://www.xabsl.de" + when nil + eh.error EmptyNamespaceWarning.new(cc, val[2]) + else + raise InternalError.new + end + + unless tag.nil? + tag.attr[ATTR_ID] = pc.namespace_symbol + tag.attr[ATTR_TITLE] = val[4].to_s + tag.attr[ATTR_DESCRIPTION] = val[0].to_s unless val[0].nil? + tag.attr[ATTR_XMLNS] = 'http://www.xabsl.de' + tag.attr[ATTR_XMLNS_XSI] = 'http://www.w3.org/2001/XMLSchema-instance' + + #inner namespace thingies + val[8].each do |sub_tag| + tag.add_child(sub_tag, cc) + end + + pc.namespace_root.add_child(tag, cc) + end + + if pc.namespace_symbol.identifier != File.basename(cc.cu.src_filename).sub(/\..*?$/, '') + eh.error NamingWarning.new(cc, val[2]) + end + if cc.cu.dest_filename =~ /^.*(\..*)$/ + ext = $1 + else + ext = ".xml" + end + cc.cu.set_dest(dir, pc.namespace_symbol.identifier + ext) + + pc.namespace_symbol = nil + end + + def behavior_declaration_early val + pc.behavior_symbol = cc.sc.from_code_declare(val[-2], BasicBehaviorSymbol) + if [nil, :behaviors].include?(pc.namespace_symbol.namespace_type) + pc.namespace_symbol.namespace_type = :behaviors + else + eh.error NamespaceSeparation.new(cc, val[-2], pc.namespace_symbol) + end + end + + def behavior_declaration val + + tag = BBTag.new + tag.attr[ATTR_NAME] = pc.behavior_symbol + tag.attr[ATTR_DESCRIPTION] = val[0].to_s unless val[0].nil? + + val[5].each do |sub_tag| + tag.add_child(sub_tag, cc) + end + + pc.behavior_symbol = nil + return tag + end + end + + class ThirdPassSyntaxTreeBuilder < SyntaxTreeBuilder + + def initialize + super + end + + + def comments val + if pc.agent_declared + agent_collection_tag = pc.agent_collection_root.child(AgentCollectionTag) + agent_collection_tag.title = $1.to_s if val[0].to_s =~ /Title:\s*(.*?)\s*$/i + agent_collection_tag.platform = $1.to_s if val[0].to_s =~ /Platform:\s*(.*?)\s*$/i + agent_collection_tag.software_environment = $1.to_s if val[0].to_s =~ /Software-Environment:\s*(.*?)\s*$/i + end + end + + + def option_early val + pc.option_symbol = cc.sc.from_code(val[-2], OptionSymbol) + end + + def option val + + oTag = OptionTag.new + pc.option_root.add_child(oTag, cc) + + oTag.attr[ATTR_NAME] = pc.option_symbol + oTag.attr[ATTR_XMLNS] = 'http://www.xabsl.de' + oTag.attr[ATTR_XMLNS_XSI] = 'http://www.w3.org/2001/XMLSchema-instance' + #oTag.attr[ATTR_XSI_SCHEMALOCATION] = "http://www.xabsl.de" + + #common decision tree/action + unless val[6].nil? + val[6].each { |cTag| + oTag.add_child(cTag, cc) + } + end + + #set initial state from cc + if pc.initial_state_symbol.nil? + cc.eh.error InitialStateMissing.new(cc, val[2]) + pc.initial_state_symbol = st.declare('__initial', StateSymbol); + else + oTag.attr[ATTR_INITIAL_STATE] = pc.initial_state_symbol + end + + #add StateTags + val[7].each { |stateTag| + oTag.add_child(stateTag, cc) + } + + if pc.option_symbol.identifier != File.basename(cc.cu.src_filename).sub(/\..*?$/, '') + eh.error NamingWarning.new(cc, val[2]) + end + if cc.cu.dest_filename =~ /^.*(\..*)$/ + ext = $1 + else + ext = ".xml" + end + cc.cu.set_dest("Options", pc.option_symbol.identifier + ext) + + pc.option_symbol = nil + pc.initial_state_symbol = nil + end + + def parameter_declaration val + return nil + end + + def state_declaration_early val + pc.state_symbol = cc.sc.from_code(val[-3], StateSymbol) + end + + + def state_declaration val + + tag = StateTag.new + + #initial + unless val[0].nil? + unless pc.initial_state_symbol.nil? + cc.eh.error InitialStateMultipleDefinition.new(cc, val[3]) + end + pc.initial_state_symbol = pc.state_symbol + end + + #target + tag.attr[ATTR_IS_TARGET_STATE] = "true" unless val[1].nil? + tag.attr[ATTR_NAME] = pc.state_symbol + + unless val[4].nil? + if val[4][0].token_type == :CAPACITY + tag.attr[ATTR_CAPACITY] = val[4][1].to_s + elsif val[4][0].token_type == :SYNCHRONIZED + tag.attr[ATTR_SYNCHRONIZED] = (val[4][1].nil?) ? "0" : val[4][1].to_s + end + end + + #SO / SBB / output symbol decls + val[10].each { |sosTag| + tag.add_child(sosTag, cc) + } + + #decisiton tree + tag.add_child(val[7], cc) + pc.state_symbol = nil + + return tag + end + + def subsequent_declaration_early val + raise InternalError.new unless pc.subsequent_dpc.nil? + raise InternalError.new unless pc.subsequent_type.nil? + + symbols = nil + if val[-2].nil? + symbols = [OptionSymbol, BasicBehaviorSymbol] + elsif val[-2].token_type == :OPTION + symbols = [OptionSymbol] + elsif val[-2].token_type == :BEHAVIOR + symbols = [BasicBehaviorSymbol] + else + raise InternalError.new + end + + symbol = cc.sc.from_code(val[-3], symbols) + case symbol + when OptionSymbol: + pc.set_subsequent(DomainParameterContext.new(symbol, cc), :option) + when BasicBehaviorSymbol: + pc.set_subsequent(DomainParameterContext.new(symbol, cc), :behavior) + else + raise InternalError.new + end + end + + + def subsequent_declaration val + tag = nil + symbol = nil + + case pc.subsequent_type + when :option + tag = SOTag.new + symbol = cc.sc.from_code(val[0], OptionSymbol) + + when :behavior + tag = SBBTag.new + symbol = cc.sc.from_code(val[0], BasicBehaviorSymbol) + else + raise InternalError.new + end + + pc.subsequent_dpc.check_used_value_symbols(val[0]) + + tag.attr[ATTR_REF] = symbol + + #parameters + val[4].each { |aTag| + tag.add_child(aTag, cc) + } + + pc.set_subsequent(nil, nil) + return tag + end + + def set_parameter_early val + case pc.subsequent_type + when :option + symbol = cc.sc.from_code(val[-1], OptionParameterSymbol, pc.subsequent_dpc.domain_symbol) + when :behavior + symbol = cc.sc.from_code(val[-1], BasicBehaviorParameterSymbol, pc.subsequent_dpc.domain_symbol) + else + raise InternalError.new + end + pc.enum_domains.push(symbol.enum_domain) if symbol.type == :enum + end + + def set_parameter val + symbol = nil + case pc.subsequent_type + when :option + symbol = cc.sc.from_code(val[0], OptionParameterSymbol, pc.subsequent_dpc.domain_symbol) + when :behavior + symbol = cc.sc.from_code(val[0], BasicBehaviorParameterSymbol, pc.subsequent_dpc.domain_symbol) + else + raise InternalError.new + end + + pc.enum_domains.pop if symbol.type == :enum + pc.subsequent_dpc.use_value_symbol(symbol, val[0]) + + tag = SPTag.new + tag.map_tokens val + + tag.attr[ATTR_REF] = symbol + tag.in_type = symbol.type + tag.add_child(val[3], cc) + return tag + end + + def with_parameter_early val + symbol = cc.sc.from_code(val[-1], InputSymbolParameterSymbol, pc.function_dpcs.last.domain_symbol) + pc.enum_domains.push(symbol.enum_domain) if symbol.type == :enum + end + + def with_parameter val + tag = WPTag.new + + domain_context = pc.function_dpcs.last + symbol = cc.sc.from_code(val[0], InputSymbolParameterSymbol, domain_context.domain_symbol) + pc.enum_domains.pop if symbol.type == :enum + domain_context.use_value_symbol(symbol, val[0]) + tag.attr[ATTR_REF] = symbol + tag.in_type = symbol.type + tag.add_child(val[3], cc) + return tag + end + + def conditional_expression val + tag = CETag.new + tag.map_tokens val + cond_tag = CondTag.new + ex1_tag = EX1Tag.new + ex1_tag.map_tokens [val[2]] + ex2_tag = EX2Tag.new + ex2_tag.map_tokens [val[4]] + + cond_tag.add_child(val[0], cc) + ex1_tag.add_child(val[2], cc) + ex2_tag.add_child(val[4], cc) + + tag.out_type = ex1_tag.in_type + + tag.add_child(cond_tag, cc) + tag.add_child(ex1_tag, cc) + tag.add_child(ex2_tag, cc) + + if tag.out_type == :enum + #domain checking + cc.eh.error MismatchingDomain.new(cc, val[3]) unless val[2].enum_domain == val[4].enum_domain + tag.enum_domain = val[4].enum_domain + end + + return tag + end + + def output_symbol_assignment_early val + symbol = cc.sc.from_code(val[-1], [DecimalOutputSymbol, BooleanOutputSymbol, EnumOutputSymbol]) + pc.enum_domains.push(symbol.enum_domain) if symbol.class == EnumOutputSymbol + end + + def output_symbol_assignment val + + symbol = cc.sc.from_code(val[0], [DecimalOutputSymbol, BooleanOutputSymbol, EnumOutputSymbol]) + + case symbol #the tag that defined the symbol name + when DecimalOutputSymbol: + tag = SDOSTag.new + when BooleanOutputSymbol: + tag = SBOSTag.new + when EnumOutputSymbol: + pc.enum_domains.pop + #domain checking + cc.eh.error MismatchingDomain.new(cc, val[2]) unless val[3].out_type == :enum && symbol.enum_domain == val[3].enum_domain + tag = SEOSTag.new + end + + tag.attr[ATTR_REF] = symbol + tag.add_child(val[3], cc) + return tag + end + + def exp_number(val) + tag = DVTag.new + tag.map_tokens val + + tag.attr[ATTR_VALUE] = val[0].to_s + + return tag + end + + def exp_boolean(val) + tag = BVTag.new + tag.map_tokens val + + tag.attr[ATTR_VALUE] = val[0].to_s + + return tag + end + + def decision_tree val + tag = DTTag.new + + #if no decision tree is given, build one for decision-tree{tts(self);} + if val[0].nil? + tts_tag = TTSTag.new + tts_tag.attr[ATTR_REF] = pc.state_symbol + tag.add_child(tts_tag, cc) + + else + # starting with else + if (val.size == 6) + cc.eh.error DecisionTreeMustNotStartWithElse.new(cc, val[0]) unless pc.has_common_decision_tree + + # description comment for first if can be before starting else + # belatedly add description to correct tag + ifTag = val[-2][0] + unless val[2].nil? || ifTag.class != IfTag + raise InternalError.new unless ifTag.children[0].class == CondTag + ifTag.children[0].attr[ATTR_DESCRIPTION] = val[2].to_s + end + else + cc.eh.error DecisionTreeMustStartWithElse.new(cc, val[0]) if pc.has_common_decision_tree + end + + #if/else + val[-2].each { |aTag| + tag.add_child(aTag, cc) + } + end + + return tag + end + + def dtree val + + ifTag = IfTag.new + tags = [ifTag] + + condTag = CondTag.new + condTag.map_tokens val + condTag.attr[ATTR_DESCRIPTION] = val[0].to_s # nil.to_s = "" --> always generate a description tag + + ifTag.add_child(condTag, cc) + condTag.add_child(val[3],cc) + + #dtree or transition + val[5].each { |aTag| + ifTag.add_child(aTag, cc) + } + + #else + + # description comment for first if after else can be before else + # belatedly add description to correct tag + ifTag = val[8][0] + unless val[6].nil? || ifTag.class != IfTag + raise InternalError.new unless ifTag.children[0].class == CondTag + ifTag.children[0].attr[ATTR_DESCRIPTION] = val[6].to_s + end + + elseTag = ElseTag.new + val[8].each { |aTag| + elseTag.add_child(aTag, cc) + } + tags << elseTag + return tags + end + + def common_decision_tree val + tag = CDTTag.new + tag.map_tokens val[1..1] + pc.has_common_decision_tree = true + + #if/else + val[1].each { |aTag| + tag.add_child(aTag, cc) + } + + return tag + end + + def common_action val + + tag = CommonActionTag.new + + #SO / SBB / output symbol decls + val[1].each { |sosTag| + tag.add_child(sosTag, cc) + } + + return tag + end + + def cdtree val + + ifTag = IfTag.new + ifTag.map_tokens val + tags = [ifTag] + + condTag = CondTag.new + condTag.map_tokens val + condTag.attr[ATTR_DESCRIPTION] = val[0].to_s # nil.to_s = "" --> always generate a description tag + + ifTag.add_child(condTag, cc) + condTag.add_child(val[3], cc) + + #cdtree or transition + val[5].each { |aTag| + ifTag.add_child(aTag, cc) + } + + tags << val[6] unless val[6].nil? + + return tags + end + + def cdtree_elseif_decision val + tag = ElseTag.new + tag.map_tokens val + + # description comment for first if after else can be before else + # belatedly add description to correct tag + ifTag = val[2][0] + unless val[0].nil? || ifTag.class != IfTag + raise InternalError.new unless ifTag.children[0].class == CondTag + ifTag.children[0].attr[ATTR_DESCRIPTION] = val[0].to_s + end + + val[2].each {|aTag| + tag.add_child(aTag, cc) + } + + return tag + end + + def transition val + + tag = TTSTag.new + tag.map_tokens val + + case val[0].token_type + when :TTS + tag.attr[ATTR_REF] = cc.sc.from_code(val[1], StateSymbol) + when :STAY #transition to current state symbol + tag.attr[ATTR_REF] = pc.state_symbol + else + raise InternalError.new + end + + return tag + end + + def exp_unary val + + tag = nil + case val[0].to_s + when '!' + tag = NotTag.new + tag.map_tokens val + when '-' #translate -(...) --> 0-(...) + + #shortcut for -(5) --> -5 + if val[1].class <= DVTag + tag = val[1] + tag.map_tokens val + tag.attr[ATTR_VALUE] = (-(tag.attr[ATTR_VALUE].to_f)).to_s + return tag + end + + dv_tag = DVTag.new + dv_tag.attr[ATTR_VALUE] = '0' + + dv_tag.map_tokens val + + tag = MinusTag.new + tag.map_tokens val + tag.add_child(dv_tag, cc) + else + raise InternalError.new("unary handler missing for #{val[0].to_s}") + end + + tag.add_child(val[1], cc) + + return tag + end + + def exp_binary_early val + if val[-1].to_s == '==' || val[-1].to_s == '!=' + if val[-2].out_type == :enum + pc.enum_domains.push(val[-2].attr[ATTR_REF].enum_domain) + end + end + end + + def exp_binary val + tag = nil + case val[1].to_s + when '*' + tag = MPLTag.new + when '/' + tag = DIVTag.new + when '%' + tag = MODTag.new + when '+' + tag = PlusTag.new + when '-' + tag = MinusTag.new + when '>' + tag = GTTag.new + when '<' + tag = LTTag.new + when '<=' + tag = LTEQTag.new + when '>=' + tag = GTEQTag.new + when '==', '!=' + if val[0].out_type == :enum + pc.enum_domains.pop + end + if (val[0].out_type == :enum && val[3].out_type == :enum) + + #domain check + cc.eh.error MismatchingDomain.new(cc, val[1]) unless val[0].enum_domain == val[3].enum_domain + + tag = EISCTag.new + tag.map_tokens val + + tag.add_child(val[0], cc) + tag.add_child(val[3], cc) + + if val[1].to_s == '!=' + not_tag = NotTag.new + not_tag.map_tokens val + not_tag.add_child(tag, cc) + + return not_tag + + end + + return tag + end + + if val[1].to_s == '!=' + tag = NEQTag.new + elsif val[1].to_s == '==' + tag = EQTag.new + end + + when '&&' + tag = AndTag.new + when '||' + tag = OrTag.new + else + raise InternalError.new("binary missing for #{val[1].to_s}") + end + + tag.map_tokens val + unless tag.in_type == val[0].out_type && tag.in_type == val[3].out_type + cc.eh.error TypeMismatch.new(cc, val[1]) + end + + # flatten trees on identical, associative tag classes + # this is only allowed on "and" and "or" operators as they have a variable parameter count in intermediate code + #if tag.associative + case tag + when OrTag, AndTag: + [0,3].each {|i| + child = val[i] + if(tag.class == child.class) + copy = Array.new(child.children) + copy.each {|grandchild| + child.remove_child grandchild + tag.add_child(grandchild, cc) + } + + else + tag.add_child(child, cc) + end + } + else + tag.add_child(val[0], cc) + tag.add_child(val[3], cc) + end + + return tag + end + + def exp_identifier val + + if pc.enum_domains.last.nil? + symbol = cc.sc.from_code(val[0], [ConstantSymbol, OptionParameterSymbol, DecimalInputSymbol, BooleanInputSymbol, EnumInputSymbol, DecimalOutputSymbol, BooleanOutputSymbol, EnumOutputSymbol]) + else + symbol = cc.sc.from_code(val[0], [EnumSymbolValueSymbol], pc.enum_domains.last) do + cc.sc.from_code(val[0], [ConstantSymbol, OptionParameterSymbol, DecimalInputSymbol, BooleanInputSymbol, EnumInputSymbol, DecimalOutputSymbol, BooleanOutputSymbol, EnumOutputSymbol]) + end + end + tag = nil + + case symbol #the tag that defined the symbol name + when DecimalInputSymbol: + tag = DISRTag.new + tag.attr[ATTR_REF] = symbol + when BooleanInputSymbol: + tag = BISRTag.new + tag.attr[ATTR_REF] = symbol + when EnumInputSymbol: + tag = EISRTag.new + tag.attr[ATTR_REF] = symbol + tag.enum_domain = symbol.enum_domain + when DecimalOutputSymbol: + tag = DOSRTag.new + tag.attr[ATTR_REF] = symbol + when BooleanOutputSymbol: + tag = BOSRTag.new + tag.attr[ATTR_REF] = symbol + when EnumOutputSymbol: + tag = EOSRTag.new + tag.attr[ATTR_REF] = symbol + tag.enum_domain = symbol.enum_domain + when ConstantSymbol: + tag = CRTag.new + tag.attr[ATTR_REF] = symbol + when OptionParameterSymbol: + tag = OPRTag.new + tag.attr[ATTR_REF] = symbol + tag.out_type = symbol.type + if symbol.type == :enum + tag.enum_domain = symbol.enum_domain + end + when EnumSymbolValueSymbol: + tag = EVTag.new + tag.attr[ATTR_REF] = symbol + tag.enum_domain = symbol.enum_domain + else + raise InternalError.new + end + + tag.map_tokens val + + return tag + end + + def function_early val + pc.function_dpcs.push(DomainParameterContext.new(cc.sc.from_code(val[-1], [DecimalInputSymbol, BooleanInputSymbol, EnumInputSymbol]), cc)) + pc.enum_domains.push(nil) + end + + def function val + pc.enum_domains.pop + case pc.function_dpcs.last.domain_symbol + when DecimalInputSymbol: + tag = DISRTag.new + when BooleanInputSymbol: + tag = BISRTag.new + when EnumInputSymbol: + tag = EISRTag.new + tag.enum_domain = pc.function_dpcs.last.domain_symbol.enum_domain + else + raise InternalError.new + end + + tag.map_tokens val + tag.attr[ATTR_REF] = pc.function_dpcs.last.domain_symbol + + #parameter + val[3].each { |aTag| + tag.add_child(aTag, cc) + } + fc = pc.function_dpcs.pop + fc.check_used_value_symbols(val[0]) + + return tag + end + + def agent(val) + assume(val, [:DOC_COMMENT, :AGENT, :IDENTIFIER, nil, :STRING, nil, :IDENTIFIER]) + + agentTag = AgentTag.new + agentTag.map_tokens val + + agentTag.attr[ATTR_DESCRIPTION] = val[0].to_s unless val[0].nil? + agentTag.attr[ATTR_ID] = cc.sc.from_code(val[2], AgentSymbol) + agentTag.attr[ATTR_TITLE] = val[4].to_s + agentTag.attr[ATTR_ROOT_OPTION] = cc.sc.from_code(val[6], OptionSymbol) + + pc.agent_collection_root.child(AgentCollectionTag).add_child(agentTag, cc) + + end + + end +end diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/tokenizer.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/tokenizer.rb new file mode 100644 index 00000000..386e017e --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/tokenizer.rb @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/translator.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/translator.rb new file mode 100644 index 00000000..a0d5bed4 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/translator.rb @@ -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' diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/translator_base.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/translator_base.rb new file mode 100644 index 00000000..ca3a7bce --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/translator_base.rb @@ -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 \ No newline at end of file diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/vcproj.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/vcproj.rb new file mode 100644 index 00000000..49652d2d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/vcproj.rb @@ -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 << "\r\n" + out << "\r\n" + + when :folder + + unless name.nil? + out << "\r\n" + end + children.each do |child| + child.print(out) + end + out << "\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 \ No newline at end of file diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xabsl.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xabsl.rb new file mode 100644 index 00000000..89e7ab31 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xabsl.rb @@ -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 = "" + 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 = "" << 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 = "" + + #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 ") 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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xabsl_parser.y.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xabsl_parser.y.rb new file mode 100644 index 00000000..b1e2da08 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xabsl_parser.y.rb @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xml_parser.rb b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xml_parser.rb new file mode 100644 index 00000000..c7691557 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/compiler/xml_parser.rb @@ -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 =~ // + 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 "" + + 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 "" + end + end +end diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/documentation.css b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/documentation.css new file mode 100644 index 00000000..220858b7 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/documentation.css @@ -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; +} diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-debug-symbols.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-debug-symbols.xsl new file mode 100644 index 00000000..05945f03 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-debug-symbols.xsl @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + // Debug Symbols for the agents of + + + + // number of enumerations + + + + // enumerations + + // (name number-of-elements (element)*)+ + + + + + // number of input symbols + + + + // input symbols + + // (d decimal-input-symbol | b boolean-input-symbol | e enum-name enumerated-input-symbol)+ + + + + + // number of output symbols + + + + // output symbols + + // (d decimal-output-symbol | b boolean-output-symbol | e enum-name enumerated-output-symbol)+ + + + + + // number of options + + + + //options: (name num-of-parameters (d decimal-parameter | b boolean_parameter | e enum-name enumerated-parameter)*)+ + + + + + // number of basic behaviors + + + + //basic behaviors: (name num-of-parameters (d decimal-parameter | b boolean_parameter | e enum-name enumerated-parameter)*)+ + + + + + + + + + + + + + + + + d + + + + + + b + + + + + + e + + + + + + + + + + + + + + + + + + + + d + + + + + + + + + b + + + + + + + + + e + + + + + + + + + + + d + + + + + + + + + b + + + + + + + + + e + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.agents.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.agents.xsl new file mode 100644 index 00000000..720106db --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.agents.xsl @@ -0,0 +1,55 @@ + + + + + + + + + + XABSL Behavior Documentation: Agents + + + + + + + + + + +
+

Agents

+ +
+ + +
+ +

+ +

+

+ +

+

Option Graph:
+ + svg/agent_ + + + + + +

+
+
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.basic-behavior-index.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.basic-behavior-index.xsl new file mode 100644 index 00000000..1878f096 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.basic-behavior-index.xsl @@ -0,0 +1,66 @@ + + + + + + + + + XABSL Behavior Documentation: Basic Behaviors + + + + + + + + + + +
+

Basic Behaviors

+ + + + + + + + + + + + +
+

 

+ +

+ +

+
+

+ +

+

+

+ + + + + +
+
+ + +
+
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.basic-behaviors.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.basic-behaviors.xsl new file mode 100644 index 00000000..dd5fe530 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.basic-behaviors.xsl @@ -0,0 +1,49 @@ + + + + + + + + + XABSL Behavior Documentation: <xsl:value-of select="@title"/> + + + + + + + + + + + +
+

+ +

+

+ +

+ +

Basic Behavior ""

+

+ +

+ +
+
+ + +
+
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.index.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.index.xsl new file mode 100644 index 00000000..71ca02bf --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.index.xsl @@ -0,0 +1,72 @@ + + + + + + + + XABSL Behavior Documentation: <xsl:value-of select="xabsl:title"/> + + + + + + + + + + + +
+

+ : Behavior Documentation

+

+

Platform:
+ +

+

+

Software Environment:
+ +

+

Table Of Contents

+ + + + + + + + + + + + + + + + + +
+ Agents + All agents of +
+ Symbols + The symbols needed to run the behavior in the software environment
+ Basic Behaviors + C++ written behaviors at the leaves of the option tree.
+ Options + All options of all agents.
+
+ + +
+
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.menu.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.menu.xsl new file mode 100644 index 00000000..3a9de138 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.menu.xsl @@ -0,0 +1,283 @@ + + + + + + + >xabsl + + + + Behavior Documentation + + + + + + >Agents + + + + + + >Agents + + + + + +
>Index + + +
+ + + +
>Index + +
+ + + + >Symbols + + + + + + >Symbols + + + + + + >Basic Behaviors + + + + + + >Basic Behaviors + + + + + + >Options + + + + + + >Options + + + + + + +    >>   + + + + + + + +         >>>   + + + + + + + + + +    >>   + + + + + +         >>>   + + + + + + + + + + +    >>   + + + + + + + + + + +    >>   + + + + + + + + + + +    >>   + + + + + + + + +    >>   + + + + +         >>>  Input Symbols + + + + + +         >>>  Input Functions + + + + + +         >>>  Output Symbols + + + + + +         >>>  Constants + + + + + + + + +    >>   + + + + + +         >>>   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
>xabsl 2
Behavior Documentation
+ + + +
+ + + +
+ + + +
+ + + +
+
+
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option-index.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option-index.xsl new file mode 100644 index 00000000..07ca6abc --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option-index.xsl @@ -0,0 +1,60 @@ + + + + + + + + + + XABSL Behavior Documentation: Options + + + + + + + + + + +
+

Options

+ + + + + + + + +
+ + + + + +
+

Option Graph:
+ + svg/options + + + + +

+
+ + +
+
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option-tree.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option-tree.xsl new file mode 100644 index 00000000..9e977e7a --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option-tree.xsl @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + option_ + _\n + + + + + + + + basic_behavior_ + _\n + + + + + + + + + option_ + option_ + + + + + option_ + basic_behavior_ + + + + + + + + + + + + + option_ + _\n + + + + + + basic_behavior_ + _\n + + + + + + + + + + + option_ + option_ + + + + + option_ + basic_behavior_ + + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option.xsl new file mode 100644 index 00000000..c9915a83 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.option.xsl @@ -0,0 +1,457 @@ + + + + + + + + + + + + + + + + + XABSL Behavior Documentation: Option <xsl:value-of select="@name"/> + + + + + + + + + + + +
+

Option +

+

+ +

+ + +

Parameters of that option: + +

+
+
+

State Machine

+ + + + + + + + + + + + + + + state_ + basic_behavior_ + + + + + + + + state_ + option_ + + + + + + state_ + basic_behavior_ + + + + + state_ + option_ + + + + + +
+ + +
+ + + +

State +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
This state is a target state.
+
+
This state is synchronized. All cooperating agents that are executing this option will enter it at once. + + Minimum number of agents required to enter the state is . + +

+
This state has a capacity of . + Only of the cooperating agents that are executing this option can enter it at the same time. +

+
If that state is active,
+  >  + + The option + + is executed. Parameters: +
+  >  + + The basic behavior + + is executed. Parameters: +
+  >  + This decimal output symbol is set:
   + + + +  =  + +
+  >  + This boolean output symbol is set:
   + + + +  =  + +
+  >  + This enumerated output symbol is set:
   + + + +  =  + +
   + + + + + + + + + + +  =  + ; +
 
The decision tree:
  + + svg/option__state_ + + + + + + + + + + + + state_ + _\n + Mcircledoublecirclecircle + + + + + + + + + + + start + + + + + + + + + start + + + + + + + + + +
 
Pseudo code of the decision tree:
  + + + + + + state__pseudo-code + + + + + + + + state__pseudo-code + + + + +
+
+ + + + + + + + + + Arial ItalicArial + 5 + option..html#state__pseudo-code_ + + + + + + _ + + + _ + 1 + + + + dashedsolid + Arial Bold ItalicArial Bold + + + + + dashedsolid + Arial Bold ItalicArial Bold + + + + + + _ + + + _ + 0 + + + + + + + _ + + + + _ + + 0 + + + + + + + dashedsolid + state_ + + + + + + + state_ + _\n + Mcircledoublecirclecircle + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + state_ + state_ + + + + + +
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.parameters.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.parameters.xsl new file mode 100644 index 00000000..cc761aab --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.parameters.xsl @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeMeasureRangeDescription
+ + decimal + + + + + +
+ + booleantrue/ false + + +
+ + enumerated + + + + +
+
+
+
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.pseudo-code.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.pseudo-code.xsl new file mode 100644 index 00000000..4d3c1799 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.pseudo-code.xsl @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + + common-pseudo-code-framepseudo-code-frame + + + +
+ + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + /** */ + +
+
+ + + + + + + + + + + + +
+ + if + else if +  ( + )
+
+ + + + +
{
+
+ + + + + +
   + + + + + _ + + +
+
+
+ + + + +
}
+
+ + + + + + + + + + + + + + + + + + + +
+ + + + +
+ else +
+
+ + + + +
{
+
+ + + + + +
   + + + + _ + + +
+
+ + + + +
}
+
+ + +
+
+ + + + + + + + + + + + + + + + + + +
+ + + + +
+ else +
+
+ + + + +
{
+
+ + + + + +
   + + + + _ + +
+
+
+ + + + +
}
+
+ + +
+ + + + + + stay; + + + goto + + ; + + + + + + + + + + + + + + + + +
+ + + + + + + + +
()
+
+ + + + + +
+ + ||  + &&  + + + + + + + + +
()
+
+
+
+ + + + + + + + + +
!()
+
+ + + + + == + != + < + < + > + >= + == + + + + + ( + + + + + - + * + / + % + + ) + + + + + ( + + + , + + ) + + + + + ( + + + , + + ) + + + + + ( + + + , + + ) + + + + + + + + + + + + + + + + + + + + + + ( + + ? + + : + + ) + + + @ + + + + + + + + + + + + + action_done + state_time + option_time + + + +
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.string-functions.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.string-functions.xsl new file mode 100644 index 00000000..6acb1896 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.string-functions.xsl @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \n + + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.symbols-index.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.symbols-index.xsl new file mode 100644 index 00000000..dd8c1579 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.symbols-index.xsl @@ -0,0 +1,65 @@ + + + + + + + + + XABSL Behavior Documentation: Symbols + + + + + + + + + + +
+

Symbols

+ + + + + + + + + + +
+
+ + + +
+
+ +
+
+ +
 
+
+ + +
+
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.symbols.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.symbols.xsl new file mode 100644 index 00000000..a420433d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/generate-documentation.symbols.xsl @@ -0,0 +1,238 @@ + + + + + + + + + XABSL Behavior Documentation: <xsl:value-of select="@title"/> + + + + + + + + + + + +
+

+ +

+

+ +

+

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.

+ +

Enumerations

+ + + + + + + + +
NameElementsInternalDescription
+
+ + +

Input Symbols

+ + + + + + + + +
NameTypeMeasureDescription / Parameters
+ + + +

Output Symbols

+ + + + + + + + + +
NameTypeMeasureInternalDescription
+ +
+ +

Constants

+ + + + + + + + +
NameValueMeasureDescription
+ +
+
+ + +
+ + + + + + + + +
+
+ + + + + + + + +
+ + + + + + decimal + + + + + + + + +   + + + + + + + + + + + boolean + true/ false + + + + + +   + + + + + + + + + + + decimal + + + + + + + + + + + + + + + + + boolean + true/ false + + + + + + + + + + + + + + enumerated + + + + + + + + +   + + + + + + + + + + + enumerated + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/remove-comments.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/remove-comments.xsl new file mode 100644 index 00000000..215d6d8e --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/Xabsl/xsl/remove-comments.xsl @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/MyBasicBehaviors.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/MyBasicBehaviors.cpp new file mode 100644 index 00000000..d28019f3 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/MyBasicBehaviors.cpp @@ -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= 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; +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/MyBasicBehaviors.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/MyBasicBehaviors.h new file mode 100644 index 00000000..b1024a75 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/MyBasicBehaviors.h @@ -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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/Tools.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/Tools.h new file mode 100644 index 00000000..10a85dbf --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/Tools.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 +#include + +// 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_ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/WorldState.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/WorldState.cpp new file mode 100644 index 00000000..04e17c65 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/WorldState.cpp @@ -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=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=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; +} diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/WorldState.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/WorldState.h new file mode 100644 index 00000000..59c58859 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/WorldState.h @@ -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_ + + + + + + + + + + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/main.cpp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/main.cpp new file mode 100644 index 00000000..0e0daa6f --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/main.cpp @@ -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;igetBehavior()) + { + strcat(string,behavior->n); + strcat(string,"("); + + bool first=true; + for(i=0; igetParameters()->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; igetParameters()->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; igetParameters()->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& actions = + option->activeState->actions; + + for(i=0;i= ball.x()) { + goto own_team_has_ball; + } + else { + stay; + } + } + action { + go_to(x = ball.x() + 10, y = ball.y()); + } + } + +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/dribble.xabsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/dribble.xabsl new file mode 100644 index 00000000..5f2e112b --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/dribble.xabsl @@ -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(); + } + } + +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/midfielder.xabsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/midfielder.xabsl new file mode 100644 index 00000000..3b13c052 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/midfielder.xabsl @@ -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(); + } + } + +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/pass.xabsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/pass.xabsl new file mode 100644 index 00000000..b9cf62bb --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/pass.xabsl @@ -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; + } + } + +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/play-soccer.xabsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/play-soccer.xabsl new file mode 100644 index 00000000..8fc3976f --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/play-soccer.xabsl @@ -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(); + } + } +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/striker.xabsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/striker.xabsl new file mode 100644 index 00000000..5da4e722 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/Options/striker.xabsl @@ -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 + } + } + +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/agents.xabsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/agents.xabsl new file mode 100644 index 00000000..0e9909ef --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/agents.xabsl @@ -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); + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/my-basic-behaviors.xabsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/my-basic-behaviors.xabsl new file mode 100644 index 00000000..0a0fe3ca --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/my-basic-behaviors.xabsl @@ -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 { + } +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/my-symbols.xabsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/my-symbols.xabsl new file mode 100644 index 00000000..f6beb650 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/XabslExampleAgentTeam/xabsl-src/my-symbols.xabsl @@ -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; +} + + + + + + + + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/GPL b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/GPL new file mode 100644 index 00000000..a43ea212 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/GPL @@ -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. + + + Copyright (C) 19yy + + 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. + + , 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. diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/README b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/README new file mode 100644 index 00000000..9ebcb18d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/README @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/contest b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/contest new file mode 100644 index 00000000..f1be9aa2 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/contest @@ -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 + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/makefile new file mode 100644 index 00000000..21169ddb --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/makefile @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/players.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/players.h new file mode 100644 index 00000000..914c4f57 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/players.h @@ -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 diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/soccer.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/soccer.c new file mode 100644 index 00000000..f6d4fdca --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/soccer.c @@ -0,0 +1,760 @@ +/***************************************************************** + + soccer.c + + A program to test and evaluate mutiagent soccer + strategies. See docs/soccer.ps for a more complete + description. + + Copyright (C) 1995 Tucker Balch + + 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. + + Modification History: + + 16 APR 95 1.0 Tucker Balch - original version. + 28 APR 95 1.1 Greg Eisenhauer - added some interactive + options. + + 19 OCT 95 1.3 Tucker Balch + + 6 NOV 95 1.4 Tucker Balch - fixed some portability bugs. + 10 NOV 95 1.5 Tucker Balch - fixed more portability bugs. + 15 NOV 95 1.99 Tucker Balch - changed directory structure + and linking. Added game_over() call + for teams to save state. + + Bugs: + East always gets to move first. + + Possible improvements: + Full sensing of all other players. + Sqrt of dx dy of other players. + +*****************************************************************/ + +#include +#include +#include "soccer.h" + + +WINDOW *game_win; + +/* + * Do not attempt to access these varibles from your + * team function. That is a violation of the rules! + */ +int ball_x, ball_y; +int player_x[8], player_y[8]; +int field[MAX_X][MAX_Y]; +int display = 1; /* indicates whether or not to display stuff */ +int points = 7; /* How many points til a win ? */ + +extern int opterr; +extern char *optarg; + + +/****************************************************************** + + report_score() + +******************************************************************/ +void report_score(int west_score, int east_score) +{ +char score_line[100]; + +sprintf(score_line, + "%s %d %s %d", + WESTteam_name(), west_score, EASTteam_name(), east_score); +if (display) mvaddstr(MAX_Y, 0, score_line); +sprintf(score_line, "ASCII=Soccer=v2.0====(q)uit====(s)lower====(f)aster"); +if (display) mvaddstr(0, 0, score_line); +if (display) wrefresh(game_win); +} + + +/****************************************************************** + + replace_ball() + + Put the ball in a random place. + +******************************************************************/ +int replace_ball() +{ +if (display) mvaddch(ball_y, ball_x, ' '); +do + { + field[ball_x][ball_y] = EMPTY; + ball_y = std::rand() % 20 + 1; + } +while (field[ball_x][ball_y] != EMPTY); +field[ball_x][ball_y] = BALL; +if (display) mvaddch(ball_y, ball_x, 'O'); +if (display) wrefresh(game_win); +} + + +/****************************************************************** + + nudge_ball() + +******************************************************************/ +int nudge_ball() +{ +int i = 1; +int temp; + +if (display) mvaddch(ball_y, ball_x, ' '); + +do + { + temp = ball_y + ((std::rand()/256) % i) - (i/2) ; + if (temp<1) temp = 1; + if (temp>22) temp = 22; + i++; + if (i > 40) i = 40; + } +while ((field[ball_x][temp] != EMPTY)&&(field[ball_x][temp] != GOAL)); +field[ball_x][ball_y] = EMPTY; +ball_y = temp; +field[ball_x][ball_y] = BALL; +if (display) mvaddch(ball_y, ball_x, 'O'); +} + + + +/****************************************************************** + + swap_heading() + + Turn heading 180 degrees. + +******************************************************************/ +int swap_heading(int heading) +{ +switch(heading) + { + case NW: return(SE); break; + case N: return(S); break; + case NE: return(SW); break; + case E: return(W); break; + case SE: return(NW); break; + case S: return(N); break; + case SW: return(NE); break; + case W: return(E); break; + case KICK: return(KICK); + case DO_NOTHING: return(DO_NOTHING); + default: return(DO_NOTHING); break; + } +} + + +/****************************************************************** + + init() + + Initialize the playing field. + +******************************************************************/ +int init() +{ +char c; +int i, j, val, r; + +/*--- Clear the screen ---*/ +if (display) wclear(game_win); + +/*--- Clear out the field map. ---*/ +for(i=0; i'); + } + +/* + * Put boundary around the field. + * That will keep the players in bounds all the time. + */ +for(i=0; i 0 (%s)\n", optarg); + } + break; + + default : break; + } + } + +/* + * Init screen + */ +if (display) initscr(); +if (display) cbreak(); +if (display) noecho(); +if (display) game_win = subwin(stdscr, LINES, COLS, 0, 0); +if (display) wmove(game_win,0,0); +if (display) wrefresh(game_win); + +/* + * Sleep to let user see what's up + */ +sleep(2); + +/* + * Call user initialization routines. + */ +EASTinitialize_game(); +WESTinitialize_game(); + +/* + * Do this until one team wins best of 7 points + */ +while (game_over != 1) + { + /* + * Set up for the point. + */ + init(); + if (display) report_score(west_score,east_score); + point_over = 0; + count = 0; + overall_count = 0; + kick_direction = -1; + kick_steps = 0; + sleep(1); + + /* + * Call user initialization functions. + */ + EASTinitialize_point(); + WESTinitialize_point(); + + /* + * Play the point til one team wins. + */ + while (point_over != 1) + { + /* + * Player's posit + */ + cur_x = player_x[cur]; + cur_y = player_y[cur]; + + /* + * Note the local field around the player + */ + k = 0; + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + { + local_field[k++] = + field[cur_x+i-1][cur_y+j-1]; + } + /* + * Note the local field around the ball + */ + k = 0; + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + { + local_ball_field[k++] = + field[ball_x+i-1][ball_y+j-1]; + } + + /* + * Figure out heading to ball + */ + if ((ball_x == cur_x) && (ball_y == cur_y)) + temp_angle = 0; + else + temp_angle = + atan2((ball_x - cur_x), + (ball_y - cur_y)); + temp_angle += PI; + temp_angle = 360.0*temp_angle/(2.0*PI); + ball_direction = N; + if (temp_angle > 22.5+0*45) + ball_direction = NW; + if (temp_angle > 22.5+1*45) + ball_direction = W; + if (temp_angle > 22.5+2*45) + ball_direction = SW; + if (temp_angle > 22.5+3*45) + ball_direction = S; + if (temp_angle > 22.5+4*45) + ball_direction = SE; + if (temp_angle > 22.5+5*45) + ball_direction = E; + if (temp_angle > 22.5+6*45) + ball_direction = NE; + if (temp_angle > 22.5+7*45) + ball_direction = N; + + /* + * Construct backwards sensing for western players. + */ + for (i = 0; i <=8; i++) + local_backwards_field[i]=local_field[8-i]; + backwards_ball_direction = swap_heading(ball_direction); + backwards_cur_x = (MAX_X - 1) - cur_x; + backwards_cur_y = (MAX_Y - 1) - cur_y; + + /* + * Find out which way to go. The variable cur + * indicates which player we are moving for now. + * East players are 0 2 4 6. The local_field and + * ball_direction are reversed for west players + * so they can think they are going east! Then + * their output is reversed again. + */ + switch(cur) + { + case 0: player_move = + EASTplayer1(local_field, ball_direction, + cur_x, cur_y); + break; + case 1: player_move = + swap_heading( + WESTplayer1(local_backwards_field, + backwards_ball_direction, + backwards_cur_x, backwards_cur_y)); + break; + case 2: player_move = + EASTplayer2(local_field, ball_direction, + cur_x, cur_y); + break; + case 3: player_move = + swap_heading( + WESTplayer2(local_backwards_field, + backwards_ball_direction, + backwards_cur_x, backwards_cur_y)); + break; + case 4: player_move = + EASTplayer3(local_field, ball_direction, + cur_x, cur_y); + break; + case 5: player_move = + swap_heading( + WESTplayer3(local_backwards_field, + backwards_ball_direction, + backwards_cur_x, backwards_cur_y)); + break; + case 6: player_move = + EASTplayer4(local_field, ball_direction, + cur_x, cur_y); + break; + case 7: player_move = + swap_heading( + WESTplayer4(local_backwards_field, + backwards_ball_direction, + backwards_cur_x, backwards_cur_y)); + break; + } + + /* + * Check for move = PLAYER + */ + if (player_move == PLAYER) + { + player_move = DO_NOTHING; + } + + /* + * Check for KICK. If the player wants to kick + * set up the kick, then set player_move to be + * heading in the direction of the ball. + */ + if (player_move == KICK) + { + for(i = 0; i<=8; i++) + { + /*--- Where is the ball ?---*/ + if (local_field[i] == BALL) + { + kick_direction = i; + kick_steps = KICK_DIST; + player_move = i; + break; + } + } + if (player_move == KICK) + { + /*--- Ball was NOT nearby ---*/ + player_move = N; + } + } + + /* + * Make sure heading is legal. + */ + if ((player_move < 0) || (player_move > 8)) + { + player_move = DO_NOTHING; + } + + /* + * Move the player in the world + */ + if (display) mvaddch(cur_y, cur_x, ' '); /* erase old spot */ + field[cur_x][cur_y] = EMPTY; + + /* + * If the cell we are going to is empty, or + * the ball is there and the next cell after that is + * empty, then . . . + */ + if ((local_field[player_move] == EMPTY) || + ((local_field[player_move] == BALL)&& + ((local_ball_field[player_move] == EMPTY)|| + (local_ball_field[player_move] == GOAL)))) + { + switch(player_move) + { + case N: player_y[cur]--; path++; break; + case S: player_y[cur]++; path++; break; + case E: player_x[cur]++; path++; break; + case W: player_x[cur]--; path++; break; + case NE: player_y[cur]--; player_x[cur]++; + path+=SQR2; break; + case NW: player_y[cur]--; player_x[cur]--; + path+=SQR2; break; + case SE: player_y[cur]++; player_x[cur]++; + path+=SQR2; break; + case SW: player_y[cur]++; player_x[cur]--; + path+=SQR2; break; + } + } + + /* + * Mark the field with the player's new position. + */ + if ((cur % 2) == 0) + field[player_x[cur]][player_y[cur]] = EAST_PLAYER; + else + field[player_x[cur]][player_y[cur]] = WEST_PLAYER; + + /* + * Now move the ball. + */ + if ((local_field[player_move] == BALL)&& + ((local_ball_field[player_move] == EMPTY)|| + (local_ball_field[player_move] == GOAL))) + { + field[ball_x][ball_y] = EMPTY; + if (display) mvaddch(ball_y, ball_x, ' '); /* new position */ + switch(player_move) + { + case N: ball_y--; break; + case S: ball_y++; break; + case E: ball_x++; break; + case W: ball_x--; break; + case NE: ball_y--; ball_x++; break; + case NW: ball_y--; ball_x--; break; + case SE: ball_y++; ball_x++; break; + case SW: ball_y++; ball_x--; break; + } + } + /* + * Place the ball on the field. + */ + field[ball_x][ball_y] = BALL; + + /* + * Now handle the case of a KICK + */ + if (kick_steps > 0) + { + /*--- Revise the local ball field ---*/ + k = 0; + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + { + local_ball_field[k++] = + field[ball_x+i-1][ball_y+j-1]; + } + + /*--- Erase old position ---*/ + field[ball_x][ball_y] = EMPTY; + if (display) mvaddch(ball_y, ball_x, ' '); + + /*--- Propel the ball if the space is empty ---*/ + if ((local_ball_field[kick_direction] == EMPTY) || + (local_ball_field[kick_direction] == GOAL)) + switch(kick_direction) + { + case N: ball_y--; break; + case S: ball_y++; break; + case E: ball_x++; break; + case W: ball_x--; break; + case NE: ball_y--; ball_x++; break; + case NW: ball_y--; ball_x--; break; + case SE: ball_y++; ball_x++; break; + case SW: ball_y++; ball_x--; break; + default: break; + } + else + { + kick_direction = -1; + kick_steps = 0; + } + kick_steps--; + field[ball_x][ball_y] = BALL; + } + + + /* + * Mark the new locations of the ball and + * the player on the field. + */ + if (display) mvaddch(ball_y, ball_x, 'O'); + if ((cur % 2) == 0) + { + if (display) mvaddch(player_y[cur], player_x[cur], '<'); + } + else + { + if (display) mvaddch(player_y[cur], player_x[cur], '>'); + } + if (display) wrefresh(game_win); + + /* + * Check for a score. + */ + if (ball_x <= 0) + { + east_score++; + point_over = 1; + if (!display) + { + printf("%s vs %s: %d to %d \n",WESTteam_name(),EASTteam_name(), + west_score,east_score); + fflush(stdout); + } + EASTwon_point(); /* Advise the teams of the point */ + WESTlost_point(); + } + if (ball_x >= (MAX_X-1)) + { + west_score++; + point_over = 1; + if (!display) + { + printf("%s vs %s: %d to %d \n",WESTteam_name(),EASTteam_name(), + west_score,east_score); + fflush(stdout); + } + WESTwon_point(); /* Advise the teams of the point */ + EASTlost_point(); + } + + /* + * Check for a stalemate. + */ + player_nearby = 0; + for (i = 0; i<=8; i++) + { + if ((local_ball_field[i] == WEST_PLAYER) || + (local_ball_field[i] == EAST_PLAYER)) + player_nearby = 1; + } + if (player_nearby && + ((last_ball_x == ball_x)&&(last_ball_y == ball_y))) + count++; + if (count > TIME_LIMIT) + { + nudge_ball(); + count = 0; + } + if ((last_ball_x != ball_x)||(last_ball_y != ball_y)) + count = 0; + last_ball_x = ball_x; + last_ball_y = ball_y; + + /* + * Check for user input. + */ + if (display) + { + fd_set inset; + struct timeval timeout; + FD_ZERO(&inset); + FD_SET(0, &inset); + timeout.tv_sec = timeout.tv_usec = 0; + if (select(FD_SETSIZE, + &inset, NULL, NULL, &timeout) > 0) + { + int input = getch(); + if (input == 'q') point_over = game_over = 1; + if (input == 's') slow*=2; + if (input == 'f') slow/=2; + if (slow < 1) slow=1; + } + if (slow>1) + { + timeout.tv_usec = (slow-1)*20; + select(32, NULL, NULL, NULL, &timeout); + } + } + + /* + * Go on to the next player. + */ + cur++; + if (cur == 8) + cur = 0; + + /* + * Check for big timeout. + */ + overall_count++; + if (overall_count >= TIME_OUT) + { + printf("TIME_OUT\n"); + /* erase old spot */ + if (display) mvaddch(ball_x, ball_y, ' '); + field[ball_x][ball_y] = EMPTY; + ball_x = 38; + ball_y = 30; + replace_ball(); + overall_count = 0; + EASTlost_point(); /* punish teams */ + WESTlost_point(); + if (display) wrefresh(game_win); + } + } + + /* + * Check for first to 7 wins. + */ + if ((west_score == points) || (east_score == points)) + game_over = 1; + } +EASTgame_over(); +WESTgame_over(); +if (display) report_score(west_score, east_score); +if (display) endwin(); +printf("\n"); +printf("%s vs %s: %d to %d \n",WESTteam_name(),EASTteam_name(), + west_score,east_score); +if (west_score < east_score) + printf("%s won\n",EASTteam_name()); +else + printf("%s won\n",WESTteam_name()); +} diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/soccer.h b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/soccer.h new file mode 100644 index 00000000..17cd6a03 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/soccer.h @@ -0,0 +1,69 @@ +#ifndef SOCCER_H + #define SOCCER_H + + #include + #include + #include + #include + #include + #include + + + #define MAX_X 80 + #define MAX_Y 23 + #define TIME_LIMIT 20 + #define TIME_OUT 3000 + #define KICK_DIST 10 + + #ifndef PI + #define PI 3.1415927 + #endif + + #define SQR2 1.4142136 + + #define EMPTY 0 + #define GOAL 1 + #define BALL 2 + #define BOUNDARY 3 + #define WEST_PLAYER 6 + #define EAST_PLAYER 7 + #define BIGGEST_SIT 7 + + #define NW 0 + #define N 1 + #define NE 2 + #define W 3 + #define PLAYER 4 + #define E 5 + #define SW 6 + #define S 7 + #define SE 8 + + #define KICK 9 + #define DO_NOTHING 10 + #define BIGGEST_ACTION 10 + + void EASTinitialize_game(void); + void EASTgame_over(void); + void EASTinitialize_point(void); + void EASTwon_point(void); + void EASTlost_point(void); + int EASTplayer1(int *, int, int, int); + int EASTplayer2(int *, int, int, int); + int EASTplayer3(int *, int, int, int); + int EASTplayer4(int *, int, int, int); + + void WESTinitialize_game(void); + void WESTgame_over(void); + void WESTinitialize_point(void); + void WESTwon_point(void); + void WESTlost_point(void); + int WESTplayer1(int *, int, int, int); + int WESTplayer2(int *, int, int, int); + int WESTplayer3(int *, int, int, int); + int WESTplayer4(int *, int, int, int); + + char *EASTteam_name(); + char *WESTteam_name(); + +#endif diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/main.c new file mode 100644 index 00000000..43e088a4 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/main.c @@ -0,0 +1,198 @@ +/*=========================================================================== + + brute.c + + Brute force soccer. All four players try to push the ball from + east to west. + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ +#include "players.h" + +int unique_name(push_from_the_east)(int obstacles[9], int ball_direction); + +/*----------------------------------------------------- + + team_name() + + Every team must have a name! Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *unique_name(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "The Brutal Brutes \0"; +return(s); +} + +/*----------------------------------------------------- + + player1() + +-----------------------------------------------------*/ +int unique_name(player1)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(push_from_the_east)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int unique_name(player2)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(push_from_the_east)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int unique_name(player3)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(push_from_the_east)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int unique_name(player4)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(push_from_the_east)(obstacles, ball_direction)); +} + + + +/*----------------------------------------------------- + + Handy Routines + +-----------------------------------------------------*/ + +int unique_name(random_heading)() +{ +int m; + +m = ((rand()/256) % 8); +switch(m) + { + case 0: return(N); break; + case 1: return(S); break; + case 2: return(E); break; + case 3: return(W); break; + case 4: return(NW); break; + case 5: return(NE); break; + case 6: return(SW); break; + case 7: return(SE); break; + default: return(N); break; + } +} + +int unique_name(push_from_the_north)(int obstacles[9], int ball_direction) +{ +int i; +switch(ball_direction) + { + case N: return(NW); + case NE: return(N); + case NW: return(NW); + case W: return(NW); + case E: return(N); + case S: return(S); + case SE: return(E); + case SW: return(SW); + default: return(N); + } +} + +int unique_name(push_from_the_east)(int obstacles[9], int ball_direction) +{ +int i; +switch(ball_direction) + { + case N: return(NE); + case NE: return(NE); + case NW: return(N); + case W: return(W); + case E: return(unique_name(random_heading)()); + case S: return(SE); + case SE: return(SE); + case SW: return(S); + default: return(N); + } +} + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once per game at the end. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/makefile new file mode 100644 index 00000000..b7b9b42c --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/brute/makefile @@ -0,0 +1,22 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + +libeast.a: east.o + ar rc libeast.a east.o + +libcommon.a: common.o + ar rc libcommon.a common.o + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/main.c new file mode 100644 index 00000000..1c5c9d4d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/main.c @@ -0,0 +1,249 @@ +/*=========================================================================== + + comm1.c + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ +#include "players.h" + +/*forward refs*/ +int unique_name(random_spread)(int obstacles[9], int ball_direction); +int unique_name(push_from_the_north)(int obstacles[9], int ball_direction); +int unique_name(push_from_the_east)(int obstacles[9], int ball_direction); +int unique_name(random_heading)(); + +static int unique_name(got_it) = -1; + +/*----------------------------------------------------- + + team_name() + + Every team must have a name! Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *unique_name(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "Commie Communicators\0"; +return(s); +} + +/*----------------------------------------------------- + + player1() + +-----------------------------------------------------*/ +int unique_name(player1)(int obstacles[9], int ball_direction, int x, int y) +{ +if (obstacles[W] == BALL) + { + unique_name(got_it) = 1; + return(unique_name(push_from_the_east)(obstacles, ball_direction)); + } +if ((unique_name(got_it) == 1) && (obstacles[E] != BALL)) + unique_name(got_it) = -1; +if (unique_name(got_it) == -1) + return(unique_name(push_from_the_east)(obstacles, ball_direction)); +else + return(unique_name(random_spread)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int unique_name(player2)(int obstacles[9], int ball_direction, int x, int y) +{ +if (obstacles[W] == BALL) + { + unique_name(got_it) = 2; + return(unique_name(push_from_the_east)(obstacles, ball_direction)); + } +if ((unique_name(got_it) == 2) && (obstacles[E] != BALL)) + unique_name(got_it) = -1; +if (unique_name(got_it) == -1) + return(unique_name(push_from_the_east)(obstacles, ball_direction)); +else + return(unique_name(random_spread)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int unique_name(player3)(int obstacles[9], int ball_direction, int x, int y) +{ +if (obstacles[W] == BALL) + { + unique_name(got_it) = 3; + return(unique_name(push_from_the_east)(obstacles, ball_direction)); + } +if ((unique_name(got_it) == 3) && (obstacles[E] != BALL)) + unique_name(got_it) = -1; +if (unique_name(got_it) == -1) + return(unique_name(push_from_the_east)(obstacles, ball_direction)); +else + return(unique_name(random_spread)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int unique_name(player4)(int obstacles[9], int ball_direction, int x, int y) +{ +if (obstacles[W] == BALL) + { + unique_name(got_it) = 4; + return(unique_name(push_from_the_east)(obstacles, ball_direction)); + } +if ((unique_name(got_it) == 4) && (obstacles[E] != BALL)) + unique_name(got_it) = -1; +if (unique_name(got_it) == -1) + return(unique_name(push_from_the_east)(obstacles, ball_direction)); +else + return(unique_name(random_spread)(obstacles, ball_direction)); +} + + +int unique_name(random_spread)(int obstacles[9], int ball_direction) +{ +if ((ball_direction == SE) || (ball_direction == NE)) + return(E); +if ((ball_direction == SW) || (ball_direction == NW)) + return(W); +return(unique_name(random_heading())); +} + + +int unique_name(random_heading)() +{ +int m; + +m = ((rand()/256) % 8); +switch(m) + { + case 0: return(N); break; + case 1: return(S); break; + case 2: return(E); break; + case 3: return(W); break; + case 4: return(NW); break; + case 5: return(NE); break; + case 6: return(SW); break; + case 7: return(SE); break; + default: return(N); break; + } +} + +int unique_name(push_from_the_north)(int obstacles[9], int ball_direction) +{ +int i; +switch(ball_direction) + { + case N: return(NW); + case NE: return(N); + case NW: return(NW); + case W: return(NW); + case E: return(N); + case S: return(S); + case SE: return(E); + case SW: return(SW); + default: return(N); + } +} + +int unique_name(push_from_the_east)(int obstacles[9], int ball_direction) +{ +int i; +switch(ball_direction) + { + case N: return(NE); + case NE: return(NE); + case NW: return(N); + case W: return(W); + case E: return(unique_name(random_heading)()); + case S: return(SE); + case SE: return(SE); + case SW: return(S); + default: return(N); + } +} + + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the game. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/comm1/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/main.c new file mode 100644 index 00000000..4403378d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/main.c @@ -0,0 +1,205 @@ +/*=========================================================================== + + diagonal.c + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ +#include "players.h" + +/*forward refs*/ +int unique_name(push_from_SE)(int obstacles[9], int ball_direction); +int unique_name(push_from_E)(int obstacles[9], int ball_direction); +int unique_name(push_from_NE)(int obstacles[9], int ball_direction); + +/*----------------------------------------------------- + + team_name() + + Every team must have a name! Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *unique_name(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "Diagonal Demons \0"; +return(s); +} + +/*----------------------------------------------------- + + player1() + +-----------------------------------------------------*/ +int unique_name(player1)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(push_from_E)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int unique_name(player2)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(push_from_NE)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int unique_name(player3)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(push_from_SE)(obstacles, ball_direction)); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int unique_name(player4)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(push_from_E)(obstacles, ball_direction)); +} + +int unique_name(random_heading)() +{ +int m; + +m = ((rand()/256) % 8); +switch(m) + { + case 0: return(N); break; + case 1: return(S); break; + case 2: return(E); break; + case 3: return(W); break; + case 4: return(NW); break; + case 5: return(NE); break; + case 6: return(SW); break; + case 7: return(SE); break; + default: return(N); break; + } +} + +int unique_name(push_from_SE)(int obstacles[9], int ball_direction) +{ +if (obstacles[N] == BALL) return(E); +if (obstacles[NE] == BALL) return(E); +if (obstacles[E] == BALL) return(S); +if (obstacles[SE] == BALL) return(S); +if (obstacles[S] == BALL) return(E); +if (obstacles[SW] == BALL) return(E); +if (obstacles[W] == BALL) return(S); +if (obstacles[NW] == BALL) return(NW); +return(ball_direction); +} + +int unique_name(push_from_E)(int obstacles[9], int ball_direction) +{ +int i; +switch(ball_direction) + { + case N: return(NE); + case NE: return(NE); + case NW: return(N); + case W: return(W); + case E: return(unique_name(random_heading)()); + case S: return(SE); + case SE: return(SE); + case SW: return(S); + default: return(N); + } +} + +int unique_name(push_from_NE)(int obstacles[9], int ball_direction) +{ +if (obstacles[N] == BALL) return(E); +if (obstacles[NE] == BALL) return(N); +if (obstacles[E] == BALL) return(N); +if (obstacles[SE] == BALL) return(E); +if (obstacles[S] == BALL) return(E); +if (obstacles[SW] == BALL) return(SW); +if (obstacles[W] == BALL) return(N); +if (obstacles[NW] == BALL) return(N); +return(ball_direction); +} + + + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the game. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/diagonal/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/main.c new file mode 100644 index 00000000..21473f1f --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/main.c @@ -0,0 +1,207 @@ +/*=========================================================================== + + example.c + + A very basic soccer strategy. All four players attempt to run + up to the ball and kick it west! + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ + +#include "players.h" +/* +players.h includes a rather unusual macro, UN(). This macro +will convert the names of the functions in this .c file to +unique names. For instance, if this were the east team, UN(team_name)() +will become EASTteam_name(). This is necessary for the automatic +compiling and linking of arbitrary teams for tournaments. + +Below are the 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. + +The function should return an integer indicating either a direction to +move (N, NE, E, S, etc) or KICK to kick the ball. +*/ + + +/*----------------------------------------------------- + + player1() + + If the ball is nearby, either get to + the east side of it, or if already on the + east, kick it. + +-----------------------------------------------------*/ +int UN(player1)(int local_area[9], int ball_direction, int x, int y) +/* +UN(player1)(int local_area[9] . . .) becomes +EASTplayer(int local_area[9] . . .) or +WESTplayer(int local_area[9] . . .) depending on whether +this team is compiled to play on the east or west. +*/ + +{ + +/* + * If right next to the ball, on the west, get to east side. + */ +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); + +/* + * If already on the west, kick! + */ +if (local_area[SW] == BALL) return(KICK); +if (local_area[W] == BALL) return(KICK); +if (local_area[NW] == BALL) return(KICK); + +/* + * If not near the ball, just go to it. + */ +return(ball_direction); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int UN(player2)(int local_area[9], int ball_direction, int x, int y) +{ +/* + * Just do the same thing as player1 + */ +return(UN(player1)(local_area, ball_direction, x, y)); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int UN(player3)(int local_area[9], int ball_direction, int x, int y) +{ +/* + * Just do the same thing as player1 + */ +return(UN(player1)(local_area, ball_direction, x, y)); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int UN(player4)(int local_area[9], int ball_direction, int x, int y) +{ +/* + * Just do the same thing as player1 + */ +return(UN(player1)(local_area, ball_direction, x, y)); +} + +/*----------------------------------------------------- + + team_name() + + Every team must have a name. Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *UN(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "Krazy Kickers \0"; +return(s); +} + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the match. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/example/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/main.c new file mode 100644 index 00000000..461c335f --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/main.c @@ -0,0 +1,249 @@ +/*=========================================================================== + + example.c + + A very basic soccer strategy. All four players attempt to run + up to the ball and kick it west! + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ + +#include +#include "players.h" +/* +players.h includes a rather unusual macro, UN(). This macro +will convert the names of the functions in this .c file to +unique names. For instance, if this were the east team, UN(team_name)() +will become EASTteam_name(). This is necessary for the automatic +compiling and linking of arbitrary teams for tournaments. + +Below are the 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. + +The function should return an integer indicating either a direction to +move (N, NE, E, S, etc) or KICK to kick the ball. +*/ + + +/*----------------------------------------------------- + + Global variables for coordination + +-----------------------------------------------------*/ +int ball_directions[4]; + +int under(int player) { + if (player < 0) + return 1; + return (ball_directions[player] == NW) || + (ball_directions[player] == N) || + (ball_directions[player] == NE); +} + +int over(int player) { + if (player >= 4) + return 1; + return (ball_directions[player] == SW) || + (ball_directions[player] == S) || + (ball_directions[player] == SE); +} + +int behind(int player) { + return (ball_directions[player] == S) || + (ball_directions[player] == SE) || + (ball_directions[player] == E) || + (ball_directions[player] == NE) || + (ball_directions[player] == N); +} + +int common_behavior(int player, int local_area[9]) { + + // Kick the ball away + if (local_area[W] == BALL) + return KICK; + + // Ball over player + if (ball_directions[player] == SW && under(player - 1)) + return S; + if (ball_directions[player] == S && under(player - 1)) + return SE; + + // Ball under player + if (ball_directions[player] == NW && over(player + 1)) + return N; + if (ball_directions[player] == N && over(player + 1)) + return NE; + + // Ball directly behind + if (ball_directions[player] == E) + if (local_area[S] == BOUNDARY) + return NE; + else + return SE; + + // Ball behind player + if (behind(player)) + return E; + + // Correct position + return DO_NOTHING; +} + + +/*----------------------------------------------------- + + player1() + + If the ball is nearby, either get to + the east side of it, or if already on the + east, kick it. + +-----------------------------------------------------*/ +int UN(player1)(int local_area[9], int ball_direction, int x, int y) +{ + ball_directions[0] = ball_direction; + return common_behavior(0, local_area); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int UN(player2)(int local_area[9], int ball_direction, int x, int y) +{ + ball_directions[1] = ball_direction; + return common_behavior(1, local_area); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int UN(player3)(int local_area[9], int ball_direction, int x, int y) +{ + ball_directions[2] = ball_direction; + return common_behavior(2, local_area); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int UN(player4)(int local_area[9], int ball_direction, int x, int y) +{ + ball_directions[3] = ball_direction; + return common_behavior(3, local_area); +} + +/*----------------------------------------------------- + + team_name() + + Every team must have a name. Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *UN(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "The Inliners \0"; +return(s); +} + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ + +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ + /* + * Initialize ball directions with useless information. + * The ball directions will be correct after the first + * iteration. + */ + for(int k = 0; k < 4; k++) + ball_directions[k] = -1; +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the match. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/inline/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/main.c new file mode 100644 index 00000000..94bbff09 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/main.c @@ -0,0 +1,331 @@ +/*=========================================================================== + + kickers.c + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ +#include "players.h" + + +/*----------------------------------------------------- + + team_name() + + Every team must have a name! Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *UN(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "Krazy Kickers 2 \0"; +return(s); +} + +static int player_x[5], player_y[5], first_time = 1; +static int have_the_ball[5], offensive = 0; + +/*----------------------------------------------------- + + player1() + +-----------------------------------------------------*/ +int UN(player1)(int local_area[9], int ball_direction, int x, int y) +{ +int i; +int my_id, partner_id; + +my_id = 1; partner_id = 2; + +player_x[my_id] = x; +player_y[my_id] = y; + +if (first_time) + { + first_time = 0; + for(i=0; i<=4; i++) + { + player_x[i] = player_y[i] = 0; + have_the_ball[i] = 0; + } + } + +for(i = 1; i <= 4; i++) + if (have_the_ball[i] == 1) + offensive = 1; + +have_the_ball[my_id] = 0; +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); +if (local_area[SW] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } +if (local_area[W] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } +if (local_area[NW] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } + +if (local_area[N] == BOUNDARY) return(ball_direction); + +if ((y >= (player_y[partner_id]-5))&&(ball_direction == N)) return(N); +if ((y >= (player_y[partner_id]-5))&&(ball_direction == NE)) return(NE); +if ((y >= (player_y[partner_id]-5))&&(ball_direction == E)) return(E); +if ((y >= (player_y[partner_id]-5))&&(ball_direction == SE)) return(E); +if ((y >= (player_y[partner_id]-5))&&(ball_direction == S)) return(DO_NOTHING); +if ((y >= (player_y[partner_id]-5))&&(ball_direction == SW)) return(SW); +if ((y >= (player_y[partner_id]-5))&&(ball_direction == W)) return(W); +if ((y >= (player_y[partner_id]-5))&&(ball_direction == NW)) return(NW); + + +return(ball_direction); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int UN(player2)(int local_area[9], int ball_direction, int x, int y) +{ +int i; +int my_id, partner_id; + +my_id = 2; partner_id = 3; + +player_x[my_id] = x; +player_y[my_id] = y; + +have_the_ball[my_id] = 0; +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); +if (local_area[SW] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } +if (local_area[W] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } +if (local_area[NW] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } + +if (local_area[N] == BOUNDARY) return(ball_direction); + +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); +if (local_area[SW] == BALL) return(KICK); +if (local_area[W] == BALL) return(KICK); +if (local_area[NW] == BALL) return(KICK); + +return(ball_direction); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int UN(player3)(int local_area[9], int ball_direction, int x, int y) +{ +int i; +int my_id, partner_id; + +my_id = 3; partner_id = 2; + +player_x[my_id] = x; +player_y[my_id] = y; + +have_the_ball[my_id] = 0; +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); +if (local_area[SW] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } +if (local_area[W] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } +if (local_area[NW] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } + +if (local_area[N] == BOUNDARY) return(ball_direction); + +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); +if (local_area[SW] == BALL) return(KICK); +if (local_area[W] == BALL) return(KICK); +if (local_area[NW] == BALL) return(KICK); + +return(ball_direction); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int UN(player4)(int local_area[9], int ball_direction, int x, int y) +{ +int i; +int my_id, partner_id; + +my_id = 4; partner_id = 3; + +player_x[my_id] = x; +player_y[my_id] = y; + +have_the_ball[my_id] = 0; +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); +if (local_area[SW] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } +if (local_area[W] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } +if (local_area[NW] == BALL) + { + have_the_ball[my_id] = 1; + return(KICK); + } + +if (local_area[N] == BOUNDARY) return(ball_direction); + +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); +if (local_area[SW] == BALL) return(KICK); +if (local_area[W] == BALL) return(KICK); +if (local_area[NW] == BALL) return(KICK); + +if (local_area[S] == BOUNDARY) return(ball_direction); + +/*printf("%d %d",y,player_y[2]);*/ +if ((y <= player_y[3]+5)&&(ball_direction == N)) return(DO_NOTHING); +if ((y <= player_y[3]+5)&&(ball_direction == NE)) return(E); +if ((y <= player_y[3]+5)&&(ball_direction == E)) return(E); +if ((y <= player_y[3]+5)&&(ball_direction == SE)) return(SE); +if ((y <= player_y[3]+5)&&(ball_direction == S)) return(S); +if ((y <= player_y[3]+5)&&(ball_direction == SW)) return(SW); +if ((y <= player_y[3]+5)&&(ball_direction == W)) return(W); +if ((y <= player_y[3]+5)&&(ball_direction == NW)) return(NW); + +return(ball_direction); +} + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the game. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/kickers2/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/main.c new file mode 100644 index 00000000..1d016ae3 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/main.c @@ -0,0 +1,195 @@ +/*=========================================================================== + + random.c + + All four players move in random directions. + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ +#include "players.h" + +/*forward ref*/ +int unique_name(random_heading)(); + +/*----------------------------------------------------- + + team_name() + + Every team must have a name! Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *unique_name(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "The Random Rangers \0"; +return(s); +} + +/*----------------------------------------------------- + + player1() + +-----------------------------------------------------*/ +int unique_name(player1)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(random_heading)()); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int unique_name(player2)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(random_heading)()); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int unique_name(player3)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(random_heading)()); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int unique_name(player4)(int obstacles[9], int ball_direction, int x, int y) +{ +return(unique_name(random_heading)()); +} + +int unique_name(random_heading)() +{ +int m; + +m = ((rand()/256) % 8); +switch(m) + { + case 0: return(N); break; + case 1: return(S); break; + case 2: return(E); break; + case 3: return(W); break; + case 4: return(NW); break; + case 5: return(NE); break; + case 6: return(SW); break; + case 7: return(SE); break; + default: return(N); break; + } +} + +int unique_name(push_from_the_north)(int obstacles[9], int ball_direction) +{ +int i; +switch(ball_direction) + { + case N: return(NW); + case NE: return(N); + case NW: return(NW); + case W: return(NW); + case E: return(N); + case S: return(S); + case SE: return(E); + case SW: return(SW); + default: return(N); + } +} + +int unique_name(push_from_the_east)(int obstacles[9], int ball_direction) +{ +int i; +switch(ball_direction) + { + case N: return(NE); + case NE: return(NE); + case NW: return(N); + case W: return(W); + case E: return(unique_name(random_heading)()); + case S: return(SE); + case SE: return(SE); + case SW: return(S); + default: return(N); + } +} + + + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the match. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/random/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/main.c new file mode 100644 index 00000000..34738904 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/main.c @@ -0,0 +1,592 @@ +/*============================================================================ + + rollers.c + + + Steve Rowe cerebus@crl.com + + This team uses a position-based strategy, with dynamic assessment of + which team member takes each position. The positions are as follows: + + + < (northWing) + + + + < (lead) + < (support) + + + + < (southWing) + + +===========================================================================*/ + +#include +#include "players.h" + +/*---------------------------------------------------------------------------- + The WINGSPAN parameter is the radius of the diamond formation. +----------------------------------------------------------------------------*/ +static int WINGSPAN; + +/*---------------------------------------------------------------------------- + The CONTROL_TIME parameter is the number of turns that the players will + stay in formation after the lead has lost contact with the ball. If + this value is too small, then the players will never get into position, + so there may as well not BE positions. If the value is too big, then + the players will take too long to decide to start looking for the ball. + + The value used for the tournament is 13, which was determined to give + the best win/loss ratio in 100 point samples played against WALL. + + Each opponent would theoretically have different "best" values for this + parameter, but I will leave the heuristic approach for next year's + tournement. +----------------------------------------------------------------------------*/ +static int CONTROL_TIME; + +static int leader; /* ID number of the current lead (0 to 3) */ +static int plx[4]; /* Last known X coordinate of each player */ +static int ply[4]; /* Last known Y coordinate of each player */ + +static int haveBall = 0; /* Down-counter indicating ball ownership */ + +/* Some useful type definitions */ +typedef int PlayerFn(int la[9], int bd, int x, int y); +typedef int (*PlayerFnPtr)(int la[9], int bd, int x, int y); + +/*---------------------------------------------------------------------------- + Function prototypes. Since I developed this code on machines with ANSI- + only compilers, and I prefer strict type checking, I provided these. +----------------------------------------------------------------------------*/ +PlayerFn UN(player1); +PlayerFn UN(player2); +PlayerFn UN(player3); +PlayerFn UN(player4); + +PlayerFn UN(lead); /* Behaviour to be used by the leader */ +PlayerFn UN(northWing); /* Behaviour to be used by the north wing */ +PlayerFn UN(southWing); /* Behaviour to be used by the south wing */ +PlayerFn UN(rear); /* Behaviour to be used by the rear */ + +/*---------------------------------------------------------------------------- + Each player function simply calls the behave function with its player ID. + It is up to the behave function to call the appropriate behaviour function + for each player based on the ID. +----------------------------------------------------------------------------*/ +int UN(behave)(int id, int la[9], int bd, int x, int y); + + +/*---------------------------------------------------------------------------- + roles[] is an array of pointers to behavior functions. There is one entry + in the array for each player on the team. The contents of this array are + chosen dynamically in the regroup function. +----------------------------------------------------------------------------*/ +static PlayerFnPtr roles[4]; + + +/*---------------------------------------------------------------------------- + The near_object function returns the direction ID of a given object + within a given local_area. If there is no such object in the local + area, 9 is returned. +----------------------------------------------------------------------------*/ +int UN(near_object)(int la[9], int obj) +{ + int i; + + for (i = 0; i < 9; ++i) + { + if (la[i] == obj) break; + } + + return i; +} + +/*============================================================================= + The player functions are basically stubs, since all players do the same + thing, which is to call their behaviour functions through the roles + array. +=============================================================================*/ + +int UN(player1)(int la[9], int bd, int x, int y) +{ + return UN(behave)(0, la, bd, x, y); +} + +int UN(player2)(int la[9], int bd, int x, int y) +{ + return UN(behave)(1, la, bd, x, y); +} + +int UN(player3)(int la[9], int bd, int x, int y) +{ + return UN(behave)(2, la, bd, x, y); +} + +int UN(player4)(int la[9], int bd, int x, int y) +{ + return UN(behave)(3, la, bd, x, y); +} + +/*---------------------------------------------------------------------------- + The regroup function is called whenever a player makes first contact + with the east side of the ball. It redesignates that player as the lead, + and reassigns the other players' roles based on their position relative + to the new leader. +----------------------------------------------------------------------------*/ +void UN(regroup)(int newLead) +{ + int i; + int score, good; + + /* Zero out all the current roles */ + for (i = 0; i < 4; ++i) + { + roles[i] = 0; + } + + /* Assign lead role to given newLead */ + leader = newLead; + roles[newLead] = UN(lead); + + /* find south wing */ + score = 0; + for (i = 0; i < 4; ++i) + { + if (roles[i]) continue; + if (ply[i] > score) + { + score = ply[i]; + good = i; + } + } + + roles[good] = UN(southWing); + + /* find north wing */ + score = 90; + for (i = 0; i < 4; ++i) + { + if (roles[i]) continue; + if (ply[i] < score) + { + score = ply[i]; + good = i; + } + } + + roles[good] = UN(northWing); + + /* Find rear */ + score = 0; + for (i = 0; i < 4; ++i) + { + if (roles[i]) continue; /* If this player already has a role, skip */ + if (plx[i] > score) + { + score = plx[i]; /* keep player with largest X (farthest back) */ + good = i; + } + } + + roles[good] = UN(rear); +} + +/*============================================================================ + Here is the cool function, which just returns a behaviour based on the + ID passed in as the first parameter. +============================================================================*/ + +int UN(behave)(int id, int la[9], int bd, int x, int y) +{ + /* Update the "where I am" array */ + plx[id] = x; ply[id] = y; + + /* At the beginning of each turn, decrement the downcounter */ + if (id == 0) --haveBall; + + /* If this player is on the business end of the ball, then assign him + as leader. */ + if ((UN(near_object)(la, BALL) < 9) && + (bd != E) && (bd != NE) && (bd != SE) && (bd != N) && (bd != S)) + { + haveBall = CONTROL_TIME; /* Reset down-counter for possession */ + + if (leader != id) + { + /* We have a new leader. Regroup! */ + UN(regroup(id)); + } + } + else + { + /* If the downcounter has expired, make leader invalid. */ + if (haveBall <= 0) leader = -1; + } + + if (leader >= 0) + { + /* If we have a leader, then perform your given duty. */ + return (*roles[id])(la, bd, x, y); + } + else + { + /* If we have NO leader, then it's every bot for itself. */ + return UN(lead)(la, bd, x, y); + } +} + +/*---------------------------------------------------------------------------- + + LEAD() + + The leader is by far the most complex of the behaviour functions, since + it is always the behaviour used by the current ball handler. The rules + used to decide how to handle various situations was determined primarily + by impiracal methods, secondarily by careful design. Given more time, + I would have used a genetic algorithm engine to find the optimal rules + for all situations. Maybe next year. + +----------------------------------------------------------------------------*/ +int UN(lead)(int local_area[9], int ball_direction, int x, int y) +{ + int i; /* Generic loop index */ + int kickSouth = 0; /* Counter used to determine whether to kick N or S */ + + /* + If I'm on the east side of the ball and there is an opponent, then + don't mess around. Kick the ball somewhere else. + */ + if ((UN(near_object)(local_area, OPPONENT) < 9) && + (local_area[SW] == BALL)) return(KICK); + if ((UN(near_object)(local_area, OPPONENT) < 9) && + (local_area[W] == BALL)) return(KICK); + if ((UN(near_object)(local_area, OPPONENT) < 9) && + (local_area[NW] == BALL)) return(KICK); + + /* + Using my own team-mates as a reference, figure out where the bulk + of the other players (both friend and foe) are at, and plan to + kick AWAY from them (making ME the closest player to the ball after + the kick). If I'm near either the north or south edge, then + this is an invalid indicator, and I know I should kick straight + west. + */ + for (i = 0; i < 4; ++i) + { + if ((y < 18) && (ply[i] < y)) ++kickSouth; + if ((y > 4) && (ply[i] > y)) --kickSouth; + } + + if (local_area[SW] == BALL) + { + if ((x > 60) || /* If near opponent's goal */ + (kickSouth > 0)) /* OR we should kick south */ + return KICK; /* Then kick */ + + return(S); /* Otherwise, move into position to kick straight west */ + } + + if (local_area[NW] == BALL) + { + if ((x > 60) || /* If near opponent's goal */ + (kickSouth < 0)) /* OR we should kick north */ + return KICK; /* Then kick */ + + return(N); /* Otherwise, move into position to kick straight west */ + } + + if (local_area[W] == BALL) + { + /* + If we have a STRONG preference to kick the ball north or south, + then move into position to do so. + */ + if (kickSouth == 3) return N; + else if (kickSouth == -3) return S; + + /* Otherwise, kick toward the opposing goal. */ + return KICK; + } + + if (local_area[N] == BALL) + { + /* + If an opponent is in position to kick the ball toward my goal, + then kick it out of their grasp. This defeats the driver for + Diagonal Demons, among others. + */ + if ((local_area[W] == OPPONENT) && + (local_area[NW] == OPPONENT)) return KICK; + + /* + If near my own goal, get more desperate about kicking away the + ball. + */ + if ((x > 60) && + ((local_area[W] == OPPONENT) || (local_area[NW] == OPPONENT))) + return KICK; + + /* + If no opponents are about and I want to kick south, move into + position to do so. + */ + if ((kickSouth >= 0) && (local_area[NE] == EMPTY)) return NE; + + /* If I want to kick north, just move east so I can kick NW */ + return E; + } + + if (local_area[NE] == BALL) + { + /* + If there's an opponent who will get to the ball next turn, + get between him and the ball. + */ + if ((local_area[N] == EMPTY) && (local_area[NW] == OPPONENT)) return N; + + /* Otherwise, maneuver toward the east side of the ball. */ + return E; + } + + if (local_area[E] == BALL) + { + /* Get into position to kick the ball, if possible */ + if ((kickSouth > 0) && (local_area[NE] == EMPTY)) return(NE); + if ((kickSouth < 0) && (local_area[SE] == EMPTY)) return(SE); + + /* Otherwise, try and block the opponent (if any) */ + if (local_area[W] == OPPONENT) return W; + + /* Otherwise, just move out of the way. */ + if (local_area[N] == EMPTY) return N; + return S; + } + + if (local_area[SE] == BALL) + { + /* + If there's an opponent who will get to the ball next turn, + get between him and the ball. + */ + if ((local_area[S] == EMPTY) && (local_area[SW] == OPPONENT)) return S; + + /* Otherwise, maneuver toward the east side of the ball. */ + return E; + } + + if (local_area[S] == BALL) + { + /* + If an opponent is in position to kick the ball toward my goal, + then kick it out of their grasp. This defeats the driver for + Diagonal Demons, among others. + */ + if ((local_area[W] == OPPONENT) && + (local_area[SW] == OPPONENT)) return KICK; + + /* + If near my own goal, get more desperate about kicking away the + ball. + */ + if ((x > 60) && + ((local_area[W] == OPPONENT) || (local_area[SW] == OPPONENT))) + return KICK; + + /* + If no opponents are about and I want to kick north, move into + position to do so. + */ + if ((kickSouth <= 0) && (local_area[SE] == EMPTY)) return(SE); + + /* Otherwise, just get on the east side of the ball. */ + return E; + } + + /* + * If not near the ball, just go to it. + */ + return(ball_direction); +} + +/*----------------------------------------------------- + + northWing() + +-----------------------------------------------------*/ +int UN(northWing)(int local_area[9], int ball_direction, int x, int y) +{ + int ew = -1; + int ns = -1; + + /* If near the ball, handle it like the leader would. */ + if (UN(near_object)(local_area, BALL) < 9) + { + return UN(lead)(local_area, ball_direction, x, y); + } + + /* Determine which direction to move in to get into position */ + if ((local_area[N] == EMPTY) && (y > (ply[leader] - WINGSPAN))) ns = N; + if ((local_area[S] == EMPTY) && (y < (ply[leader] - WINGSPAN))) ns = S; + if ((x < plx[leader]) && (y == ply[leader])) ns = S; + if ((local_area[W] == EMPTY) && (x > (plx[leader] + WINGSPAN))) ew = W; + if ((local_area[E] == EMPTY) && (x < (plx[leader] + WINGSPAN))) ew = E; + + /* Combine preferred directions */ + if ((ew >= 0) && (ns >= 0)) + { + if ((ew == E) && (ns == N)) return NE; + if ((ew == E) && (ns == S)) return SE; + if ((ew == W) && (ns == N)) return NW; + if ((ew == W) && (ns == S)) return SW; + } + else if (ew >= 0) return ew; + else if (ns >= 0) return ns; + + /* If in position, then move toward the ball. */ + return ball_direction; +} + + +/*----------------------------------------------------- + + southWing() + +-----------------------------------------------------*/ +int UN(southWing)(int local_area[9], int ball_direction, int x, int y) +{ + int ew = -1; + int ns = -1; + + if (UN(near_object)(local_area, BALL) < 9) + { + return UN(lead)(local_area, ball_direction, x, y); + } + + if ((local_area[N] == EMPTY) && (y > (ply[leader] + WINGSPAN))) ns = N; + if ((local_area[S] == EMPTY) && (y < (ply[leader] + WINGSPAN))) ns = S; + if ((x < plx[leader]) && (y == ply[leader])) ns = N; + if ((local_area[E] == EMPTY) && (x < (plx[leader] + WINGSPAN))) ew = E; + if ((local_area[W] == EMPTY) && (x > (plx[leader] + WINGSPAN))) ew = W; + + if ((ew >= 0) && (ns >= 0)) + { + if ((ew == E) && (ns == N)) return NE; + if ((ew == E) && (ns == S)) return SE; + if ((ew == W) && (ns == N)) return NW; + if ((ew == W) && (ns == S)) return SW; + } + else if (ew >= 0) return ew; + else if (ns >= 0) return ns; + + return ball_direction; +} + +/*----------------------------------------------------- + + REAR() + +-----------------------------------------------------*/ +int UN(rear)(int local_area[9], int ball_direction, int x, int y) +{ + return UN(lead)(local_area, ball_direction, x, y); +} + +/*----------------------------------------------------- + + team_name() + + Every team must have a name. Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *UN(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "Dynamic Rollers \0"; +return(s); +} + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ + WINGSPAN = 8; + CONTROL_TIME = 13; /* 13 yields +38 index. 5 yields +26 index. */ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ + leader = -1; + haveBall = 0; + roles[0] = UN(lead); + roles[1] = UN(northWing); + roles[2] = UN(southWing); + roles[3] = UN(rear); +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)(void) +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)(void) +{ +} + + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the game. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/rollers/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/main.c new file mode 100644 index 00000000..251a341d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/main.c @@ -0,0 +1,260 @@ +/*=========================================================================== + + eisenhauer2.c + + Everyone is the same, rather nominal player. If the ball is + ahead of him (toward the goal), he pushes it that way. Otherwise + he tries to go toward (but stay behind) the ball. + + This version is slightly smarter than eisenhauer.c + In particular: + it can kick + it doesn't kick into walls (uses x value for that!) + it tries to be a bit smarter about how it moves when + it is away from the ball (in obscure ways) + + Greg Eisenhauer eisen@cc.gatech.edu + +===========================================================================*/ +#include "players.h" + +/*forward refs*/ +int unique_name(nominal_player)(int player, int obstacles[9], + int ball_direction, int x, int y); +int unique_name(ball_ahead)(int obstacles[9]); +int unique_name(get_behind_it)(int obstacles[9], int ball_direction); + +/* this 'got_it' variable is unused in this player. */ +static int unique_name(got_it) = -1; + +/*----------------------------------------------------- + + team_name() + + Every team must have a name! Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *unique_name(team_name)() +{ + char *s; + + /* "####################\0" <--- 20 characters */ + s = "Socker Spaniels \0"; + return(s); +} + +/*----------------------------------------------------- + + player1() + +-----------------------------------------------------*/ +int unique_name(player1)(int obstacles[9], int ball_direction, int x, int y) +{ + return unique_name(nominal_player)(1, obstacles, ball_direction, x, y); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int unique_name(player2)(int obstacles[9], int ball_direction, int x, int y) +{ + return unique_name(nominal_player)(2, obstacles, ball_direction, x, y); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int unique_name(player3)(int obstacles[9], int ball_direction, int x, int y) +{ + return unique_name(nominal_player)(3, obstacles, ball_direction, x, y); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int unique_name(player4)(int obstacles[9], int ball_direction, int x, int y) +{ + return unique_name(nominal_player)(4, obstacles, ball_direction, x, y); +} + + +int unique_name(nominal_player)(int player, int obstacles[9], + int ball_direction, int x, int y) { + if (unique_name(ball_ahead)(obstacles)) { + unique_name(got_it) = player; + if ((obstacles[SW] == BALL) && (y == (MAX_Y-3))) { +/* kicking into a wall is pointless. Step behind it instead + printf("player %d would kick into bottom wall\n", player); +*/ + return S; + } + if ((obstacles[NW] == BALL) && (y == 2)) { +/* kicking into a wall is pointless. Step behind it instead */ + return N; + } + return(KICK); + } + if ((unique_name(got_it) == player) && + (!unique_name(ball_ahead)(obstacles))) { + unique_name(got_it) = -1; + } + /* who's got it? */ + return(unique_name(get_behind_it)(obstacles, ball_direction)); +} + +int unique_name(random_heading)() +{ + int m; + + m = ((rand()/256) % 8); + switch(m){ + case 0: return(N); break; + case 1: return(S); break; + case 2: return(E); break; + case 3: return(W); break; + case 4: return(NW); break; + case 5: return(NE); break; + case 6: return(SW); break; + case 7: return(SE); break; + default: return(N); break; + } +} + +int unique_name(eeny_meeny_2)(int obstacles[9], int choice1, int choice2) +{ + if ((rand() %2) == 0) { + if (obstacles[choice1] == EMPTY) return choice1; + if (obstacles[choice2] == EMPTY) return choice2; + } else { + if (obstacles[choice2] == EMPTY) return choice2; + if (obstacles[choice1] == EMPTY) return choice1; + } + return unique_name(random_heading)(); +} +int unique_name(get_behind_it)(int obstacles[9], int ball_direction) +{ + int eeny; + switch(ball_direction) { + case N: + if (obstacles[NE] == EMPTY) return NE; + return unique_name(eeny_meeny_2)(obstacles, N, E); + case NE: + if (obstacles[NE] == EMPTY) return NE; + return unique_name(eeny_meeny_2)(obstacles, N, E); + case NW: + if (obstacles[NW] == EMPTY) return NW; + return unique_name(eeny_meeny_2)(obstacles, N, W); + case W: + if ((obstacles[NW] == EMPTY) || + (obstacles[SW] == EMPTY)) { + return unique_name(eeny_meeny_2)(obstacles, NW, SW); + } + if (obstacles[W] == EMPTY) return W; + return unique_name(random_heading)(); + case E: + if ((obstacles[NE] == EMPTY) || + (obstacles[SE] == EMPTY)) { + return unique_name(eeny_meeny_2)(obstacles, NE, SE); + } + if (obstacles[E] == EMPTY) return E; + return unique_name(random_heading)(); + case S: + if (obstacles[SE] == EMPTY) return SE; + if (obstacles[S] == EMPTY) return S; + if (obstacles[SW] == EMPTY) return SW; + return unique_name(random_heading)(); + case SE: + if (obstacles[SE] == EMPTY) return SE; + return unique_name(eeny_meeny_2)(obstacles, S, W); + case SW: + if (obstacles[SW] == EMPTY) return SW; + return unique_name(eeny_meeny_2)(obstacles, S, W); + default: return(N); + } +} + +int unique_name(ball_ahead)(int obstacles[9]) +{ + return ((obstacles[NW] == BALL) || + (obstacles[W] == BALL) || + (obstacles[SW] == BALL)); +} + +/*----------------------------------------------------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the game. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/spaniels/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/main.c new file mode 100644 index 00000000..4f3e0340 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/main.c @@ -0,0 +1,235 @@ +/*=========================================================================== + + example.c + + A very basic soccer strategy. All four players attempt to run + up to the ball and kick it west! + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ + +#include "players.h" +/* +players.h includes a rather unusual macro, UN(). This macro +will convert the names of the functions in this .c file to +unique names. For instance, if this were the east team, UN(team_name)() +will become EASTteam_name(). This is necessary for the automatic +compiling and linking of arbitrary teams for tournaments. + +Below are the 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. + +The function should return an integer indicating either a direction to +move (N, NE, E, S, etc) or KICK to kick the ball. +*/ + + +/*----------------------------------------------------- + + player1() + + If the ball is nearby, either get to + the east side of it, or if already on the + east, kick it. + +-----------------------------------------------------*/ +int UN(player1)(int local_area[9], int ball_direction, int x, int y) +/* +UN(player1)(int local_area[9] . . .) becomes +EASTplayer(int local_area[9] . . .) or +WESTplayer(int local_area[9] . . .) depending on whether +this team is compiled to play on the east or west. +*/ + +{ + +/* + * If right next to the ball, on the west, get to east side. + */ +/*if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); +*/ +/* + * If already on the west, kick! + */ +//if (local_area[SW] == BALL) return(KICK); +//if (local_area[W] == BALL) return(KICK); +//if (local_area[NW] == BALL) return(KICK); + +/* + * If not near the ball, just go to it. + */ +//return(ball_direction); + +if (x<65 && y==18) return(E); +if (x<65 && y>18) return(NE); +if (x<65 && y<18) return(SE); +if (x==65 && y==18) return(DO_NOTHING); +if (x==65 && y>18) return(N); +if (x==65 && y<18) return(S); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int UN(player2)(int local_area[9], int ball_direction, int x, int y) +{ +/* + * Just do the same thing as player1 + */ +//return(UN(player1)(local_area, ball_direction, x, y)); + +if (x<60 && y==12) return(E); +if (x<60 && y>12) return(NE); +if (x<60 && y<12) return(SE); +if (x==60 && y==12) return(DO_NOTHING); +if (x==60 && y>12) return(N); +if (x==60 && y<12) return(S); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int UN(player3)(int local_area[9], int ball_direction, int x, int y) +{ +/* + * Just do the same thing as player1 + */ +//return(UN(player1)(local_area, ball_direction, x, y)); + +if (x<60 && y==10) return(E); +if (x<60 && y>10) return(NE); +if (x<60 && y<10) return(SE); +if (x==60 && y==10) return(DO_NOTHING); +if (x==60 && y>10) return(N); +if (x==60 && y<10) return(S); +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int UN(player4)(int local_area[9], int ball_direction, int x, int y) +{ +/* + * Just do the same thing as player1 + */ +//return(UN(player1)(local_area, ball_direction, x, y)); + + if (x<65 && y==5) return(E); + if (x<65 && y>5) return(NE); + if (x<65 && y<5) return(SE); + if (x==65 && y==5) return(DO_NOTHING); + if (x==65 && y>5) return(N); + if (x==65 && y<5) return(S); +} + +/*----------------------------------------------------- + + team_name() + + Every team must have a name. Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *UN(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "Test Case \0"; +return(s); +} + +/*--------------------------------------------- -------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the match. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/common.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/common.c new file mode 100644 index 00000000..220e425d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/common.c @@ -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() +{ +} + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/main.c b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/main.c new file mode 100644 index 00000000..0c24e406 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/main.c @@ -0,0 +1,231 @@ +/*=========================================================================== + + example.c + + A very basic soccer strategy. All four players attempt to run + up to the ball and kick it west! + + Tucker Balch tucker@cc.gatech.edu + +===========================================================================*/ + +#include "players.h" +/* +players.h includes a rather unusual macro, UN(). This macro +will convert the names of the functions in this .c file to +unique names. For instance, if this were the east team, UN(team_name)() +will become EASTteam_name(). This is necessary for the automatic +compiling and linking of arbitrary teams for tournaments. + +Below are the 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. + +The function should return an integer indicating either a direction to +move (N, NE, E, S, etc) or KICK to kick the ball. +*/ + + +/*----------------------------------------------------- + + player1() + + If the ball is nearby, either get to + the east side of it, or if already on the + east, kick it. + +-----------------------------------------------------*/ +int UN(player1)(int local_area[9], int ball_direction, int x, int y) +/* +UN(player1)(int local_area[9] . . .) becomes +EASTplayer(int local_area[9] . . .) or +WESTplayer(int local_area[9] . . .) depending on whether +this team is compiled to play on the east or west. +*/ + +{ + +/* + * If right next to the ball, on the west, get to east side. + */ +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(SE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(SE); + +/* + * If already on the west, kick! + */ +//if (local_area[SW] == BALL) return(KICK); +//if (local_area[W] == BALL) return(KICK); +//if (local_area[NW] == BALL) return(KICK); + +/* + * If not near the ball, just go to it. + */ +return(ball_direction); +} + +/*----------------------------------------------------- + + player2() + +-----------------------------------------------------*/ +int UN(player2)(int local_area[9], int ball_direction, int x, int y) +{ + +if (local_area[N] == BALL) return(NE); +if (local_area[NE] == BALL) return(E); +if (local_area[E] == BALL) return(NE); +if (local_area[SE] == BALL) return(E); +if (local_area[S] == BALL) return(E); +if (local_area[W] == BALL) return(E); +if (local_area[SW] == BALL) return(DO_NOTHING); +if (local_area[NW] == BALL) return(DO_NOTHING); + +/* + * Just do the same thing as player1 + */ +return(UN(player1)(local_area, ball_direction, x, y)); +} + +/*----------------------------------------------------- + + player3() + +-----------------------------------------------------*/ +int UN(player3)(int local_area[9], int ball_direction, int x, int y) +{ +/* + * Just do the same thing as player1 + */ +return(UN(player2)(local_area, ball_direction, x, y)); + +/*if (x<60 && y==10) return(E); +if (x<60 && y>10) return(NE); +if (x<60 && y<10) return(SE); +if (x==60 && y==10) return(DO_NOTHING); +if (x==60 && y>10) return(N); +if (x==60 && y<10) return(S);*/ +} + +/*----------------------------------------------------- + + player4() + +-----------------------------------------------------*/ +int UN(player4)(int local_area[9], int ball_direction, int x, int y) +{ +/* + * Just do the same thing as player1 + */ +//return(UN(player1)(local_area, ball_direction, x, y)); + + if (x<65 && y==5) return(E); + if (x<65 && y>5) return(NE); + if (x<65 && y<5) return(SE); + if (x==65 && y==5) return(DO_NOTHING); + if (x==65 && y>5) return(N); + if (x==65 && y<5) return(S); +} + +/*----------------------------------------------------- + + team_name() + + Every team must have a name. Make sure it + is exactly 20 characters. Pad with spaces. + +-----------------------------------------------------*/ +char *UN(team_name)() +{ +char *s; + +/* "####################\0" <--- 20 characters */ +s = "Test Case 2 \0"; +return(s); +} + +/*--------------------------------------------- -------- + + initialize_game() + + This function is called only once per + game, before play begins. You can leave it + empty, or put code here to initialize your + variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_game)() +{ +} + +/*----------------------------------------------------- + + initialize_point() + + This function is called once per point, just + before play begins for that point. + You can leave it empty, or put code here to initialize + your variables, etc. + +-----------------------------------------------------*/ +void UN(initialize_point)() +{ +} + +/*----------------------------------------------------- + + lost_point() + + If your team loses a point, this function is + called, otherwise, if you win the point, won_point() + is called. You can leave it empty, or put code here + for negative re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(lost_point)() +{ +} + +/*----------------------------------------------------- + + won_point() + + If your team wins a point, this function is + called, otherwise, if you lose the point, lost_point() + is called. You can leave it empty, or put code here + for positive re-inforcement, etc. + +-----------------------------------------------------*/ +void UN(won_point)() +{ +} + +/*----------------------------------------------------- + + game_over() + + This function is called once at the end of + the match. You can leave it empty, or put code + here to save things to a file, etc. + +-----------------------------------------------------*/ +void UN(game_over)() +{ +} + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/makefile new file mode 100644 index 00000000..4c849a16 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/ascii-soccer/teams/testcase2/makefile @@ -0,0 +1,25 @@ +east.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DEAST_TEAM main.c -o east.o + +west.o: main.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM main.c -o west.o + +common.o: common.c ../../soccer.h ../../players.h + g++ -I../.. -c -DWEST_TEAM common.c -o common.o + +libwest.a: west.o + ar rc libwest.a west.o + ranlib libwest.a + +libeast.a: east.o + ar rc libeast.a east.o + ranlib libeast.a + +libcommon.a: common.o + ar rc libcommon.a common.o + ranlib libcommon.a + +clean: + rm -f *.o + rm -f *.a + rm -f core diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/licence.txt b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/licence.txt new file mode 100644 index 00000000..af98cc67 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/licence.txt @@ -0,0 +1,40 @@ +---------------------------------------------------------------------- +Copyright (c) 2002-2009 XABSL Developer Team +www.xabsl.de + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +3. The end-user documentation included with the redistribution, if + any, must include the following acknowledgment: + "This product includes XABSL developed by Martin Loetzsch, + Max Risler and Matthias Juengel + (http://www.xabsl.de)." + Alternately, this acknowledgment may appear in the software + itself, if and wherever such third-party acknowledgments + normally appear. + +THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY +EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +---------------------------------------------------------------------- diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/makefile b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/makefile new file mode 100644 index 00000000..8ba714ae --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/makefile @@ -0,0 +1,65 @@ +# makefile +# +# author: Martin Loetzsch +# +# compiles the XABSL example agent team, comiles an opponent team, compiles the ascii-soccer environment, +# and linkes all together. +# +# The standard opponent team is "spaniels". You can change this by invoking the makefile with +# make opponent-team=other_team_directory + +opponent-team=rollers + +compile-xabsl-files=ascii-soccer/intermediate-code.dat +compile-soccer=ascii-soccer/soccer.exe +copy-xabsl-team=ascii-soccer/libeastcommon.a ascii-soccer/libeast.a +compile-xabsl-team=XabslExampleAgentTeam/Build/libcommon.a XabslExampleAgentTeam/Build/libeast.a +copy-opponent-team=ascii-soccer/last-linked-opponent-team-was-$(opponent-team) ascii-soccer/libwestcommon.a ascii-soccer/libwest.a +compile-opponent-team=ascii-soccer/teams/$(opponent-team)/libcommon.a ascii-soccer/teams/$(opponent-team)/libwest.a + + +all: $(compile-xabsl-files) $(compile-soccer) + +$(compile-xabsl-files): XabslExampleAgentTeam/xabsl-src/*.xabsl XabslExampleAgentTeam/xabsl-src/Options/*.xabsl + @echo compiling XABSL source files and generating the intermediate code + @make -s -C Xabsl/compiler + @make -s -C XabslExampleAgentTeam/xabsl-src + +$(compile-soccer): $(copy-xabsl-team) $(copy-opponent-team) + @echo compiling and linking soccer + @make -s -C ascii-soccer soccer + +$(copy-xabsl-team): $(compile-xabsl-team) + @echo copying files for Xabsl example agent team + @cp XabslExampleAgentTeam/Build/libcommon.a ascii-soccer/libeastcommon.a + @cp XabslExampleAgentTeam/Build/libeast.a ascii-soccer + +$(compile-xabsl-team): XabslExampleAgentTeam/*.h XabslExampleAgentTeam/*.cpp + @echo compiling the Xabsl example agent team + @make -s -C XabslExampleAgentTeam + +$(copy-opponent-team): $(compile-opponent-team) + @echo copying files for "$(opponent-team)" team + @rm -f ascii-soccer/last-linked* + @cp ascii-soccer/teams/$(opponent-team)/libcommon.a ascii-soccer/libwestcommon.a + @cp ascii-soccer/teams/$(opponent-team)/libwest.a ascii-soccer/libwest.a + @echo foo > $(copy-opponent-team) + +$(compile-opponent-team): ascii-soccer/teams/$(opponent-team)/*.c + @echo compiling the "$(opponent-team)" team + @make -s -C ascii-soccer/teams/$(opponent-team) libwest.a + @make -s -C ascii-soccer/teams/$(opponent-team) libcommon.a + +DOC: + @make -s -C XabslExampleAgentTeam/xabsl-src DOC +clean: + @make -s -C XabslExampleAgentTeam clean + @make -s -C ascii-soccer clean + @make -s -C XabslExampleAgentTeam/xabsl-src clean + @make -s -C Xabsl/compiler clean + @rm -f ascii-soccer/last-linked* + @rm -f ascii-soccer/messages.log + @rm -f ascii-soccer/soccer.exe + @rm -f ascii-soccer/soccer + @find ascii-soccer/teams/ | grep "\.o" | sed "s%\([.]*\)%rm -f \1%" | bash + @find ascii-soccer/teams/ | grep "\.a" | sed "s%\([.]*\)%rm -f \1%" | bash diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/start-game.bash b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/start-game.bash new file mode 100644 index 00000000..0318c061 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/start-game.bash @@ -0,0 +1,13 @@ +#!/bin/bash + +if test -d ascii-soccer/teams/$1 && test $1; then + if (make -s opponent-team=$1); then + echo Starting the game + cd ascii-soccer + ./soccer -p 7 + fi; +else + echo usage: start-game.bash [teamname] + echo teams: `ls ascii-soccer/teams` + echo +fi diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml-1.2.spp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml-1.2.spp new file mode 100644 index 00000000..158b7d79 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml-1.2.spp @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml-1.2.xsd b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml-1.2.xsd new file mode 100644 index 00000000..30b5c244 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml-1.2.xsd @@ -0,0 +1,387 @@ + + + + A schema for a graph representation as used by the graph drawing tool 'dot' + (AT&T Bell Laboratories, http://www.research.att.com/sw/tools/graphviz/). + Please note that the dotml language covers only a subset of the dot language. + (c) 2002 Martin Lötzsch (martin@martin-loetzsch.de) + + + + + The root element of a 'dot' graph. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A rectangular cluster of nodes. + + + + + + + + + + + + + + The base class for clusters and graphs. + + + + + + A single node. + + + + + A rectangular cluster of nodes. + + + + + A group of nodes with rank constraints. + + + + + A record node. + + + + + An edge. + + + + + + + + + + + + A group of nodes with rank constraints + + + + + + A node of the sub-graph + + + + + A record node of the sub-graph + + + + + + + + + Represents a single node in the graph. + + + + + + + + + + Attributes that are used both by records and by nodes. + + + + + + + + + + + + The root element of a record. + + + + + + + + + + A record inside a record + + + + + + A node inside a record. + + + + + + + + + A record inside a record. + + + + + + + + Represents a single edge in the graph. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Possible node shapes. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Common font attributes + + + + + + + + The label attached to an object. + + + + + + The id of a node. + + + + + + A RGB color. + + + + + + + + The general layout direction of the graph. + + + + + + + + + The direction of edges. + + + + + + + + + + + Rank types for sub-graphs + + + + + + + + + + + + Possible types for edge arrows. + + + + + + + + + + + + + + + + + + + + + + + + The style of nodes or edges. + + + + + + + + + + + + + Port where an edge can atach to a node. + + + + + + + + + + + + + + + Describes a x-y point. + + + + + + + + The aspect ratio of a graph. + + + + + + + + + + The vertical cluster label location. + + + + + + + + + The horizontal cluster label location. + + + + + + + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml2dot.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml2dot.xsl new file mode 100644 index 00000000..8c7b3843 Binary files /dev/null and b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/dotml2dot.xsl differ diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/embed-svg-graphics.xsl b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/embed-svg-graphics.xsl new file mode 100644 index 00000000..215e9aa3 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/embed-svg-graphics.xsl @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + svg-size- + This browser can't display the SVG file + .svg.
+
The Adobe SVG Viewer 3.0 can be downloaded from http://www.adobe.com/svg/viewer/install/main.html +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/generate-svg-graphics.bash b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/generate-svg-graphics.bash new file mode 100644 index 00000000..ed203904 --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/generate-svg-graphics.bash @@ -0,0 +1,89 @@ +#!/bin/bash + +# +# file: generate-svg-graphics.bash +# author: Martin Loetzsch +# +# Generates for each DotML "graph" element in a XML document a SVG graphic and a +# CSS style sheet containing the width and the height of the graphic. +# +# First, the XSL style sheet dotml2dot.xsl is applied to the source XML file. +# It generates for each graph a notation that is understood by the 'dot' tool. +# Then, the dot tool generates the SVG graphics from the output of the XSLT +# transformation. The file names for the .svg files are taken from the "file-name" +# attribute of the DotML "graph" element in the source XML file. +# +# As at the moment most of the HTML browsers can't scale SVG graphics automatically, +# a CSS file that only contains the width and the height for each .svg file is also +# generated. +# +# Usage: generate-svg-graphics.bash SOURCE_XML_FILE OUTPUT_DIR +# SOURCE_XML_FILE can contain one or more elements "graph" from the dotml namespace +# at any position. OUTPUT_DIR is the directory where the images are stored. +# +# The following environment variables have to be set: +# - "DOT": the executable Graphviz dot tool. If not defined, "dot" is used. +# - "DOTML_DIR": the directory of "dotml2dot.xsl" +# - "DOTML_XSLT": a parameterized call of a XSLT processor of your choice. +# Use the string "(INPUT)" for as a placeholder for the input XML file +# and the string "(XSL)" for the stylesheet. +# Examples: +# export DOTML_XSLT="Xalan -XD -Q -IN (INPUT) -XSL (XSL)" +# export DOTML_XSLT="MyXSLTProcessor (INPUT) (XSL)" +# Set the parameters of the XSLT processor such that the output is written to stdout +# + +if test $1'x' = 'x'; then + echo "generate-svg-graphics.bash: Parameter 1 (input XML file) is missing." +else + if !(test -e $1); then + echo "generate-svg-graphics.bash: Input file $1 does not exist" + else + if test $2'x' = 'x'; then + echo "generate-svg-graphics.bash: Parameter 2 (output directory) is missing." + else + if !(test -d $2); then + echo "generate-svg-graphics.bash: Output directory $2 does not exist" + else + if !(test -e $DOTML_DIR/dotml2dot.xsl); then + echo "generate-svg-graphics.bash: Environment variable DOTML_DIR (path to DotML stylesheets) was not set correct. (Can't find dotml2dot.xsl there.)" + else + if test "$DOTML_XSLT"'x' = 'x'; then + echo "generate-svg-graphics.bash: Environment variable DOTML_XSLT (executable XSLT processor with parameters) was not set." + else + if test $DOT'x' = 'x'; then + export DOT=dot + fi + input=$(echo $1 | sed "s/\//\\\\\//g") + dotml_dir=$(echo $DOTML_DIR | sed "s/\//\\\\\//g") + output_dir=$(echo $2 | sed "s/\//\\\\\//g") + xslt=$(echo $DOTML_XSLT | sed "s/(INPUT)/$input/;s/(XSL)/$dotml_dir\/dotml2dot.xsl/;") + + $xslt \ + | sed -n \ + "s/\"/\\\\\\\"/g; \ + s/^[ ]*digraph/echo \"digraph/; \ + s/\([^<]*\)<\/dot-filename>/ \ + \" > $output_dir\/\1.dot.new \; \ + echo $output_dir\/\1.dot \; \ + if ! test -f $output_dir\/\1.dot\; then echo new > $output_dir\/\1.dot\; fi\; \ + diff -q $output_dir\/\1.dot $output_dir\/\1.dot.new >\& \/dev\/null \ + || \(echo $output_dir\/\1.svg \; \ + \$DOT -Tsvg -o $output_dir\/\1.svg $output_dir\/\1.dot.new\; \ + echo $output_dir\/\1.size.css \; \ + mv $output_dir\/\1.dot.new $output_dir\/\1.dot\; \ + echo .svg-size-\$(echo \1 | sed \"s\/.*\\\\\/\/\/\;\"\ + ){\$(cat $output_dir\/\1.svg \ + | grep \" $output_dir\/\1.size.css\)/;\ + p;" \ + | bash + fi + fi + fi + fi + fi +fi + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/licence.txt b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/licence.txt new file mode 100644 index 00000000..5afd97dd --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XABSL-Soccer2011/util/dotml-1.2/licence.txt @@ -0,0 +1,34 @@ +Copyright (c) 2002-2004 Martin Loetzsch. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +3. The end-user documentation included with the redistribution, if + any, must include the following acknowledgment: + "This product includes DOTML developed by Martin Loetzsch + (http://www.martin-loetzsch.de/DOTML)." + Alternately, this acknowledgment may appear in the software + itself, if and wherever such third-party acknowledgments + normally appear. + +THIS SOFTWARE IS PROVIDED BY MARTIN LOETZSCH ``AS IS'' AND ANY +EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARTIN LOETZSCH BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XabslEditor.jnlp b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XabslEditor.jnlp new file mode 100644 index 00000000..de695e9d --- /dev/null +++ b/ws2011/CE/Uebungen/1. Programmieraufgabe/XABSL-Soccer2011/XabslEditor.jnlp @@ -0,0 +1,36 @@ + + + + XabslEditor + NaoTeam Humboldt + + The XabslEditor is a graphical editor for the "Extensible Agent Behavior Specification Language" XABSL. + XabslEditor + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ws2011/CE/Uebungen/uebung_01.zip b/ws2011/CE/Uebungen/uebung_01.zip deleted file mode 100644 index 5a670ca1..00000000 Binary files a/ws2011/CE/Uebungen/uebung_01.zip and /dev/null differ diff --git a/ws2011/CE/Uebungen/uebung_2.pdf b/ws2011/CE/Uebungen/uebung_2.pdf new file mode 100644 index 00000000..d6f896ab Binary files /dev/null and b/ws2011/CE/Uebungen/uebung_2.pdf differ diff --git a/ws2011/FOC/Folien/Module02-Modellierung1-v1.0.pdf b/ws2011/FOC/Folien/Module02-Modellierung1-v1.0.pdf new file mode 100644 index 00000000..d7545e14 Binary files /dev/null and b/ws2011/FOC/Folien/Module02-Modellierung1-v1.0.pdf differ diff --git a/ws2011/FOC/Uebungen/Loesung00-v1.0.pdf b/ws2011/FOC/Uebungen/Loesung00-v1.0.pdf new file mode 100644 index 00000000..f040c143 Binary files /dev/null and b/ws2011/FOC/Uebungen/Loesung00-v1.0.pdf differ diff --git a/ws2011/FOC/Uebungen/Uebung02-v1.0.pdf b/ws2011/FOC/Uebungen/Uebung02-v1.0.pdf new file mode 100644 index 00000000..5482d949 Binary files /dev/null and b/ws2011/FOC/Uebungen/Uebung02-v1.0.pdf differ