From b020b2047a92e6691102ba6f8d77675f41460fa8 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 5 Oct 2004 06:12:50 +0000 Subject: [PATCH] more parsing games --- pandatool/src/xfile/xFile.cxx | 66 ++++++---- pandatool/src/xfile/xFile.h | 11 +- pandatool/src/xfile/xFileDataDef.I | 54 +++++++- pandatool/src/xfile/xFileDataDef.h | 15 ++- pandatool/src/xfile/xFileDataObject.I | 117 +++++++++++++++++- pandatool/src/xfile/xFileDataObject.cxx | 33 +++++ pandatool/src/xfile/xFileDataObject.h | 26 +++- .../src/xfile/xFileDataObjectTemplate.cxx | 74 ++++++++++- pandatool/src/xfile/xFileDataObjectTemplate.h | 38 +++++- pandatool/src/xfile/xFileNode.cxx | 56 ++++++++- pandatool/src/xfile/xFileNode.h | 13 +- pandatool/src/xfile/xFileTemplate.I | 10 -- pandatool/src/xfile/xFileTemplate.cxx | 24 +++- pandatool/src/xfile/xFileTemplate.h | 5 +- pandatool/src/xfile/xLexer.lxx | 8 +- pandatool/src/xfile/xParser.yxx | 84 +++++++++++-- pandatool/src/xfile/xParserDefs.h | 2 +- 17 files changed, 569 insertions(+), 67 deletions(-) diff --git a/pandatool/src/xfile/xFile.cxx b/pandatool/src/xfile/xFile.cxx index c5dda8576d..248185528f 100644 --- a/pandatool/src/xfile/xFile.cxx +++ b/pandatool/src/xfile/xFile.cxx @@ -20,6 +20,7 @@ #include "xParserDefs.h" #include "xLexerDefs.h" #include "xFileTemplate.h" +#include "xFileDataObject.h" #include "config_xfile.h" #include "standard_templates.h" #include "zStream.h" @@ -36,7 +37,7 @@ PT(XFile) XFile::_standard_templates; // Description: //////////////////////////////////////////////////////////////////// XFile:: -XFile() : XFileNode("") { +XFile() : XFileNode(this, "") { _major_version = 3; _minor_version = 2; _format_type = FT_text; @@ -53,21 +54,6 @@ XFile:: clear(); } -//////////////////////////////////////////////////////////////////// -// Function: XFile::add_child -// Access: Public, Virtual -// Description: Adds the indicated node as a child of this node. -//////////////////////////////////////////////////////////////////// -void XFile:: -add_child(XFileNode *node) { - XFileNode::add_child(node); - - if (node->is_of_type(XFileTemplate::get_class_type())) { - XFileTemplate *xtemplate = DCAST(XFileTemplate, node); - _templates_by_guid[xtemplate->get_guid()] = xtemplate; - } -} - //////////////////////////////////////////////////////////////////// // Function: XFile::clear // Access: Public, Virtual @@ -77,6 +63,8 @@ add_child(XFileNode *node) { void XFile:: clear() { XFileNode::clear(); + + _nodes_by_guid.clear(); } //////////////////////////////////////////////////////////////////// @@ -192,7 +180,7 @@ write(Filename filename) const { } //////////////////////////////////////////////////////////////////// -// function: XFile::write +// Function: XFile::write // Access: Public // Description: Writes a parseable description of all the known // nodes and templates to the stream. @@ -241,10 +229,11 @@ find_template(const string &name) const { //////////////////////////////////////////////////////////////////// XFileTemplate *XFile:: find_template(const WindowsGuid &guid) const { - TemplatesByGuid::const_iterator gi; - gi = _templates_by_guid.find(guid); - if (gi != _templates_by_guid.end()) { - return (*gi).second; + NodesByGuid::const_iterator gi; + gi = _nodes_by_guid.find(guid); + if (gi != _nodes_by_guid.end() && + (*gi).second->is_of_type(XFileTemplate::get_class_type())) { + return DCAST(XFileTemplate, (*gi).second); } const XFile *standard_templates = get_standard_templates(); @@ -255,6 +244,41 @@ find_template(const WindowsGuid &guid) const { return NULL; } +//////////////////////////////////////////////////////////////////// +// Function: XFile::find_data_object +// Access: Public +// Description: Returns the data object associated with the indicated +// name, if any, or NULL if none. +//////////////////////////////////////////////////////////////////// +XFileDataObject *XFile:: +find_data_object(const string &name) const { + XFileNode *child = find_descendent(name); + if (child != (XFileNode *)NULL && + child->is_of_type(XFileDataObject::get_class_type())) { + return DCAST(XFileDataObject, child); + } + + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFile::find_data_object +// Access: Public +// Description: Returns the data object associated with the indicated +// GUID, if any, or NULL if none. +//////////////////////////////////////////////////////////////////// +XFileDataObject *XFile:: +find_data_object(const WindowsGuid &guid) const { + NodesByGuid::const_iterator gi; + gi = _nodes_by_guid.find(guid); + if (gi != _nodes_by_guid.end() && + (*gi).second->is_of_type(XFileDataObject::get_class_type())) { + return DCAST(XFileDataObject, (*gi).second); + } + + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: XFile::write_text // Access: Public, Virtual diff --git a/pandatool/src/xfile/xFile.h b/pandatool/src/xfile/xFile.h index b9cc615fa5..1f029583ad 100644 --- a/pandatool/src/xfile/xFile.h +++ b/pandatool/src/xfile/xFile.h @@ -27,6 +27,7 @@ #include "pointerTo.h" class XFileTemplate; +class XFileDataObject; //////////////////////////////////////////////////////////////////// // Class : XFile @@ -39,7 +40,6 @@ public: XFile(); ~XFile(); - virtual void add_child(XFileNode *node); virtual void clear(); bool read(Filename filename); @@ -51,6 +51,9 @@ public: XFileTemplate *find_template(const string &name) const; XFileTemplate *find_template(const WindowsGuid &guid) const; + XFileDataObject *find_data_object(const string &name) const; + XFileDataObject *find_data_object(const WindowsGuid &guid) const; + virtual void write_text(ostream &out, int indent_level) const; enum FormatType { @@ -73,8 +76,8 @@ private: FormatType _format_type; FloatSize _float_size; - typedef pmap TemplatesByGuid; - TemplatesByGuid _templates_by_guid; + typedef pmap NodesByGuid; + NodesByGuid _nodes_by_guid; static PT(XFile) _standard_templates; @@ -94,6 +97,8 @@ public: private: static TypeHandle _type_handle; + + friend class XFileNode; }; #include "xFile.I" diff --git a/pandatool/src/xfile/xFileDataDef.I b/pandatool/src/xfile/xFileDataDef.I index 7c7331c1ab..92543fd6fb 100644 --- a/pandatool/src/xfile/xFileDataDef.I +++ b/pandatool/src/xfile/xFileDataDef.I @@ -23,10 +23,58 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE XFileDataDef:: -XFileDataDef(XFileDataDef::Type type, const string &name, - XFileTemplate *xtemplate) : - XFileNode(name), +XFileDataDef(XFile *x_file, const string &name, + XFileDataDef::Type type, XFileTemplate *xtemplate) : + XFileNode(x_file, name), _type(type), _template(xtemplate) { } + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataDef::get_data_type +// Access: Public +// Description: Returns the primitive type of this element, or +// T_template if this represents a nested template +// object. +//////////////////////////////////////////////////////////////////// +INLINE XFileDataDef::Type XFileDataDef:: +get_data_type() const { + return _type; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataDef::get_template +// Access: Public +// Description: If get_data_type() returned T_template, this returns +// the particular template pointer that this object +// represents. +//////////////////////////////////////////////////////////////////// +INLINE XFileTemplate *XFileDataDef:: +get_template() const { + return _template; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataDef::get_num_array_defs +// Access: Public +// Description: Returns the number of dimensions of array elements on +// this data object, or 0 if the data object is not an +// array. +//////////////////////////////////////////////////////////////////// +INLINE int XFileDataDef:: +get_num_array_defs() const { + return _array_def.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataDef::get_array_def +// Access: Public +// Description: Returns the description of the nth dimension of array +// elements on this data object. +//////////////////////////////////////////////////////////////////// +INLINE const XFileArrayDef &XFileDataDef:: +get_array_def(int i) const { + nassertr(i >= 0 && i < (int)_array_def.size(), _array_def[0]); + return _array_def[i]; +} diff --git a/pandatool/src/xfile/xFileDataDef.h b/pandatool/src/xfile/xFileDataDef.h index d08e15d791..c9c833e8b9 100644 --- a/pandatool/src/xfile/xFileDataDef.h +++ b/pandatool/src/xfile/xFileDataDef.h @@ -30,7 +30,10 @@ //////////////////////////////////////////////////////////////////// // Class : XFileDataDef // Description : A definition of a single data element appearing -// within a template record. +// within a template record. This class represents the +// *definition* of the data element (e.g. DWORD +// nVertices); see XFileDataObject for its *value* +// (e.g. 12). //////////////////////////////////////////////////////////////////// class XFileDataDef : public XFileNode { public: @@ -49,13 +52,19 @@ public: T_template, }; - INLINE XFileDataDef(Type type, const string &name, - XFileTemplate *xtemplate = NULL); + INLINE XFileDataDef(XFile *x_file, const string &name, + Type type, XFileTemplate *xtemplate = NULL); virtual ~XFileDataDef(); virtual void clear(); void add_array_def(const XFileArrayDef &array_def); + INLINE Type get_data_type() const; + INLINE XFileTemplate *get_template() const; + + INLINE int get_num_array_defs() const; + INLINE const XFileArrayDef &get_array_def(int i) const; + virtual void write_text(ostream &out, int indent_level) const; private: diff --git a/pandatool/src/xfile/xFileDataObject.I b/pandatool/src/xfile/xFileDataObject.I index a717d0f45d..884316414b 100644 --- a/pandatool/src/xfile/xFileDataObject.I +++ b/pandatool/src/xfile/xFileDataObject.I @@ -23,6 +23,121 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE XFileDataObject:: -XFileDataObject(const string &name) : XFileNode(name) +XFileDataObject(XFile *x_file, const string &name) : + XFileNode(x_file, name) { } + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::get_data_def +// Access: Public +// Description: Returns the data object that this object is +// represented by, if any, or NULL if there is none. +//////////////////////////////////////////////////////////////////// +INLINE XFileDataDef *XFileDataObject:: +get_data_def() const { + return _data_def; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::i +// Access: Public +// Description: Unambiguously returns the object's representation as +// an integer, or 0 if the object has no integer +// representation. See also the typecast operators, and +// get_data_def() to determine what kind of +// representation this object has. +//////////////////////////////////////////////////////////////////// +INLINE int XFileDataObject:: +i() const { + return as_integer_value(); +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::d +// Access: Public +// Description: Unambiguously returns the object's representation as +// a double, or 0.0 if the object has no double +// representation. See also the typecast operators, and +// get_data_def() to determine what kind of +// representation this object has. +//////////////////////////////////////////////////////////////////// +INLINE double XFileDataObject:: +d() const { + return as_double_value(); +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::s +// Access: Public +// Description: Unambiguously returns the object's representation as +// a string, or empty string if the object has no string +// representation. See also the typecast operators, and +// get_data_def() to determine what kind of +// representation this object has. +//////////////////////////////////////////////////////////////////// +INLINE string XFileDataObject:: +s() const { + return as_string_value(); +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::int typecast operator +// Access: Public +// Description: Returns the object's representation as an integer, or +// 0 if the object has no integer representation. +//////////////////////////////////////////////////////////////////// +INLINE XFileDataObject:: +operator int () const { + return as_integer_value(); +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::double typecast operator +// Access: Public +// Description: Returns the object's representation as a double, or +// 0.0 if the object has no integer representation. +//////////////////////////////////////////////////////////////////// +INLINE XFileDataObject:: +operator double () const { + return as_double_value(); +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::string typecast operator +// Access: Public +// Description: Returns the object's representation as a string, or +// empty string if the object has no string +// representation. +//////////////////////////////////////////////////////////////////// +INLINE XFileDataObject:: +operator string () const { + return as_string_value(); +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::operator [] (int) +// Access: Public +// Description: Returns the nth nested object within this object. +// Call get_num_children() to determine the number of +// nested objects. +//////////////////////////////////////////////////////////////////// +INLINE const XFileDataObject &XFileDataObject:: +operator [] (int n) const { + nassertr(n >= 0 && n < get_num_children(), *this); + return *DCAST(XFileDataObject, get_child(n)); +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::operator [] (string) +// Access: Public +// Description: Returns the named nested object within this object. +// It is an error if the named object does not exist. +// Call find_child() instead if there is any doubt. +//////////////////////////////////////////////////////////////////// +INLINE const XFileDataObject &XFileDataObject:: +operator [] (const string &name) const { + XFileNode *child = find_child(name); + nassertr(child != (XFileNode *)NULL, *this); + return *DCAST(XFileDataObject, child); +} diff --git a/pandatool/src/xfile/xFileDataObject.cxx b/pandatool/src/xfile/xFileDataObject.cxx index e465d646bb..b84969cf9a 100644 --- a/pandatool/src/xfile/xFileDataObject.cxx +++ b/pandatool/src/xfile/xFileDataObject.cxx @@ -19,3 +19,36 @@ #include "xFileDataObject.h" TypeHandle XFileDataObject::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::as_integer_value +// Access: Protected, Virtual +// Description: Returns the object's representation as an integer, if +// it has one. +//////////////////////////////////////////////////////////////////// +int XFileDataObject:: +as_integer_value() const { + return 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::as_double_value +// Access: Protected, Virtual +// Description: Returns the object's representation as a double, if +// it has one. +//////////////////////////////////////////////////////////////////// +double XFileDataObject:: +as_double_value() const { + return 0.0; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObject::as_string_value +// Access: Protected, Virtual +// Description: Returns the object's representation as a string, if +// it has one. +//////////////////////////////////////////////////////////////////// +string XFileDataObject:: +as_string_value() const { + return string(); +} diff --git a/pandatool/src/xfile/xFileDataObject.h b/pandatool/src/xfile/xFileDataObject.h index 88f711791d..f23593fe2a 100644 --- a/pandatool/src/xfile/xFileDataObject.h +++ b/pandatool/src/xfile/xFileDataObject.h @@ -21,6 +21,9 @@ #include "pandatoolbase.h" #include "xFileNode.h" +#include "xFileDataDef.h" +#include "pointerTo.h" +#include "dcast.h" //////////////////////////////////////////////////////////////////// // Class : XFileDataObject @@ -30,8 +33,27 @@ //////////////////////////////////////////////////////////////////// class XFileDataObject : public XFileNode { public: - INLINE XFileDataObject(const string &name); - + INLINE XFileDataObject(XFile *x_file, const string &name); + + INLINE XFileDataDef *get_data_def() const; + + INLINE int i() const; + INLINE double d() const; + INLINE string s() const; + INLINE operator int () const; + INLINE operator double () const; + INLINE operator string () const; + + INLINE const XFileDataObject &operator [] (int n) const; + INLINE const XFileDataObject &operator [] (const string &name) const; + +protected: + virtual int as_integer_value() const; + virtual double as_double_value() const; + virtual string as_string_value() const; + + PT(XFileDataDef) _data_def; + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/pandatool/src/xfile/xFileDataObjectTemplate.cxx b/pandatool/src/xfile/xFileDataObjectTemplate.cxx index de941d0831..b86913abe0 100644 --- a/pandatool/src/xfile/xFileDataObjectTemplate.cxx +++ b/pandatool/src/xfile/xFileDataObjectTemplate.cxx @@ -27,8 +27,9 @@ TypeHandle XFileDataObjectTemplate::_type_handle; // Description: //////////////////////////////////////////////////////////////////// XFileDataObjectTemplate:: -XFileDataObjectTemplate(XFileTemplate *xtemplate, const string &name) : - XFileDataObject(name), +XFileDataObjectTemplate(XFile *x_file, const string &name, + XFileTemplate *xtemplate) : + XFileDataObject(x_file, name), _template(xtemplate) { } @@ -51,3 +52,72 @@ write_text(ostream &out, int indent_level) const { indent(out, indent_level) << "}\n"; } + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObjectTemplate::add_parse_object +// Access: Public +// Description: Adds the indicated object as a nested object +// encountered in the parser. It will later be +// processed by finalize_parse_data(). +//////////////////////////////////////////////////////////////////// +void XFileDataObjectTemplate:: +add_parse_object(XFileDataObjectTemplate *object, bool reference) { +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObjectTemplate::add_parse_double +// Access: Public +// Description: Adds the indicated list of doubles as a data element +// encountered in the parser. It will later be +// processed by finalize_parse_data(). +//////////////////////////////////////////////////////////////////// +void XFileDataObjectTemplate:: +add_parse_double(PTA_double double_list, char separator) { +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObjectTemplate::add_parse_int +// Access: Public +// Description: Adds the indicated list of ints as a data element +// encountered in the parser. It will later be +// processed by finalize_parse_data(). +//////////////////////////////////////////////////////////////////// +void XFileDataObjectTemplate:: +add_parse_int(PTA_int int_list, char separator) { +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObjectTemplate::add_parse_string +// Access: Public +// Description: Adds the indicated string as a data element +// encountered in the parser. It will later be +// processed by finalize_parse_data(). +//////////////////////////////////////////////////////////////////// +void XFileDataObjectTemplate:: +add_parse_string(const string &str, char separator) { +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObjectTemplate::add_parse_separator +// Access: Public +// Description: Adds the indicated separator character as an isolated +// separator encountered in the parser. It will later +// be processed by finalize_parse_data(). +//////////////////////////////////////////////////////////////////// +void XFileDataObjectTemplate:: +add_parse_separator(char separator) { +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileDataObjectTemplate::finalize_parse_data +// Access: Public +// Description: Processes all of the data elements added by +// add_parse_*(), checks them for syntactic and semantic +// correctness against the Template definition, and +// stores the appropriate child data elements. Returns +// true on success, false if there is a mismatch. +//////////////////////////////////////////////////////////////////// +bool XFileDataObjectTemplate:: +finalize_parse_data() { + return true; +} diff --git a/pandatool/src/xfile/xFileDataObjectTemplate.h b/pandatool/src/xfile/xFileDataObjectTemplate.h index dc0c8001a8..10b1e67542 100644 --- a/pandatool/src/xfile/xFileDataObjectTemplate.h +++ b/pandatool/src/xfile/xFileDataObjectTemplate.h @@ -23,6 +23,8 @@ #include "xFileDataObject.h" #include "xFileTemplate.h" #include "pointerTo.h" +#include "pta_int.h" +#include "pta_double.h" //////////////////////////////////////////////////////////////////// // Class : XFileDataObjectTemplate @@ -34,14 +36,48 @@ //////////////////////////////////////////////////////////////////// class XFileDataObjectTemplate : public XFileDataObject { public: - XFileDataObjectTemplate(XFileTemplate *xtemplate, const string &name); + XFileDataObjectTemplate(XFile *x_file, const string &name, + XFileTemplate *xtemplate); INLINE XFileTemplate *get_template() const; virtual void write_text(ostream &out, int indent_level) const; +public: + void add_parse_object(XFileDataObjectTemplate *object, bool reference); + void add_parse_double(PTA_double double_list, char separator); + void add_parse_int(PTA_int int_list, char separator); + void add_parse_string(const string &str, char separator); + void add_parse_separator(char separator); + bool finalize_parse_data(); + private: PT(XFileTemplate) _template; + + // This class is used to fill up the data as the values are parsed. + // It only has a temporary lifespan; it will be converted into + // actual data by finalize_parse_data(). + enum ParseFlags { + PF_object = 0x001, + PF_reference = 0x002, + PF_double = 0x004, + PF_int = 0x008, + PF_string = 0x010, + PF_comma = 0x020, + PF_semicolon = 0x040, + }; + + class ParseData { + public: + PT(XFileDataObjectTemplate) _object; + PTA_double _double_list; + PTA_int _int_list; + string _string; + int _parse_flags; + }; + + typedef pvector ParseDataList; + ParseDataList _parse_data_list; public: static TypeHandle get_class_type() { diff --git a/pandatool/src/xfile/xFileNode.cxx b/pandatool/src/xfile/xFileNode.cxx index e4ef19a99b..cf2c0935f0 100644 --- a/pandatool/src/xfile/xFileNode.cxx +++ b/pandatool/src/xfile/xFileNode.cxx @@ -17,6 +17,8 @@ //////////////////////////////////////////////////////////////////// #include "xFileNode.h" +#include "windowsGuid.h" +#include "xFile.h" TypeHandle XFileNode::_type_handle; @@ -26,7 +28,9 @@ TypeHandle XFileNode::_type_handle; // Description: //////////////////////////////////////////////////////////////////// XFileNode:: -XFileNode(const string &name) : Namable(name) +XFileNode(XFile *x_file, const string &name) : + Namable(name), + _x_file(x_file) { } @@ -57,6 +61,53 @@ find_child(const string &name) const { return NULL; } +//////////////////////////////////////////////////////////////////// +// Function: XFileNode::find_descendent +// Access: Public +// Description: Returns the first child or descendent found with the +// indicated name after a depth-first search, if any, or +// NULL if none. +//////////////////////////////////////////////////////////////////// +XFileNode *XFileNode:: +find_descendent(const string &name) const { + XFileNode *child = find_child(name); + if (child != (XFileNode *)NULL) { + return child; + } + + Children::const_iterator ci; + for (ci = _children.begin(); ci != _children.end(); ++ci) { + XFileNode *child = (*ci)->find_descendent(name); + if (child != (XFileNode *)NULL){ + return child; + } + } + + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileNode::has_guid +// Access: Public, Virtual +// Description: Returns true if this node has a GUID associated. +//////////////////////////////////////////////////////////////////// +bool XFileNode:: +has_guid() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileNode::get_guid +// Access: Public, Virtual +// Description: If has_guid() returned true, returns the particular +// GUID associated with this node. +//////////////////////////////////////////////////////////////////// +const WindowsGuid &XFileNode:: +get_guid() const { + static WindowsGuid empty; + return empty; +} + //////////////////////////////////////////////////////////////////// // Function: XFileNode::add_child // Access: Public, Virtual @@ -68,6 +119,9 @@ add_child(XFileNode *node) { if (node->has_name()) { _children_by_name[node->get_name()] = node; } + if (node->has_guid()) { + _x_file->_nodes_by_guid[node->get_guid()] = node; + } } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/xfile/xFileNode.h b/pandatool/src/xfile/xFileNode.h index 5e445dd537..b61d41ecc1 100644 --- a/pandatool/src/xfile/xFileNode.h +++ b/pandatool/src/xfile/xFileNode.h @@ -27,6 +27,9 @@ #include "pvector.h" #include "pmap.h" +class XFile; +class WindowsGuid; + //////////////////////////////////////////////////////////////////// // Class : XFileNode // Description : A single node of an X file. This may be either a @@ -34,12 +37,16 @@ //////////////////////////////////////////////////////////////////// class XFileNode : public TypedReferenceCount, public Namable { public: - XFileNode(const string &name); + XFileNode(XFile *x_file, const string &name); virtual ~XFileNode(); INLINE int get_num_children() const; INLINE XFileNode *get_child(int n) const; XFileNode *find_child(const string &name) const; + XFileNode *find_descendent(const string &name) const; + + virtual bool has_guid() const; + virtual const WindowsGuid &get_guid() const; virtual void add_child(XFileNode *node); virtual void clear(); @@ -47,12 +54,14 @@ public: virtual void write_text(ostream &out, int indent_level) const; protected: + XFile *_x_file; + typedef pvector< PT(XFileNode) > Children; Children _children; typedef pmap ChildrenByName; ChildrenByName _children_by_name; - + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/pandatool/src/xfile/xFileTemplate.I b/pandatool/src/xfile/xFileTemplate.I index 72626b0623..598f31255b 100644 --- a/pandatool/src/xfile/xFileTemplate.I +++ b/pandatool/src/xfile/xFileTemplate.I @@ -17,16 +17,6 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: XFileTemplate::get_guid -// Access: Public -// Description: Returns the GUID associated with this template. -//////////////////////////////////////////////////////////////////// -INLINE const WindowsGuid &XFileTemplate:: -get_guid() const { - return _guid; -} - //////////////////////////////////////////////////////////////////// // Function: XFileTemplate::set_open // Access: Public diff --git a/pandatool/src/xfile/xFileTemplate.cxx b/pandatool/src/xfile/xFileTemplate.cxx index 79cdca4b58..f7f1f5a617 100644 --- a/pandatool/src/xfile/xFileTemplate.cxx +++ b/pandatool/src/xfile/xFileTemplate.cxx @@ -27,8 +27,8 @@ TypeHandle XFileTemplate::_type_handle; // Description: //////////////////////////////////////////////////////////////////// XFileTemplate:: -XFileTemplate(const string &name, const WindowsGuid &guid) : - XFileNode(name), +XFileTemplate(XFile *x_file, const string &name, const WindowsGuid &guid) : + XFileNode(x_file, name), _guid(guid), _open(false) { @@ -44,6 +44,26 @@ XFileTemplate:: clear(); } +//////////////////////////////////////////////////////////////////// +// Function: XFileTemplate::has_guid +// Access: Public, Virtual +// Description: Returns true if this node has a GUID associated. +//////////////////////////////////////////////////////////////////// +bool XFileTemplate:: +has_guid() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileTemplate::get_guid +// Access: Public, Virtual +// Description: Returns the GUID associated with this template. +//////////////////////////////////////////////////////////////////// +const WindowsGuid &XFileTemplate:: +get_guid() const { + return _guid; +} + //////////////////////////////////////////////////////////////////// // Function: XFileTemplate::clear // Access: Public, Virtual diff --git a/pandatool/src/xfile/xFileTemplate.h b/pandatool/src/xfile/xFileTemplate.h index 11236f4127..4bd32afa22 100644 --- a/pandatool/src/xfile/xFileTemplate.h +++ b/pandatool/src/xfile/xFileTemplate.h @@ -32,10 +32,11 @@ class XFileDataDef; //////////////////////////////////////////////////////////////////// class XFileTemplate : public XFileNode { public: - XFileTemplate(const string &name, const WindowsGuid &guid); + XFileTemplate(XFile *x_file, const string &name, const WindowsGuid &guid); virtual ~XFileTemplate(); - INLINE const WindowsGuid &get_guid() const; + virtual bool has_guid() const; + virtual const WindowsGuid &get_guid() const; virtual void clear(); virtual void write_text(ostream &out, int indent_level) const; diff --git a/pandatool/src/xfile/xLexer.lxx b/pandatool/src/xfile/xLexer.lxx index d5187927bd..2571346bc4 100644 --- a/pandatool/src/xfile/xLexer.lxx +++ b/pandatool/src/xfile/xLexer.lxx @@ -542,7 +542,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) // An integer as part of a semicolon-delimited list. accept(); xyylval.int_list = parse_int_list(xyytext, ";"); - xyylval.u.separator_token = TOKEN_SEMICOLON; + xyylval.u.separator = ';'; return TOKEN_INTEGER_LIST; } @@ -551,7 +551,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) // A floating-point number as part of a semicolon-delimited list. accept(); xyylval.double_list = parse_double_list(xyytext, ";"); - xyylval.u.separator_token = TOKEN_SEMICOLON; + xyylval.u.separator = ';'; return TOKEN_REALNUM_LIST; } @@ -560,7 +560,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) // An integer as part of a semicolon-delimited list. accept(); xyylval.int_list = parse_int_list(xyytext, ","); - xyylval.u.separator_token = TOKEN_COMMA; + xyylval.u.separator = ','; return TOKEN_INTEGER_LIST; } @@ -569,7 +569,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) // A floating-point number as part of a semicolon-delimited list. accept(); xyylval.double_list = parse_double_list(xyytext, ","); - xyylval.u.separator_token = TOKEN_COMMA; + xyylval.u.separator = ','; return TOKEN_REALNUM_LIST; } diff --git a/pandatool/src/xfile/xParser.yxx b/pandatool/src/xfile/xParser.yxx index d2bcfbdb09..472811da60 100644 --- a/pandatool/src/xfile/xParser.yxx +++ b/pandatool/src/xfile/xParser.yxx @@ -98,6 +98,8 @@ x_cleanup_parser() { %type string %type class_id %type optional_class_id +%type list_separator +%type data_reference %% @@ -111,7 +113,7 @@ template: TOKEN_TEMPLATE name TOKEN_OBRACE class_id { $$ = current_node; - XFileTemplate *templ = new XFileTemplate($2, $4); + XFileTemplate *templ = new XFileTemplate(x_file, $2, $4); current_node->add_child(templ); current_node = templ; } @@ -154,7 +156,7 @@ template_members: primitive: primitive_type optional_name TOKEN_SEMICOLON { - current_data_def = new XFileDataDef($1, $2); + current_data_def = new XFileDataDef(x_file, $2, $1); current_node->add_child(current_data_def); } ; @@ -170,7 +172,7 @@ template_reference: if (xtemplate == (XFileTemplate *)NULL) { yyerror("Unknown template: " + $1); } else { - current_data_def = new XFileDataDef(XFileDataDef::T_template, $2, xtemplate); + current_data_def = new XFileDataDef(x_file, $2, XFileDataDef::T_template, xtemplate); current_node->add_child(current_data_def); } } @@ -226,7 +228,7 @@ primitive_type: array_data_type: primitive_type name { - current_data_def = new XFileDataDef($1, $2); + current_data_def = new XFileDataDef(x_file, $2, $1); current_node->add_child(current_data_def); } | name name @@ -235,7 +237,7 @@ array_data_type: if (xtemplate == (XFileTemplate *)NULL) { yyerror("Unknown template: " + $1); } else { - current_data_def = new XFileDataDef(XFileDataDef::T_template, $2, xtemplate); + current_data_def = new XFileDataDef(x_file, $2, XFileDataDef::T_template, xtemplate); current_node->add_child(current_data_def); } } @@ -285,7 +287,7 @@ template_option_part: DCAST(XFileTemplate, current_node)->add_option(xtemplate); } } - | name TOKEN_GUID + | name class_id { XFileTemplate *xtemplate = x_file->find_template($2); if (xtemplate == (XFileTemplate *)NULL) { @@ -338,13 +340,19 @@ object: yyerror("Unknown template: " + $1); } else { XFileDataObjectTemplate *templ = - new XFileDataObjectTemplate(xtemplate, $2); + new XFileDataObjectTemplate(x_file, $2, xtemplate); current_node->add_child(templ); current_node = templ; } } optional_class_id data_parts_list TOKEN_CBRACE { + XFileDataObjectTemplate *current_template = + DCAST(XFileDataObjectTemplate, current_node); + if (!current_template->finalize_parse_data()) { + yyerror("Invalid data for object."); + } + $$ = current_node; current_node = $4; } @@ -356,23 +364,53 @@ data_parts_list: ; data_part: - data_reference + TOKEN_OBRACE data_reference TOKEN_CBRACE { + if ($2 != (XFileNode *)NULL) { + if (!$2->is_of_type(XFileDataObjectTemplate::get_class_type())) { + // Actually, maybe you can--the docs aren't clear about this. + // But I don't think there's any real reason to. + yyerror("Can't reference primitive data type."); + } else { + XFileDataObjectTemplate *object = + DCAST(XFileDataObjectTemplate, $2); + XFileDataObjectTemplate *current_template = + DCAST(XFileDataObjectTemplate, current_node); + current_template->add_parse_object(object, true); + } + } } | object { + XFileDataObjectTemplate *object = + DCAST(XFileDataObjectTemplate, $1); + XFileDataObjectTemplate *current_template = + DCAST(XFileDataObjectTemplate, current_node); + current_template->add_parse_object(object, false); } | integer_list { + XFileDataObjectTemplate *current_template = + DCAST(XFileDataObjectTemplate, current_node); + current_template->add_parse_int($1, $1); } | realnum_list { + XFileDataObjectTemplate *current_template = + DCAST(XFileDataObjectTemplate, current_node); + current_template->add_parse_double($1, $1); } | string list_separator { + XFileDataObjectTemplate *current_template = + DCAST(XFileDataObjectTemplate, current_node); + current_template->add_parse_string($1, $2); } | list_separator { + XFileDataObjectTemplate *current_template = + DCAST(XFileDataObjectTemplate, current_node); + current_template->add_parse_separator($1); } ; @@ -390,11 +428,39 @@ string: list_separator: TOKEN_SEMICOLON +{ + $$ = ';'; +} | TOKEN_COMMA +{ + $$ = ','; +} ; data_reference: - TOKEN_OBRACE name optional_class_id TOKEN_CBRACE + name +{ + XFileDataObject *data_object = x_file->find_data_object($1); + if (data_object == (XFileDataObject *)NULL) { + yyerror("Unknown data_object: " + $1); + } + + $$ = data_object; +} + | name class_id +{ + XFileDataObject *data_object = x_file->find_data_object($2); + if (data_object == (XFileDataObject *)NULL) { + yyerror("Unknown data_object: " + $1); + } else { + if (data_object->get_name() != $1) { + xyywarning("GUID identifies data_object " + data_object->get_name() + + ", not " + $1); + } + } + + $$ = data_object; +} ; empty: diff --git a/pandatool/src/xfile/xParserDefs.h b/pandatool/src/xfile/xParserDefs.h index 207a2f1dc2..38e32165fa 100644 --- a/pandatool/src/xfile/xParserDefs.h +++ b/pandatool/src/xfile/xParserDefs.h @@ -45,7 +45,7 @@ public: int number; XFileNode *node; XFileDataDef::Type primitive_type; - int separator_token; // This is filled in for double_list and int_list. + char separator; // This is filled in for double_list and int_list. } u; string str; WindowsGuid guid;