📄 predicate.hh
字号:
/* * Little Green BATS (2006) * * Authors: Martin Klomp (martin@ai.rug.nl) * Mart van de Sanden (vdsanden@ai.rug.nl) * Sander van Dijk (sgdijk@ai.rug.nl) * A. Bram Neijt (bneijt@gmail.com) * Matthijs Platje (mplatje@gmail.com) * * Date: September 14, 2006 * * Website: http://www.littlegreenbats.nl * * Comment: Please feel free to contact us if you have any * problems or questions about the code. * * * License: 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., 59 Temple Place - * Suite 330, Boston, MA 02111-1307, USA. * */#ifndef __INC_BATS_PREDICATE_HH_#define __INC_BATS_PREDICATE_HH_#include <string>#include <vector>#include <set>#include <list>#include <iosfwd>#include <clocale>#include <cassert>#include "aref.hh"#include "path.hh"//using namespace std;namespace bats { /**\brief Communication predicate wrapper * */ class Predicate; typedef aref<Predicate> rPredicate; /** * The Predicate class... * * Isues: * - Should a predicate be strongly typed? * * Predicate is a tree structure which is outputted by the parser and * can be used by the parser to generate the list like language that * is used for communication with the soccer server. * * The lisp like language looks like this: (foo (bar 10) (node leave)). * This is then parsed in a tree looking like this: * * <ul> * <li>foo * <ul> * <li>bar * <ul> * <li>"10"</li> * </ul> * </li> * <li>node * <ul> * <li>"leave"</li> * </ul> * </li> * </ul> * </li> * </ul> * * In short: [[foo [bar 10] [node leave]]] (I use different brackets to * specify the differense between the input lisp like language and the * tree that is generated). * If you look closely you will see that the tree has an extra root node. * The reason for this is that there can be more then one predicate per * parsed line; thus the root node acts as a list op predicates (and * actually has the type <i>type_list</i>). * * There are three types of nodes in a Predicate tree: type_node, type_list * and type_leave @see Type. * * <b>type_node</b> * <br> * This is a very straight forward tree node in the sense that it has a value (its * name) and one or more children (e.g. [node0 [node1 leave]], here node1 * is a child of node0 (and leave is a child of node1, but more on that * later). * * <b>type_leave</b> * <br> * This is a leave node. It has no children and only a value. This value * is always stored as a string, but can represent a string, an int and a * double value. Which can be gotten via the getStr(), getInt() or * getDouble() methods, or by using the type conversion operators * (e.g. Predicate p("100",type_leave); int v = p; // -> v = 100;). * * <b>type_list</b> * <br> * A list is a node without a value. The main use for it is to be able * to parse more then one predicate per line without changing the * apparent structure of the predicate (although it is internally different). * The line "(bla bla)(bar foo)" will be represented by the tree * [[bla bla][bar foo]] (pay attention to the extra '['s surrounding the * predicates). * List type nodes will also be treated differently by the select() and * selectAll() methods. */ class Predicate { friend std::ostream &operator<<(ostream &, Predicate const &); // (so the parser can interate trought the arguments). friend class Parser; // So aref can be used with objects of this class. friend class aref<Predicate>; unsigned ref_count; void incRef() { ref_count++; } bool decRef() { return --ref_count; } typedef std::vector<rPredicate> Children; // typedef multiset<rPredicate> Children; public: // typedef Children::iterator iterator; typedef Children::const_iterator iterator; /** * The predicate node types. */ enum Type { type_node, type_leave, type_list, }; static bool pred_comp(rPredicate const &p, std::string const &val) { return p->getStr() < val; } private: Type type; std::string value; Children children; void copy(Predicate const &_other); void destroy(); public: /** * @param _value specifies the value of the Predicate. * @param _type specifies the type of the Predicate @see Type. */ Predicate(std::string const &_value, Type _type = type_node) : ref_count(0), type(_type), value(_value) {}; /** * @param _type specifies the type of the Predicate. * @see Type */ Predicate(Type _type) : ref_count(0), type(_type) {}; Predicate(Predicate const &_other) { copy(_other); } ~Predicate() { destroy(); } Predicate &operator=(Predicate const &_other) { if (this != &_other) { destroy(); copy(_other); } return *this; } /** * Pushes a Predicate to the back of the children list. * * Note: no circular predicates should be created * (because they won't be destroyed automaticaly). */ // void push(rPredicate const &_msg) { children.insert(_msg); } void push(rPredicate const &_msg) { children.push_back(_msg); } /** * Gets the child with index @_id. */ rPredicate const &get(unsigned _id) { assert(_id < children.size()); return children[_id]; } rPredicate const &operator[](unsigned _id) { assert(_id < children.size()); return get(_id); } /** * @returns the number of children. */ unsigned size() const { return children.size(); } /** * The STL iterators. These return iterators to the children * container. */ iterator begin() const { return children.begin(); } iterator end() const { return children.end(); } /** * @returns true if the predicate node is a node (has a * meaningful value). */ bool isNode() const { return type == type_node; } /** * @returns true if the predicate node is a leave (has no * children). */ bool isLeave() const { return type == type_leave; } /** * @returns true if the predicate node is a list (has no * value). */ bool isList() const { return type == type_list; } /** * @returns true when the predicate has no value and no children. */ bool isEmpty() const { return (value.empty() && children.empty()); } /** * @returns the string value of argument @_name. */ std::string getStr() const { return value; } /** * @returns the int value of argument @_name. */ int getInt() const { return atoi(value.c_str()); } /** * @returns the double value of argument @_name. */ double getDouble() const { setlocale(LC_NUMERIC, "C"); return atof(value.c_str()); } /** * Conversion operators. */ operator std::string() const { return getStr(); } operator int() const { return getInt(); } operator double() const { return getDouble(); } bool operator<(Predicate const &other) const { return value < other.value; } bool operator==(Predicate const &other) const { return value == other.value; } /** * @returns the predicate's type. */ Type getType() const { return type; } /** * Finds all predicates with the name @_name and pushes them * into @_res. * @returns the number of hits. */ unsigned findAll(vector<rPredicate> &_res, std::string const &_name); /** * Finds the first predicate with the name @_name and returns it. */ rPredicate find(std::string const &_name); /** * Finds all predicates in the entier tree with the name @_name and pushes them * into @_res. * * Warning: If there is a loop in the tree, this function will * never exit! (but when parsed from a predicate there will never be a loop) * * @returns the number of hits. */ unsigned findAllDeep(vector<rPredicate> &_res, std::string const &_name); /** * Finds the first predicate in the entier tree with the name @_name and returns it. * * Warning: If there is a loop in the tree, this function will * never exit! * */ rPredicate findDeep(std::string const &_name); /** * Finds all the predicates that comply with the specified @_select string * and pushes them into @_res. * @return ths number of hits. */ unsigned selectAll(vector<rPredicate> &_res, Path const &_select); /** * @returns the first predicate that complies with @_select. */ rPredicate select(Path const &_select); /** * @returns a lisp like string of the Predicate without the * parentices of the list nodes. */ ostream &generate(std::ostream &_os) const; }; /** * So the predicate can be written to the stdout. */ std::ostream &operator<<(std::ostream &_os, Predicate const &_pred);};#endif // __INC_BATS_PREDICATE_HH_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -