Browse Source

make an effort to use the official grammar

David Rose 21 years ago
parent
commit
365a7db25f

+ 6 - 2
pandatool/src/xfile/xFileDataDef.cxx

@@ -92,8 +92,12 @@ write_text(ostream &out, int indent_level) const {
     out << "UCHAR";
     out << "UCHAR";
     break;
     break;
 
 
-  case T_byte:
-    out << "BYTE";
+  case T_sword:
+    out << "SWORD";
+    break;
+
+  case T_sdword:
+    out << "SDWORD";
     break;
     break;
 
 
   case T_string:
   case T_string:

+ 2 - 1
pandatool/src/xfile/xFileDataDef.h

@@ -41,7 +41,8 @@ public:
     T_double,
     T_double,
     T_char,
     T_char,
     T_uchar,
     T_uchar,
-    T_byte,
+    T_sword,
+    T_sdword,
     T_string,
     T_string,
     T_cstring,
     T_cstring,
     T_unicode,
     T_unicode,

+ 15 - 17
pandatool/src/xfile/xFileTemplate.I

@@ -32,7 +32,7 @@ get_guid() const {
 //       Access: Public
 //       Access: Public
 //  Description: Sets whether the template is considered "open" or
 //  Description: Sets whether the template is considered "open" or
 //               not.  If it is open (this flag is true), the set of
 //               not.  If it is open (this flag is true), the set of
-//               restrictions is ignored and the instances of this
+//               options is ignored and the instances of this
 //               template may include any types of children.  If it is
 //               template may include any types of children.  If it is
 //               closed (false), only the named types may be added.
 //               closed (false), only the named types may be added.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -46,7 +46,7 @@ set_open(bool open) {
 //       Access: Public
 //       Access: Public
 //  Description: Returns whether the template is considered "open" or
 //  Description: Returns whether the template is considered "open" or
 //               not.  If it is open (this flag is true), the set of
 //               not.  If it is open (this flag is true), the set of
-//               restrictions is ignored and the instances of this
+//               options is ignored and the instances of this
 //               template may include any types of children.  If it is
 //               template may include any types of children.  If it is
 //               closed (false), only the named types may be added.
 //               closed (false), only the named types may be added.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -56,36 +56,34 @@ get_open() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: XFileTemplate::add_restriction
+//     Function: XFileTemplate::add_option
 //       Access: Public
 //       Access: Public
 //  Description: Adds a new type to the list of allowable types of
 //  Description: Adds a new type to the list of allowable types of
-//               child nodes for an instance of this template.  The
-//               method is a little misnamed; we are actually removing
-//               a restriction by adding this type to the list.
+//               child nodes for an instance of this template.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void XFileTemplate::
 INLINE void XFileTemplate::
-add_restriction(XFileTemplate *restriction) {
-  _restrictions.push_back(restriction);
+add_option(XFileTemplate *option) {
+  _options.push_back(option);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: XFileTemplate::get_num_restrictions
+//     Function: XFileTemplate::get_num_options
 //       Access: Public
 //       Access: Public
-//  Description: Returns the number of templates on the restrictions
+//  Description: Returns the number of templates on the options
 //               list.
 //               list.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int XFileTemplate::
 INLINE int XFileTemplate::
-get_num_restrictions() const {
-  return _restrictions.size();
+get_num_options() const {
+  return _options.size();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: XFileTemplate::get_restriction
+//     Function: XFileTemplate::get_option
 //       Access: Public
 //       Access: Public
-//  Description: Returns the nth template on the restrictions list.
+//  Description: Returns the nth template on the options list.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE XFileTemplate *XFileTemplate::
 INLINE XFileTemplate *XFileTemplate::
-get_restriction(int n) const {
-  nassertr(n >= 0 && n < (int)_restrictions.size(), NULL);
-  return _restrictions[n];
+get_option(int n) const {
+  nassertr(n >= 0 && n < (int)_options.size(), NULL);
+  return _options[n];
 }
 }

+ 6 - 6
pandatool/src/xfile/xFileTemplate.cxx

@@ -53,7 +53,7 @@ XFileTemplate::
 void XFileTemplate::
 void XFileTemplate::
 clear() {
 clear() {
   XFileNode::clear();
   XFileNode::clear();
-  _restrictions.clear();
+  _options.clear();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -76,16 +76,16 @@ write_text(ostream &out, int indent_level) const {
     indent(out, indent_level + 2)
     indent(out, indent_level + 2)
       << "[ ... ]\n";
       << "[ ... ]\n";
 
 
-  } else if (!_restrictions.empty()) {
+  } else if (!_options.empty()) {
     // A restricted template
     // A restricted template
     indent(out, indent_level + 2);
     indent(out, indent_level + 2);
 
 
     char delimiter = '[';
     char delimiter = '[';
-    Restrictions::const_iterator ri;
-    for (ri = _restrictions.begin(); ri != _restrictions.end(); ++ri) {
-      XFileTemplate *restriction = (*ri);
+    Options::const_iterator ri;
+    for (ri = _options.begin(); ri != _options.end(); ++ri) {
+      XFileTemplate *option = (*ri);
       out << delimiter << " " 
       out << delimiter << " " 
-          << restriction->get_name() << " <" << restriction->get_guid()
+          << option->get_name() << " <" << option->get_guid()
           << ">";
           << ">";
       delimiter = ',';
       delimiter = ',';
     }
     }

+ 5 - 5
pandatool/src/xfile/xFileTemplate.h

@@ -43,16 +43,16 @@ public:
   INLINE void set_open(bool open);
   INLINE void set_open(bool open);
   INLINE bool get_open() const;
   INLINE bool get_open() const;
 
 
-  INLINE void add_restriction(XFileTemplate *restriction);
-  INLINE int get_num_restrictions() const;
-  INLINE XFileTemplate *get_restriction(int n) const;
+  INLINE void add_option(XFileTemplate *option);
+  INLINE int get_num_options() const;
+  INLINE XFileTemplate *get_option(int n) const;
   
   
 private:
 private:
   WindowsGuid _guid;
   WindowsGuid _guid;
   bool _open;
   bool _open;
 
 
-  typedef pvector< PT(XFileTemplate) > Restrictions;
-  Restrictions _restrictions;
+  typedef pvector< PT(XFileTemplate) > Options;
+  Options _options;
   
   
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 123 - 60
pandatool/src/xfile/xLexer.lxx

@@ -10,6 +10,7 @@
 #include "xParserDefs.h"
 #include "xParserDefs.h"
 #include "xParser.h"
 #include "xParser.h"
 #include "indent.h"
 #include "indent.h"
+#include "string_utils.h"
 #include "notify.h"
 #include "notify.h"
 
 
 static int yyinput(void);        // declared by flex.
 static int yyinput(void);        // declared by flex.
@@ -340,6 +341,42 @@ scan_guid_string() {
   return result;
   return result;
 }
 }
 
 
+// Parses the text into a list of integers and returns them.
+static PTA_int
+parse_int_list(const string &text, const string &delimiter) {
+  PTA_int result;
+
+  vector_string words;
+  tokenize(text, words, delimiter);
+
+  vector_string::const_iterator wi;
+  for (wi = words.begin(); wi != words.end(); ++wi) {
+    int number = 0;
+    string_to_int(*wi, number);
+    result.push_back(number);
+  }
+
+  return result;
+}
+
+// Parses the text into a list of doubles and returns them.
+static PTA_double
+parse_double_list(const string &text, const string &delimiter) {
+  PTA_double result;
+
+  vector_string words;
+  tokenize(text, words, delimiter);
+
+  vector_string::const_iterator wi;
+  for (wi = words.begin(); wi != words.end(); ++wi) {
+    double number = 0;
+    string_to_double(*wi, number);
+    result.push_back(number);
+  }
+
+  return result;
+}
+
 
 
 
 
 // accept() is called below as each piece is pulled off and
 // accept() is called below as each piece is pulled off and
@@ -351,7 +388,6 @@ inline void accept() {
 %}
 %}
 
 
 INTEGERNUM           ([+-]?([0-9]+))
 INTEGERNUM           ([+-]?([0-9]+))
-UNSIGNED_HEXNUM      (0x[0-9a-fA-F]*)
 REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
 REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
 
 
 %%
 %%
@@ -388,128 +424,161 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
   accept();
   accept();
 }
 }
 
 
+"{" {
+  accept();
+  return TOKEN_OBRACE;
+}
 
 
-"array" {
+"}" {
+  accept();
+  return TOKEN_CBRACE;
+}
+
+"[" {
+  accept();
+  return TOKEN_OBRACKET;
+}
+
+"]" {
+  accept();
+  return TOKEN_CBRACKET;
+}
+
+"." {
+  accept();
+  return TOKEN_DOT;
+}
+
+"," {
   accept();
   accept();
-  return KW_ARRAY;
+  return TOKEN_COMMA;
 }
 }
 
 
-"binary" {
+";" {
   accept();
   accept();
-  return KW_BINARY;
+  return TOKEN_SEMICOLON;
+}
+
+"array" {
+  accept();
+  return TOKEN_ARRAY;
 }
 }
 
 
 "byte" {
 "byte" {
   accept();
   accept();
-  return KW_BYTE;
+  return TOKEN_UCHAR;
 }
 }
 
 
 "char" {
 "char" {
   accept();
   accept();
-  return KW_CHAR;
+  return TOKEN_CHAR;
 }
 }
 
 
 "cstring" {
 "cstring" {
   accept();
   accept();
-  return KW_CSTRING;
+  return TOKEN_CSTRING;
 }
 }
 
 
 "double" {
 "double" {
   accept();
   accept();
-  return KW_DOUBLE;
+  return TOKEN_DOUBLE;
 }
 }
 
 
 "dword" {
 "dword" {
   accept();
   accept();
-  return KW_DWORD;
+  return TOKEN_DWORD;
+}
+
+"sdword" {
+  accept();
+  return TOKEN_SDWORD;
 }
 }
 
 
 "float" {
 "float" {
   accept();
   accept();
-  return KW_FLOAT;
+  return TOKEN_FLOAT;
 }
 }
 
 
 "string" {
 "string" {
   accept();
   accept();
-  return KW_STRING;
+  return TOKEN_LPSTR;
 }
 }
 
 
 "template" {
 "template" {
   accept();
   accept();
-  return KW_TEMPLATE;
+  return TOKEN_TEMPLATE;
 }
 }
 
 
 "uchar" {
 "uchar" {
   accept();
   accept();
-  return KW_UCHAR;
+  return TOKEN_UCHAR;
 }
 }
 
 
 "unicode" {
 "unicode" {
   accept();
   accept();
-  return KW_UNICODE;
+  return TOKEN_UNICODE;
+}
+
+"sword" {
+  accept();
+  return TOKEN_SWORD;
 }
 }
 
 
 "word" {
 "word" {
   accept();
   accept();
-  return KW_WORD;
+  return TOKEN_WORD;
 }
 }
 
 
 {INTEGERNUM} { 
 {INTEGERNUM} { 
   // A signed or unsigned integer number.
   // A signed or unsigned integer number.
   accept();
   accept();
-  xyylval.u.s_int = atol(xyytext); 
+  xyylval.u.number = atol(xyytext); 
   xyylval.str = yytext;
   xyylval.str = yytext;
 
 
-  return INTEGER;
+  return TOKEN_INTEGER;
 }
 }
 
 
-{UNSIGNED_HEXNUM} {
-  // A hexadecimal integer number.
+({INTEGERNUM};)+ { 
+  // An integer as part of a semicolon-delimited list.
+  accept();
+  xyylval.int_list = parse_int_list(xyytext, ";");
+  xyylval.u.separator_token = TOKEN_SEMICOLON;
+
+  return TOKEN_INTEGER_LIST;
+}
+
+({REALNUM};)+ { 
+  // A floating-point number as part of a semicolon-delimited list.
   accept(); 
   accept(); 
+  xyylval.double_list = parse_double_list(xyytext, ";");
+  xyylval.u.separator_token = TOKEN_SEMICOLON;
 
 
-  // As above, we'll decode the hex string by hand.
-  xyylval.str = xyytext;
-  xyylval.u.s_int = 0;
-  const char *p = xyytext + 2;
-  while (*p != '\0') {
-    int next_value = xyylval.u.s_int * 16;
-    if (next_value < xyylval.u.s_int) {
-      xyyerror("Number out of range.");
-      xyylval.u.s_int = 1;
-      return INTEGER;
-    }
+  return TOKEN_REALNUM_LIST;
+}
 
 
-    if (isalpha(*p)) {
-      xyylval.u.s_int = next_value + (tolower(*p) - 'a' + 10);
-    } else {
-      xyylval.u.s_int = next_value + (*p - '0');
-    }
-    ++p;
-  }
+({INTEGERNUM},)+ { 
+  // An integer as part of a semicolon-delimited list.
+  accept();
+  xyylval.int_list = parse_int_list(xyytext, ",");
+  xyylval.u.separator_token = TOKEN_COMMA;
 
 
-  return INTEGER; 
+  return TOKEN_INTEGER_LIST;
 }
 }
 
 
-{REALNUM} { 
-  // A floating-point number.
+({REALNUM},)+ { 
+  // A floating-point number as part of a semicolon-delimited list.
   accept(); 
   accept(); 
-  xyylval.u.real = atof(xyytext); 
-  xyylval.str = xyytext;
-  return REAL; 
+  xyylval.double_list = parse_double_list(xyytext, ",");
+  xyylval.u.separator_token = TOKEN_COMMA;
+
+  return TOKEN_REALNUM_LIST;
 }
 }
 
 
 ["] {
 ["] {
   // Quoted string.
   // Quoted string.
   accept();
   accept();
   xyylval.str = scan_quoted_string('"');
   xyylval.str = scan_quoted_string('"');
-  return STRING;
-}
-
-['] {
-  // Single-quoted string.
-  accept();
-  xyylval.str = scan_quoted_string('\'');
-  return STRING;
+  return TOKEN_STRING;
 }
 }
 
 
 [<] {
 [<] {
@@ -521,20 +590,14 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
     xyyerror("Malformed GUID.");
     xyyerror("Malformed GUID.");
   }
   }
 
 
-  return WINDOWS_GUID;
+  return TOKEN_GUID;
 }
 }
 
 
 [A-Za-z_-][A-Za-z_0-9-]* { 
 [A-Za-z_-][A-Za-z_0-9-]* { 
   // Identifier.
   // Identifier.
   accept();
   accept();
   xyylval.str = xyytext;
   xyylval.str = xyytext;
-  return IDENTIFIER;
+  return TOKEN_NAME;
 }
 }
 
 
-
-. {
-  // Send any other printable character as itself.
-  accept(); 
-  return xyytext[0];
-}
   
   

+ 228 - 125
pandatool/src/xfile/xParser.yxx

@@ -3,6 +3,12 @@
 // 
 // 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
+// The grammar defined in this file is taken more-or-less from the
+// Microsoft DirectX File Format Specification document, version 1.13.
+// The document actually describes a slightly incomplete and incorrect
+// grammar, so small changes had to be made, but an attempt was made
+// to be as faithful as possible to the intention of the spec.
+
 %{
 %{
 #include "xLexerDefs.h"
 #include "xLexerDefs.h"
 #include "xParserDefs.h"
 #include "xParserDefs.h"
@@ -45,114 +51,184 @@ x_cleanup_parser() {
 
 
 %}
 %}
 
 
-%token <u.s_int> INTEGER
-%token <u.real> REAL
-%token <str> STRING IDENTIFIER
-%token <guid> WINDOWS_GUID
-
-%token KW_ARRAY 
-%token KW_BINARY
-%token KW_BYTE
-%token KW_CHAR
-%token KW_CSTRING
-%token KW_DOUBLE
-%token KW_DWORD
-%token KW_FLOAT
-%token KW_STRING
-%token KW_TEMPLATE
-%token KW_UCHAR
-%token KW_UNICODE
-%token KW_WORD
-
-%type <u.node> xtemplate
-%type <u.node> data_object
-%type <str> optional_identifier
+// These token values are taken from the DirectX spec; the particular
+// numeric values are useful when reading an .x file in binary mode
+// (which basically just streams the tokens retrieved by the lexer).
+
+%token <str> TOKEN_NAME 1
+%token <str> TOKEN_STRING 2
+%token <u.number> TOKEN_INTEGER 3
+%token <guid> TOKEN_GUID 5
+%token <int_list> TOKEN_INTEGER_LIST 6
+%token <double_list> TOKEN_REALNUM_LIST 7
+
+%token TOKEN_OBRACE 10
+%token TOKEN_CBRACE 11
+%token TOKEN_OPAREN 12
+%token TOKEN_CPAREN 13
+%token TOKEN_OBRACKET 14
+%token TOKEN_CBRACKET 15
+%token TOKEN_OANGLE 16
+%token TOKEN_CANGLE 17
+%token TOKEN_DOT 18
+%token TOKEN_COMMA 19
+%token TOKEN_SEMICOLON 20
+%token TOKEN_TEMPLATE 31
+%token TOKEN_WORD 40
+%token TOKEN_DWORD 41
+%token TOKEN_FLOAT 42
+%token TOKEN_DOUBLE 43
+%token TOKEN_CHAR 44
+%token TOKEN_UCHAR 45
+%token TOKEN_SWORD 46
+%token TOKEN_SDWORD 47
+%token TOKEN_VOID 48
+%token TOKEN_LPSTR 49
+%token TOKEN_UNICODE 50
+%token TOKEN_CSTRING 51
+%token TOKEN_ARRAY 52
+
+%type <u.node> template
+%type <u.node> object
+%type <u.primitive_type> primitive_type
+%type <int_list> integer_list
+%type <double_list> realnum_list
+%type <str> name
+%type <str> optional_name
+%type <guid> class_id
+%type <guid> optional_class_id
 
 
 %%
 %%
 
 
 xfile:
 xfile:
         empty
         empty
-        | xfile xtemplate
-        | xfile data_object
+        | xfile template
+        | xfile object
         ;
         ;
 
 
-xtemplate:
-	KW_TEMPLATE IDENTIFIER '{' WINDOWS_GUID
+template:
+	 TOKEN_TEMPLATE name TOKEN_OBRACE class_id
 {
 {
   $$ = current_node;
   $$ = current_node;
   XFileTemplate *templ = new XFileTemplate($2, $4);
   XFileTemplate *templ = new XFileTemplate($2, $4);
   current_node->add_child(templ);
   current_node->add_child(templ);
   current_node = templ;
   current_node = templ;
 }
 }
-	template_members template_restrictions '}'
+	 template_parts TOKEN_CBRACE
 {
 {
   $$ = current_node;
   $$ = current_node;
   current_node = $<u.node>5;
   current_node = $<u.node>5;
 }
 }
-	;
+         ;
 
 
-template_members:
-	empty
-	| template_members template_member ';'
-	;
+template_parts: 
+         template_members_part TOKEN_OBRACKET template_option_info TOKEN_CBRACKET
+         | template_members_list
+         ;
 
 
-template_member:
-        data_def
-        | KW_ARRAY data_def array_dimensions
-	;
+template_members_part: 
+         empty
+         | template_members_list
+         ;
 
 
-data_def:
-        KW_WORD optional_identifier
+template_option_info: 
+         ellipsis
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_word, $2);
-  current_node->add_child(current_data_def);
+  DCAST(XFileTemplate, current_node)->set_open(true);
 }
 }
-	| KW_DWORD optional_identifier
+         | template_option_list
+         ;
+                       
+template_members_list:
+         template_members
+         | template_members_list template_members
+         ;
+
+template_members: 
+         primitive
+         | array
+         | template_reference
+         ;
+
+primitive:
+         primitive_type optional_name TOKEN_SEMICOLON
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_dword, $2);
+  current_data_def = new XFileDataDef($1, $2);
   current_node->add_child(current_data_def);
   current_node->add_child(current_data_def);
 }
 }
-	| KW_FLOAT optional_identifier
+         ;
+
+array: 
+         TOKEN_ARRAY array_data_type dimension_list TOKEN_SEMICOLON
+         ;
+
+template_reference: 
+         name optional_name TOKEN_SEMICOLON
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_float, $2);
-  current_node->add_child(current_data_def);
+  XFileTemplate *xtemplate = x_file->find_template($1);
+  if (xtemplate == (XFileTemplate *)NULL) {
+    yyerror("Unknown template: " + $1);
+  } else {
+    current_data_def = new XFileDataDef(XFileDataDef::T_template, $2, xtemplate);
+    current_node->add_child(current_data_def);
+  }
 }
 }
-	| KW_DOUBLE optional_identifier
+         ;
+
+primitive_type:
+        TOKEN_WORD
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_double, $2);
-  current_node->add_child(current_data_def);
+  $$ = XFileDataDef::T_word;
 }
 }
-	| KW_CHAR optional_identifier
+        | TOKEN_DWORD
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_char, $2);
-  current_node->add_child(current_data_def);
+  $$ = XFileDataDef::T_dword;
 }
 }
-	| KW_UCHAR optional_identifier
+        | TOKEN_FLOAT
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_uchar, $2);
-  current_node->add_child(current_data_def);
+  $$ = XFileDataDef::T_float;
 }
 }
-	| KW_BYTE optional_identifier
+        | TOKEN_DOUBLE
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_byte, $2);
-  current_node->add_child(current_data_def);
+  $$ = XFileDataDef::T_double;
 }
 }
-	| KW_STRING optional_identifier
+        | TOKEN_CHAR
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_string, $2);
-  current_node->add_child(current_data_def);
+  $$ = XFileDataDef::T_char;
 }
 }
-	| KW_CSTRING optional_identifier
+        | TOKEN_UCHAR
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_cstring, $2);
-  current_node->add_child(current_data_def);
+  $$ = XFileDataDef::T_uchar;
+}
+        | TOKEN_SWORD
+{
+  $$ = XFileDataDef::T_sword;
+}
+        | TOKEN_SDWORD
+{
+  $$ = XFileDataDef::T_sdword;
 }
 }
-	| KW_UNICODE optional_identifier
+        | TOKEN_LPSTR
 {
 {
-  current_data_def = new XFileDataDef(XFileDataDef::T_unicode, $2);
+  $$ = XFileDataDef::T_string;
+}
+        | TOKEN_UNICODE
+{
+  $$ = XFileDataDef::T_unicode;
+}
+        | TOKEN_CSTRING
+{
+  $$ = XFileDataDef::T_cstring;
+}
+        ;
+
+array_data_type:
+        primitive_type name
+{
+  current_data_def = new XFileDataDef($1, $2);
   current_node->add_child(current_data_def);
   current_node->add_child(current_data_def);
 }
 }
-	| IDENTIFIER optional_identifier
+        | name name
 {
 {
   XFileTemplate *xtemplate = x_file->find_template($1);
   XFileTemplate *xtemplate = x_file->find_template($1);
   if (xtemplate == (XFileTemplate *)NULL) {
   if (xtemplate == (XFileTemplate *)NULL) {
@@ -162,58 +238,53 @@ data_def:
     current_node->add_child(current_data_def);
     current_node->add_child(current_data_def);
   }
   }
 }
 }
-	;
+        ;
 
 
-array_dimensions:
-	array_level
-	| array_dimensions array_level
-	;
+dimension_list:
+        dimension
+        | dimension_list dimension
+        ;
+
+dimension:
+        TOKEN_OBRACKET dimension_size TOKEN_CBRACKET
+        ;
 
 
-array_level:
-	'[' INTEGER ']'
+dimension_size:
+        TOKEN_INTEGER
 {
 {
-  current_data_def->add_array_def(XFileArrayDef($2));
+  current_data_def->add_array_def(XFileArrayDef($1));
 }
 }
-	| '[' IDENTIFIER ']'
+        | name
 {
 {
-  XFileNode *data_def = current_node->find_child($2);
+  XFileNode *data_def = current_node->find_child($1);
   if (data_def == (XFileNode *)NULL) {
   if (data_def == (XFileNode *)NULL) {
-    yyerror("Unknown identifier: " + $2);
+    yyerror("Unknown identifier: " + $1);
   } else {
   } else {
     current_data_def->add_array_def(XFileArrayDef(DCAST(XFileDataDef, data_def)));
     current_data_def->add_array_def(XFileArrayDef(DCAST(XFileDataDef, data_def)));
   }
   }
 }
 }
-	;
-
-template_restrictions:
-	empty
-	| '[' '.' '.' '.' ']'
-{
-  DCAST(XFileTemplate, current_node)->set_open(true);
-}
-        | '[' template_restriction_list ']'
-	;
+        ;
 
 
-template_restriction_list:
-        template_restriction_element
+template_option_list: 
+        template_option_part
 {
 {
 }
 }
-	| template_restriction_list ',' template_restriction_element
+        | template_option_list template_option_part
 {
 {
 }
 }
 	;
 	;
 
 
-template_restriction_element:
-	IDENTIFIER
+template_option_part:
+	name
 {
 {
   XFileTemplate *xtemplate = x_file->find_template($1);
   XFileTemplate *xtemplate = x_file->find_template($1);
   if (xtemplate == (XFileTemplate *)NULL) {
   if (xtemplate == (XFileTemplate *)NULL) {
     yyerror("Unknown template: " + $1);
     yyerror("Unknown template: " + $1);
   } else {
   } else {
-    DCAST(XFileTemplate, current_node)->add_restriction(xtemplate);
+    DCAST(XFileTemplate, current_node)->add_option(xtemplate);
   }
   }
 }
 }
-	| IDENTIFIER WINDOWS_GUID
+	| name TOKEN_GUID
 {
 {
   XFileTemplate *xtemplate = x_file->find_template($2);
   XFileTemplate *xtemplate = x_file->find_template($2);
   if (xtemplate == (XFileTemplate *)NULL) {
   if (xtemplate == (XFileTemplate *)NULL) {
@@ -223,13 +294,41 @@ template_restriction_element:
       xyywarning("GUID identifies template " + xtemplate->get_name() +
       xyywarning("GUID identifies template " + xtemplate->get_name() +
                  ", not " + $1);
                  ", not " + $1);
     }
     }
-    DCAST(XFileTemplate, current_node)->add_restriction(xtemplate);
+    DCAST(XFileTemplate, current_node)->add_option(xtemplate);
   }
   }
 }
 }
-	;
+        ;
+
+name: 
+        TOKEN_NAME
+        ;
+
+optional_name:
+        empty
+{
+  $$ = string();
+}
+        | name
+        ;
+
+class_id:
+  	TOKEN_GUID
+        ;
+
+optional_class_id: 
+        empty
+{
+  $$ = WindowsGuid();
+}
+        | class_id
+        ;
+
+ellipsis:
+        TOKEN_DOT TOKEN_DOT TOKEN_DOT
+        ;
 
 
-data_object:
-	IDENTIFIER optional_identifier '{'
+object:
+        name optional_name TOKEN_OBRACE
 {
 {
   XFileTemplate *xtemplate = x_file->find_template($1);
   XFileTemplate *xtemplate = x_file->find_template($1);
   $$ = current_node;
   $$ = current_node;
@@ -243,55 +342,59 @@ data_object:
     current_node = templ;
     current_node = templ;
   }
   }
 }
 }
-	data_object_members '}'
+	optional_class_id data_parts_list TOKEN_CBRACE
 {
 {
   $$ = current_node;
   $$ = current_node;
   current_node = $<u.node>4;
   current_node = $<u.node>4;
 }
 }
 	;
 	;
 
 
+data_parts_list:
+        data_part
+        | data_parts_list data_part
+        ;
 
 
-data_object_members:
-	empty
-	| data_object_members data_object_member
-	;
-
-data_object_member:
-	data_object
+data_part:
+        data_reference
 {
 {
 }
 }
-        | data_reference
+	| object
 {
 {
 }
 }
-	| INTEGER
+        | integer_list
 {
 {
 }
 }
-	| REAL
+        | realnum_list
 {
 {
 }
 }
-        | STRING
+	| string list_separator
 {
 {
 }
 }
-        | ';'
+        | list_separator
 {
 {
 }
 }
-        | ','
-{
-}
-	;
+        ;
+        
+integer_list:
+	TOKEN_INTEGER_LIST
+        ;
 
 
-data_reference:
-	'{' IDENTIFIER '}'
-	;
+realnum_list:
+	TOKEN_REALNUM_LIST
+        ;
 
 
-optional_identifier:
-	empty
-{
-  $$ = string();
-}
-	| IDENTIFIER
+string:
+	TOKEN_STRING
+        ;
+
+list_separator:
+	TOKEN_SEMICOLON
+	| TOKEN_COMMA
 	;
 	;
 
 
-empty:
+data_reference:
+	TOKEN_OBRACE name optional_class_id TOKEN_CBRACE
         ;
         ;
 
 
+empty:
+        ;

+ 8 - 3
pandatool/src/xfile/xParserDefs.h

@@ -20,8 +20,10 @@
 #define XPARSERDEFS_H
 #define XPARSERDEFS_H
 
 
 #include "pandatoolbase.h"
 #include "pandatoolbase.h"
-
 #include "windowsGuid.h"
 #include "windowsGuid.h"
+#include "xFileDataDef.h"
+#include "pta_int.h"
+#include "pta_double.h"
 
 
 class XFile;
 class XFile;
 class XFileNode;
 class XFileNode;
@@ -40,12 +42,15 @@ int xyyparse();
 class XTokenType {
 class XTokenType {
 public:
 public:
   union U {
   union U {
-    int s_int;
-    double real;
+    int number;
     XFileNode *node;
     XFileNode *node;
+    XFileDataDef::Type primitive_type;
+    int separator_token;  // This is filled in for double_list and int_list.
   } u;
   } u;
   string str;
   string str;
   WindowsGuid guid;
   WindowsGuid guid;
+  PTA_double double_list;
+  PTA_int int_list;
 };
 };
 
 
 // The yacc-generated code expects to use the symbol 'YYSTYPE' to
 // The yacc-generated code expects to use the symbol 'YYSTYPE' to