Browse Source

more parsing games

David Rose 21 years ago
parent
commit
b020b2047a

+ 45 - 21
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

+ 8 - 3
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<WindowsGuid, XFileTemplate *> TemplatesByGuid;
-  TemplatesByGuid _templates_by_guid;
+  typedef pmap<WindowsGuid, XFileNode *> 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"

+ 51 - 3
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];
+}

+ 12 - 3
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:

+ 116 - 1
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);
+}

+ 33 - 0
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();
+}

+ 24 - 2
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;

+ 72 - 2
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;
+}

+ 37 - 1
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<ParseData> ParseDataList;
+  ParseDataList _parse_data_list;
   
 public:
   static TypeHandle get_class_type() {

+ 55 - 1
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;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////

+ 11 - 2
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<string, XFileNode *> ChildrenByName;
   ChildrenByName _children_by_name;
-  
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 0 - 10
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

+ 22 - 2
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

+ 3 - 2
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;

+ 4 - 4
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;
 }

+ 76 - 10
pandatool/src/xfile/xParser.yxx

@@ -98,6 +98,8 @@ x_cleanup_parser() {
 %type <str> string
 %type <guid> class_id
 %type <guid> optional_class_id
+%type <u.separator> list_separator
+%type <u.node> 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 = $<u.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, $<u.separator>1);
 }
         | realnum_list
 {
+  XFileDataObjectTemplate *current_template = 
+    DCAST(XFileDataObjectTemplate, current_node);
+  current_template->add_parse_double($1, $<u.separator>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:

+ 1 - 1
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;