Przeglądaj źródła

support methods (atomic fields) as switch parameters

David Rose 20 lat temu
rodzic
commit
90c52414db

+ 21 - 2
direct/src/dcparser/dcParser.yxx

@@ -158,6 +158,7 @@ dc_cleanup_parser() {
 %type <u.parameter> parameter
 %type <u.parameter> parameter_with_default
 %type <u.parameter> parameter_definition
+%type <u.field> parameter_or_atomic
 %type <str> import_identifier
 %type <str> slash_identifier
 %type <str> optional_name
@@ -471,7 +472,13 @@ atomic_field:
         optional_name '('
 {
   $$ = current_atomic;
-  current_atomic = new DCAtomicField($1, current_class);
+  if (current_class == (DCClass *)NULL) {
+    yyerror("Cannot define a method outside of a struct or class.");
+    DCClass *temp_class = new DCClass(dc_file, "temp", false, false);  // memory leak.
+    current_atomic = new DCAtomicField($1, temp_class);
+  } else {
+    current_atomic = new DCAtomicField($1, current_class);
+  }
 }
         parameter_list ')'
 {
@@ -584,6 +591,17 @@ parameter_with_default:
         | unnamed_parameter_with_default
         ;
 
+parameter_or_atomic:
+        parameter
+{
+  $$ = $1;
+}
+        | atomic_field
+{
+  $$ = $1;
+}
+	;
+
 parameter_description:
 	atomic_field no_server_flags
 {
@@ -1211,7 +1229,7 @@ optional_name:
 	;
 
 switch:
-	KW_SWITCH optional_name '(' parameter ')' '{'
+	KW_SWITCH optional_name '(' parameter_or_atomic ')' '{'
 {
   $$ = current_switch;
   current_switch = new DCSwitch($2, $4);
@@ -1253,6 +1271,7 @@ switch_case:
 {
   if (!current_packer->end_pack()) {
     yyerror("Invalid value for switch parameter");
+    current_switch->add_invalid_case();
   } else {
     int case_index = current_switch->add_case(current_packer->get_string());
     if (case_index == -1) {

+ 21 - 4
direct/src/dcparser/dcSwitch.cxx

@@ -31,7 +31,7 @@
 //               destructs.
 ////////////////////////////////////////////////////////////////////
 DCSwitch::
-DCSwitch(const string &name, DCParameter *key_parameter) :
+DCSwitch(const string &name, DCField *key_parameter) :
   _name(name),
   _key_parameter(key_parameter)
 {
@@ -46,7 +46,7 @@ DCSwitch(const string &name, DCParameter *key_parameter) :
 ////////////////////////////////////////////////////////////////////
 DCSwitch::
 ~DCSwitch() {
-  nassertv(_key_parameter != (DCParameter *)NULL);
+  nassertv(_key_parameter != (DCField *)NULL);
   delete _key_parameter;
 
   Cases::iterator ci;
@@ -106,7 +106,7 @@ get_name() const {
 //               determines which one of the several cases within the
 //               switch will be used.
 ////////////////////////////////////////////////////////////////////
-DCParameter *DCSwitch::
+DCField *DCSwitch::
 get_key_parameter() const {
   return _key_parameter;
 }
@@ -231,6 +231,7 @@ int DCSwitch::
 add_case(const string &value) {
   int case_index = (int)_cases.size();
   if (!_cases_by_value.insert(CasesByValue::value_type(value, case_index)).second) {
+    add_invalid_case();
     return -1;
   }
 
@@ -240,6 +241,20 @@ add_case(const string &value) {
   return case_index;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitch::add_invalid_case
+//       Access: Public
+//  Description: Adds a new case to the switch that will never be
+//               matched.  This is only used by the parser, to handle
+//               an error condition more gracefully without bitching
+//               the parsing (which behaves differently according to
+//               whether a case has been encountered or not).
+////////////////////////////////////////////////////////////////////
+void DCSwitch::
+add_invalid_case() {
+  start_new_case();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSwitch::add_default
 //       Access: Public
@@ -251,10 +266,12 @@ add_case(const string &value) {
 bool DCSwitch::
 add_default() {
   if (_default_case != (SwitchFields *)NULL) {
+    add_invalid_case();
     return false;
   }
 
-  _default_case = start_new_case();
+  SwitchFields *fields = start_new_case();
+  _default_case = fields;
   return true;
 }
 

+ 4 - 3
direct/src/dcparser/dcSwitch.h

@@ -36,7 +36,7 @@ class DCField;
 ////////////////////////////////////////////////////////////////////
 class EXPCL_DIRECT DCSwitch : public DCDeclaration {
 public:
-  DCSwitch(const string &name, DCParameter *key_parameter);
+  DCSwitch(const string &name, DCField *key_parameter);
   virtual ~DCSwitch();
 
 PUBLISHED:
@@ -44,7 +44,7 @@ PUBLISHED:
   virtual const DCSwitch *as_switch() const;
 
   const string &get_name() const;
-  DCParameter *get_key_parameter() const;
+  DCField *get_key_parameter() const;
 
   int get_num_cases() const;
   int get_case_by_value(const string &case_value) const;
@@ -58,6 +58,7 @@ PUBLISHED:
 public:
   bool is_field_valid() const;
   int add_case(const string &value);
+  void add_invalid_case();
   bool add_default();
   bool add_field(DCField *field);
   void add_break();
@@ -118,7 +119,7 @@ private:
 
 private:
   string _name;
-  DCParameter *_key_parameter;
+  DCField *_key_parameter;
 
   typedef pvector<SwitchCase *> Cases;
   Cases _cases;

+ 1 - 1
direct/src/dcparser/dcSwitchParameter.cxx

@@ -44,7 +44,7 @@ DCSwitchParameter(const DCSwitch *dswitch) :
 
   _pack_type = PT_switch;
 
-  DCParameter *key_parameter = dswitch->get_key_parameter();
+  DCField *key_parameter = dswitch->get_key_parameter();
   _has_fixed_byte_size = _has_fixed_byte_size && key_parameter->has_fixed_byte_size();
   _has_range_limits = _has_range_limits || key_parameter->has_range_limits();
   _has_default_value = _has_default_value || key_parameter->has_default_value();