code: private void parseElements(char[] saved) throws Exception {
          char c;
          char sep;
  
          // Parse the first content particle
          skipWhitespace();
          parseCp();
  
          // Check for end or for a separator.
          skipWhitespace();
          c = readCh();
          switch (c) {
              case ')':
                  // VC: Proper Group/PE Nesting
                  if (readBuffer != saved) {
                      handler.verror("Illegal Group/PE nesting");
                  }
  
                  dataBufferAppend(')');
                  c = readCh();
                  switch (c) {
                      case '*':
                      case '+':
                      case '?':
                          dataBufferAppend(c);
                          break;
                      default:
                          unread(c);
                  }
                  return;
              case ',': // Register the separator.
              case '|':
                  sep = c;
                  dataBufferAppend(c);
                  break;
              default:
                  fatal("bad separator in content model", c, null);
                  return;
          }
  
          // Parse the rest of the content model.
          while (true) {
              skipWhitespace();
              parseCp();
              skipWhitespace();
              c = readCh();
              if (c == ')') {
                  // VC: Proper Group/PE Nesting
                  if (readBuffer != saved) {
                      handler.verror("Illegal Group/PE nesting");
                  }
  
                  dataBufferAppend(')');
                  break;
              } else if (c != sep) {
                  fatal("bad separator in content model", c, null);
                  return;
              } else {
                  dataBufferAppend(c);
              }
          }
  
          // Check for the occurrence indicator.
          c = readCh();
          switch (c) {
              case '?':
              case '*':
              case '+':
                  dataBufferAppend(c);
                  return;
              default:
                  unread(c);
                  return;
          }
      }
docs: Parse an element-content model.
  
  <pre>
  [47] elements ::= (choice | seq) ('?' | '*' | '+')?
  [49] choice ::= '(' S? cp (S? '|' S? cp)+ S? ')'
  [50] seq ::= '(' S? cp (S? ',' S? cp)* S? ')'
  </pre>
  
  <p>
  NOTE: the opening '(' and S have already been read.
  
  @param saved
  Buffer for entity that should have the terminal ')'