title: Parsing of nested structures and object model
body: <p>I am trying to parse a binary file format with nested structures. In procedural pseudo-code, the process would be as such:</p>
  
  <pre><code>// A structure contains:
  // tag | oneof(a, b, c) | oneof(oneof(aa, ab, ac), oneof(ba, bb, bc), oneof(ca, cb, cc))
  PROCEDURE parse() {
      RECORD read_type;
  
      read_tag(read_type);
  
      if (read_type == TYPE_A) {
          read_a(read_type);
          if (read_type == TYPE_AA) {
              read_aa();
          } else if (read_type == TYPE_AB) {
              read_ab();
          } else if (read_type == TYPE_AC) {
              read_ac();
          }
      } else if (read_type == TYPE_B) {
          // see above
      } else if (read_type == TYPE_C) {
          // see above
      }
  }
  </code></pre>
  
  <p>An outer structure such as AA can not be interpreted without context from its parent object A, which in turn requires its tag/header to interpret. When working with these structures, it makes sense to manipulate structures that contain A, that contain AA, etc., but never only the A or AA portion of a structure.</p>
  
  <p>My question is then how to create a class model for this procedure. Should the structure be:</p>
  
  <pre><code>class Base;
  class A: Base;
  class B: Base;
  class C: Base;
  class AA: A;
  class AB: A;
  class AC: A;
  // ...
  </code></pre>
  
  <p>In which case, AA might be constructed as such:</p>
  
  <pre><code>AA::AA(): A() {
      read_aa();
  }
  
  A::A(): Base() {
      read_a();
  }
  
  Base::Base() {
      read_tag();
  }
  </code></pre>
  
  <p>However, the issue would be that it would not be possible to know what derived object to construct without first constructing the base object. This could be worked around by having a constructor AA::AA(A*) that copy constructs its parent, but this seems like an unnecessary inefficiency. Further, this would require an external factory function such as:</p>
  
  <pre><code>Base *read_object() {
      Base *base = new Base();
      if (b-&gt;tag_type == TYPE_A) {
          A *a = new A(base);
          if (a-&gt;tag_type == TYPE_AA) {
              return new AA(a);
          } else if (a-&gt;tag_type == TYPE_AB) {
              // ...
          } else if (a-&gt;tag_type == TYPE_AC) {
              // ...
          }
      } else if (b-&gt;tag_type == TYPE_B) {
          // ...
      } else if (b-&gt;tag_type == TYPE_C) {
          // ...
      }
  }
  </code></pre>
  
  <p>The other option is to have classes that refer to sub-regions of the structure such as:</p>
  
  <pre><code>class CompleteStructure;
  class StructureA;
  class StructureB;
  class StructureC;
  class StructureAA;
  class StructureAB;
  class StructureAC;
  // ...
  
  class CompleteStructure {
      union {StructureA a, StructureB b, StructureC c} sub;
  }
  
  class StructureA {
      CompleteStructure *parent;
      union {StructureAA aa, StructureAB ab, StructureAC ac} sub;
  }
  
  class StructureAA {
      StructureA *parent;
  }
  </code></pre>
  
  <p>In this case, the constructor CompleteStructure::CompleteStructure() would read the tag and then construct one of StructureA, StructureB, or StructureC, which would in turn construct is own sub-structure. The issue with this is that each sub-structure would need an explicit reference to its parent in order to "cast" up the hierarchy and implement its methods/functions.</p>
  
  <p>Is one of these approaches better than the other in terms of space/time efficiency and "cleanness"? Is there a superior third approach?</p>
  
  <p>EDIT:
  To respond to the two answers below, the question is both about parsing and object behavior. My initial goal is merely to read the structures from the file, print out their fields, and then write them back to disk in the same order. Later on, there will be additional goals such as finding all instances of A-derived structures and sorting them by certain fields or checking for illegal combinations of structures (e.g. having both BA and BB).</p>
  
  <p>EDIT2:
  Here is an example schema of one of the structures I refer to (with generic field names). u8/16/32 refer to integer types, sz is a C string, upper-case names are fields that need to be read, and constants are prefixed with underscores.</p>
  
  <pre><code>DEF AA {
      // Identifies and deliminates complete records.
      TAG {
          u32 SYNC_CODE = 0xFFFFFFFF;
      }
  
      // Metadata for high level identification of data.
      A {
          u32 TYPE = __TYPE_A;
          u16 CATEGORY = __CATEGORY_1; // A defines the "category" of the following file data
          u32 NUM_OF_KV_PAIRS;
          for (int i = 0; i &lt; NUM_OF_KV_PAIRS; ++i) { // unspecified metadata
              sz KEY;
              sz VALUE;
          }
          u8 HAS_EXTENSION_FLAG = true; // indicates presence of next record
          if (!HAS_EXTENSION_FLAG) {
              DEFAULT_PARAMS; // legacy
          }
      }
  
      // Indicates a specific data layout and version.
      AA {
          u32 TYPE = __TYPE_AA;
          u8[16] ACCESS_KEY;
          u32 NUM_OFFSETS;
          for (int i = 0; i &lt; NUM_OFFSETS; ++i) {
              // stuff
          }
      }
  }
  </code></pre>