class_docstr: A DataShape parser object.
class_docstr_tok: ["A","DataShape","parser","object","."]
docstr: struct_type : LBRACE struct_field_list RBRACE
              | LBRACE struct_field_list COMMA RBRACE
  
  Returns a struct type, or None.
docstr_tok: ["struct_type",":","LBRACE","struct_field_list","RBRACE","|","LBRACE","struct_field_list","COMMA","RBRACE","Returns","a","struct","type",",","or","None","."]
code: def parse_struct_type(self):
      """
      struct_type : LBRACE struct_field_list RBRACE
                  | LBRACE struct_field_list COMMA RBRACE
  
      Returns a struct type, or None.
      """
      if self.tok.id != lexer.LBRACE:
          return None
      saved_pos = self.pos
      self.advance_tok()
      fields = (
          self.parse_homogeneous_list(
              self.parse_struct_field,
              lexer.COMMA,
              "Invalid field in struct",
              trailing_sep=True,
          )
          or []
      )
      if self.tok.id != lexer.RBRACE:
          self.raise_error("Invalid field in struct")
      self.advance_tok()
      # Split apart the names and types into separate lists,
      # compatible with type constructor parameters
      names = [f[0] for f in fields]
      types = [f[1] for f in fields]
      # Structs are treated as the "struct" dtype
      tconstr = self.syntactic_sugar(
          self.sym.dtype_constr,
          "struct",
          "{...} dtype constructor",
          saved_pos,
      )
      return tconstr(names, types)
  
imports: from __future__ import absolute_import, division, print_function
  from .None import lexer, error
  from .None import coretypes
label_desc: Use image node_id 21 for calling the DataShapeParser obj's underlying member method code with example usage: obj.parse_struct_type() and returns: tconstr, None