You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@daffodil.apache.org by GitBox <gi...@apache.org> on 2018/08/13 16:38:10 UTC

[GitHub] mbeckerle closed pull request #88: Daffodil 1919 separators

mbeckerle closed pull request #88: Daffodil 1919 separators
URL: https://github.com/apache/incubator-daffodil/pull/88
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
index 3e82a9122..b42017e2b 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
@@ -71,57 +71,61 @@ class TestCLIdebugger {
     }
   }
 
-  @Test def test_3263_CLI_Debugger_occursBounds() {
-    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
-    val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input8.txt")
-    val (testSchemaFile, testInputFile) = if (Util.isWindows) (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile, inputFile)
-
-    val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS) else Util.start("")
-
-    try {
-      val cmd = String.format("%s -d parse -s %s -r matrix %s", Util.binPath, testSchemaFile, testInputFile)
-      shell.sendLine(cmd)
-      shell.expect(contains("(debug)"))
-
-      shell.sendLine("display info occursBounds")
-      shell.expect(contains("(debug)"))
-
-      shell.sendLine("s")
-      shell.expect(contains("occursBounds: 1"))
-
-      shell.sendLine("complete")
-      shell.sendLine("quit")
-    } finally {
-      shell.close()
-    }
-  }
-
-  @Test def test_3266_CLI_Debugger_occursBounds_shortForm() {
-    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
-    val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input8.txt")
-    val (testSchemaFile, testInputFile) = if (Util.isWindows) (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile, inputFile)
-
-    val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS) else Util.start("")
-
-    try {
-      val cmd = String.format("%s -d parse -s %s -r matrix %s", Util.binPath, testSchemaFile, testInputFile)
-      shell.sendLine(cmd)
-      shell.expect(contains("(debug)"))
-
-      shell.sendLine("display info ob")
-      shell.expect(contains("(debug)"))
-      shell.sendLine("info oc")
-      shell.expect(contains("error: undefined info command: oc"))
-
-      shell.sendLine("s")
-      shell.expect(contains("occursBounds: 1"))
-
-      shell.sendLine("complete")
-      shell.sendLine("quit")
-    } finally {
-      shell.close()
-    }
-  }
+  //
+  // There is no more occursBounds command, as that stack in the PState/UState
+  // has been removed as part of the rewrite of sequences and separators.
+  //
+  //  @Test def test_3263_CLI_Debugger_occursBounds() {
+  //    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
+  //    val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input8.txt")
+  //    val (testSchemaFile, testInputFile) = if (Util.isWindows) (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile, inputFile)
+  //
+  //    val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS) else Util.start("")
+  //
+  //    try {
+  //      val cmd = String.format("%s -d parse -s %s -r matrix %s", Util.binPath, testSchemaFile, testInputFile)
+  //      shell.sendLine(cmd)
+  //      shell.expect(contains("(debug)"))
+  //
+  //      shell.sendLine("display info occursBounds")
+  //      shell.expect(contains("(debug)"))
+  //
+  //      shell.sendLine("s")
+  //      shell.expect(contains("occursBounds: 1"))
+  //
+  //      shell.sendLine("complete")
+  //      shell.sendLine("quit")
+  //    } finally {
+  //      shell.close()
+  //    }
+  //  }
+
+  //  @Test def test_3266_CLI_Debugger_occursBounds_shortForm() {
+  //    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
+  //    val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input8.txt")
+  //    val (testSchemaFile, testInputFile) = if (Util.isWindows) (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile, inputFile)
+  //
+  //    val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS) else Util.start("")
+  //
+  //    try {
+  //      val cmd = String.format("%s -d parse -s %s -r matrix %s", Util.binPath, testSchemaFile, testInputFile)
+  //      shell.sendLine(cmd)
+  //      shell.expect(contains("(debug)"))
+  //
+  //      shell.sendLine("display info ob")
+  //      shell.expect(contains("(debug)"))
+  //      shell.sendLine("info oc")
+  //      shell.expect(contains("error: undefined info command: oc"))
+  //
+  //      shell.sendLine("s")
+  //      shell.expect(contains("occursBounds: 1"))
+  //
+  //      shell.sendLine("complete")
+  //      shell.sendLine("quit")
+  //    } finally {
+  //      shell.close()
+  //    }
+  //  }
 
   @Test def test_1591_CLI_Debugger_invalidCommandError() {
     val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
@@ -142,72 +146,76 @@ class TestCLIdebugger {
     }
   }
 
-  @Test def test_1336_CLI_Debugger_occursBounds() {
-    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
-    val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input8.txt")
-    val (testSchemaFile, testInputFile) = if (Util.isWindows) (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile, inputFile)
-
-    val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS) else Util.start("")
-
-    try {
-      val cmd = String.format("%s -d parse -s %s -r file %s", Util.binPath, testSchemaFile, testInputFile)
-      shell.sendLine(cmd)
-      shell.expect(contains("(debug)"))
-
-      shell.sendLine("display info occursBounds")
-      shell.sendLine("display info infoset")
-      shell.expect(contains("(debug)"))
-
-      shell.sendLine("break item")
-
-      shell.sendLine("continue")
-      shell.expect(contains("occursBounds: 5"))
-
-      shell.sendLine("continue")
-      shell.expect(contains("occursBounds: 5"))
-
-      shell.sendLine("complete")
-      shell.sendLine("quit")
-    } finally {
-      shell.close()
-    }
-  }
-
-  @Test def test_3398_CLI_Debugger_occursBounds_2() {
-    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
-    val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input11.txt")
-    val (testSchemaFile, testInputFile) = if (Util.isWindows) (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile, inputFile)
-
-    val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS) else Util.start("")
-
-    try {
-      val cmd = String.format("%s -d parse -s %s -r file %s", Util.binPath, testSchemaFile, testInputFile)
-      shell.sendLine(cmd)
-      shell.expect(contains("(debug)"))
-
-      shell.sendLine("display info occursBounds")
-      shell.sendLine("display info infoset")
-      shell.expect(contains("(debug)"))
-
-      shell.sendLine("break title")
-      shell.sendLine("break item")
-
-      shell.sendLine("continue")
-      shell.expect(contains("breakpoint 1: title"))
-      shell.expect(contains("occursBounds: 1024")) //occursCount is not set, so default is used
-
-      shell.sendLine("disable breakpoint 1")
-
-      shell.sendLine("continue")
-      shell.expect(contains("breakpoint 2: item"))
-      shell.expect(contains("occursBounds: 3"))
-
-      shell.sendLine("complete")
-      shell.sendLine("quit")
-    } finally {
-      shell.close()
-    }
-  }
+  //
+  // There is no more occursBounds command, as that stack in the PState/UState
+  // has been removed as part of the rewrite of sequences and separators.
+  //
+  //  @Test def test_1336_CLI_Debugger_occursBounds() {
+  //    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
+  //    val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input8.txt")
+  //    val (testSchemaFile, testInputFile) = if (Util.isWindows) (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile, inputFile)
+  //
+  //    val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS) else Util.start("")
+  //
+  //    try {
+  //      val cmd = String.format("%s -d parse -s %s -r file %s", Util.binPath, testSchemaFile, testInputFile)
+  //      shell.sendLine(cmd)
+  //      shell.expect(contains("(debug)"))
+  //
+  //      shell.sendLine("display info occursBounds")
+  //      shell.sendLine("display info infoset")
+  //      shell.expect(contains("(debug)"))
+  //
+  //      shell.sendLine("break item")
+  //
+  //      shell.sendLine("continue")
+  //      shell.expect(contains("occursBounds: 5"))
+  //
+  //      shell.sendLine("continue")
+  //      shell.expect(contains("occursBounds: 5"))
+  //
+  //      shell.sendLine("complete")
+  //      shell.sendLine("quit")
+  //    } finally {
+  //      shell.close()
+  //    }
+  //  }
+  //
+  //  @Test def test_3398_CLI_Debugger_occursBounds_2() {
+  //    val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
+  //    val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input11.txt")
+  //    val (testSchemaFile, testInputFile) = if (Util.isWindows) (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile)) else (schemaFile, inputFile)
+  //
+  //    val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS) else Util.start("")
+  //
+  //    try {
+  //      val cmd = String.format("%s -d parse -s %s -r file %s", Util.binPath, testSchemaFile, testInputFile)
+  //      shell.sendLine(cmd)
+  //      shell.expect(contains("(debug)"))
+  //
+  //      shell.sendLine("display info occursBounds")
+  //      shell.sendLine("display info infoset")
+  //      shell.expect(contains("(debug)"))
+  //
+  //      shell.sendLine("break title")
+  //      shell.sendLine("break item")
+  //
+  //      shell.sendLine("continue")
+  //      shell.expect(contains("breakpoint 1: title"))
+  //      shell.expect(contains("occursBounds: 1024")) //occursCount is not set, so default is used
+  //
+  //      shell.sendLine("disable breakpoint 1")
+  //
+  //      shell.sendLine("continue")
+  //      shell.expect(contains("breakpoint 2: item"))
+  //      shell.expect(contains("occursBounds: 3"))
+  //
+  //      shell.sendLine("complete")
+  //      shell.sendLine("quit")
+  //    } finally {
+  //      shell.close()
+  //    }
+  //  }
 
   @Test def test_1335_CLI_Debugger_dataAndWrapLength() {
     val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/parsing/TestCLIParsing.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/parsing/TestCLIParsing.scala
index be998eb0f..ddd34c71b 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/parsing/TestCLIParsing.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/parsing/TestCLIParsing.scala
@@ -197,7 +197,7 @@ class TestCLIparsing {
       val cmd = String.format("echo 1/3| %s -vv parse -s %s", Util.binPath, testSchemaFile)
       shell.sendLine(cmd)
 
-      shell.expect(contains("<OptionalInfixSep><Separator/></OptionalInfixSep>"))
+      shell.expect(contains("<Sequence><Separator/><RepMinMax name='s1'>"))
       shell.sendLine("exit")
       shell.expect(eof)
     } finally {
@@ -909,7 +909,7 @@ class TestCLIparsing {
       shell.close()
     }
   }
-  
+
   @Test def test_CLI_Parsing_built_in_formats() {
     val schemaFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/cli_schema_04.dfdl.xsd")
     val inputFile = Util.daffodilPath("daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input6.txt")
@@ -940,8 +940,8 @@ class TestCLIparsing {
     val schemaFile = Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.dfdl.xsd")
     val testSchemaFile = if (Util.isWindows) Util.cmdConvert(schemaFile) else schemaFile
     val java_opts = Map("DAFFODIL_JAVA_OPTS" ->
-                          ("-Djavax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl " +
-                           "-Djavax.xml.xml.validation.SchemaFactory=com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory"))
+      ("-Djavax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl " +
+        "-Djavax.xml.xml.validation.SchemaFactory=com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory"))
 
     val shell = Util.start("", envp = java_opts)
 
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
index fb5944c85..e76c9fd7e 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
@@ -47,9 +47,6 @@ import org.apache.daffodil.api.WarnID
 trait ResolvesProperties
   extends FindPropertyMixin { self: AnnotatedSchemaComponent =>
 
-  /** Returns Term corresponding to this object. */
-  def term: Term
-
   private def findNonDefaultProperty(pname: String): PropertyLookupResult = {
     val result = findDefaultOrNonDefaultProperty(pname, nonDefaultPropertySources)
     result match {
@@ -81,12 +78,12 @@ trait ResolvesProperties
   override def findPropertyOption(pname: String): PropertyLookupResult = {
     ExecutionMode.requireCompilerMode
     // first try in regular properties
-    val regularResult = resolver.findNonDefaultProperty(pname)
+    val regularResult = findNonDefaultProperty(pname)
     regularResult match {
       case f: Found => f
       case NotFound(nonDefaultLocsTried1, defaultLocsTried1, _) => {
         Assert.invariant(defaultLocsTried1.isEmpty)
-        val defaultResult = resolver.findDefaultProperty(pname)
+        val defaultResult = findDefaultProperty(pname)
         defaultResult match {
           case f: Found => f
           case NotFound(nonDefaultLocsTried2, defaultLocsTried2, _) => {
@@ -122,34 +119,34 @@ trait AnnotatedSchemaComponent
   requiredEvaluations(nonDefaultPropertySources)
   requiredEvaluations(defaultPropertySources)
 
-  /** Returns the Term corresponding to this component. */
-  final lazy val term: Term = this match {
-    case gr: GroupRef => gr.asModelGroup
-    //    case mg: ModelGroup => mg.parent match {
-    //      case ggd: GlobalGroupDef => {
-    //        // this is the model group that is the definition of
-    //        // a global group, so our term is the group reference referring to this.
-    //        ggd.groupRef.asModelGroup
-    //      }
-    //      case _ => mg
-    //    }
-    case t: Term => t
-    case ged: GlobalElementDecl => ged.elementRef
-    case ty: SimpleTypeDefBase => ty.elementBase
-    case ty: ComplexTypeBase => ty.elementBase
-    case ggd: GlobalGroupDef => ggd.groupRef.asModelGroup
-    case sd: SchemaDocument =>
-      Assert.usageError("not to be called for schema documents")
-  }
+  //  /** Returns the Term corresponding to this component. */
+  //  final lazy val term: Term = this match {
+  //    case gr: GroupRef => gr.asModelGroup
+  //    //    case mg: ModelGroup => mg.parent match {
+  //    //      case ggd: GlobalGroupDef => {
+  //    //        // this is the model group that is the definition of
+  //    //        // a global group, so our term is the group reference referring to this.
+  //    //        ggd.groupRef.asModelGroup
+  //    //      }
+  //    //      case _ => mg
+  //    //    }
+  //    case t: Term => t
+  //    case ged: GlobalElementDecl => ged.elementRef
+  //    case ty: SimpleTypeDefBase => ty.elementBase
+  //    case ty: ComplexTypeBase => ty.elementBase
+  //    case ggd: GlobalGroupDef => ggd.groupRef.asModelGroup
+  //    case sd: SchemaDocument =>
+  //      Assert.usageError("not to be called for schema documents")
+  //  }
 
-  /** Returns the property resolver for this component. */
-  final lazy val resolver: ResolvesProperties = {
-    val res = this match {
-      case sd: SchemaDocument => sd
-      case _ => term
-    }
-    res
-  }
+  //  /** Returns the property resolver for this component. */
+  //  final lazy val resolver: ResolvesProperties = {
+  //    val res = this match {
+  //      case sd: SchemaDocument => sd
+  //      case _ => term
+  //    }
+  //    res
+  //  }
 
   /**
    * Since validation of extra attributes on XML Schema elements is
@@ -175,7 +172,7 @@ trait AnnotatedSchemaComponent
 
   protected def optReferredToComponent: Option[AnnotatedSchemaComponent] // override in ref objects
 
-  final protected lazy val nonDefaultPropertySources: Seq[ChainPropProvider] = LV('nonDefaultPropertySources) {
+  lazy val nonDefaultPropertySources: Seq[ChainPropProvider] = LV('nonDefaultPropertySources) {
     this match {
       case sd: SchemaDocument => Nil
       case _ => {
@@ -265,8 +262,7 @@ trait AnnotatedSchemaComponent
  * or made smaller anyway.
  *
  */
-trait AnnotatedMixin
-  extends EscapeSchemeRefMixin { self: AnnotatedSchemaComponent =>
+trait AnnotatedMixin { self: AnnotatedSchemaComponent =>
 
   /**
    * Anything annotated must be able to construct the
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ChoiceGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ChoiceGroup.scala
index 428ac9eb9..7e9a0abec 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ChoiceGroup.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ChoiceGroup.scala
@@ -236,7 +236,9 @@ abstract class ChoiceTermBase( final override val xml: Node,
     noDupes
   }.value
 
-  final lazy val modelGroupRuntimeData = {
+  final lazy val modelGroupRuntimeData = choiceRuntimeData
+
+  final lazy val choiceRuntimeData = {
     new ChoiceRuntimeData(
       schemaSet.variableMap,
       encodingInfo,
@@ -262,6 +264,17 @@ abstract class ChoiceTermBase( final override val xml: Node,
       maybeCheckByteAndBitOrderEv,
       maybeCheckBitOrderAndCharset)
   }
+  
+  final lazy val groupMembersWithImpliedSequences = {
+    val rawGMs = groupMembers
+    val wrappedGMs = rawGMs.map {
+      gm =>
+        if (gm.isScalar) gm
+        else
+          new ChoiceBranchImpliedSequence(gm)
+    }
+    wrappedGMs
+  }
 }
 
 final class Choice(xmlArg: Node, parent: SchemaComponent, position: Int)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ComplexTypes.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ComplexTypes.scala
index a62e9b0a4..3f5bf5aaa 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ComplexTypes.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ComplexTypes.scala
@@ -18,15 +18,13 @@
 package org.apache.daffodil.dsom
 
 import scala.xml.Node
-import org.apache.daffodil.grammar.ComplexTypeBaseGrammarMixin
 import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.xml.QName
 
 abstract class ComplexTypeBase(xmlArg: Node, parentArg: SchemaComponent)
   extends SchemaComponentImpl(xmlArg, parentArg)
   with TypeBase
-  with NonPrimTypeMixin
-  with ComplexTypeBaseGrammarMixin {
+  with NonPrimTypeMixin {
 
   final override def optRestriction = None
   final override def optUnion = None
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAnnotation.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAnnotation.scala
index abac9c9f5..74c2b44f5 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAnnotation.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAnnotation.scala
@@ -19,8 +19,6 @@ package org.apache.daffodil.dsom
 
 import scala.xml.Node
 import org.apache.daffodil.util.Misc
-import org.apache.daffodil.schema.annotation.props.PropertyLookupResult
-import org.apache.daffodil.schema.annotation.props.FindPropertyMixin
 
 /**
  * Base class for any DFDL annotation
@@ -38,19 +36,18 @@ import org.apache.daffodil.schema.annotation.props.FindPropertyMixin
  */
 abstract class DFDLAnnotation(xmlArg: Node, annotatedSCArg: AnnotatedSchemaComponent)
   extends SchemaComponent
-  with NestingLexicalMixin
-  with FindPropertyMixin // only needed because unit tests look at properties on annotations
+  with NestingLexicalMixin //with  FindPropertyMixin // only needed because unit tests look at properties on annotations
   {
 
   final override val xml = xmlArg
   final override def parent = annotatedSCArg
   final override val context: AnnotatedSchemaComponent = annotatedSCArg
 
-  // delegate to the annotated component.
-  override def findPropertyOption(pname: String): PropertyLookupResult = {
-    val res = annotatedSC.resolver.findPropertyOption(pname)
-    res
-  }
+  //  // delegate to the annotated component.
+  //  override def findPropertyOption(pname: String): PropertyLookupResult = {
+  //    val res = annotatedSC.resolver.findPropertyOption(pname)
+  //    res
+  //  }
 
   final lazy val annotatedSC = annotatedSCArg
 
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAssertion.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAssertion.scala
index dd2dd8592..a9ac8d44e 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAssertion.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLAssertion.scala
@@ -33,6 +33,8 @@ import org.apache.daffodil.api.WarnID
 abstract class DFDLAssertionBase(node: Node, decl: AnnotatedSchemaComponent)
   extends DFDLStatement(node, decl) {
 
+  override protected def check(term: Term) = checkPattern(term)
+
   private lazy val testAttrib = getAttributeOption("test")
 
   // tolerate whitespace. E.g.,
@@ -55,28 +57,41 @@ abstract class DFDLAssertionBase(node: Node, decl: AnnotatedSchemaComponent)
 
   private lazy val testPattern = {
     val optPattern = getAttributeOption("testPattern")
-    if (optPattern.isDefined) {
-      val thePattern = optPattern.get
-
+    optPattern.foreach { thePattern =>
       try {
         // val icu =
         UnicodeRegex.compile(thePattern) // Check against ICU
         // val java =
         Pattern.compile(thePattern) // Check against Java
       } catch { case e: PatternSyntaxException => SDE("The pattern contained invalid syntax: %s", e.getMessage()) }
+    }
+    optPattern
+  }
+
+  /**
+   * This assertion can appear on a global element def, for example, which is
+   * not a term, and so we cannot ask it for properties and get all the properties
+   * in the scope.
+   *
+   * To avoid reaching backward from a global element decl to the element ref
+   * that is the start of the property assembling for that term, we instead call
+   * from a term to its statements, passing them the Term they need to verify
+   * that they are compatible with the properties of that term.
+   *
+   * This is a technique to avoid backpointers from shared definitions/decls to
+   * the referencing objects that refer to them.
+   */
+  private def checkPattern(term: Term) = {
+
+    if (testPattern.isDefined) {
+      val thePattern = testPattern.get
 
       val hasWord = thePattern.contains("\\w")
-      decl match {
-        case term: Term => {
-          val encInfo = term.termRuntimeData.encodingInfo
-          if (encInfo.knownEncodingIsUnicode && hasWord)
-            SDW(WarnID.PatternEncodingSlashW, "The encoding is '%s' and \\w was detected in the pattern '%s'.  This is not recommended with Unicode encodings.",
-              encInfo.knownEncodingName, thePattern)
-        }
-        case _ => // ok
-      }
+      val encInfo = term.termRuntimeData.encodingInfo
+      if (encInfo.knownEncodingIsUnicode && hasWord)
+        SDW(WarnID.PatternEncodingSlashW, "The encoding is '%s' and \\w was detected in the pattern '%s'.  This is not recommended with Unicode encodings.",
+          encInfo.knownEncodingName, thePattern)
     }
-    optPattern
   }
 
   final lazy val testKind = getAttributeOption("testKind") match {
@@ -118,10 +133,10 @@ abstract class DFDLAssertionBase(node: Node, decl: AnnotatedSchemaComponent)
 final class DFDLAssert(node: Node, decl: AnnotatedSchemaComponent)
   extends DFDLAssertionBase(node, decl) { // with Assert_AnnotationMixin // Note: don't use these generated mixins. Statements don't have format properties
 
-  final def gram = LV('gram) {
+  final def gram(term: Term) = LV('gram) {
     testKind match {
-      case TestKind.Pattern => AssertPatternPrim(decl.term, this)
-      case TestKind.Expression => AssertBooleanPrim(decl.term, this)
+      case TestKind.Pattern => AssertPatternPrim(term, this)
+      case TestKind.Expression => AssertBooleanPrim(term, this)
     }
   }.value
 }
@@ -129,10 +144,10 @@ final class DFDLAssert(node: Node, decl: AnnotatedSchemaComponent)
 final class DFDLDiscriminator(node: Node, decl: AnnotatedSchemaComponent)
   extends DFDLAssertionBase(node, decl) { // with Discriminator_AnnotationMixin
 
-  final def gram = LV('gram) {
+  final def gram(term: Term) = LV('gram) {
     testKind match {
-      case TestKind.Pattern => DiscriminatorPatternPrim(decl.term, this)
-      case TestKind.Expression => DiscriminatorBooleanPrim(decl.term, this)
+      case TestKind.Pattern => DiscriminatorPatternPrim(term, this)
+      case TestKind.Expression => DiscriminatorBooleanPrim(term, this)
     }
   }.value
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLDefineVariable.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLDefineVariable.scala
index 424307b56..e066265f8 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLDefineVariable.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLDefineVariable.scala
@@ -28,8 +28,6 @@ import org.apache.daffodil.xml.QName
 import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.grammar.primitives.SetVariable
-import org.apache.daffodil.grammar.primitives.NewVariableInstanceStart
-import org.apache.daffodil.grammar.primitives.NewVariableInstanceEnd
 import org.apache.daffodil.schema.annotation.props.Found
 
 class DFDLDefineVariable(node: Node, doc: SchemaDocument)
@@ -107,12 +105,10 @@ abstract class VariableReference(node: Node, decl: AnnotatedSchemaComponent)
 final class DFDLNewVariableInstance(node: Node, decl: AnnotatedSchemaComponent)
   extends VariableReference(node, decl) // with NewVariableInstance_AnnotationMixin
   {
-  requiredEvaluations(endGram)
-
   lazy val defaultValue = getAttributeOption("defaultValue")
 
-  lazy val gram: Gram = NewVariableInstanceStart(decl, this)
-  lazy val endGram: Gram = NewVariableInstanceEnd(decl, this)
+  def gram(term: Term): Gram = ??? // NewVariableInstanceStart(decl, term)
+  def endGram(term: Term): Gram = ??? // NewVariableInstanceEnd(decl, this)
 
   lazy val newVariableInstance = defv.newVariableInstance
 
@@ -131,7 +127,7 @@ final class DFDLSetVariable(node: Node, decl: AnnotatedSchemaComponent)
     case (None, "") => decl.SDE("Must have either a value attribute or an element value: %s", node)
   }
 
-  final def gram = LV('gram) {
-    SetVariable(decl, this)
+  final def gram(term: Term) = LV('gram) {
+    SetVariable(this)
   }.value
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLEscapeScheme.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLEscapeScheme.scala
index a4565eeda..05eedb11f 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLEscapeScheme.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLEscapeScheme.scala
@@ -68,6 +68,12 @@ final class DFDLEscapeScheme(node: Node, decl: AnnotatedSchemaComponent, defES:
     }
   }
 
+  /**
+   * For unit testing. Must override because of multiple inheritance.
+   */
+  override def verifyPropValue(key: String, value: String): Boolean =
+    super.verifyPropValue(key, value)
+
   final def escapeCharacterEv = LV('escapeCharacterEv) {
     val qn = this.qNameForProperty("escapeCharacter")
     val expr = ExpressionCompilers.String.compileProperty(qn, NodeInfo.NonEmptyString, escapeCharacterRaw, this)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLFormatAnnotation.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLFormatAnnotation.scala
index 679fcfbb9..f0f78f646 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLFormatAnnotation.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLFormatAnnotation.scala
@@ -238,4 +238,20 @@ abstract class DFDLFormatAnnotation(nodeArg: Node, annotatedSCArg: AnnotatedSche
     res
   }.value
 
+  /**
+   * For unit testing convenience, or for use when debugging.
+   */
+  def getPropertyForUnitTest(propName: String) =
+    justThisOneProperties.get(propName).get._1
+
+  /**
+   * For unit testing convenience, or for use when debugging.
+   */
+  def verifyPropValue(propName: String, expectedValue: String): Boolean = {
+    val optInfo = justThisOneProperties.get(propName)
+    optInfo match {
+      case None => false
+      case Some((actualValue, _)) => actualValue == expectedValue
+    }
+  }
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLStatement.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLStatement.scala
index 0f5adc7cf..edb9bffb2 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLStatement.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLStatement.scala
@@ -26,9 +26,10 @@ import org.apache.daffodil.grammar.Gram
 abstract class DFDLStatement(node: Node,
   annotatedSCArg: AnnotatedSchemaComponent)
   extends DFDLAnnotation(node, annotatedSCArg)
-  with NestingLexicalMixin {
+  with NestingLexicalMixin 
+  with HasTermCheck {
 
-  requiredEvaluations(gram)
+  /// requiredEvaluations(gram)
 
-  def gram: Gram
+  def gram(term: Term): Gram
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLStatementMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLStatementMixin.scala
index ee901ec1e..c58c1ffc9 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLStatementMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLStatementMixin.scala
@@ -37,7 +37,7 @@ trait ResolvesDFDLStatementMixin
     f: ContentValueReferencedElementInfoMixin => Set[DPathElementCompileInfo]) = {
     s match {
       case a: DFDLAssertionBase if (a.testKind eq TestKind.Expression) => {
-        a.gram match {
+        a.gram(self) match {
           case ab: AssertBase => f(ab.expr)
           case _ => ReferencedElementInfos.None
         }
@@ -97,10 +97,10 @@ trait ResolvesDFDLStatementMixin
  *
  * Factory for creating the corresponding DFDLAnnotation objects.
  */
-trait ProvidesDFDLStatementMixin extends ThrowsSDE { self: AnnotatedSchemaComponent =>
+trait ProvidesDFDLStatementMixin extends ThrowsSDE with HasTermCheck { self: AnnotatedSchemaComponent =>
 
   final def annotationFactoryForDFDLStatement(node: Node, self: AnnotatedSchemaComponent): Option[DFDLAnnotation] = {
-    val term = self.term
+    val term = self
     node match {
       case <dfdl:assert>{ content @ _* }</dfdl:assert> => Some(new DFDLAssert(node, term))
       case <dfdl:discriminator>{ content @ _* }</dfdl:discriminator> => Some(new DFDLDiscriminator(node, term))
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
index 7972f1ddb..93c07ce1c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
@@ -42,6 +42,7 @@ import org.apache.daffodil.infoset.OnlyOnePossibilityForNextElement
 import org.apache.daffodil.infoset.NextElementResolver
 import org.apache.daffodil.infoset.ChildResolver
 import org.apache.daffodil.api.WarnID
+import org.apache.daffodil.util.Maybe
 
 /**
  * Note about DSOM design versus say XSOM or Apache XSD library.
@@ -522,8 +523,9 @@ trait ElementBase
       targetNamespace,
       thisElementsNamespace,
       optSimpleTypeRuntimeData,
-      optMinOccurs,
-      optMaxOccurs,
+      minOccurs,
+      maxOccurs,
+      Maybe.toMaybe(optionOccursCountKind),
       name,
       targetNamespacePrefix,
       thisElementsNamespacePrefix,
@@ -792,8 +794,8 @@ trait ElementBase
   private def NVDP = NilValueDelimiterPolicy
   private def EVDP = EmptyValueDelimiterPolicy
 
-  private lazy val hasNilValueInitiator = initTermTestExpression(initiatorParseEv, nilValueDelimiterPolicy, NVDP.Both, NVDP.Initiator)
-  private lazy val hasNilValueTerminator = initTermTestExpression(terminatorParseEv, nilValueDelimiterPolicy, NVDP.Both, NVDP.Terminator)
+  protected final lazy val hasNilValueInitiator = initTermTestExpression(initiatorParseEv, nilValueDelimiterPolicy, NVDP.Both, NVDP.Initiator)
+  protected final lazy val hasNilValueTerminator = initTermTestExpression(terminatorParseEv, nilValueDelimiterPolicy, NVDP.Both, NVDP.Terminator)
 
   /**
    * We need the nil values in raw form for diagnostic messages.
@@ -861,6 +863,12 @@ trait ElementBase
     }
   }.value
 
+
+    final lazy val hasEmptyValueZLSyntax =
+    !hasEmptyValueInitiator && !hasEmptyValueTerminator && isSimpleType &&
+(simpleType.primType =:= PrimType.String ||
+    simpleType.primType =:= PrimType.HexBinary)
+
   import org.apache.daffodil.dsom.FacetTypes._
 
   private lazy val hasPattern: Boolean = typeDef.optRestriction.map { _.hasPattern }.getOrElse(false)
@@ -1087,12 +1095,12 @@ trait ElementBase
           SDW(WarnID.NoEmptyDefault, "Element with no empty representation. XSD default='%s' can only be used when unparsing.", defaultValueAsString)
         schemaDefinitionWhen(isOptional, "Optional elements cannot have default values but default='%s' was found.", defaultValueAsString)
         if (isArray && !isRequiredArrayElement) {
-          (optMinOccurs, occursCountKind) match {
+          (minOccurs, occursCountKind) match {
             case (_, OccursCountKind.Parsed) |
               (_, OccursCountKind.StopValue) =>
               SDE("XSD default='%s' can never be used since an element with dfdl:occursCountKind='%s' has no required occurrences.",
                 defaultValueAsString, occursCountKind)
-            case (Some(0), _) => SDE("XSD default='%s' can never be used since an element with XSD minOccurs='0' has no required occurrences.",
+            case (0, _) => SDE("XSD default='%s' can never be used since an element with XSD minOccurs='0' has no required occurrences.",
               defaultValueAsString)
             case _ => // ok
           }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementRef.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementRef.scala
index cce469f01..f01fe10f1 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementRef.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementRef.scala
@@ -18,9 +18,7 @@
 package org.apache.daffodil.dsom
 
 import scala.xml.Node
-import org.apache.daffodil.grammar._
 import org.apache.daffodil.xml._
-import org.apache.daffodil.grammar.ElementReferenceGrammarMixin
 import org.apache.daffodil.dpath.NodeInfo
 
 /**
@@ -34,7 +32,6 @@ abstract class AbstractElementRef(xmlArg: Node,
   parentArg: SchemaComponent,
   positionArg: Int)
   extends ElementBase
-  with ElementReferenceGrammarMixin
   with HasRefMixin
   with NamedMixin
   with NestingLexicalMixin {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/EscapeSchemeRefMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/EscapeSchemeRefMixin.scala
index 463372f9f..461f8552d 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/EscapeSchemeRefMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/EscapeSchemeRefMixin.scala
@@ -21,7 +21,7 @@ import org.apache.daffodil.api.WarnID
 import org.apache.daffodil.schema.annotation.props.Found
 import org.apache.daffodil.schema.annotation.props.NotFound
 
-trait EscapeSchemeRefMixin { self: AnnotatedSchemaComponent =>
+trait EscapeSchemeRefMixin { self: Term =>
   /**
    * Changed to use findProperty, and to resolve the namespace properly.
    *
@@ -43,7 +43,7 @@ trait EscapeSchemeRefMixin { self: AnnotatedSchemaComponent =>
    * issue DFDL-77)
    */
   final lazy val optionEscapeScheme: Option[DFDLEscapeScheme] = {
-    val er = self.resolver.findPropertyOption("escapeSchemeRef")
+    val er = self.findPropertyOption("escapeSchemeRef")
     er match {
       case _: NotFound => {
         SDW(WarnID.EscapeSchemeRefUndefined,
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupDef.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupDef.scala
index 6664f8d8b..7ed1a603c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupDef.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupDef.scala
@@ -67,7 +67,7 @@ trait GroupDefLike
   def xmlChildren: Seq[Node]
 
   /** Returns the group members that are elements or model groups. */
-  final lazy val groupMembers: Seq[Term] = LV('groupMembers) {
+  final lazy val groupMembers : Seq[Term] = {
     //
     // So we have to flatMap, so that we can tolerate annotation objects (like documentation objects).
     // and our ModelGroup factory has to return Nil for annotations and Text nodes.
@@ -79,8 +79,8 @@ trait GroupDefLike
       case (n, i) =>
         TermFactory(n, this, i)
     }
-  }.value
-
+  }
+  
   /**
    * XML is full of uninteresting text nodes. We just want the element children, not all children.
    */
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupRef.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupRef.scala
index aa6bb1a7c..0bf076616 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupRef.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupRef.scala
@@ -77,7 +77,7 @@ final class SequenceGroupRef(globalGroupDef: => GlobalSequenceGroupDef,
   refLexicalParent: SchemaComponent,
   positionArg: Int,
   isHiddenArg: Boolean)
-  extends SequenceTermBase(refXML, refLexicalParent, positionArg)
+  extends SequenceGroupTermBase(refXML, refLexicalParent, positionArg)
   with GroupRef {
 
   override def isHidden = isHiddenArg
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/InitiatedTerminatedMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/InitiatedTerminatedMixin.scala
index bd098f852..d7fb7f1d1 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/InitiatedTerminatedMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/InitiatedTerminatedMixin.scala
@@ -37,14 +37,14 @@ trait InitiatedTerminatedMixin
     parentSays
   }
 
-  final lazy val hasInitiator = {
+  lazy val hasInitiator = {
     val hasOne = initiatorExpr.isKnownNonEmpty
     if (parentSaysInitiatedContent)
       schemaDefinitionUnless(hasOne, "Enclosing group has initiatedContent='yes', but initiator is not defined.")
     hasOne
   }
 
-  final lazy val hasTerminator = {
+  lazy val hasTerminator = {
     val res = terminatorExpr.isKnownNonEmpty
     res
   }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ModelGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ModelGroup.scala
index f9d3b3757..06cee914c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ModelGroup.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ModelGroup.scala
@@ -184,14 +184,17 @@ abstract class ModelGroup
 
   final override lazy val termRuntimeData: TermRuntimeData = modelGroupRuntimeData
 
-  protected lazy val groupMembersRuntimeData = this match {
-    case mg: ModelGroup => mg.groupMembers.map {
-      _ match {
-        case eb: ElementBase => eb.erd
-        case t: Term => t.termRuntimeData
+  protected lazy val groupMembersRuntimeData = {
+    val res = this match {
+      case mg: ModelGroup => mg.groupMembers.map {
+        _ match {
+          case eb: ElementBase => eb.erd
+          case t: Term => t.termRuntimeData
+        }
       }
+      case _ => Nil
     }
-    case _ => Nil
+    res
   }
 
   def modelGroupRuntimeData: ModelGroupRuntimeData
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ParticleMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ParticleMixin.scala
index b17974814..5c2f579c6 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ParticleMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ParticleMixin.scala
@@ -27,11 +27,19 @@ trait RequiredOptionalMixin { self: ElementBase =>
 
   final override lazy val isScalar = minOccurs == 1 && maxOccurs == 1
 
+  /**
+   * Distinguishes elements which have minOccurs 0, maxOccurs 1, and
+   * a dfdl:occursCountKind that means parsing/unparsing will respect these
+   * bounds.
+   *
+   * This enables implementations to use different, lighter weight, representations
+   * for optional elements (e.g., null or not null object reference) vs what
+   * is required for arrays (growable vector of slots).
+   */
   final override lazy val isOptional = {
-    // minOccurs == 0
-    (optMinOccurs, optMaxOccurs) match {
-      case (Some(1), Some(1)) => false // scalars are not optional
-      case (Some(0), max) => {
+    (minOccurs, maxOccurs) match {
+      case (1, 1) => false // scalars are not optional
+      case (0, max) => {
         // now we must check on occursCountKind.
         // if parsed or stopValue then we consider it an array
         if (occursCountKind =:= OccursCountKind.Parsed ||
@@ -41,9 +49,8 @@ trait RequiredOptionalMixin { self: ElementBase =>
           false
         } else {
           max match {
-            case Some(1) => true
-            case None => true
-            case Some(_) => false
+            case 1 => true
+            case _ => false
           }
         }
       }
@@ -51,7 +58,18 @@ trait RequiredOptionalMixin { self: ElementBase =>
     }
   }
 
+  /**
+   * True if the element is required to appear in the DFDL Infoset.
+   *
+   * This includes elements that have no representation in the
+   * data stream. That is, an element with dfdl:inputValueCalc will be isRequired true.
+   *
+   * Takes into account that some dfdl:occursCountKind can make
+   * seemingly required elements (based on minOccurs) optional or
+   * repeating.
+   */
   final override def isRequired: Boolean = LV('isRequired) {
+    // TODO: Rename to isRequiredOrComputed
     val res = {
       if (isScalar) true
       else if (isOptional) false
@@ -61,24 +79,26 @@ trait RequiredOptionalMixin { self: ElementBase =>
     res
   }.value
 
+  /**
+   * True if a "real" array, i.e., not an optional element, but something
+   * that can potentially have 2 or more occurrences based on maxOccurs
+   * and dfdl:occursCountKind that indicates whether maxOccurs will be respected.
+   */
   final override lazy val isArray = {
-    // maxOccurs > 1 || maxOccurs == -1
-
     if (isOptional) false
     else {
       val UNBOUNDED = -1
-      (optMinOccurs, optMaxOccurs) match {
-        case (None, None) => false
-        case (Some(1), Some(1)) => false
-        case (_, Some(n)) if n > 1 => true
-        case (_, Some(UNBOUNDED)) => true
+      (minOccurs, maxOccurs) match {
+        case (1, 1) => false
+        case (_, n) if n > 1 => true
+        case (_, UNBOUNDED) => true
         /**
          * This next case is for occursCountKinds parsed and stopValue.
          * These only use min/maxOccurs for validation, so anything
          * with these occursCountKinds is an array (so long as it isn't
          * scalar)
          */
-        case (_, Some(1)) if (occursCountKind == OccursCountKind.Parsed ||
+        case (_, 1) if (occursCountKind == OccursCountKind.Parsed ||
           occursCountKind == OccursCountKind.StopValue ||
           occursCountKind == OccursCountKind.Expression) => true
         case _ => false
@@ -86,7 +106,13 @@ trait RequiredOptionalMixin { self: ElementBase =>
     }
   }
 
+  /**
+   * True if an array has at least one required element based
+   * on a minOccurs and a dfdl:occursCountKind that means that
+   * minOccurs will be respected.
+   */
   final lazy val isRequiredArrayElement = {
+    // TODO: rename to isArraywithAtLeastOneRequiredArrayElement
     isArray &&
       minOccurs > 0 &&
       (occursCountKind == OccursCountKind.Fixed ||
@@ -95,12 +121,9 @@ trait RequiredOptionalMixin { self: ElementBase =>
   }
 }
 
-// A Particle is something that can be repeating.
+// A Particle is something that can be repeating or optional.
 trait ParticleMixin extends RequiredOptionalMixin { self: ElementBase =>
 
-  final lazy val optMinOccurs: Option[Int] = Some(minOccurs)
-  final lazy val optMaxOccurs: Option[Int] = Some(maxOccurs)
-
   lazy val minOccurs = {
     val min = (self.xml \ "@minOccurs").text.toString
     min match {
@@ -117,23 +140,31 @@ trait ParticleMixin extends RequiredOptionalMixin { self: ElementBase =>
       case _ => max.toInt
     }
   }
+  
+  /**
+   * Can have a varying number of occurrences.
+   */
+  final override lazy val isVariableOccurrences = minOccurs != maxOccurs
 
   final lazy val isFixedOccurrences = {
-    // TODO optimizations to take scope into consideration. E.g.,
+    // TODO maybe do optimizations to take scope into consideration. E.g.,
     // We could be in a context where the value of our occursCount expression
     // will always be a constant.
     occursCountKind == OccursCountKind.Fixed
   }
 
   /**
-   * Does this node have statically required instances.
+   * Does this node have statically required instances in the data stream.
+   *
+   * This excludes elements that have no representation e.g., elements with dfdl:inputValueCalc.
    */
   final def hasStaticallyRequiredInstances = LV('hasStaticallyRequiredInstances) {
+    // TODO: Rename to hasStaticallyRequiredOccurrencesInDataRepresentation
     val res =
       if (!isRepresented) false // if there's no rep, then it's not statically required.
       else if (isScalar) true
       else if (isFixedOccurrences) true
-      else if (minOccurs > 0) true
+      else if (minOccurs > 0) true // FIXME: should call isRequiredArrayElement
       else false
     res
   }.value
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/RuntimePropertyMixins.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/RuntimePropertyMixins.scala
index 5fcc7a2ca..4e34440ae 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/RuntimePropertyMixins.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/RuntimePropertyMixins.scala
@@ -541,6 +541,7 @@ trait SequenceRuntimeValuedPropertiesMixin
     ev.compile()
     ev
   }
+
   lazy val separatorUnparseEv = {
     val ev = new SeparatorUnparseEv(separatorExpr, outputNewLineEv, decl.termRuntimeData)
     ev.compile()
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SequenceGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SequenceGroup.scala
index e5f6a5967..7ec21a461 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SequenceGroup.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SequenceGroup.scala
@@ -17,12 +17,8 @@
 
 package org.apache.daffodil.dsom
 
-import scala.xml.Attribute
 import scala.xml.Elem
 import scala.xml.Node
-import scala.xml.NodeSeq.seqToNodeSeq
-import scala.xml.Null
-import scala.xml.Text
 import scala.xml._
 import org.apache.daffodil.schema.annotation.props.gen.Sequence_AnnotationMixin
 import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicyMixin
@@ -37,15 +33,63 @@ import org.apache.daffodil.schema.annotation.props.Found
 import org.apache.daffodil.schema.annotation.props.PropertyLookupResult
 import org.apache.daffodil.processors.LayerTransformerEv
 import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
+import org.apache.daffodil.schema.annotation.props.gen.SeparatorPosition
+import org.apache.daffodil.processors.SeparatorParseEv
+import org.apache.daffodil.processors.ModelGroupRuntimeData
+import org.apache.daffodil.schema.annotation.props.gen.LayerLengthUnits
+import org.apache.daffodil.processors.SeparatorUnparseEv
 
+/**
+ * Base for anything sequence-like.
+ *
+ * Sequences, group refs to sequences, and the implied sequences
+ * that are choice branches, are all instances.
+ */
 abstract class SequenceTermBase(
   final override val xml: Node,
   final override val parent: SchemaComponent,
   final override val position: Int)
   extends ModelGroup
+  with SequenceGrammarMixin {
+
+  def separatorSuppressionPolicy: SeparatorSuppressionPolicy
+
+  def sequenceKind: SequenceKind
+
+  def separatorPosition: SeparatorPosition
+
+  def isLayered: Boolean
+
+  // def hasSeparator: Boolean
+
+  def separatorParseEv: SeparatorParseEv
+  def separatorUnparseEv: SeparatorUnparseEv
+
+  def sequenceRuntimeData: SequenceRuntimeData
+
+  def layerLengthUnits: LayerLengthUnits
+
+  def isOrdered: Boolean
+
+  def maybeLayerTransformerEv: Maybe[LayerTransformerEv]
+
+  def checkHiddenSequenceIsDefaultableOrOVC: Unit
+
+}
+
+/**
+ * Base for anything sequence-like that actually
+ * has the sequence properties. So actual sequences, group refs to them,
+ * but NOT implied sequences inside choice branches.
+ */
+abstract class SequenceGroupTermBase(
+  xml: Node,
+  parent: SchemaComponent,
+  position: Int)
+  extends SequenceTermBase(xml, parent, position)
   with Sequence_AnnotationMixin
   with SequenceRuntimeValuedPropertiesMixin
-  with SequenceGrammarMixin
   with SeparatorSuppressionPolicyMixin
   with LayeringRuntimeValuedPropertiesMixin {
 
@@ -67,6 +111,11 @@ abstract class SequenceTermBase(
       groupMembers.exists { _.hasStaticallyRequiredInstances }
   }
 
+  final override def hasPotentiallyTrailingInstances = {
+    isPotentiallyTrailing ||
+      groupMembers.exists { _.hasPotentiallyTrailingInstances }
+  }
+
   final override def hasKnownRequiredSyntax = LV('hasKnownRequiredSyntax) {
     lazy val memberHasRequiredSyntax = groupMembers.exists(_.hasKnownRequiredSyntax)
     lazy val prefixOrPostfixAndStaticallyRequiredInstance =
@@ -143,7 +192,8 @@ abstract class SequenceTermBase(
             // Now we're looking at the individual name buckets within the
             // individual namespace bucket.
             if (children.length > 1)
-              this.SDE("Two or more members of the unordered sequence (%s) have the same name and the same namespace." +
+              this.SDE(
+                "Two or more members of the unordered sequence (%s) have the same name and the same namespace." +
                 "\nNamespace: %s\tName: %s.",
                 this.path, ns, name)
         }
@@ -166,62 +216,9 @@ abstract class SequenceTermBase(
     case SequenceKind.Unordered => false
   }
 
-  final lazy val unorderedSeq: Option[UnorderedSequence] = if (!isOrdered) {
+  final lazy val modelGroupRuntimeData = sequenceRuntimeData
 
-    val children = apparentXMLChildren.map(c => {
-      c match {
-        case elem: Elem => {
-          val elemMin = elem % Attribute(None, "minOccurs", Text("1"), Null)
-          val elemMax = elemMin % Attribute(None, "maxOccurs", Text("1"), Null)
-          elemMax
-        }
-        case x => x
-      }
-    })
-
-    // Create a list of the min/maxOccur pairs for each child
-    val elementChildrenMinMaxOccurs = apparentXMLChildren.map(c =>
-      c match {
-        case elem: Elem => {
-          val min = Integer.parseInt(elem.attributes.get("minOccurs").get.text)
-          val max = Integer.parseInt(elem.attributes.get("maxOccurs").get.text)
-          Some(min, max)
-        }
-        case x => None
-      }).filter(_.isDefined).map(_.get)
-
-    // Compute minimal number of elements required
-    val newMinOccurs = {
-      val minRequired = elementChildrenMinMaxOccurs.map { case (minVal, _) => minVal }.foldLeft(0)(_ + _)
-      minRequired.toString
-    }
-
-    // Compute maximal number of elements required
-    val newMaxOccurs = {
-      val maxRequired = elementChildrenMinMaxOccurs.map { case (_, maxVal) => maxVal }.foldLeft(0)(_ + _)
-      maxRequired.toString
-    }
-
-    val newContent: Node =
-      <element name="choiceElement" minOccurs={ newMinOccurs } maxOccurs={ newMaxOccurs } dfdl:occursCountKind="parsed" dfdl:lengthKind="implicit">
-        <complexType>
-          <choice dfdl:choiceLengthKind="implicit">{ children }</choice>
-        </complexType>
-      </element>
-
-    // Constructs a sequence of choice using newContent
-    val newXML = {
-      xml match {
-        case Elem(prefix, "sequence", attrs, scope, content @ _*) => Elem(prefix, "sequence", attrs, scope, true, newContent: _*)
-        case other => other
-      }
-    }
-
-    Some(new UnorderedSequence(newXML, children, parent, position))
-
-  } else None
-
-  final lazy val modelGroupRuntimeData = {
+  final lazy val sequenceRuntimeData = {
     new SequenceRuntimeData(
       schemaSet.variableMap,
       encodingInfo,
@@ -259,7 +256,8 @@ abstract class SequenceTermBase(
       if (disallowedKeys.size > 0)
         SDE("Sequence has dfdl:layerTransform specified, so cannot have non-layering properties: %s", disallowedKeys.mkString(", "))
 
-      val lt = new LayerTransformerEv(maybeLayerTransformEv.get,
+      val lt = new LayerTransformerEv(
+        maybeLayerTransformEv.get,
         maybeLayerCharsetEv,
         Maybe.toMaybe(optionLayerLengthKind),
         maybeLayerLengthInBytesEv,
@@ -313,7 +311,7 @@ trait SequenceDefMixin
  * Represents a local sequence definition.
  */
 class Sequence(xmlArg: Node, parent: SchemaComponent, position: Int)
-  extends SequenceTermBase(xmlArg, parent, position)
+  extends SequenceGroupTermBase(xmlArg, parent, position)
   with SequenceDefMixin {
 
   requiredEvaluations(checkHiddenGroupRefHasNoChildren)
@@ -339,8 +337,89 @@ class Sequence(xmlArg: Node, parent: SchemaComponent, position: Int)
   }.value
 }
 
-final class UnorderedSequence(xmlArg: Node, xmlContents: Seq[Node], parent: SchemaComponent, position: Int)
-  extends Sequence(xmlArg, parent, position) {
-  // A shell, the actual XML representation is passed in
-  // from Sequence
+/**
+ * A choice branch can be an element with multiple occurrances, or varying occurrences.
+ *
+ * There can't be separators, but the driving of the iteration for the occurences, is
+ * in the sequence parsers/unparsers. So this implements that, leveraging the
+ * sequence machinery, but specifying the properties needed to insure it is
+ * handled as a degenerate sequence having only one element decl within it.
+ */
+final class ChoiceBranchImpliedSequence(rawGM: Term)
+  extends SequenceTermBase(rawGM.xml, rawGM.parent, rawGM.position)
+  with GroupDefLike {
+
+  override def separatorSuppressionPolicy: SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.TrailingEmptyStrict
+
+  override def sequenceKind: SequenceKind = SequenceKind.Ordered
+
+  override def separatorPosition: SeparatorPosition = SeparatorPosition.Infix
+
+  override def isLayered: Boolean = false
+
+  override lazy val hasSeparator = false
+  override lazy val hasTerminator = false
+  override lazy val hasInitiator = false
+
+  override def separatorParseEv: SeparatorParseEv = Assert.usageError("Not to be called on choice branches.")
+
+  override def separatorUnparseEv: SeparatorUnparseEv = Assert.usageError("Not to be called on choice branches.")
+
+  override def layerLengthUnits: LayerLengthUnits = LayerLengthUnits.Bytes
+
+  override def isOrdered = true
+
+  override def maybeLayerTransformerEv: Maybe[LayerTransformerEv] = Maybe.Nope
+
+  override def checkHiddenSequenceIsDefaultableOrOVC: Unit = ()
+
+  override lazy val sequenceRuntimeData: SequenceRuntimeData = {
+    new SequenceRuntimeData(
+      schemaSet.variableMap,
+      encodingInfo,
+      // elementChildren.map { _.elementRuntimeData.dpathElementCompileInfo },
+      schemaFileLocation,
+      dpathCompileInfo,
+      diagnosticDebugName,
+      path,
+      namespaces,
+      defaultBitOrder,
+      groupMembersRuntimeData,
+      enclosingElement.map { _.elementRuntimeData }.getOrElse(
+        Assert.invariantFailed("model group with no surrounding element.")),
+      enclosingTerm.map { _.termRuntimeData }.getOrElse {
+        Assert.invariantFailed("model group with no surrounding term.")
+      },
+      isRepresented,
+      couldHaveText,
+      alignmentValueInBits,
+      true,
+      None,
+      Maybe.Nope,
+      Maybe.Nope,
+      Maybe.Nope)
+  }
+
+  /**
+   * Implied sequence doesn't exist textually, so can't have properties on it.
+   */
+  override lazy val nonDefaultPropertySources: Seq[ChainPropProvider] = groupMembers(0).nonDefaultPropertySources
+
+  // Members declared in AnnotatedMixin
+  protected def annotationFactory(node: scala.xml.Node): Option[DFDLAnnotation] = None
+  protected def emptyFormatFactory: DFDLFormatAnnotation = Assert.usageError("Not to be called on choice branches.")
+  protected def isMyFormatAnnotation(a: DFDLAnnotation): Boolean = false
+
+  // Members declared in AnnotatedSchemaComponent
+  protected def optReferredToComponent: Option[AnnotatedSchemaComponent] = None
+
+  def modelGroupRuntimeData: ModelGroupRuntimeData = sequenceRuntimeData
+
+  protected def myPeers: Option[Seq[ModelGroup]] = None
+
+  def xmlChildren: Seq[scala.xml.Node] = Seq(xml)
+
+  // Members declared in Term
+  def hasStaticallyRequiredInstances: Boolean = groupMembers(0).hasStaticallyRequiredInstances
+
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Term.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Term.scala
index 9d1597660..f6bd6c76c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Term.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Term.scala
@@ -26,6 +26,44 @@ import java.lang.{ Integer => JInt }
 import org.apache.daffodil.schema.annotation.props.Found
 import org.apache.daffodil.schema.annotation.props.gen.NilKind
 
+/**
+ * Mixin for objects that are shared, but have consistency checks to be run
+ * that are based on the concrete Term objects they are associated with.
+ *
+ * E.g., DFDL statements may have checks that need to know the encoding
+ * (if it is known at compile time). We call this on each statement to enable
+ * the checking code to be expressed on that statement where it is relevant,
+ * but have it be callable from the concrete Term once it is created.
+ *
+ * This is a way to avoid use of backpointers from shared objects to every
+ * thing referencing them.
+ */
+trait HasTermCheck {
+
+  /**
+   * Perform checking of an object against the supplied Term arg.
+   */
+  final def checkTerm(term: Term): Unit = {
+    //
+    // This public method calling a protected method lets us play tricks
+    // in the future to avoid repeated check calls by memoizing the
+    // results.
+    //
+    check(term)
+  }
+
+  /**
+   * Override to perform necessary checks that require information about the
+   * concrete Term.
+   *
+   * This avoids the need for the checking code to have a backpointer to the
+   * Term.
+   */
+  protected def check(term: Term): Unit = {
+    // by default this does nothing.
+  }
+}
+
 /**
  * Term, and what is and isn't a Term, is a key concept in DSOM.
  *
@@ -44,7 +82,14 @@ trait Term
   with TermGrammarMixin
   with DelimitedRuntimeValuedPropertiesMixin
   with InitiatedTerminatedMixin
-  with TermEncodingMixin {
+  with TermEncodingMixin
+  with EscapeSchemeRefMixin {
+
+  requiredEvaluations(termChecks)
+
+  private lazy val termChecks = {
+    statements.foreach { _.checkTerm(this) }
+  }
 
   def position: Int
 
@@ -71,9 +116,9 @@ trait Term
    * There are two senses of optional
    *
    * 1) Optional as in "might not be present" but for any reason.
-   * Consistent with this is Required meaning must occur (but for any
+   * Consistent with this is Required meaning must occur but for any
    * reason. So all the occurrences of an array that has fixed number of
-   * occurrences are required, and some of the occurrances of an array
+   * occurrences are required, and some of the occurrences of an array
    * that has a variable number of occurrences are optional.
    *
    * 2) Optional is in minOccurs="0" maxOccurs="1".
@@ -90,6 +135,8 @@ trait Term
   /**
    * Something is required if it is not optional
    * and not an array, unless that array has required elements.
+   *
+   * Does not exclude computed elements however. So can be !isRepresented.
    */
   def isRequired: Boolean
 
@@ -359,6 +406,38 @@ trait Term
   def isKnownRequiredElement = false
   def hasKnownRequiredSyntax = false
 
+  /**
+   * Override in particle mixin
+   */
+  def isVariableOccurrences: Boolean = false
+
+  def hasPotentiallyTrailingInstances: Boolean = false
+
+  lazy val isPotentiallyTrailing = {
+    if (!isRepresented) false
+    else if (!isRequired ||
+      (isRequired && isLastDeclaredRepresentedInSequence && isVariableOccurrences)) {
+      val es = nearestEnclosingSequence
+      val res = es match {
+        case None => true
+        case Some(s) => {
+          val allRequired = s.groupMembers.filter(_.isRequired)
+          if (allRequired.isEmpty) true
+          else {
+            val lastDeclaredRequired = allRequired.last
+            val thisLoc = s.groupMembers.indexOf(this)
+            val lastDeclaredRequiredLoc = s.groupMembers.indexOf(lastDeclaredRequired)
+            val res = lastDeclaredRequiredLoc <= thisLoc
+            res
+          }
+        }
+      }
+      res
+      // Since we can't determine at compile time, return false so that we can continue processing.
+      // Runtime checks will make final determination.
+    } else false
+  }
+
   /**
    * Returns a tuple, where the first item in the tuple is the list of sibling
    * terms that could appear before this. The second item in the tuple is a
@@ -532,6 +611,11 @@ trait Term
     listOfNextTerm
   }.value
 
+  final lazy val isLastDeclaredRepresentedInSequence = {
+    val res = laterSiblings.forall(!_.isRepresented)
+    res
+  }
+
   final def isDeclaredLastInSequence = LV('isDeclaredLastInSequence) {
     val es = nearestEnclosingSequence
     // how do we determine what child node we are? We search.
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/TermEncodingMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/TermEncodingMixin.scala
index bf4b8fb78..1fe9e846c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/TermEncodingMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/TermEncodingMixin.scala
@@ -200,6 +200,7 @@ trait TermEncodingMixin extends KnownEncodingMixin { self: Term =>
    * for a character.
    */
   final lazy val hasTextAlignment = {
+    // FIXME: Duplicate method?? Same as AlignedMixin.isKnownToBeTextAligned ??
     val av = alignmentValueInBits
     val kav = this.knownEncodingAlignmentInBits
     av % kav == 0
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ChoiceGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ChoiceGrammarMixin.scala
index 5bbb10604..37375c5db 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ChoiceGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ChoiceGrammarMixin.scala
@@ -26,5 +26,5 @@ trait ChoiceGrammarMixin extends GrammarMixin { self: ChoiceTermBase =>
     ChoiceCombinator(this, alternatives)
   }
 
-  private lazy val alternatives = groupMembers.map { _.asTermInChoice }
+  private lazy val alternatives = groupMembersWithImpliedSequences.map{ _.termContentBody }
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
index db1e65aac..79c0631dc 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
@@ -101,7 +101,6 @@ import org.apache.daffodil.grammar.primitives.LiteralCharacterNilOfSpecifiedLeng
 import org.apache.daffodil.grammar.primitives.LiteralNilDelimitedEndOfData
 import org.apache.daffodil.grammar.primitives.LiteralValueNilOfSpecifiedLength
 import org.apache.daffodil.grammar.primitives.LogicalNilValue
-import org.apache.daffodil.grammar.primitives.NilLiteralCharacter
 import org.apache.daffodil.grammar.primitives.OVCRetry
 import org.apache.daffodil.grammar.primitives.OnlyPadding
 import org.apache.daffodil.grammar.primitives.PackedDecimalDelimitedEndOfData
@@ -140,6 +139,7 @@ import org.apache.daffodil.schema.annotation.props.gen.YesNo
 import org.apache.daffodil.util.PackedSignCodes
 import org.apache.daffodil.xml.GlobalQName
 import org.apache.daffodil.xml.XMLUtils
+import org.apache.daffodil.grammar.primitives.ComplexTypeCombinator
 
 /////////////////////////////////////////////////////////////////
 // Elements System
@@ -311,10 +311,10 @@ trait ElementBaseGrammarMixin
       ((lengthKind eq LengthKind.Implicit) ||
         ((lengthKind eq LengthKind.Explicit) &&
           lengthEv.optConstant.isDefined)) // TODO: consider if delimiters matter, alignment, nil values,.... Are we excluding
-          // that stuff here? For example, if the element is nillable, but
-          // if isNilled, the representation will still be exactly the same
-          // length, then we'd like this to be true.
-          ) ||
+    // that stuff here? For example, if the element is nillable, but
+    // if isNilled, the representation will still be exactly the same
+    // length, then we'd like this to be true.
+    ) ||
           (
             // a fixed-length textual number, where a legal value
             // (or nil value) must by definition be smaller than the
@@ -341,7 +341,7 @@ trait ElementBaseGrammarMixin
             // for the largest possible textNumber matching the pattern.
             //
             false // TODO: implement this
-            ) ||
+          ) ||
             (isComplexType && !isNillable &&
               (
                 //
@@ -351,7 +351,7 @@ trait ElementBaseGrammarMixin
                 // alignment regions.
                 //
                 false // TODO: implement this
-                ))
+              ))
   }
 
   /**
@@ -412,18 +412,7 @@ trait ElementBaseGrammarMixin
 
   private lazy val rightFill = new RightFill(context)
 
-  // maybe can be private - if it is used still
-  protected lazy val elementUnused = new ElementUnused(context)
-
-  /**
-   * provided by ElementBase for array considerations, and GlobalElementDecl - scalar only
-   */
-  protected def allowedValue: Gram
-  //
-  // This silly redundancy where the variable name has to also be passed as a string,
-  // is, by the way, a good reason Scala needs real Lisp-style macros, that can take an argument and
-  // turn it into a type/class, object, def, or val/var name, as well as a string, etc.
-  //
+  private lazy val elementUnused = new ElementUnused(context)
 
   private lazy val parsedNil = prod("parsedNil", NYI && isNillable && nilKind == NilKind.LogicalValue) {
     nilElementInitiator ~
@@ -447,7 +436,7 @@ trait ElementBaseGrammarMixin
   private lazy val parsedValue = prod("parsedValue", isSimpleType) {
     initiatorRegion ~
       valueMTA ~
-      captureLengthRegions(leftPadding, ovcRetry(allowedValue), rightPadding ~ rightFill) ~
+      captureLengthRegions(leftPadding, ovcRetry(value), rightPadding ~ rightFill) ~
       terminatorRegion
   }
 
@@ -529,7 +518,6 @@ trait ElementBaseGrammarMixin
   }
 
   private lazy val stringDelimitedEndOfData = prod("stringDelimitedEndOfData") { StringDelimitedEndOfData(this) }
-  //  private lazy val stringPatternMatched = prod("stringPatternMatched") { StringPatternMatched(this) }
 
   private lazy val stringValue = prod("stringValue") { stringPrim }
 
@@ -661,13 +649,13 @@ trait ElementBaseGrammarMixin
 
 
   private lazy val bcdKnownLengthCalendar = prod("bcdKnownLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Bcd) {
-    bcdDateKnownLength | bcdTimeKnownLength | bcdDateTimeKnownLength
+    bcdDateKnownLength || bcdTimeKnownLength || bcdDateTimeKnownLength
   }
   private lazy val bcdRuntimeLengthCalendar = prod("bcdRuntimeLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Bcd) {
-    bcdDateRuntimeLength | bcdTimeRuntimeLength | bcdDateTimeRuntimeLength
+    bcdDateRuntimeLength || bcdTimeRuntimeLength || bcdDateTimeRuntimeLength
   }
   private lazy val bcdDelimitedLengthCalendar = prod("bcdDelimitedLengthCalendar", binaryCalendarRep == BinaryCalendarRep.Bcd) {
-    bcdDateDelimitedLength | bcdTimeDelimitedLength | bcdDateTimeDelimitedLength
+    bcdDateDelimitedLength || bcdTimeDelimitedLength || bcdDateTimeDelimitedLength
   }
 
   // BCD calendar with known length
@@ -871,13 +859,13 @@ trait ElementBaseGrammarMixin
         (primType, binaryCalendarRep) match {
           case (PrimType.DateTime, BinaryCalendarRep.BinarySeconds) => (lengthUnits, binaryNumberKnownLengthInBits) match {
             case (LengthUnits.Bytes, 32) => new ConvertBinaryDateTimeSecMilliPrim(this, binaryNumberKnownLengthInBits)
-            case (_, 32)  => SDE("lengthUnits must be 'bytes' when binaryCalendarRep='binarySeconds'")
+            case (_, 32) => SDE("lengthUnits must be 'bytes' when binaryCalendarRep='binarySeconds'")
             case (_, n) => SDE("binary xs:dateTime must be 32 bits when binaryCalendarRep='binarySeconds'. Length in bits was %s.", n)
           }
           case (_, BinaryCalendarRep.BinarySeconds) => SDE("binaryCalendarRep='binarySeconds' is not allowed with type %s", primType.name)
           case (PrimType.DateTime, BinaryCalendarRep.BinaryMilliseconds) => (lengthUnits, binaryNumberKnownLengthInBits) match {
             case (LengthUnits.Bytes, 64) => new ConvertBinaryDateTimeSecMilliPrim(this, binaryNumberKnownLengthInBits)
-            case (_, 64)  => SDE("lengthUnits must be 'bytes' when binaryCalendarRep='binaryMilliseconds'")
+            case (_, 64) => SDE("lengthUnits must be 'bytes' when binaryCalendarRep='binaryMilliseconds'")
             case (_, n) => SDE("binary xs:dateTime must be 64 bits when binaryCalendarRep='binaryMilliseconds'. Length in bits was %s.", n)
           }
           case (_, BinaryCalendarRep.BinaryMilliseconds) => SDE("binaryCalendarRep='binaryMilliseconds' is not allowed with type %s", primType.name)
@@ -936,41 +924,14 @@ trait ElementBaseGrammarMixin
 
   protected final lazy val empty = prod("empty", NYI && emptyIsAnObservableConcept) { EmptyGram }
 
-  //  private lazy val emptyRepresentation = prod("emptyRepresentation") {
-  //    simpleOrNonImplicitComplexEmpty | complexImplicitEmpty
-  //  }
-
-  //  private lazy val simpleOrNonImplicitComplexEmpty = prod("simpleOrNonImplicitComplexEmpty",
-  //    isSimpleType | isComplexType && lengthKind != LengthKind.Implicit) {
-  //      emptyElementInitiator ~
-  //        valueMTA ~
-  //        captureLengthRegions(EmptyGram, EmptyGram, EmptyGram) ~
-  //        emptyElementTerminator
-  //    }
-  //
-  //  /**
-  //   * This is about the case where we take an empty, parse a complex type recursively from it
-  //   * and potentially succeed.
-  //   */
-  //  private lazy val complexImplicitEmpty = prod("complexImplicitEmpty",
-  //    isComplexType && lengthKind == LengthKind.Implicit) {
-  //      SaveInputStream(this) ~ SetEmptyInputStream(this) ~ complexType.mainGrammar ~
-  //        RestoreInputStream(this) ~ emptyElementTerminator
-  //    }
-
-  //  private lazy val emptyDefaulted = prod("emptyDefaulted",
-  //    isDefaultable && emptyIsAnObservableConcept) {
-  //      empty ~ TheDefaultValue(this)
-  //    }
-
-  private lazy val nilElementInitiator = prod("nilElementInitiator", hasInitiator) { delimMTA ~ Initiator(this) }
-  private lazy val nilElementTerminator = prod("nilElementTerminator", hasTerminator) { delimMTA ~ Terminator(this) }
+  private lazy val nilElementInitiator = prod("nilElementInitiator", hasNilValueInitiator) { delimMTA ~ Initiator(this) }
+  private lazy val nilElementTerminator = prod("nilElementTerminator", hasNilValueTerminator) { delimMTA ~ Terminator(this) }
 
   //  private lazy val emptyElementInitiator = prod("emptyElementInitiator", NYI && hasEmptyValueInitiator) { delimMTA ~ Initiator(this) }
   //  private lazy val emptyElementTerminator = prod("emptyElementTerminator", NYI && hasEmptyValueTerminator) { delimMTA ~ Terminator(this) }
 
   private lazy val complexContent = prod("complexContent", isComplexType) {
-    complexType.mainGrammar
+    ComplexTypeCombinator(complexType, complexType.group.termContentBody)
   }
 
   private lazy val isNilLit = isNillable && ((nilKind == NilKind.LiteralValue) || (nilKind == NilKind.LiteralCharacter))
@@ -990,8 +951,7 @@ trait ElementBaseGrammarMixin
 
   private lazy val nilLitSimple = prod("nilLitSimple", isSimpleType) {
     captureLengthRegions(leftPadding,
-      specifiedLength(nilLitContent) ~ // for parser
-        NilLiteralCharacter(context), // for unparser
+      specifiedLength(nilLitContent),
       rightPadding ~ rightFill)
   }
 
@@ -1007,7 +967,11 @@ trait ElementBaseGrammarMixin
 
   }
 
-  private lazy val nilLitMTA = prod("nilLitMTA", isNilLit) { mtaBase }
+  /**
+   * mandatory text alignment for a literal nil value is only needed
+   * if there is no initiator that gets its own mandatory text alignment.
+   */
+  private lazy val nilLitMTA = prod("nilLitMTA", isNilLit && !hasNilValueInitiator) { mtaBase }
 
   private lazy val nilLitContent = prod("nilLitContent",
     isNillable && (nilKind == NilKind.LiteralValue || nilKind == NilKind.LiteralCharacter)) {
@@ -1052,31 +1016,16 @@ trait ElementBaseGrammarMixin
     else body
   }
 
-  private lazy val nilOrEmptyOrValue = prod("nilOrEmptyOrValue") {
-    // anyOfNilOrEmptyOrValue ||
-    nilOrValue ||
-      //   emptyOrValue ||
-      nonNilNonEmptyParsedValue
-  }
-
-  //  private lazy val anyOfNilOrEmptyOrValue = prod("anyOfNilOrEmptyOrValue", isNillable && NYI && emptyIsAnObservableConcept) {
-  //    SimpleNilOrEmptyOrValue(this, nilLit || parsedNil, empty, parsedValue)
-  //  }
-
   private lazy val nilOrValue = prod("nilOrValue", isNillable) { // TODO: make it exclude emptyness once emptyness is implemented
     SimpleNilOrValue(this, nilLit || parsedNil, parsedValue)
   }
 
-  //  private lazy val emptyOrValue = prod("emptyOrValue", NYI && emptyIsAnObservableConcept && !isNillable) {
-  //    SimpleEmptyOrValue(this, empty, parsedValue)
-  //  }
-
-  private lazy val nonNilNonEmptyParsedValue = prod("nonNilnonEmptyParsedValue", !isNillable) { // TODO: make it exclude emptyness once emptyness is implemented
+  private lazy val nonNillableParsedValue = prod("nonNilnonEmptyParsedValue", !isNillable) {
     parsedValue
   }
 
   private lazy val scalarDefaultableSimpleContent = prod("scalarDefaultableSimpleContent", isSimpleType) {
-    nilOrEmptyOrValue
+    nilOrValue || nonNillableParsedValue
   }
 
   /**
@@ -1163,7 +1112,7 @@ trait ElementBaseGrammarMixin
 
   private lazy val elementRightFraming = prod("elementRightFraming") { TrailingSkipRegion(this) }
 
-  protected lazy val enclosedElement = prod("enclosedElement") {
+  lazy val enclosedElement = prod("enclosedElement") {
     //
     // not isScalar, because this is reused inside arrays
     // that is, we're counting on reusuing this production for array elements
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementReferenceGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementReferenceGrammarMixin.scala
index 0f3aa35c0..b0a05a34f 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementReferenceGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementReferenceGrammarMixin.scala
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.daffodil.grammar
-
-import org.apache.daffodil.dsom.AbstractElementRef
-
-trait ElementReferenceGrammarMixin { self: AbstractElementRef =>
-
-}
+//
+//package org.apache.daffodil.grammar
+//
+//import org.apache.daffodil.dsom.AbstractElementRef
+//
+//trait ElementReferenceGrammarMixin { self: AbstractElementRef =>
+//
+//}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Grammar.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Grammar.scala
index eeb7bc22e..bfe6edbac 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Grammar.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Grammar.scala
@@ -21,14 +21,11 @@ import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.Implicits._; object INoWarn { ImplicitsSuppressUnusedImportWarning() }
 import org.apache.daffodil.processors.unparsers.SeqCompUnparser
 import org.apache.daffodil.dsom._
-import org.apache.daffodil.grammar.primitives.Nada
 import org.apache.daffodil.processors.parsers.SeqCompParser
-import org.apache.daffodil.processors.parsers.AltCompParser
 import org.apache.daffodil.compiler.ForUnparser
 import org.apache.daffodil.compiler.ForParser
 import org.apache.daffodil.processors.unparsers.NadaUnparser
 import org.apache.daffodil.processors.parsers.NadaParser
-import org.apache.daffodil.processors.unparsers.EmptyGramUnparser
 
 abstract class UnaryGram(context: Term, rr: => Gram) extends NamedGram(context) {
   private lazy val r = rr
@@ -95,8 +92,6 @@ class SeqComp private (context: SchemaComponent, children: Seq[Gram]) extends Bi
   protected final override def open = "("
   protected final override def close = ")"
 
-  Assert.invariant(!children.exists { _.isInstanceOf[Nada] })
-
   lazy val parserChildren = children.filter(_.forWhat != ForUnparser).map { _.parser }.filterNot { _.isInstanceOf[NadaParser] }
 
   final override lazy val parser = {
@@ -124,56 +119,20 @@ class SeqComp private (context: SchemaComponent, children: Seq[Gram]) extends Bi
   }
 }
 
-/**
- * Alternative composition of grammar terms.
- *
- * Flattens nests of these into a single flat list.
- */
-object AltComp {
-  def apply(context: SchemaComponent, p: => Gram, q: => Gram) = {
-    val children = (p, q) match {
-      case (ps: AltComp, qs: AltComp) => {
-        ps.children ++ qs.children
-      }
-      case (ps: AltComp, _) => ps.children ++ List(q)
-      case (_, qs: AltComp) => p +: qs.children
-      case (_, _) => List(p, q)
-    }
-    val res = new AltComp(context, children)
-    res
-  }
-}
-
-class AltComp private (context: SchemaComponent, children: Seq[Gram]) extends BinaryGram(context, children)
-  with HasNoUnparser {
-  protected final override def op = "|"
-  protected final override def open = "["
-  protected final override def close = "]"
-
-  final override lazy val parser = new AltCompParser(context.runtimeData, children.map { _.parser })
-}
-
 object EmptyGram extends Gram(null) {
   override def isEmpty = true
   override def toString = "Empty"
 
   override lazy val parser = new NadaParser(null)
-  override lazy val unparser = // hasNoUnparser
-    // we depend on this unparser being returned, even though it cannot be called to unparse anything.
-    // As there are unit tests which test attributes where those attributes cause a DummyUnparser to be created.
-    // That is later optimized out (or needs to be).
-    //
-    // FIXME: switch back to hasNoUnparser, find where this is being used and have it not ask for
-    // this unparser.
-    new EmptyGramUnparser(null) // DummyUnparser(Misc.getNameFromClass(this))
-
+  override lazy val unparser = new NadaUnparser(null)
 }
 
-object ErrorGram extends Gram(null) with HasNoUnparser {
+object ErrorGram extends Gram(null) {
   override def isEmpty = false
   override def toString = "Error"
 
-  override lazy val parser = hasNoParser // new ErrorParser
+  override lazy val parser = hasNoParser
+  override lazy val unparser = hasNoUnparser
 }
 
 abstract class NamedGram(context: SchemaComponent) extends Gram(context) {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarMixins.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarMixins.scala
index 8c3d7dc86..bddd4d4d0 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarMixins.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarMixins.scala
@@ -14,25 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.daffodil.grammar
-import org.apache.daffodil.dsom.ComplexTypeBase
-import org.apache.daffodil.dsom.GroupRef
-import org.apache.daffodil.grammar.primitives.ComplexTypeCombinator
-
-trait GroupRefGrammarMixin extends GrammarMixin { self: GroupRef =>
-
-}
-
-/////////////////////////////////////////////////////////////////
-// Types System
-/////////////////////////////////////////////////////////////////
-
-trait ComplexTypeBaseGrammarMixin extends GrammarMixin { self: ComplexTypeBase =>
-
-  override protected final def grammarContext = this
-
-  lazy val mainGrammar = prod("mainGrammar") {
-    ComplexTypeCombinator(this, group.asChildOfComplexType)
-  }
-}
+//
+//package org.apache.daffodil.grammar
+//import org.apache.daffodil.dsom.ComplexTypeBase
+//import org.apache.daffodil.dsom.GroupRef
+//import org.apache.daffodil.grammar.primitives.ComplexTypeCombinator
+//
+///////////////////////////////////////////////////////////////////
+//// Types System
+///////////////////////////////////////////////////////////////////
+//
+//trait ComplexTypeBaseGrammarMixin extends GrammarMixin { self: ComplexTypeBase =>
+//
+//  override protected final def grammarContext = this
+//
+//  lazy val mainGrammar = prod("mainGrammar") {
+//    ComplexTypeCombinator(this, group.asChildOfComplexType)
+//  }
+//}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
index 14b3796f1..3b3d33b2f 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
@@ -20,25 +20,20 @@ package org.apache.daffodil.grammar
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.processors.parsers.Parser
 import org.apache.daffodil.processors.unparsers.Unparser
-import org.apache.daffodil.grammar.primitives.Nada
 import org.apache.daffodil.dsom.SchemaComponent
 import org.apache.daffodil.oolag.OOLAG.OOLAGHostImpl
 import org.apache.daffodil.compiler.ParserOrUnparser
-import org.apache.daffodil.util.Misc
 import org.apache.daffodil.compiler.BothParserAndUnparser
 import org.apache.daffodil.api.WarnID
-
-trait HasNoUnparser {
-  final lazy val unparser: Unparser = hasNoUnparser
-  private def hasNoUnparser = Assert.invariantFailed("no unparser for " + Misc.getNameFromClass(this))
-}
+import org.apache.daffodil.util.Maybe
 
 /**
  * Gram - short for "Grammar Term"
  *
- * These are the objects in the grammar. The grammar is supposed to be
- * roughly the grammar in the DFDL specification, but some differences are expected
- * because this one has to actually be operationalized.
+ * These are the objects in the grammar.
+ *
+ * This grammar really differs a great deal from what we find in the DFDL specification
+ * because it actually has to be operationalized.
  */
 abstract class Gram(contextArg: SchemaComponent)
   extends OOLAGHostImpl(contextArg) {
@@ -75,37 +70,21 @@ abstract class Gram(contextArg: SchemaComponent)
   def ~(qq: => Gram) = {
     lazy val q = qq.deref
     val self = this.deref
-    //
-    // The Nada terminal also behaves like empty for sequential composition
-    // It is not empty for alternative composition though.
-    //
+
     val res =
-      if (self.isEmpty || self.isInstanceOf[Nada]) {
-        if (q.isEmpty || q.isInstanceOf[Nada]) // Nada might get through to this point. Let's optimize it out.
+      if (self.isEmpty) {
+        if (q.isEmpty)
           EmptyGram
         else q
-      } else if (q.isEmpty || q.isInstanceOf[Nada]) self
+      } else if (q.isEmpty) self
       else {
-        Assert.invariant(!self.isInstanceOf[Nada])
         Assert.invariant(!self.isEmpty)
-        Assert.invariant(!q.isInstanceOf[Nada])
         Assert.invariant(!q.isEmpty)
         SeqComp(context, self, q)
       }
     res
   }
 
-  def |(qq: => Gram) = {
-    lazy val q = qq.deref
-    val self = this.deref
-    if (self.isEmpty)
-      if (q.isEmpty) EmptyGram
-      else q
-    else if (q.isEmpty) self
-    else
-      AltComp(context, self, q)
-  }
-
   /**
    * This || operator means one of the operands ONLY. I.e., statically
    * they are supposed to be mutually exclusive, so only one (or none) of them should
@@ -127,9 +106,27 @@ abstract class Gram(contextArg: SchemaComponent)
    */
   def parser: Parser
 
+  final def maybeParser: Maybe[Parser] = {
+    if (this.isEmpty) Maybe.Nope
+    else {
+      val p = this.parser
+      if (p.isEmpty) Maybe.Nope
+      else Maybe(p)
+    }
+  }
+
   protected final def hasNoParser: Parser = Assert.invariantFailed("Has no parser.")
   protected final def hasNoUnparser: Unparser = Assert.invariantFailed("Has no unparser.")
 
-  def unparser: Unparser // = DummyUnparser(Misc.getNameFromClass(this)) // context.runtimeData
+  def unparser: Unparser
+
+  final def maybeUnparser: Maybe[Unparser] = {
+    if (this.isEmpty) Maybe.Nope
+    else {
+      val u = this.unparser
+      if (u.isEmpty) Maybe.Nope
+      else Maybe(u)
+    }
+  }
 
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/HasStatementsGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/HasStatementsGrammarMixin.scala
index d6fc27f74..463c99830 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/HasStatementsGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/HasStatementsGrammarMixin.scala
@@ -21,7 +21,7 @@ import org.apache.daffodil.dsom.Term
 
 trait HasStatementsGrammarMixin extends GrammarMixin { self: Term =>
 
-  private lazy val statementGrams = statements.map { _.gram }
+  private lazy val statementGrams = statements.map { _.gram(self) }
   // TODO: statements (but specifically not newVariableInstance) can appear on simple type definitions as well as terms.
 
   final lazy val dfdlStatementEvaluations = prod("dfdlStatementEvaluations", statementGrams.length > 0) {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/LocalElementGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/LocalElementGrammarMixin.scala
index ce33817c4..30726cdf8 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/LocalElementGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/LocalElementGrammarMixin.scala
@@ -16,206 +16,190 @@
  */
 
 package org.apache.daffodil.grammar
-import org.apache.daffodil.schema.annotation.props._
-import org.apache.daffodil.schema.annotation.props.gen._
 import org.apache.daffodil.dsom.ElementBase
-import org.apache.daffodil.equality._; object ENoWarn2 { EqualitySuppressUnusedImportWarning() }
-import org.apache.daffodil.grammar.primitives.StopValue
-import org.apache.daffodil.grammar.primitives.NotStopValue
-import org.apache.daffodil.grammar.primitives.RepUnbounded
-import org.apache.daffodil.grammar.primitives.RepExactlyTotalOccursCount
-import org.apache.daffodil.grammar.primitives.RepExactlyTotalN
-import org.apache.daffodil.grammar.primitives.RepExactlyN
-import org.apache.daffodil.grammar.primitives.RepAtMostTotalN
-import org.apache.daffodil.grammar.primitives.RepAtMostOccursCount
-import org.apache.daffodil.grammar.primitives.OccursCountExpression
-import org.apache.daffodil.grammar.primitives.OptionalCombinator
-import org.apache.daffodil.grammar.primitives.ArrayCombinator
 
 trait LocalElementGrammarMixin extends GrammarMixin { self: ElementBase =>
 
-  override lazy val termContentBody = prod("termContentBody") { // override in ElementRef
-    (if (isScalar) enclosedElement else recurrance)
-  }
-
-  protected final lazy val allowedValue = prod("allowedValue") { notStopValue | value }
-
-  private lazy val notStopValue = prod("notStopValue", hasStopValue) { NotStopValue(this) }
-
-  private lazy val separatedEmpty = prod("separatedEmpty",
-    emptyIsAnObservableConcept && !isScalar) {
-      separatedForArrayPosition(empty)
-    }
-
-  private lazy val separatedRecurringDefaultable = prod("separatedRecurringDefaultable", !isScalar) {
-    separatedForArrayPosition(enclosedElement)
-  }
-
-  private lazy val separatedRecurringNonDefault = prod("separatedRecurringNonDefault", !isScalar) {
-    separatedForArrayPosition(enclosedElementNonDefault)
-  }
-
-  private lazy val nonSeparatedScalarDefaultable = prod("nonSeparatedScalarDefaultable", isScalar) { enclosedElement }
-
-  private lazy val recurrance = prod("recurrance", !isScalar) {
-    if (isOptional) {
-      OptionalCombinator(this, arrayContents)
-    } else {
-      ArrayCombinator(this, arrayContents)
-    }
-  }
-
-  final override lazy val asTermInChoice = prod("asTermInChoice") {
-    nonSeparatedScalarDefaultable || recurrance
-  }
-
-  /**
-   * speculate parsing forward until we get an error
-   */
-  private lazy val separatedContentWithMinUnboundedWithoutTrailingEmpties = prod("separatedContentWithMinUnboundedWithoutTrailingEmpties", !isScalar) {
-    RepExactlyN(self, minOccurs, separatedRecurringDefaultable) ~
-      RepUnbounded(self, separatedRecurringNonDefault) ~
-      StopValue(this)
-  }
-
-  private lazy val separatedContentWithMinAndMaxWithoutTrailingEmpties = prod("separatedContentWithMinAndMaxWithoutTrailingEmpties", !isScalar) {
-    RepExactlyN(self, minOccurs, separatedRecurringDefaultable) ~
-      RepAtMostTotalN(self, maxOccurs, separatedRecurringNonDefault) ~
-      StopValue(this)
-  }
-
-  private lazy val separatedContentWithMinUnbounded = prod("separatedContentWithMinUnbounded", !isScalar) {
-    separatedContentWithMinUnboundedWithoutTrailingEmpties // These are for tolerating trailing empties. Let's not tolerate them for now.
-  }
-
-  private lazy val separatedContentWithMinAndMax = prod("separatedContentWithMinAndMax", !isScalar) {
-    separatedContentWithMinAndMaxWithoutTrailingEmpties // These are for tolerating trailing empties. Let's not tolerate them for now.
-  }
-
-  private lazy val separatedContentZeroToUnbounded = prod("separatedContentZeroToUnbounded", !isScalar) {
-    RepUnbounded(self, separatedRecurringNonDefault) ~
-      StopValue(this)
-  }
-
-  private lazy val separatedContentAtMostNWithoutTrailingEmpties = prod("separatedContentAtMostNWithoutTrailingEmpties", !isScalar) {
-    RepExactlyN(self, minOccurs, separatedRecurringDefaultable) ~
-      RepAtMostTotalN(this, maxOccurs, separatedRecurringNonDefault) ~
-      StopValue(this)
-  }
-
-  // TODO: Do we have to adjust the count to take stopValue into account?
-  // Answer: No because the counts are never used when there is a stopValue (at least in current
-  // thinking about how occursCountKind='stopValue' works.)
-
-  private lazy val separatedContentAtMostN = prod("separatedContentAtMostN") {
-    (separatedContentAtMostNWithoutTrailingEmpties // FIXME: We don't know whether we can absorb trailing separators or not here.
-    // We don't know if this repeating thing is in trailing position, or in the middle
-    // of a sequence. There is also ambiguity if the enclosing sequence and this sequence
-    // have the same separator.
-    //      ~
-    //      RepAtMostTotalN(self, maxOccurs, separatedEmpty) // absorb extra separators, if found.
-    )
-  }
-
-  /**
-   *  parse counted number of occurrences exactly.
-   */
-  private lazy val stopValueSize = if (hasStopValue) 1 else 0
-
-  // TODO FIXME: We really want to have different productions for parsing and unparsing in these
-  // complex cases where there is defaulting, etc. Unparsing has many fewer cases, and is just not
-  // symmetric with parsing in these situations.
-  private def separatedContentExactlyN(count: Long) = prod("separatedContentExactlyN") {
-    if (minOccurs == maxOccurs) {
-      // fixed length case. All are defaultable. Still might have a stop value tho.
-      RepExactlyN(self, count, separatedRecurringDefaultable) ~
-        StopValue(this)
-    } else {
-      // variable length case. So some defaultable, some not.
-      RepExactlyN(self, minOccurs, separatedRecurringDefaultable) ~
-        RepAtMostTotalN(self, count, separatedRecurringNonDefault) ~
-        StopValue(this) ~
-        RepExactlyTotalN(self, maxOccurs + stopValueSize, separatedEmpty) // absorb remaining separators after stop value.
-    }
-  }
-
-  private lazy val separatedContentExactlyNComputed = prod("separatedContentExactlyNComputed") {
-    OccursCountExpression(this) ~
-      RepAtMostOccursCount(this, minOccurs, separatedRecurringDefaultable) ~
-      RepExactlyTotalOccursCount(this, separatedRecurringNonDefault)
-  }
-
-  // keep in mind that anything here that scans for a representation either knows the length it is going after, or knows what the terminating markup is, and
-  // our invariant is, that it does NOT consume that markup ever. The parser consumes it with appropriate grammar terminals.
-
-  private val UNB = -1 // UNBOUNDED
-  private val ZERO = 0 // ZERO
-
-  lazy val arrayContents = prod("arrayContents", !isScalar) {
-    arrayContentsNoSeparators || arrayContentsWithSeparators
-  }
-
-  private lazy val contentUnbounded = prod("contentUnbounded") {
-    RepUnbounded(self, separatedRecurringDefaultable)
-  }
+  override lazy val termContentBody = enclosedElement
 
+  //  override lazy val termContentBody = prod("termContentBody") {
+  //    (if (isScalar) enclosedElement else recurrance)
+  //  }
   //
-  // Silly constants to make the lookup tables below more readable without using fragile whitespace
+  //  private def separatedForArrayPosition(bodyArg: => Gram): Gram = {
+  //    val body = bodyArg
+  //    val (isElementWithNoRep, isRepeatingElement) = body.context match {
+  //      case e: ElementBase => (!e.isRepresented, !e.isScalar)
+  //      case other => (false, false)
+  //    }
+  //    Assert.usage(isRepeatingElement)
+  //    Assert.invariant(!isElementWithNoRep) //inputValueCalc not allowed on arrays in DFDL v1.0
+  //    // val res = prefixSep ~ infixSepRule ~ body ~ postfixSep
+  //    val res = new OptionalInfixSep(this, arraySeparator) ~ body
+  //    res
+  //  }
   //
-  private val Never______ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.Never
-  private val Trailing___ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.TrailingEmpty
-  private val TrailingStr: SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.TrailingEmptyStrict
-  private val Always_____ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.AnyEmpty
-
-  private val StopValue_ = OccursCountKind.StopValue
-  private val Implicit__ = OccursCountKind.Implicit
-  private val Parsed____ = OccursCountKind.Parsed
-  private val Fixed_____ = OccursCountKind.Fixed
-  private val Expression = OccursCountKind.Expression
-
-  private lazy val arrayContentsNoSeparators = prod("arrayContentsNoSeparators", !isScalar && !hasSep) {
-    val res = (occursCountKind, minOccurs, maxOccurs) match {
-      case (Expression, ____, __2) => separatedContentExactlyNComputed
-      case (Fixed_____, ____, UNB) => SDE("occursCountKind='fixed' not allowed with unbounded maxOccurs")
-      case (Fixed_____, min_, max) if (min_ != max) => SDE("occursCountKind='fixed' requires minOccurs and maxOccurs to be equal (%d != %d)", min_, max)
-      case (Fixed_____, ____, max) => separatedContentExactlyN(max)
-      case (Implicit__, ZERO, UNB) => contentUnbounded // same as parsed
-      case (Implicit__, min_, UNB) => RepExactlyN(self, min_, separatedRecurringDefaultable) ~ contentUnbounded // respects minOccurs
-      case (Implicit__, ____, __2) => separatedContentAtMostN // uses min and maxOccurs
-      case (Parsed____, ____, __2) => contentUnbounded
-      case (StopValue_, ____, __2) => contentUnbounded
-    }
-    res
-  }
-
-  /**
-   * Matches the table about separator suppression policy.
-   *
-   * TODO: Update this table to match the final spec.
-   */
-  private lazy val arrayContentsWithSeparators = prod("arrayContentsWithSeparators", !isScalar && hasSep) {
-    val triple = (separatorSuppressionPolicy, occursCountKind, maxOccurs, minOccurs)
-    val res = triple match {
-      case (___________, Expression, ___, __2) => separatedContentExactlyNComputed
-      case (___________, Fixed_____, UNB, ___) => SDE("occursCountKind='fixed' not allowed with unbounded maxOccurs")
-      case (___________, Fixed_____, max, min) if (max != min) => SDE("occursCountKind='fixed' requires minOccurs to equal maxOccurs (%d != %d)", minOccurs, max)
-      case (___________, Fixed_____, max, ___) => separatedContentExactlyN(max)
-      case (Never______, Implicit__, UNB, ___) => SDE("separatorSuppressionPolicy='never' with occursCountKind='implicit' required bounded maxOccurs.")
-      case (Never______, Implicit__, max, ___) => separatedContentExactlyN(max)
-      case (Never______, ock /****/ , ___, __2) => SDE("separatorSuppressionPolicy='never' not allowed in combination with occursCountKind='" + ock + "'.")
-      case (Trailing___, Implicit__, UNB, ___) if (!isLastDeclaredRequiredElementOfSequence) => SDE("occursCountKind='implicit' with unbounded maxOccurs only allowed for last element of a sequence")
-      case (Trailing___, Implicit__, UNB, min) => separatedContentWithMinUnbounded
-      case (Trailing___, Implicit__, max, min) if min > 0 => separatedContentWithMinAndMax
-      case (Trailing___, Implicit__, max, ___) => separatedContentAtMostN // FIXME: have to have all of them - not trailing position
-      case (TrailingStr, Implicit__, UNB, ___) if (!isLastDeclaredRequiredElementOfSequence) => SDE("occursCountKind='implicit' with unbounded maxOccurs only allowed for last element of a sequence")
-      case (TrailingStr, Implicit__, UNB, ___) => separatedContentWithMinUnboundedWithoutTrailingEmpties // we're depending on optionalEmptyPart failing on empty content.
-      case (TrailingStr, Implicit__, max, ___) => separatedContentAtMostNWithoutTrailingEmpties
-      case (Always_____, Implicit__, UNB, ___) => separatedContentWithMinUnbounded
-      case (Always_____, Implicit__, max, ___) => separatedContentAtMostN
-      case (Always_____, Parsed____, ___, __2) => separatedContentZeroToUnbounded
-      case (Always_____, StopValue_, ___, __2) => separatedContentZeroToUnbounded
-      case (policy /**/ , ock /****/ , max, __2) => SDE("separatorSuppressionPolicy='" + policy + "' not allowed with occursCountKind='" + ock + "'.")
-    }
-    res
-  }
+  //  private lazy val arraySeparator = prod("separator", !ignoreES && hasES) {
+  //    delimMTA ~ ArrayElementSeparator(es, self)
+  //  }
+  //
+  //  private lazy val separatedEmpty = prod("separatedEmpty",
+  //    emptyIsAnObservableConcept && !isScalar) {
+  //      separatedForArrayPosition(empty)
+  //    }
+  //
+  //  private lazy val separatedRecurring = prod("separatedRecurring", !isScalar) {
+  //    separatedForArrayPosition(enclosedElement)
+  //  }
+  //
+  //  //  private lazy val separatedRecurringNonDefault = prod("separatedRecurringNonDefault", !isScalar) {
+  //  //    separatedForArrayPosition(enclosedElementNonDefault)
+  //  //  }
+  //
+  //  private lazy val nonSeparatedScalarDefaultable = prod("nonSeparatedScalarDefaultable", isScalar) { enclosedElement }
+  //
+  //  final override lazy val asTermInChoice = prod("asTermInChoice") {
+  //    nonSeparatedScalarDefaultable || recurrance
+  //  }
+  //
+  //  /**
+  //   * speculate parsing forward until we get an error
+  //   */
+  //  private lazy val separatedContentWithMinUnboundedWithoutTrailingEmpties = prod("separatedContentWithMinUnboundedWithoutTrailingEmpties", !isScalar) {
+  //    RepExactlyN(self, minOccurs, separatedRecurring) ~
+  //      RepUnbounded(self, separatedRecurring)
+  //  }
+  //
+  //  private lazy val separatedContentWithMinAndMaxWithoutTrailingEmpties = prod("separatedContentWithMinAndMaxWithoutTrailingEmpties", !isScalar) {
+  //    RepExactlyN(self, minOccurs, separatedRecurring) ~
+  //      RepAtMostTotalN(self, maxOccurs, separatedRecurring)
+  //  }
+  //
+  //  private lazy val separatedContentWithMinUnbounded = prod("separatedContentWithMinUnbounded", !isScalar) {
+  //    separatedContentWithMinUnboundedWithoutTrailingEmpties ~ unboundedTrailingEmpties
+  //  }
+  //
+  //  private lazy val unboundedTrailingEmpties = prod("unboundedTrailingEmpties", couldBeLastElementInModelGroup, forWhat = ForParser) {
+  //    RepUnbounded(self, separatedEmpty)
+  //  }
+  //
+  //  private lazy val separatedContentWithMinAndMax = prod("separatedContentWithMinAndMax", !isScalar) {
+  //    separatedContentWithMinAndMaxWithoutTrailingEmpties ~ unboundedTrailingEmpties
+  //  }
+  //
+  //  private lazy val separatedContentZeroToUnbounded = prod("separatedContentZeroToUnbounded", !isScalar) {
+  //    RepUnbounded(self, separatedRecurring)
+  //  }
+  //
+  //  private lazy val separatedContentAtMostNWithoutTrailingEmpties = prod("separatedContentAtMostNWithoutTrailingEmpties", !isScalar) {
+  //    RepExactlyN(self, minOccurs, separatedRecurring) ~
+  //      RepAtMostTotalN(this, maxOccurs, separatedRecurring)
+  //  }
+  //
+  //  // Question: Do we have to adjust the count to take stopValue into account?
+  //  // Answer: No because the counts are never used when there is a stopValue (at least in current
+  //  // thinking about how occursCountKind='stopValue' works.)
+  //
+  //  private lazy val separatedContentAtMostN = prod("separatedContentAtMostN") {
+  //    separatedContentAtMostNWithoutTrailingEmpties ~ repAtMostTotalNTrailingEmpties
+  //  }
+  //
+  //  private lazy val repAtMostTotalNTrailingEmpties = prod("repAtMostTotalNTrailingEmpties", couldBeLastElementInModelGroup, forWhat = ForParser) {
+  //    RepAtMostTotalN(self, maxOccurs, separatedEmpty)
+  //  }
+  //
+  //  // TODO FIXME: We really want to have different productions for parsing and unparsing in these
+  //  // complex cases where there is defaulting, etc. Unparsing has many fewer cases, and is just not
+  //  // symmetric with parsing in these situations.
+  //  private def separatedContentExactlyN(count: Long) = prod("separatedContentExactlyN") {
+  //    if (minOccurs == maxOccurs) {
+  //      // fixed length case. All are defaultable. Still might have a stop value tho.
+  //      RepExactlyN(self, count, separatedRecurring)
+  //    } else {
+  //      // variable length case. So some defaultable, some not.
+  //      RepExactlyN(self, minOccurs, separatedRecurring) ~
+  //        RepAtMostTotalN(self, count, separatedRecurring) ~
+  //        RepExactlyTotalN(self, maxOccurs, separatedEmpty) // absorb remaining separators after stop value.
+  //    }
+  //  }
+  //
+  //  private lazy val separatedContentExactlyNComputed = prod("separatedContentExactlyNComputed") {
+  //    OccursCountExpression(this) ~
+  //      RepAtMostOccursCount(this, minOccurs, separatedRecurring) ~
+  //      RepExactlyTotalOccursCount(this, separatedRecurring)
+  //  }
+  //
+  //  // keep in mind that anything here that scans for a representation either knows the length it is going after, or knows what the terminating markup is, and
+  //  // our invariant is, that it does NOT consume that markup ever. The parser consumes it with appropriate grammar terminals.
+  //
+  //  private val UNB = -1 // UNBOUNDED
+  //  private val ZERO = 0 // ZERO
+  //
+  //  lazy val recurrance = prod("recurrance", !isScalar) {
+  //    arrayContentsNoSeparators || arrayContentsWithSeparators
+  //  }
+  //
+  //  private lazy val contentUnbounded = prod("contentUnbounded") {
+  //    RepUnbounded(self, separatedRecurring)
+  //  }
+  //
+  //  //
+  //  // Silly constants to make the lookup tables below more readable without using fragile whitespace
+  //  //
+  //  private val Never______ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.Never
+  //  private val Trailing___ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.TrailingEmpty
+  //  private val TrailingStr: SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.TrailingEmptyStrict
+  //  private val Always_____ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.AnyEmpty
+  //
+  //  private val StopValue_ = OccursCountKind.StopValue
+  //  private val Implicit__ = OccursCountKind.Implicit
+  //  private val Parsed____ = OccursCountKind.Parsed
+  //  private val Fixed_____ = OccursCountKind.Fixed
+  //  private val Expression = OccursCountKind.Expression
+  //
+  //  private lazy val arrayContentsNoSeparators = prod("arrayContentsNoSeparators", !isScalar && !hasSep) {
+  //    val res = (occursCountKind, minOccurs, maxOccurs) match {
+  //      case (Expression, ____, __2) => separatedContentExactlyNComputed
+  //      case (Fixed_____, ____, UNB) => SDE("occursCountKind='fixed' not allowed with unbounded maxOccurs")
+  //      case (Fixed_____, min_, max) if (min_ != max) => SDE("occursCountKind='fixed' requires minOccurs and maxOccurs to be equal (%d != %d)", min_, max)
+  //      case (Fixed_____, ____, max) => separatedContentExactlyN(max)
+  //      case (Implicit__, ZERO, UNB) => contentUnbounded // same as parsed
+  //      case (Implicit__, min_, UNB) => RepExactlyN(self, min_, separatedRecurring) ~ contentUnbounded // respects minOccurs
+  //      case (Implicit__, ____, __2) => separatedContentAtMostN // uses min and maxOccurs
+  //      case (Parsed____, ____, __2) => contentUnbounded
+  //      case (StopValue_, ____, __2) => contentUnbounded
+  //    }
+  //    res
+  //  }
+  //
+  //  /**
+  //   * Matches the table about separator suppression policy.
+  //   *
+  //   * TODO: Update this table to match the final spec.
+  //   */
+  //  private lazy val arrayContentsWithSeparators = prod("arrayContentsWithSeparators", !isScalar && hasSep) {
+  //    val triple = (separatorSuppressionPolicy, occursCountKind, maxOccurs, minOccurs)
+  //    val res = triple match {
+  //      case (___________, Expression, ___, __2) => separatedContentExactlyNComputed
+  //      case (___________, Fixed_____, UNB, ___) => SDE("occursCountKind='fixed' not allowed with unbounded maxOccurs")
+  //      case (___________, Fixed_____, max, min) if (max != min) => SDE("occursCountKind='fixed' requires minOccurs to equal maxOccurs (%d != %d)", minOccurs, max)
+  //      case (___________, Fixed_____, max, ___) => separatedContentExactlyN(max)
+  //      case (Never______, Implicit__, UNB, ___) => SDE("separatorSuppressionPolicy='never' with occursCountKind='implicit' required bounded maxOccurs.")
+  //      case (Never______, Implicit__, max, ___) => separatedContentExactlyN(max)
+  //      case (Never______, ock /****/ , ___, __2) => SDE("separatorSuppressionPolicy='never' not allowed in combination with occursCountKind='" + ock + "'.")
+  //      case (Trailing___, Implicit__, UNB, ___) if (!isLastDeclaredRequiredElementOfSequence) => SDE("occursCountKind='implicit' with unbounded maxOccurs only allowed for last element of a sequence")
+  //      case (Trailing___, Implicit__, UNB, min) => separatedContentWithMinUnbounded
+  //      case (Trailing___, Implicit__, max, min) if min > 0 => separatedContentWithMinAndMax
+  //      case (Trailing___, Implicit__, max, ___) => separatedContentAtMostN
+  //      case (TrailingStr, Implicit__, UNB, ___) if (!isLastDeclaredRequiredElementOfSequence) => SDE("occursCountKind='implicit' with unbounded maxOccurs only allowed for last element of a sequence")
+  //      case (TrailingStr, Implicit__, UNB, ___) => separatedContentWithMinUnboundedWithoutTrailingEmpties // we're depending on optionalEmptyPart failing on empty content.
+  //      case (TrailingStr, Implicit__, max, ___) => separatedContentAtMostNWithoutTrailingEmpties
+  //      case (Always_____, Implicit__, UNB, ___) => separatedContentWithMinUnboundedWithoutTrailingEmpties
+  //      case (Always_____, Implicit__, max, ___) => separatedContentAtMostNWithoutTrailingEmpties
+  //      case (Always_____, Parsed____, ___, __2) => separatedContentZeroToUnbounded
+  //      case (Always_____, StopValue_, ___, __2) => separatedContentZeroToUnbounded
+  //      case (policy /**/ , ock /****/ , max, __2) => SDE("separatorSuppressionPolicy='" + policy + "' not allowed with occursCountKind='" + ock + "'.")
+  //    }
+  //    res
+  //  }
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ModelGroupGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ModelGroupGrammarMixin.scala
index bcbbc8629..351ac8648 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ModelGroupGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ModelGroupGrammarMixin.scala
@@ -40,10 +40,6 @@ trait ModelGroupGrammarMixin
 
   private lazy val groupRightFraming = prod("groupRightFraming") { TrailingSkipRegion(this) }
 
-  // I believe we can have the same grammar rules whether we're directly inside a complex type, or
-  // we're nested inside another group as a term.
-  final lazy val asChildOfComplexType = termContentBody
-
   final override lazy val termContentBody = prod("termContentBody") {
     dfdlStatementEvaluations ~ groupLeftFraming ~ _content ~ groupRightFraming
   }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
index 724b29cbd..fa076a4ed 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
@@ -17,36 +17,122 @@
 
 package org.apache.daffodil.grammar
 import org.apache.daffodil.schema.annotation.props.gen._
-import org.apache.daffodil.grammar.primitives.SequenceCombinator
-import org.apache.daffodil.dsom.SequenceTermBase
-import org.apache.daffodil.grammar.primitives.LayeredSequence
+import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
+import org.apache.daffodil.dsom._
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.grammar.primitives._
+import org.apache.daffodil.grammar.primitives.OrderedSequence
 
 trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
 
   final override lazy val groupContent = prod("groupContent") {
-    if (isLayered) layeredSequenceContent
-    else {
-      self.sequenceKind match {
-        case SequenceKind.Ordered => orderedSequenceContent
-        case SequenceKind.Unordered => subsetError("Unordered sequences are not supported.") // unorderedSequenceContent
-      }
+    if (isLayered) layerContent
+    else sequenceContent
+  }
+
+  final lazy val sequenceContent = {
+    import columnConstants._
+    self.sequenceKind match {
+      case Ordered__ => orderedSequence
+      case Unordered => subsetError("Unordered sequences are not supported.") // unorderedSequenceContent
     }
   }
 
-  private lazy val layeredSequenceContent = {
+  private lazy val layerContent = {
     schemaDefinitionUnless(groupMembers.length == 1, "Layered sequence can have only 1 child term. %s were found: %s", groupMembers.length,
       groupMembers.mkString(", "))
     val term = groupMembers(0)
     schemaDefinitionWhen(term.isArray, "Layered sequence body cannot be an array.")
-    val termGram = term.termContentBody
-    LayeredSequence(this, termGram)
+    LayeredSequence(this, new ScalarOrderedSequenceChild(this, term, 1))
+  }
+
+  private lazy val seqChildren = (groupMembers zip Stream.from(1)).map {
+    case (gm, i) =>
+      sequenceChild(gm, i)
+  }
+
+  private lazy val orderedSequence = {
+    val res = new OrderedSequence(this, seqChildren)
+    res
   }
 
-  private lazy val orderedSequenceContent = prod("sequenceContent") {
-    SequenceCombinator(this, terms)
+  /**
+   * Constants to make the lookup tables below more readable without using fragile whitespace
+   */
+  object columnConstants {
+    val UNB = -1 // UNBOUNDED
+    val ZER = 0
+    val ONE = 1
+
+    val Sep__ = true
+    val NoSep = false
+
+    val Ordered__ = SequenceKind.Ordered
+    val Unordered = SequenceKind.Unordered
+
+    val Never______ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.Never
+    val Trailing___ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.TrailingEmpty
+    val TrailingStr: SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.TrailingEmptyStrict
+    val Always_____ : SeparatorSuppressionPolicy = SeparatorSuppressionPolicy.AnyEmpty
+
+    val StopValue_ = OccursCountKind.StopValue
+    val Implicit__ = OccursCountKind.Implicit
+    val Parsed____ = OccursCountKind.Parsed
+    val Fixed_____ = OccursCountKind.Fixed
+    val Expression = OccursCountKind.Expression
+
+    val True_ = true
+
+    type EB = ElementBase
+    type MG = ModelGroup
+    type SG = SequenceTermBase
+    type CG = ChoiceTermBase
+
   }
 
-  protected lazy val terms = groupMembers.map { _.asTermInSequence }
+  /**
+   * Produces the right kind of SequenceChild object for this particular child
+   * for the role it must play within this sequence's behavior.
+   *
+   * A SequenceChild object is effectively generator for part of the Sequence's parse/unparse
+   * algorithm. For arrays these SequenceChild objects enable processing exactly one array instance at
+   * a time, orchestrated by the surrounding sequence's processor.
+   */
+  protected def sequenceChild(child: Term, groupIndex: Int): SequenceChild = {
+    import columnConstants._
+
+    val (max, min, ock) = child match {
+      case e: EB =>
+        // don't require OCK unnecessarily
+        (e.maxOccurs, e.minOccurs, if (e.isScalar) null else e.occursCountKind)
+      case _ => (1, 1, null)
+    }
+    // don't require SSP unnecessarily
+    val ssp = if (!hasSeparator) SeparatorSuppressionPolicy.AnyEmpty else separatorSuppressionPolicy
+
+    val res = (child, sequenceKind, ssp, ock, min, max) match {
+      case (e: EB, Ordered__, ___________, _________, ONE, ONE) => new ScalarOrderedSequenceChild(this, e, groupIndex)
+      case (e: EB, _________, ___________, StopValue_, ___, __2) => e.subsetError("dfdl:occursCountKind 'stopValue' is not supported.")
+      case (_____, Unordered, ___________, __________, ___, __2) => this.subsetError("Unordered sequences are not supported.")
+      case (e: EB, Ordered__, ___________, Parsed____, ___, __2) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
+      case (e: EB, Ordered__, ___________, Fixed_____, ___, UNB) => e.SDE("occursCountKind='fixed' not allowed with unbounded maxOccurs")
+      case (e: EB, Ordered__, ___________, Fixed_____, ___, `min`) => new RepOrderedExactlyNSequenceChild(this, e, groupIndex, min)
+      case (e: EB, Ordered__, ___________, Fixed_____, ___, max) => { Assert.invariant(min != max); e.SDE("occursCountKind='fixed' requires minOccurs and maxOccurs to be equal (%d != %d)", min, max) }
+      case (e: EB, Ordered__, ___________, Expression, ___, __2) => new RepOrderedExactlyTotalOccursCountSequenceChild(this, e, groupIndex)
+      case (e: EB, Ordered__, Never______, Implicit__, ___, UNB) => e.SDE("separatorSuppressionPolicy='never' with occursCountKind='implicit' requires bounded maxOccurs.")
+      case (e: EB, Ordered__, Never______, Implicit__, ___, max) => new RepOrderedExactlyNSequenceChild(this, e, groupIndex, max)
+      case (e: EB, Ordered__, Never______, ock /****/ , ___, __2) if (ock ne null) => e.SDE("separatorSuppressionPolicy='never' not allowed in combination with occursCountKind='" + ock + "'.")
+      case (e: EB, Ordered__, Trailing___, Implicit__, ___, UNB) if !e.isLastDeclaredRequiredElementOfSequence => e.SDE("occursCountKind='implicit' with unbounded maxOccurs only allowed for last element of a sequence")
+      case (e: EB, Ordered__, Trailing___, Implicit__, ___, max) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
+      case (e: EB, Ordered__, TrailingStr, Implicit__, ___, UNB) if !e.isLastDeclaredRequiredElementOfSequence => e.SDE("occursCountKind='implicit' with unbounded maxOccurs only allowed for last element of a sequence")
+      case (e: EB, Ordered__, TrailingStr, Implicit__, ___, UNB) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
+      case (e: EB, Ordered__, TrailingStr, Implicit__, ___, max) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
+      case (e: EB, Ordered__, Always_____, Implicit__, ___, max) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
+      case (m: MG, Ordered__, ___________, __________, ___, __2) => new ScalarOrderedSequenceChild(this, m, groupIndex)
+      case (_____, _________, policy /**/ , ock /**/ , ___, __2) => child.SDE("separatorSuppressionPolicy='" + policy + "' not allowed with occursCountKind='" + ock + "'.")
+    }
+    res
+  }
 
   /**
    * These are static properties even though the delimiters can have runtime-computed values.
@@ -64,6 +150,20 @@ trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
     else false
   }
 
-  final lazy val hasSeparator = separatorParseEv.isKnownNonEmpty
+  lazy val hasSeparator = separatorParseEv.isKnownNonEmpty
+
+  lazy val sequenceSeparator = prod("separator", hasSeparator) {
+    //
+    // TODO: (JIRA DFDL-1400) The separators may be in a different encoding than the terms
+    // that they separate.
+    //
+    // So we must allow for a change of encoding (which may also imply a change
+    // of bit order)
+    //
+    // However, this isn't the same as just plopping down a bitOrderChange ~ encodingChange, since
+    // those examine prior peer, and what we want to scrutinize is the prior term being separated.
+    //
+    delimMTA ~ SequenceSeparator(this)
+  }
 }
 
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/TermGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/TermGrammarMixin.scala
index 5d086cf8e..b7018c4f0 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/TermGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/TermGrammarMixin.scala
@@ -16,17 +16,12 @@
  */
 
 package org.apache.daffodil.grammar
-import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.dsom.DFDLNewVariableInstance
-import org.apache.daffodil.dsom.ElementBase
 import org.apache.daffodil.dsom.Term
-import org.apache.daffodil.grammar.primitives.OptionalInfixSep
-import org.apache.daffodil.grammar.primitives.Nada
-import org.apache.daffodil.grammar.primitives.MandatoryTextAlignment
-import org.apache.daffodil.grammar.primitives.Separator
+import org.apache.daffodil.grammar.primitives._
 
 /////////////////////////////////////////////////////////////////
-// Groups System
+// Common to all Terms (Elements and ModelGroups
 /////////////////////////////////////////////////////////////////
 
 trait TermGrammarMixin
@@ -41,8 +36,8 @@ trait TermGrammarMixin
     st.isInstanceOf[DFDLNewVariableInstance]
   }.asInstanceOf[Seq[DFDLNewVariableInstance]]
 
-  private lazy val newVarStarts = newVars.map { _.gram }
-  private lazy val newVarEnds = newVars.map { _.endGram }
+  private lazy val newVarStarts = newVars.map { _.gram(self) }
+  private lazy val newVarEnds = newVars.map { _.endGram(self) }
 
   protected lazy val hasEncoding = optionEncodingRaw.isDefined
 
@@ -55,46 +50,19 @@ trait TermGrammarMixin
     newVarEnds.fold(mt) { _ ~ _ }
   }
 
-  // I am not sure we need to distinguish these two.
-  final lazy val asTermInSequence = prod("asTermInSequence") {
-    separatedForSequencePosition(termContentBody)
-  }
-
-  /**
-   * overridden in LocalElementGrammarMixin
-   */
-  lazy val asTermInChoice = termContentBody
-
-  /**
-   * separator combinators - detect cases where no separator applies.
-   * Note that repeating elements are excluded because they have to
-   * managed their own separatedForArrayPosition inside the repetition.
-   */
-  protected final def separatedForArrayPosition(bodyArg: => Gram): Gram = {
-    val body = bodyArg
-    val (isElementWithNoRep, isRepeatingElement) = body.context match {
-      case e: ElementBase => (!e.isRepresented, !e.isScalar)
-      case other => (false, false)
-    }
-    Assert.usage(isRepeatingElement)
-    Assert.invariant(!isElementWithNoRep) //inputValueCalc not allowed on arrays in DFDL v1.0
-    val res = prefixSep ~ infixSepRule ~ body ~ postfixSep
-    res
-  }
-
-  protected final def separatedForSequencePosition(bodyArg: => Gram): Gram = {
-    val body = bodyArg
-    val (isElementWithNoRep, isRepeatingElement) = body.context match {
-      case e: ElementBase => (!e.isRepresented, !e.isScalar)
-      case other => (false, false)
-    }
-    if (isElementWithNoRep) body // no separators for things that have no representation in the data stream
-    else if (isRepeatingElement) body
-    else {
-      val res = prefixSep ~ infixSepRule ~ body ~ postfixSep
-      res
-    }
-  }
+  //  protected final def separatedForSequencePosition(bodyArg: => Gram): Gram = {
+  //    val body = bodyArg
+  //    val (isElementWithNoRep, isRepeatingElement) = body.context match {
+  //      case e: ElementBase => (!e.isRepresented, !e.isScalar)
+  //      case other => (false, false)
+  //    }
+  //    if (isElementWithNoRep) body // no separators for things that have no representation in the data stream
+  //    else if (isRepeatingElement) body
+  //    else {
+  //      val res = prefixSep ~ infixSepRule ~ body ~ postfixSep
+  //      res
+  //    }
+  //  }
 
   // public for unit testing use.
   final lazy val Some(es) = {
@@ -128,46 +96,31 @@ trait TermGrammarMixin
     nearestEnclosingSequence
   }
 
-  private def hasES = nearestEnclosingSequence != None
-  private def ignoreES = inChoiceBeforeNearestEnclosingSequence == true
+  protected final def hasES = nearestEnclosingSequence != None
+  protected final def ignoreES = inChoiceBeforeNearestEnclosingSequence == true
 
-  private lazy val separatorItself = prod("separator", !ignoreES && hasES) {
-    //
-    // TODO: (JIRA DFDL-1400) The separators may be in a different encoding than the terms
-    // that they separate.
-    //
-    // So we must allow for a change of encoding (which may also imply a change
-    // of bit order)
-    //
-    // However, this isn't the same as just plopping down a bitOrderChange ~ encodingChange, since
-    // those examine prior peer, and what we want to scrutinize is the prior term being separated.
-    //
-    delimMTA ~ Separator(es, self)
-  }
+  //  private lazy val sepRule = separatorItself
 
-  private lazy val sepRule = separatorItself
+  //  private lazy val prefixSep = prod("prefixSep", !ignoreES && hasES && es.hasPrefixSep) {
+  //    sepRule
+  //  }
 
-  private lazy val prefixSep = prod("prefixSep", !ignoreES && hasES && es.hasPrefixSep) {
-    sepRule
-  }
-
-  private lazy val postfixSep = prod("postfixSep", !ignoreES && hasES && es.hasPostfixSep) { sepRule }
-  private lazy val infixSep = prod("infixSep", !ignoreES && hasES && es.hasInfixSep) { sepRule }
+  //  private lazy val postfixSep = prod("postfixSep", !ignoreES && hasES && es.hasPostfixSep) { sepRule }
+  // private lazy val infixSep = prod("infixSep", !ignoreES && hasES && es.hasInfixSep) { separatorItself }
 
-  private lazy val isStaticallyFirst = {
-    es.hasInfixSep &&
-      this.positionInNearestEnclosingSequence == 1 &&
-      isScalar &&
-      !hasPriorRequiredSiblings
-  }
-
-  private lazy val infixSepRule = prod("infixSepRule", !ignoreES && hasES && es.hasInfixSep) {
-    if (isStaticallyFirst) Nada(this) // we're first, no infix sep.
-    else if (hasPriorRequiredSiblings) infixSep // always in this case
-    else if (positionInNearestEnclosingSequence > 1 || !isScalar) {
-      new OptionalInfixSep(this, infixSep)
-    } else Assert.invariantFailed("infixSepRule didn't understand what to lay down as grammar for this situation: " + this)
-  }
+  //  private lazy val isStaticallyFirst = {
+  //    es.hasInfixSep &&
+  //      this.positionInNearestEnclosingSequence == 1 &&
+  //      isScalar &&
+  //      !hasPriorRequiredSiblings
+  //  }
+  //
+  //  private lazy val infixSepRule = prod("infixSepRule", !ignoreES && hasES && es.hasInfixSep) {
+  //    if (hasPriorRequiredSiblings) infixSep // always in this case
+  //    else if (positionInNearestEnclosingSequence > 1 || !isScalar) {
+  //      new OptionalInfixSep(this, separatorItself)
+  //    } else Assert.invariantFailed("infixSepRule didn't understand what to lay down as grammar for this situation: " + this)
+  //  }
 
   /**
    * Mandatory text alignment or mta
@@ -178,14 +131,14 @@ trait TermGrammarMixin
    * in the property environment shouldn't get you an MTA region. It has
    * to be textual.
    */
-  protected lazy val mtaBase = prod("mandatoryTextAlignment", hasEncoding) {
+  protected final lazy val mtaBase = prod("mandatoryTextAlignment", hasEncoding) {
     MandatoryTextAlignment(this, knownEncodingAlignmentInBits, false)
   }
 
   /**
    * Mandatory text alignment for delimiters
    */
-  protected lazy val delimMTA = prod("delimMTA",
+  protected final lazy val delimMTA = prod("delimMTA",
     {
       hasDelimiters
     }) {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ChoiceCombinator.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ChoiceCombinator.scala
new file mode 100644
index 000000000..842a98ed1
--- /dev/null
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ChoiceCombinator.scala
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.grammar.primitives
+
+import org.apache.daffodil.grammar.Terminal
+import org.apache.daffodil.dsom._
+import org.apache.daffodil.processors.parsers._
+import org.apache.daffodil.processors.unparsers._
+import org.apache.daffodil.grammar.Gram
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.cookers.ChoiceBranchKeyCooker
+import org.apache.daffodil.api.WarnID
+import org.apache.daffodil.equality._
+
+/*
+ * The purpose of the ChoiceCombinator (and the parsers it creates) is to
+ * determine which branch to go down. In the parser case, for non-direct
+ * dispatch, we just rely on backtracking here.
+ *
+ * For direct dispatch, we create a disapatch-branch key map
+ * which is used to determine which branch to parse at runtime.
+ *
+ * In the unparser case, we know which element we got from the infoset, but we
+ * need to determine which branch of the choice to take at runtime. This
+ * unparser uses a Map to make the determination based on the element seen.
+ */
+case class ChoiceCombinator(ch: ChoiceTermBase, rawAlternatives: Seq[Gram])
+  extends Terminal(ch, !rawAlternatives.isEmpty) {
+
+  private lazy val alternatives = rawAlternatives.filterNot(_.isEmpty)
+
+  private lazy val parsers = alternatives.map { _.parser }.filterNot { _.isEmpty }
+
+  override def isEmpty = super.isEmpty || alternatives.isEmpty
+
+  lazy val parser: Parser = {
+    if (!ch.isDirectDispatch) {
+      new ChoiceParser(ch.termRuntimeData, parsers)
+    } else {
+      val dispatchBranchKeyValueTuples = alternatives.flatMap { alt =>
+        val keyTerm = alt.context.asInstanceOf[Term]
+        val cbk = keyTerm.choiceBranchKey
+        // Note that this behaves differently than the specification, since
+        // this accepts a space separated list of keys
+        val cbks = ChoiceBranchKeyCooker.convertConstant(cbk, keyTerm.runtimeData, forUnparse = false)
+        cbks.map { (_, alt) }
+      }
+
+      // check for duplicate dfdl:choiceBranchKeys
+      val groupedByKey = dispatchBranchKeyValueTuples.groupBy(_._1)
+      groupedByKey.foreach {
+        case (k, kvs) =>
+          if (kvs.length > 1) {
+            SDE("dfdl:choiceBranchKey value (%s) is not unique across all branches of a direct dispatch choice. Offending branches are:\n%s",
+              k, kvs.map(_._2.context.runtimeData).map(rd => rd.diagnosticDebugName + " " + rd.schemaFileLocation.locationDescription).mkString("- ", "\n- ", ""))
+          }
+      }
+
+      val dispatchBranchKeyMap = dispatchBranchKeyValueTuples.toMap.mapValues(_.parser)
+      val serializableMap = dispatchBranchKeyMap.map(identity)
+
+      new ChoiceDispatchCombinatorParser(ch.termRuntimeData, ch.choiceDispatchKeyEv, serializableMap)
+    }
+  }
+
+  override lazy val unparser: Unparser = {
+    if (!ch.isHidden) {
+      val eventRDMap = ch.choiceBranchMap
+      val eventUnparserMap = eventRDMap.flatMap {
+        case (cbe, rd) =>
+          // if we don't find a matching RD for a term that's probably
+          // because the term is an empty sequence or empty choice (which do happen
+          // and we even have tests for them). Since those can never be chosen by
+          // means of an element event, they don't appear in the map.
+          val altGram = alternatives.find { alt =>
+            val crd = alt.context.runtimeData
+            val found = crd =:= rd
+            found
+          }
+          altGram.map { ag => (cbe, ag.unparser) }
+      }
+      val mapValues = eventUnparserMap.map { case (k, v) => v }.toSeq.filterNot(_.isEmpty)
+      if (mapValues.isEmpty)
+        new NadaUnparser(null)
+      else
+        new ChoiceCombinatorUnparser(ch.modelGroupRuntimeData, eventUnparserMap)
+    } else {
+      // Choices inside a hidden group ref are slightly different because we
+      // will never see events for any of the branches. Instead, we will just
+      // always pick the branch in which every thing is defaultble or OVC. It
+      // is a warning if more than one of those branches exist. It is an SDE if
+      // such a branch does not exist, which is detected elsewhere
+
+      // this call is necessary since it will throw an SDE if no choice branch
+      // was defaultable
+      ch.childrenInHiddenGroupNotDefaultableOrOVC
+      val defaultableBranches = ch.groupMembers.filter { _.childrenInHiddenGroupNotDefaultableOrOVC.length == 0 }
+      Assert.invariant(defaultableBranches.length > 0)
+      if (defaultableBranches.length > 1) {
+        SDW(WarnID.ChoiceInsideHiddenGroup, "xs:choice inside a hidden group has unparse ambiguity: multiple branches exist with all children either defaulable or have the dfdl:outputValueCalc property set. The first branch will be chosen during unparse. Defaultable branches are:\n%s",
+          defaultableBranches.mkString("\n"))
+      }
+      val defaultableBranchRD = defaultableBranches(0).runtimeData
+      val defaultableBranchUnparser = alternatives.find(_.context.runtimeData =:= defaultableBranchRD).get.unparser
+      new HiddenChoiceCombinatorUnparser(ch.modelGroupRuntimeData, defaultableBranchUnparser)
+    }
+  }
+}
+
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ComplexTypeCombinator.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ComplexTypeCombinator.scala
new file mode 100644
index 000000000..5ff78e603
--- /dev/null
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ComplexTypeCombinator.scala
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.grammar.primitives
+
+import org.apache.daffodil.grammar.Terminal
+import org.apache.daffodil.dsom._
+import org.apache.daffodil.processors.parsers.{ Parser => DaffodilParser }
+import org.apache.daffodil.processors.unparsers.{ Unparser => DaffodilUnparser }
+import org.apache.daffodil.processors.parsers._
+import org.apache.daffodil.processors.unparsers._
+import org.apache.daffodil.grammar.Gram
+import org.apache.daffodil.util.Misc
+
+case class ComplexTypeCombinator(ct: ComplexTypeBase, body: Gram) extends Terminal(ct.elementDecl, !body.isEmpty) {
+
+  override def isEmpty = body.isEmpty
+
+  private lazy val p = body.parser
+  private lazy val u = body.unparser
+
+  override def toString() =
+    "<" + Misc.getNameFromClass(this) + ">" +
+      body.toString() +
+      "</" + Misc.getNameFromClass(this) + ">"
+
+  override lazy val parser: DaffodilParser =
+    if (p.isEmpty)
+      p
+    else
+      new ComplexTypeParser(ct.runtimeData, p)
+
+  override lazy val unparser: DaffodilUnparser =
+    if (u.isEmpty)
+      u
+    else
+      new ComplexTypeUnparser(ct.runtimeData, u)
+}
+
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/DelimiterAndEscapeRelated.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/DelimiterAndEscapeRelated.scala
new file mode 100644
index 000000000..faa3dbd8b
--- /dev/null
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/DelimiterAndEscapeRelated.scala
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.grammar.primitives
+
+import org.apache.daffodil.grammar.Terminal
+import org.apache.daffodil.dsom._
+import org.apache.daffodil.processors.parsers.{ Parser => DaffodilParser }
+import org.apache.daffodil.processors.unparsers.{ Unparser => DaffodilUnparser }
+import org.apache.daffodil.processors.parsers._
+import org.apache.daffodil.processors.unparsers._
+import org.apache.daffodil.grammar.Gram
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.util.Maybe._
+import org.apache.daffodil.util.Misc
+import org.apache.daffodil.xml.XMLUtils
+
+case class DelimiterStackCombinatorSequence(sq: SequenceTermBase, body: Gram) extends Terminal(sq, !body.isEmpty) {
+  lazy val pInit = if (sq.initiatorParseEv.isKnownNonEmpty) One(sq.initiatorParseEv) else Nope
+  lazy val pSep = if (sq.hasSeparator && sq.separatorParseEv.isKnownNonEmpty) One(sq.separatorParseEv) else Nope
+  lazy val pTerm = if (sq.terminatorParseEv.isKnownNonEmpty) One(sq.terminatorParseEv) else Nope
+
+  lazy val uInit = if (sq.initiatorParseEv.isKnownNonEmpty) One(sq.initiatorUnparseEv) else Nope
+  lazy val uSep = if (sq.hasSeparator && sq.separatorParseEv.isKnownNonEmpty) One(sq.separatorUnparseEv) else Nope
+  lazy val uTerm = if (sq.terminatorParseEv.isKnownNonEmpty) One(sq.terminatorUnparseEv) else Nope
+
+  lazy val parser: DaffodilParser = new DelimiterStackParser((pInit.toList ++ pSep.toList ++ pTerm.toList).toArray, sq.runtimeData, body.parser)
+
+  override lazy val unparser: DaffodilUnparser = new DelimiterStackUnparser(uInit, uSep, uTerm, sq.termRuntimeData, body.unparser)
+}
+
+case class DelimiterStackCombinatorChoice(ch: ChoiceTermBase, body: Gram) extends Terminal(ch, !body.isEmpty) {
+  lazy val pInit = if (ch.initiatorParseEv.isKnownNonEmpty) One(ch.initiatorParseEv) else Nope
+  lazy val pTerm = if (ch.terminatorParseEv.isKnownNonEmpty) One(ch.terminatorParseEv) else Nope
+
+  lazy val uInit = if (ch.initiatorParseEv.isKnownNonEmpty) One(ch.initiatorUnparseEv) else Nope
+  lazy val uTerm = if (ch.terminatorParseEv.isKnownNonEmpty) One(ch.terminatorUnparseEv) else Nope
+
+  lazy val parser: DaffodilParser = new DelimiterStackParser((pInit.toList ++ pTerm.toList).toArray, ch.runtimeData, body.parser)
+
+  override lazy val unparser: DaffodilUnparser = new DelimiterStackUnparser(uInit, None, uTerm, ch.termRuntimeData, body.unparser)
+}
+
+case class DelimiterStackCombinatorElement(e: ElementBase, body: Gram) extends Terminal(e, !body.isEmpty) {
+  lazy val pInit = if (e.initiatorParseEv.isKnownNonEmpty) One(e.initiatorParseEv) else Nope
+  lazy val pTerm = if (e.terminatorParseEv.isKnownNonEmpty) One(e.terminatorParseEv) else Nope
+
+  lazy val uInit = if (e.initiatorParseEv.isKnownNonEmpty) One(e.initiatorUnparseEv) else Nope
+  lazy val uTerm = if (e.terminatorParseEv.isKnownNonEmpty) One(e.terminatorUnparseEv) else Nope
+
+  lazy val delims = (pInit.toList ++ pTerm.toList)
+
+  override def toString() = {
+    val delimAttrib = delims.map { _.toString }.map { XMLUtils.escape(_).toString() }.mkString(" ")
+    "<" + Misc.getNameFromClass(this) + " delims='" + delimAttrib + "'>" +
+      body.toString() +
+      "</" + Misc.getNameFromClass(this) + ">"
+  }
+  lazy val parser: DaffodilParser = {
+    val p = body.parser
+    if (p.isEmpty) p
+    else new DelimiterStackParser(delims.toArray, e.termRuntimeData, p)
+  }
+
+  override lazy val unparser: DaffodilUnparser = {
+    val u = body.unparser
+    if (u.isEmpty) u
+    else new DelimiterStackUnparser(uInit, None, uTerm, e.termRuntimeData, u)
+  }
+}
+
+case class DynamicEscapeSchemeCombinatorElement(e: ElementBase, body: Gram) extends Terminal(e, !body.isEmpty) {
+
+  val schemeParseOpt = e.optionEscapeScheme.map { _.escapeSchemeParseEv }
+  val schemeUnparseOpt = e.optionEscapeScheme.map { _.escapeSchemeUnparseEv }
+
+  Assert.invariant(schemeParseOpt.isDefined && !schemeParseOpt.get.isConstant)
+  Assert.invariant(schemeUnparseOpt.isDefined && !schemeUnparseOpt.get.isConstant)
+
+  lazy val parser: DaffodilParser = {
+    val p = body.parser
+    if (p.isEmpty) p
+    else new DynamicEscapeSchemeParser(schemeParseOpt.get, e.termRuntimeData, p)
+  }
+
+  override lazy val unparser: DaffodilUnparser = {
+    val u = body.unparser
+    if (u.isEmpty) u
+    else new DynamicEscapeSchemeUnparser(schemeUnparseOpt.get, e.termRuntimeData, u)
+  }
+}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
index 7dcc7b1fa..f72d3e36d 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
@@ -21,7 +21,6 @@ import org.apache.daffodil.dsom.ElementBase
 import org.apache.daffodil.equality.TypeEqual
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.grammar.Gram
-import org.apache.daffodil.grammar.HasNoUnparser
 import org.apache.daffodil.grammar.NamedGram
 import org.apache.daffodil.grammar.Terminal
 import org.apache.daffodil.processors.parsers.ChoiceElementParser
@@ -43,14 +42,12 @@ import org.apache.daffodil.processors.unparsers.ElementUnparserNoRep
 import org.apache.daffodil.processors.unparsers.ElementUnspecifiedLengthUnparser
 import org.apache.daffodil.processors.unparsers.ElementUnusedUnparser
 import org.apache.daffodil.processors.unparsers.LeftCenteredPaddingUnparser
-import org.apache.daffodil.processors.unparsers.NilLiteralCharacterUnparser
 import org.apache.daffodil.processors.unparsers.OVCRetryUnparser
 import org.apache.daffodil.processors.unparsers.OnlyPaddingUnparser
 import org.apache.daffodil.processors.unparsers.RightCenteredPaddingUnparser
 import org.apache.daffodil.processors.unparsers.RightFillUnparser
 import org.apache.daffodil.processors.unparsers.Unparser
 import org.apache.daffodil.schema.annotation.props.gen.LengthKind
-import org.apache.daffodil.schema.annotation.props.gen.NilKind
 import org.apache.daffodil.schema.annotation.props.gen.Representation
 import org.apache.daffodil.schema.annotation.props.gen.TestKind
 import org.apache.daffodil.util.Maybe
@@ -97,7 +94,7 @@ class ElementCombinator(context: ElementBase,
     subComb.parser
   }
 
-  private lazy val uSetVars = context.setVariableStatements.map(_.gram.unparser).toArray
+  private lazy val uSetVars = context.setVariableStatements.map(_.gram(context).unparser).toArray
 
   private lazy val eBeforeUnparser: Maybe[Unparser] =
     if (eBeforeContent.isEmpty) Maybe.Nope
@@ -167,22 +164,22 @@ case class OnlyPadding(ctxt: ElementBase)
   }
 }
 
-case class NilLiteralCharacter(ctxt: ElementBase)
-  extends Terminal(ctxt, ctxt.maybeUnparseTargetLengthInBitsEv.isDefined &&
-    ctxt.isNillable && ctxt.nilKind == NilKind.LiteralCharacter)
-  with Padded {
-
-  override def parser = new NadaParser(ctxt.erd)
-
-  private lazy val nilLitCharacter = ctxt.cookedNilValuesForUnparse.head(0)
-
-  override lazy val unparser: Unparser =
-    new NilLiteralCharacterUnparser(ctxt.erd,
-      ctxt.maybeUnparseTargetLengthInBitsEv.get,
-      ctxt.maybeLengthEv,
-      ctxt.maybeCharsetEv,
-      nilLitCharacter)
-}
+//case class NilLiteralCharacter(ctxt: ElementBase)
+//  extends Terminal(ctxt, ctxt.maybeUnparseTargetLengthInBitsEv.isDefined &&
+//    ctxt.isNillable && ctxt.nilKind == NilKind.LiteralCharacter)
+//  with Padded {
+//
+//  override def parser = new NadaParser(ctxt.erd)
+//
+//  private lazy val nilLitCharacter = ctxt.cookedNilValuesForUnparse.head(0)
+//
+//  override lazy val unparser: Unparser =
+//    new NilLiteralCharacterUnparser(ctxt.erd,
+//      ctxt.maybeUnparseTargetLengthInBitsEv.get,
+//      ctxt.maybeLengthEv,
+//      ctxt.maybeCharsetEv,
+//      nilLitCharacter)
+//}
 
 case class RightCenteredPadding(ctxt: ElementBase)
   extends Terminal(ctxt, ctxt.shouldAddPadding)
@@ -390,7 +387,7 @@ class ElementParseAndUnspecifiedLength(context: ElementBase, eBeforeGram: Gram,
 }
 
 class ChoiceElementCombinator(context: ElementBase, eGramBefore: Gram, eGram: Gram, eAfterGram: Gram)
-  extends ElementCombinatorBase(context, eGramBefore, eGram, eAfterGram) with HasNoUnparser {
+  extends ElementCombinatorBase(context, eGramBefore, eGram, eAfterGram) {
 
   lazy val parser: Parser = new ChoiceElementParser(
     context.erd,
@@ -404,6 +401,8 @@ class ChoiceElementCombinator(context: ElementBase, eGramBefore: Gram, eGram: Gr
     eParser,
     eAfterParser)
 
+  lazy val unparser = hasNoUnparser
+
 }
 
 abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eGram: Gram, eGramAfter: Gram)
@@ -431,50 +430,53 @@ abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eG
     if (pd.size == 0) {
       Maybe.Nope
     } else {
-      Maybe(pd(0).gram.parser)
+      pd(0).gram(context).maybeParser
     }
   }
-  lazy val patAssert = context.assertStatements.filter(_.testKind == TestKind.Pattern).map(_.gram.parser).toArray
-  lazy val pSetVar = context.setVariableStatements.map(_.gram.parser).toArray
+  lazy val patAssert = context.assertStatements.filter(_.testKind == TestKind.Pattern).map(_.gram(context).parser).toArray
+  lazy val pSetVar = context.setVariableStatements.map(_.gram(context).parser).toArray
   lazy val testDiscrim = {
     val td = context.discriminatorStatements.filter(_.testKind == TestKind.Expression)
     Assert.invariant(td.size <= 1)
     if (td.size == 0) {
       Maybe.Nope
     } else {
-      Maybe(td(0).gram.parser)
+      td(0).gram(context).maybeParser
     }
   }
-  lazy val testAssert = context.assertStatements.filter(_.testKind == TestKind.Expression).map(_.gram.parser).toArray
+  lazy val testAssert = context.assertStatements.filter(_.testKind == TestKind.Expression).map(_.gram(context).parser).toArray
 
-  lazy val eBeforeParser: Maybe[Parser] =
-    if (eGramBefore.isEmpty) Maybe.Nope
-    else Maybe(eGramBefore.parser)
+  lazy val eBeforeParser: Maybe[Parser] = eGramBefore.maybeParser
 
-  lazy val eParser: Maybe[Parser] =
-    if (eGram.isEmpty) Maybe.Nope
-    else Maybe(eGram.parser)
+  lazy val eParser: Maybe[Parser] = eGram.maybeParser
 
-  lazy val eAfterParser: Maybe[Parser] =
-    if (eGramAfter.isEmpty) Maybe.Nope
-    else Maybe(eGramAfter.parser)
+  lazy val eAfterParser: Maybe[Parser] = eGramAfter.maybeParser
 
   def parser: Parser
 
-  lazy val uSetVar = context.setVariableStatements.map(_.gram.unparser).toArray
+  lazy val uSetVar = context.setVariableStatements.map(_.gram(context).unparser).toArray
 
-  lazy val eBeforeUnparser: Maybe[Unparser] =
-    if (eGramBefore.isEmpty) Maybe.Nope
-    else Maybe(eGramBefore.unparser)
+  lazy val eBeforeUnparser: Maybe[Unparser] = eGramBefore.maybeUnparser
 
-  lazy val eUnparser: Maybe[Unparser] =
-    if (eGram.isEmpty) Maybe.Nope
-    else Maybe(eGram.unparser)
+  lazy val eUnparser: Maybe[Unparser] = eGram.maybeUnparser
 
-  lazy val eAfterUnparser: Maybe[Unparser] =
-    if (eGramAfter.isEmpty) Maybe.Nope
-    else Maybe(eGramAfter.unparser)
+  lazy val eAfterUnparser: Maybe[Unparser] = eGramAfter.maybeUnparser
 
   def unparser: Unparser
 
 }
+
+//
+//case class ArrayCombinator(e: ElementBase, body: Gram) extends Terminal(e, !body.isEmpty) {
+//  override def toString() = "<Array>" + body.toString + "</Array>"
+//
+//  lazy val parser: Parser = new ArrayCombinatorParser(e.elementRuntimeData, body.parser)
+//  override lazy val unparser: Unparser = new ArrayCombinatorUnparser(e.elementRuntimeData, body.unparser)
+//}
+//
+//case class OptionalCombinator(e: ElementBase, body: Gram) extends Terminal(e, !body.isEmpty) {
+//
+//  override def toString() = "<Optional>" + body.toString + "</Optional>"
+//  lazy val parser: Parser = new OptionalCombinatorParser(e.elementRuntimeData, body.parser)
+//  override lazy val unparser: Unparser = new OptionalCombinatorUnparser(e.elementRuntimeData, body.unparser)
+//}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/LayeredSequence.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/LayeredSequence.scala
index 0e355b1e1..7563912ff 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/LayeredSequence.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/LayeredSequence.scala
@@ -21,23 +21,29 @@ import org.apache.daffodil.grammar.Terminal
 import org.apache.daffodil.dsom._
 import org.apache.daffodil.processors.parsers.{ Parser => DaffodilParser }
 import org.apache.daffodil.processors.unparsers.{ Unparser => DaffodilUnparser }
-import org.apache.daffodil.grammar.Gram
 import org.apache.daffodil.util.Misc
 import org.apache.daffodil.processors.parsers.LayeredSequenceParser
 import org.apache.daffodil.processors.unparsers.LayeredSequenceUnparser
+import org.apache.daffodil.processors.parsers.ScalarOrderedUnseparatedSequenceChildParser
+import org.apache.daffodil.processors.unparsers.ScalarOrderedUnseparatedSequenceChildUnparser
 
-case class LayeredSequence(sq: SequenceTermBase, bodyTerm: Gram)
+case class LayeredSequence(sq: SequenceTermBase, bodyTerm: SequenceChild)
   extends Terminal(sq, true) {
 
+  private val srd = sq.sequenceRuntimeData
+  private val trd = bodyTerm.trd
+
   override def toString() =
     "<" + Misc.getNameFromClass(this) + ">" +
       bodyTerm.toString() +
       "</" + Misc.getNameFromClass(this) + ">"
 
   override lazy val parser: DaffodilParser =
-    new LayeredSequenceParser(sq.termRuntimeData, sq.maybeLayerTransformerEv.get, bodyTerm.parser)
+    new LayeredSequenceParser(srd, sq.maybeLayerTransformerEv.get,
+      new ScalarOrderedUnseparatedSequenceChildParser(bodyTerm.parser, srd, trd))
 
   override lazy val unparser: DaffodilUnparser = {
-    new LayeredSequenceUnparser(sq.modelGroupRuntimeData, sq.maybeLayerTransformerEv.get, bodyTerm.unparser)
+    new LayeredSequenceUnparser(sq.sequenceRuntimeData, sq.maybeLayerTransformerEv.get,
+      new ScalarOrderedUnseparatedSequenceChildUnparser(bodyTerm.unparser, srd, trd))
   }
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Nada.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Nada.scala
index 4e0f1dbef..272163d7f 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Nada.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Nada.scala
@@ -14,17 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.daffodil.grammar.primitives
-
-import org.apache.daffodil.grammar.Terminal
-import org.apache.daffodil.dsom.Term
-import org.apache.daffodil.grammar.HasNoUnparser
-import org.apache.daffodil.processors.parsers.NadaParser
-
-case class Nada(sc: Term) extends Terminal(sc, true) with HasNoUnparser {
-  // cannot optimize this out! It is used as an alternative to things
-  // with the intention of "find this and this, or find nothing"
-
-  override lazy val parser = new NadaParser(sc.runtimeData)
-}
+//
+//package org.apache.daffodil.grammar.primitives
+//
+//import org.apache.daffodil.grammar.Terminal
+//import org.apache.daffodil.dsom.Term
+//import org.apache.daffodil.processors.parsers.NadaParser
+//
+//case class Nada(sc: Term) extends Terminal(sc, true) {
+//  // cannot optimize this out! It is used as an alternative to things
+//  // with the intention of "find this and this, or find nothing"
+//
+//  override lazy val parser = new NadaParser(sc.runtimeData)
+//
+//  override lazy val unparser = hasNoUnparser
+//}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/NilEmptyCombinators.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/NilEmptyCombinators.scala
index aff3c48d3..972dce328 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/NilEmptyCombinators.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/NilEmptyCombinators.scala
@@ -20,35 +20,12 @@ package org.apache.daffodil.grammar.primitives
 import org.apache.daffodil.grammar.Gram
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.dsom.ElementBase
-import org.apache.daffodil.processors.parsers.SimpleNilOrEmptyOrValueParser
-import org.apache.daffodil.processors.unparsers.SimpleNilOrEmptyOrValueUnparser
 import org.apache.daffodil.processors.parsers.SimpleNilOrValueParser
 import org.apache.daffodil.processors.unparsers.SimpleNilOrValueUnparser
-import org.apache.daffodil.processors.parsers.SimpleEmptyOrValueParser
-import org.apache.daffodil.processors.unparsers.SimpleEmptyOrValueUnparser
 import org.apache.daffodil.processors.parsers.ComplexNilOrContentParser
 import org.apache.daffodil.processors.unparsers.ComplexNilOrContentUnparser
 import org.apache.daffodil.grammar.Terminal
 
-case class SimpleNilOrEmptyOrValue(ctxt: ElementBase, nilGram: Gram, emptyGram: Gram, valueGram: Gram) extends Terminal(ctxt, true) {
-  Assert.invariant(!nilGram.isEmpty)
-  Assert.invariant(!emptyGram.isEmpty)
-  Assert.invariant(!valueGram.isEmpty)
-
-  lazy val nilParser = nilGram.parser
-  lazy val emptyParser = emptyGram.parser
-  lazy val valueParser = valueGram.parser
-
-  lazy val nilUnparser = nilGram.unparser
-  lazy val emptyUnparser = emptyGram.unparser
-  lazy val valueUnparser = valueGram.unparser
-
-  override lazy val parser = SimpleNilOrEmptyOrValueParser(ctxt.erd, nilParser, emptyParser, valueParser)
-
-  override lazy val unparser = SimpleNilOrEmptyOrValueUnparser(ctxt.erd, nilUnparser, emptyUnparser, valueUnparser)
-
-}
-
 case class SimpleNilOrValue(ctxt: ElementBase, nilGram: Gram, valueGram: Gram) extends Terminal(ctxt, true) {
   Assert.invariant(!nilGram.isEmpty)
   Assert.invariant(!valueGram.isEmpty)
@@ -65,22 +42,6 @@ case class SimpleNilOrValue(ctxt: ElementBase, nilGram: Gram, valueGram: Gram) e
 
 }
 
-case class SimpleEmptyOrValue(ctxt: ElementBase, emptyGram: Gram, valueGram: Gram) extends Terminal(ctxt, true) {
-  Assert.invariant(!emptyGram.isEmpty)
-  Assert.invariant(!valueGram.isEmpty)
-
-  lazy val emptyParser = emptyGram.parser
-  lazy val valueParser = valueGram.parser
-
-  lazy val emptyUnparser = emptyGram.unparser
-  lazy val valueUnparser = valueGram.unparser
-
-  override lazy val parser = SimpleEmptyOrValueParser(ctxt.erd, emptyParser, valueParser)
-
-  override lazy val unparser = SimpleEmptyOrValueUnparser(ctxt.erd, emptyUnparser, valueUnparser)
-
-}
-
 case class ComplexNilOrContent(ctxt: ElementBase, nilGram: Gram, contentGram: Gram) extends Terminal(ctxt, true) {
   Assert.invariant(!nilGram.isEmpty)
   Assert.invariant(!contentGram.isEmpty)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Padded.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Padded.scala
index af961572d..972fa4a03 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Padded.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Padded.scala
@@ -34,7 +34,7 @@ import org.apache.daffodil.schema.annotation.props.gen.YesNo
 import org.apache.daffodil.util.MaybeChar
 
 trait PaddingInfoMixin {
-  def eBase: ElementBase
+  protected def eBase: ElementBase
 
   /**
    * parsingPadChar is the pad character for parsing
@@ -128,6 +128,6 @@ trait PaddingInfoMixin {
 }
 
 trait Padded extends PaddingInfoMixin { self: Gram =>
-  override final def eBase = self.context.asInstanceOf[ElementBase]
+  override final protected def eBase = self.context.asInstanceOf[ElementBase]
 
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Primitives.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Primitives.scala
index 7f784f695..1babfcae3 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Primitives.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/Primitives.scala
@@ -19,7 +19,6 @@ package org.apache.daffodil.grammar.primitives
 
 import org.apache.daffodil.dsom._
 import org.apache.daffodil.grammar.Terminal
-import org.apache.daffodil.grammar.HasNoUnparser
 
 abstract class Primitive(e: Term, guard: Boolean = false)
   extends Terminal(e, guard) {
@@ -30,25 +29,9 @@ abstract class Primitive(e: Term, guard: Boolean = false)
  * For stubbing out primitives that are placeholders
  */
 abstract class UnimplementedPrimitive(e: Term, guard: Boolean = false)
-  extends Primitive(e, guard)
-  with HasNoUnparser {
+  extends Primitive(e, guard) {
   override final lazy val parser = hasNoParser
+  override final lazy val unparser = hasNoUnparser
 }
 
-// base stub classes
-
-// case class NoValue(e: GlobalElementDecl, guard: Boolean = true) extends UnimplementedPrimitive(e, guard)
-
-case class SaveInputStream(e: ElementBase, guard: Boolean = true) extends UnimplementedPrimitive(e, guard)
-
-case class SetEmptyInputStream(e: ElementBase, guard: Boolean = true) extends UnimplementedPrimitive(e, guard)
-
-case class RestoreInputStream(e: ElementBase, guard: Boolean = true) extends UnimplementedPrimitive(e, guard)
-
-case class NotStopValue(e: ElementBase with LocalElementMixin) extends UnimplementedPrimitive(e, e.hasStopValue)
-
-case class StopValue(e: ElementBase with LocalElementMixin) extends UnimplementedPrimitive(e, e.hasStopValue)
-
-case class TheDefaultValue(e: ElementBase) extends UnimplementedPrimitive(e, e.isDefaultable)
-
 case class UnicodeByteOrderMark(e: Root) extends UnimplementedPrimitive(e, false)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesDelimiters.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesDelimiters.scala
index f876bb25c..25a857e53 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesDelimiters.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesDelimiters.scala
@@ -157,8 +157,10 @@ case class Initiator(e: Term) extends DelimiterText(e, e) {
   Assert.invariant(e.hasInitiator)
   val delimiterType: DelimiterTextType.Type = DelimiterTextType.Initiator
 }
-case class Separator(s: SequenceTermBase, t: Term) extends DelimiterText(s, t) {
-  Assert.invariant(s.hasSeparator)
+//case class ArrayElementSeparator(s: SequenceTermBase, t: Term) extends DelimiterText(s, t, s.hasSeparator) {
+//  val delimiterType: DelimiterTextType.Type = DelimiterTextType.Separator
+//}
+case class SequenceSeparator(s: SequenceTermBase) extends DelimiterText(s, s, s.hasSeparator) {
   val delimiterType: DelimiterTextType.Type = DelimiterTextType.Separator
 }
 case class Terminator(e: Term) extends DelimiterText(e, e) {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesElementKinds.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesElementKinds.scala
deleted file mode 100644
index 549c4a05e..000000000
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesElementKinds.scala
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.daffodil.grammar.primitives
-
-import org.apache.daffodil.grammar.Terminal
-import org.apache.daffodil.dsom._
-import org.apache.daffodil.processors.parsers.{ Parser => DaffodilParser }
-import org.apache.daffodil.processors.unparsers.{ Unparser => DaffodilUnparser }
-import org.apache.daffodil.grammar.Gram
-import org.apache.daffodil.processors.parsers.ComplexTypeParser
-import org.apache.daffodil.processors.parsers.SequenceCombinatorParser
-import org.apache.daffodil.processors.parsers.ChoiceCombinatorParser
-import org.apache.daffodil.processors.parsers.ChoiceDispatchCombinatorParser
-import org.apache.daffodil.processors.parsers.ArrayCombinatorParser
-import org.apache.daffodil.processors.parsers.OptionalCombinatorParser
-import org.apache.daffodil.processors.unparsers.ComplexTypeUnparser
-import org.apache.daffodil.processors.unparsers.SequenceCombinatorUnparser
-import org.apache.daffodil.processors.unparsers.ChoiceCombinatorUnparser
-import org.apache.daffodil.processors.unparsers.HiddenChoiceCombinatorUnparser
-import org.apache.daffodil.processors.parsers.DelimiterStackParser
-import org.apache.daffodil.processors.parsers.DynamicEscapeSchemeParser
-import org.apache.daffodil.processors.unparsers.DynamicEscapeSchemeUnparser
-import org.apache.daffodil.processors.unparsers.Unparser
-import org.apache.daffodil.processors.unparsers.ArrayCombinatorUnparser
-import org.apache.daffodil.processors.unparsers.OptionalCombinatorUnparser
-import org.apache.daffodil.processors.unparsers.DelimiterStackUnparser
-import org.apache.daffodil.grammar.EmptyGram
-import org.apache.daffodil.equality._;
-import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.util.Maybe._
-import org.apache.daffodil.cookers.ChoiceBranchKeyCooker
-import org.apache.daffodil.api.WarnID
-import org.apache.daffodil.util.Misc
-import org.apache.daffodil.xml.XMLUtils
-
-object ENoWarn3 { EqualitySuppressUnusedImportWarning() }
-
-case class DelimiterStackCombinatorSequence(sq: SequenceTermBase, body: Gram) extends Terminal(sq, !body.isEmpty) {
-  lazy val pInit = if (sq.initiatorParseEv.isKnownNonEmpty) One(sq.initiatorParseEv) else Nope
-  lazy val pSep = if (sq.separatorParseEv.isKnownNonEmpty) One(sq.separatorParseEv) else Nope
-  lazy val pTerm = if (sq.terminatorParseEv.isKnownNonEmpty) One(sq.terminatorParseEv) else Nope
-
-  lazy val uInit = if (sq.initiatorParseEv.isKnownNonEmpty) One(sq.initiatorUnparseEv) else Nope
-  lazy val uSep = if (sq.separatorParseEv.isKnownNonEmpty) One(sq.separatorUnparseEv) else Nope
-  lazy val uTerm = if (sq.terminatorParseEv.isKnownNonEmpty) One(sq.terminatorUnparseEv) else Nope
-
-  lazy val parser: DaffodilParser = new DelimiterStackParser((pInit.toList ++ pSep.toList ++ pTerm.toList).toArray, sq.runtimeData, body.parser)
-
-  override lazy val unparser: DaffodilUnparser = new DelimiterStackUnparser(uInit, uSep, uTerm, sq.termRuntimeData, body.unparser)
-}
-
-case class DelimiterStackCombinatorChoice(ch: ChoiceTermBase, body: Gram) extends Terminal(ch, !body.isEmpty) {
-  lazy val pInit = if (ch.initiatorParseEv.isKnownNonEmpty) One(ch.initiatorParseEv) else Nope
-  lazy val pTerm = if (ch.terminatorParseEv.isKnownNonEmpty) One(ch.terminatorParseEv) else Nope
-
-  lazy val uInit = if (ch.initiatorParseEv.isKnownNonEmpty) One(ch.initiatorUnparseEv) else Nope
-  lazy val uTerm = if (ch.terminatorParseEv.isKnownNonEmpty) One(ch.terminatorUnparseEv) else Nope
-
-  lazy val parser: DaffodilParser = new DelimiterStackParser((pInit.toList ++ pTerm.toList).toArray, ch.runtimeData, body.parser)
-
-  override lazy val unparser: DaffodilUnparser = new DelimiterStackUnparser(uInit, None, uTerm, ch.termRuntimeData, body.unparser)
-}
-
-case class DelimiterStackCombinatorElement(e: ElementBase, body: Gram) extends Terminal(e, !body.isEmpty) {
-  lazy val pInit = if (e.initiatorParseEv.isKnownNonEmpty) One(e.initiatorParseEv) else Nope
-  lazy val pTerm = if (e.terminatorParseEv.isKnownNonEmpty) One(e.terminatorParseEv) else Nope
-
-  lazy val uInit = if (e.initiatorParseEv.isKnownNonEmpty) One(e.initiatorUnparseEv) else Nope
-  lazy val uTerm = if (e.terminatorParseEv.isKnownNonEmpty) One(e.terminatorUnparseEv) else Nope
-
-  lazy val delims = (pInit.toList ++ pTerm.toList)
-
-  override def toString() = {
-    val delimAttrib = delims.map { _.toString }.map { XMLUtils.escape(_).toString() }.mkString(" ")
-    "<" + Misc.getNameFromClass(this) + " delims='" + delimAttrib + "'>" +
-      body.toString() +
-      "</" + Misc.getNameFromClass(this) + ">"
-  }
-  lazy val parser: DaffodilParser = new DelimiterStackParser(delims.toArray, e.termRuntimeData, body.parser)
-
-  override lazy val unparser: DaffodilUnparser = new DelimiterStackUnparser(uInit, None, uTerm, e.termRuntimeData, body.unparser)
-}
-
-case class DynamicEscapeSchemeCombinatorElement(e: ElementBase, body: Gram) extends Terminal(e, !body.isEmpty) {
-
-  val schemeParseOpt = e.optionEscapeScheme.map { _.escapeSchemeParseEv }
-  val schemeUnparseOpt = e.optionEscapeScheme.map { _.escapeSchemeUnparseEv }
-
-  Assert.invariant(schemeParseOpt.isDefined && !schemeParseOpt.get.isConstant)
-  Assert.invariant(schemeUnparseOpt.isDefined && !schemeUnparseOpt.get.isConstant)
-
-  lazy val parser: DaffodilParser = new DynamicEscapeSchemeParser(schemeParseOpt.get, e.termRuntimeData, body.parser)
-
-  override lazy val unparser: DaffodilUnparser = new DynamicEscapeSchemeUnparser(schemeUnparseOpt.get, e.termRuntimeData, body.unparser)
-}
-
-case class ComplexTypeCombinator(ct: ComplexTypeBase, body: Gram) extends Terminal(ct.elementDecl, !body.isEmpty) {
-
-  override def isEmpty = body.isEmpty
-
-  override def toString() =
-    "<" + Misc.getNameFromClass(this) + ">" +
-      body.toString() +
-      "</" + Misc.getNameFromClass(this) + ">"
-
-  lazy val parser: DaffodilParser = new ComplexTypeParser(ct.runtimeData, body.parser)
-
-  override lazy val unparser: DaffodilUnparser =
-    new ComplexTypeUnparser(ct.runtimeData, body.unparser)
-}
-
-case class SequenceCombinator(sq: SequenceTermBase, rawTerms: Seq[Gram])
-  extends Terminal(sq, true) {
-
-  override lazy val isEmpty = {
-    val rt = rawTerms
-    val frt = rt.filterNot { _.isEmpty }
-    val res = frt.isEmpty
-    res
-  }
-
-  override def toString() =
-    "<" + Misc.getNameFromClass(this) + ">" +
-      terms.map { _.toString() }.mkString +
-      "</" + Misc.getNameFromClass(this) + ">"
-
-  private val mt: Gram = EmptyGram
-  lazy val body = rawTerms.foldRight(mt) { _ ~ _ }
-
-  lazy val terms = rawTerms.filterNot { _.isEmpty }
-
-  lazy val unparsers = terms.map { term =>
-    term.unparser
-  }.toVector
-
-  lazy val parser: DaffodilParser = new SequenceCombinatorParser(sq.termRuntimeData, body.parser)
-
-  override lazy val unparser: DaffodilUnparser = {
-    sq.checkHiddenSequenceIsDefaultableOrOVC
-    new SequenceCombinatorUnparser(sq.modelGroupRuntimeData, unparsers)
-  }
-}
-
-case class UnorderedSequenceCombinator(s: Sequence, terms: Seq[Gram])
-  extends UnimplementedPrimitive(s, false) {
-  // stub for now. These are not implemented currently.
-}
-
-case class ArrayCombinator(e: ElementBase, body: Gram) extends Terminal(e, !body.isEmpty) {
-  override def toString() = "<Array>" + body.toString + "</Array>"
-
-  lazy val parser: DaffodilParser = new ArrayCombinatorParser(e.elementRuntimeData, body.parser)
-  override lazy val unparser: Unparser = new ArrayCombinatorUnparser(e.elementRuntimeData, body.unparser)
-}
-
-case class OptionalCombinator(e: ElementBase, body: Gram) extends Terminal(e, !body.isEmpty) {
-
-  override def toString() = "<Optional>" + body.toString + "</Optional>"
-  lazy val parser: DaffodilParser = new OptionalCombinatorParser(e.elementRuntimeData, body.parser)
-  override lazy val unparser: Unparser = new OptionalCombinatorUnparser(e.elementRuntimeData, body.unparser)
-}
-
-/*
- * The purpose of the ChoiceCombinator (and the parsers it creates) is to
- * determine which branch to go down. In the parser case, for non-direct
- * dispatch, we just rely on the AltCompParser behavior to handle the
- * backtracking. For direct dispatch, we create a disapatch-branch key map
- * which is used to determine which branch to parse at runtime.
- *
- * In the unparser case, we know which element we got from the infoset, but we
- * need to determine which branch of the choice to take at runtime. This
- * unparser uses a Map to make the determination based on the element seen.
- */
-case class ChoiceCombinator(ch: ChoiceTermBase, alternatives: Seq[Gram]) extends Terminal(ch, !alternatives.isEmpty) {
-  lazy val parser: DaffodilParser = {
-    if (!ch.isDirectDispatch) {
-      val folded = alternatives.map { gf => gf }.foldRight(EmptyGram.asInstanceOf[Gram]) { _ | _ }
-      new ChoiceCombinatorParser(ch.termRuntimeData, folded.parser)
-    } else {
-      val dispatchBranchKeyValueTuples = alternatives.flatMap { alt =>
-        val keyTerm = alt.context.asInstanceOf[Term]
-        val cbk = keyTerm.choiceBranchKey
-        // Note that this behaves differently than the specification, since
-        // this accepts a space separated list of keys
-        val cbks = ChoiceBranchKeyCooker.convertConstant(cbk, keyTerm.runtimeData, forUnparse = false)
-        cbks.map { (_, alt) }
-      }
-
-      // check for duplicate dfdl:choiceBranchKeys
-      val groupedByKey = dispatchBranchKeyValueTuples.groupBy(_._1)
-      groupedByKey.foreach {
-        case (k, kvs) =>
-          if (kvs.length > 1) {
-            SDE("dfdl:choiceBranchKey value (%s) is not unique across all branches of a direct dispatch choice. Offending branches are:\n%s",
-              k, kvs.map(_._2.context.runtimeData).map(rd => rd.diagnosticDebugName + " " + rd.schemaFileLocation.locationDescription).mkString("- ", "\n- ", ""))
-          }
-      }
-
-      val dispatchBranchKeyMap = dispatchBranchKeyValueTuples.toMap.mapValues(_.parser)
-      val serializableMap = dispatchBranchKeyMap.map(identity)
-
-      new ChoiceDispatchCombinatorParser(ch.termRuntimeData, ch.choiceDispatchKeyEv, serializableMap)
-    }
-  }
-
-  override lazy val unparser: DaffodilUnparser = {
-    if (!ch.isHidden) {
-      val eventRDMap = ch.choiceBranchMap
-      val eventUnparserMap = eventRDMap.mapValues { rd =>
-        alternatives.find(_.context.runtimeData =:= rd).get.unparser
-      }
-
-      // The following line is required because mapValues() creates a "view" of
-      // the map, which is not serializable. map()ing this "view" with the
-      // identity forces evaluation of the "view", creating a map that is
-      // serializable and can be safely passed to a parser. See SI-7005 for
-      // discussions about this issue.
-      val serializableMap = eventUnparserMap.map(identity)
-
-      new ChoiceCombinatorUnparser(ch.modelGroupRuntimeData, serializableMap)
-    } else {
-      // Choices inside a hidden group ref are slightly different because we
-      // will never see events for any of the branches. Instead, we will just
-      // always pick the branch in which every thing is defaultble or OVC. It
-      // is a warning if more than one of those branches exist. It is an SDE if
-      // such a branch does not exist, which is detected elsewhere
-
-      // this call is necessary since it will throw an SDE if no choice branch
-      // was defaultable
-      ch.childrenInHiddenGroupNotDefaultableOrOVC
-      val defaultableBranches = ch.groupMembers.filter { _.childrenInHiddenGroupNotDefaultableOrOVC.length == 0 }
-      Assert.invariant(defaultableBranches.length > 0)
-      if (defaultableBranches.length > 1) {
-        SDW(WarnID.ChoiceInsideHiddenGroup, "xs:choice inside a hidden group has unparse ambiguity: multiple branches exist with all children either defaulable or have the dfdl:outputValueCalc property set. The first branch will be chosen during unparse. Defaultable branches are:\n%s",
-          defaultableBranches.mkString("\n"))
-      }
-      val defaultableBranchRD = defaultableBranches(0).runtimeData
-      val defaultableBranchUnparser = alternatives.find(_.context.runtimeData =:= defaultableBranchRD).get.unparser
-      new HiddenChoiceCombinatorUnparser(ch.modelGroupRuntimeData, defaultableBranchUnparser)
-    }
-  }
-}
-
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesExpressions.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesExpressions.scala
index a810d0850..83a1f1653 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesExpressions.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesExpressions.scala
@@ -38,7 +38,6 @@ import org.apache.daffodil.processors.unparsers.SetVariableUnparser
 import org.apache.daffodil.processors.unparsers.NewVariableInstanceEndUnparser
 import org.apache.daffodil.processors.unparsers.NewVariableInstanceStartUnparser
 import org.apache.daffodil.compiler.ForParser
-import org.apache.daffodil.processors.unparsers.NadaUnparser
 import org.apache.daffodil.schema.annotation.props.PropertyLookupResult
 import org.apache.daffodil.schema.annotation.props.Found
 import org.apache.daffodil.dsom.ExpressionCompilers
@@ -73,7 +72,7 @@ abstract class AssertBase(decl: AnnotatedSchemaComponent,
 
   lazy val parser: DaffodilParser = new AssertExpressionEvaluationParser(msg, discrim, decl.runtimeData, expr)
 
-  override def unparser: DaffodilUnparser = new NadaUnparser(decl.runtimeData) // Assert.invariantFailed("should not request unparser for asserts/discriminators")
+  override def unparser: DaffodilUnparser = hasNoUnparser
 
 }
 
@@ -108,8 +107,8 @@ case class InitiatedContent(
     "initiatedContent") {
 }
 
-case class SetVariable(decl: AnnotatedSchemaComponent, stmt: DFDLSetVariable)
-  extends ExpressionEvaluatorBase(decl) {
+case class SetVariable(stmt: DFDLSetVariable)
+  extends ExpressionEvaluatorBase(stmt.context) {
 
   val baseName = "SetVariable[" + stmt.varQName.local + "]"
 
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesLengthKind.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesLengthKind.scala
index f2e66dd36..683f03575 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesLengthKind.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesLengthKind.scala
@@ -335,7 +335,7 @@ case class LiteralNilDelimitedEndOfData(eb: ElementBase)
 
 case class PrefixLength(e: ElementBase) extends UnimplementedPrimitive(e, e.lengthKind == LengthKind.Prefixed)
 
-class OptionalInfixSep(term: Term, sep: => Gram, guard: Boolean = true) extends Terminal(term, guard) {
+class OptionalInfixSep(term: Term, sep: Gram) extends Terminal(term, !sep.isEmpty) {
 
   lazy val parser: DaffodilParser = new OptionalInfixSepParser(term.termRuntimeData, sep.parser)
 
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesNil.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesNil.scala
index 52ed6dab8..49b3df8ac 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesNil.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesNil.scala
@@ -23,7 +23,8 @@ import org.apache.daffodil.processors.parsers.LiteralValueNilOfSpecifiedLengthPa
 import org.apache.daffodil.processors.parsers.LiteralCharacterNilOfSpecifiedLengthParser
 import org.apache.daffodil.processors.unparsers.LiteralValueNilOfSpecifiedLengthUnparser
 import org.apache.daffodil.schema.annotation.props.gen.LengthKind
-import org.apache.daffodil.processors.unparsers.NadaUnparser
+import org.apache.daffodil.processors.unparsers.NilLiteralCharacterUnparser
+import org.apache.daffodil.processors.unparsers.Unparser
 
 case class LiteralValueNilOfSpecifiedLength(e: ElementBase)
   extends Terminal(e, true)
@@ -49,7 +50,14 @@ case class LiteralCharacterNilOfSpecifiedLength(e: ElementBase)
     e.ignoreCaseBool,
     e.elementRuntimeData)
 
-  override lazy val unparser = new NadaUnparser(e.termRuntimeData)
+  private lazy val nilLitCharacter = e.cookedNilValuesForUnparse.head(0)
+
+  override lazy val unparser: Unparser =
+    new NilLiteralCharacterUnparser(e.erd,
+      e.maybeUnparseTargetLengthInBitsEv.get,
+      e.maybeLengthEv,
+      e.maybeCharsetEv,
+      nilLitCharacter)
 }
 
 case class LogicalNilValue(e: ElementBase) extends UnimplementedPrimitive(e, e.isNillable)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesUnorderedSequence.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesUnorderedSequence.scala
index 44f94b494..9667edb5e 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesUnorderedSequence.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesUnorderedSequence.scala
@@ -23,9 +23,9 @@ import org.apache.daffodil.dsom.ElementBase
 import org.apache.daffodil.dsom.Term
 import org.apache.daffodil.dsom.SequenceTermBase
 import org.apache.daffodil.grammar.UnaryGram
-import org.apache.daffodil.grammar.HasNoUnparser
 import org.apache.daffodil.processors.ElementRuntimeData
 import org.apache.daffodil.processors.parsers.Parser
+import org.apache.daffodil.processors.unparsers.Unparser
 
 object UnorderedSequence {
   def apply(context: Term, eGram: => Gram) = {
@@ -41,7 +41,7 @@ object UnorderedSequence {
 }
 
 class UnorderedSequence private (context: SequenceTermBase, eGramArg: => Gram) // private to force use of the object as factory
-  extends UnaryGram(context, eGramArg) with HasNoUnparser {
+  extends UnaryGram(context, eGramArg) {
 
   lazy val eGram = eGramArg // once only
 
@@ -76,5 +76,6 @@ class UnorderedSequence private (context: SequenceTermBase, eGramArg: => Gram) /
     }
 
   lazy val parser: Parser = ??? // new UnorderedSequenceParser(context.modelGroupRuntimeData, sortOrder, scalarMembers, uoSeqParser)
+  lazy val unparser: Unparser = ???
 
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/RepPrims.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/RepPrims.scala
index 1c8ad613f..01d97a6cf 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/RepPrims.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/RepPrims.scala
@@ -14,125 +14,111 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.daffodil.grammar.primitives
-
-import org.apache.daffodil.grammar._
-import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.Implicits._;
-import org.apache.daffodil.dsom._
-import RepPrims._
-import org.apache.daffodil.processors.parsers.RepAtMostTotalNParser
-import org.apache.daffodil.processors.parsers.RepExactlyTotalNParser
-import org.apache.daffodil.processors.parsers.RepUnboundedParser
-import org.apache.daffodil.processors.parsers.OccursCountExpressionParser
-import org.apache.daffodil.processors.parsers.RepExactlyNParser
-import org.apache.daffodil.processors.parsers.RepAtMostOccursCountParser
-import org.apache.daffodil.processors.parsers.RepExactlyTotalOccursCountParser
-import org.apache.daffodil.processors.unparsers.RepExactlyNUnparser
-import org.apache.daffodil.processors.unparsers.RepAtMostOccursCountUnparser
-import org.apache.daffodil.processors.unparsers.RepUnboundedUnparser
-import org.apache.daffodil.processors.unparsers.RepExactlyTotalNUnparser
-import org.apache.daffodil.processors.unparsers.RepAtMostTotalNUnparser
-import org.apache.daffodil.equality._;
-import org.apache.daffodil.processors.unparsers.NadaUnparser
-
-object INoWarn6 { ImplicitsSuppressUnusedImportWarning() }
-
-object ENoWarn6 { EqualitySuppressUnusedImportWarning() }
-
-object RepPrims {
-  abstract class RepPrim(context: ElementBase, n: Long, r: => Gram)
-    extends UnaryGram(context, r) {
-    Assert.invariant(n > 0)
-    lazy val rd = context.elementRuntimeData
-    lazy val intN = n.toInt
-    lazy val rParser = r.parser
-    lazy val rUnparser = r.unparser
-
-  }
-
-  abstract class Rep3Arg(f: (ElementBase, Long, => Gram) => Gram) {
-    def apply(context: ElementBase, n: Long, rr: => Gram) = {
-      lazy val r = rr
-      if (n == 0 || r.isEmpty) EmptyGram
-      else f(context, n, r)
-    }
-  }
-
-  abstract class Rep2Arg(f: (ElementBase, => Gram) => Gram) {
-    def apply(context: ElementBase, r: => Gram) = {
-      lazy val rr = r
-      if (rr.isEmpty) EmptyGram
-      else f(context, r)
-    }
-  }
-
-  class RepExactlyNPrim(context: ElementBase, n: Long, r: => Gram) extends RepPrim(context, n, r) {
-
-    // Since this is Exactly N, there is no new point of uncertainty considerations here.
-    override lazy val parser = new RepExactlyNParser(n, r.parser, context.elementRuntimeData)
-    override lazy val unparser = new RepExactlyNUnparser(n, r.unparser, context.elementRuntimeData)
-
-  }
-
-  class RepAtMostTotalNPrim(context: ElementBase, n: Long, r: => Gram) extends RepPrim(context, n, r) {
-
-    override lazy val parser = new RepAtMostTotalNParser(n, r.parser, context.elementRuntimeData)
-    override lazy val unparser = new RepAtMostTotalNUnparser(n, r.unparser, context.elementRuntimeData)
-
-  }
-
-  class RepExactlyTotalNPrim(context: ElementBase, n: Long, r: => Gram) extends RepPrim(context, n, r) {
-
-    override lazy val parser = new RepExactlyTotalNParser(n, r.parser, context.elementRuntimeData)
-    override lazy val unparser = new RepExactlyTotalNUnparser(n, r.unparser, context.elementRuntimeData)
-
-  }
-
-  class RepUnboundedPrim(e: ElementBase, r: => Gram) extends RepPrim(e, 1, r) {
-
-    override lazy val parser = new RepUnboundedParser(e.occursCountKind, r.parser, e.elementRuntimeData)
-    override lazy val unparser = new RepUnboundedUnparser(e.occursCountKind, r.unparser, e.elementRuntimeData)
-  }
-
-  class RepAtMostOccursCountPrim(e: ElementBase, n: Long, r: => Gram)
-    extends RepPrim(e, n, r) {
-
-    override lazy val parser = new RepAtMostOccursCountParser(r.parser, n, e.elementRuntimeData)
-    override lazy val unparser = new RepAtMostOccursCountUnparser(r.unparser, n, e.elementRuntimeData)
-
-  }
-
-  class RepExactlyTotalOccursCountPrim(e: ElementBase, r: => Gram)
-    extends RepPrim(e, 1, r) {
-
-    override lazy val parser = new RepExactlyTotalOccursCountParser(r.parser, e.elementRuntimeData)
-
-    /**
-     * Unparser for this is exactly the same as unbounded case - we output all the occurrences in the infoset.
-     */
-    override lazy val unparser = new RepUnboundedUnparser(e.occursCountKind, r.unparser, e.elementRuntimeData)
-
-  }
-}
-
-object RepExactlyN extends Rep3Arg(new RepExactlyNPrim(_, _, _))
-
-object RepAtMostTotalN extends Rep3Arg(new RepAtMostTotalNPrim(_, _, _))
-
-object RepUnbounded extends Rep2Arg(new RepUnboundedPrim(_, _))
-
-object RepExactlyTotalN extends Rep3Arg(new RepExactlyTotalNPrim(_, _, _))
-
-object RepAtMostOccursCount extends Rep3Arg(new RepAtMostOccursCountPrim(_, _, _))
-
-object RepExactlyTotalOccursCount extends Rep2Arg(new RepExactlyTotalOccursCountPrim(_, _))
-
-case class OccursCountExpression(e: ElementBase)
-  extends Terminal(e, true) {
-
-  override lazy val parser = new OccursCountExpressionParser(e.occursCountEv, e.elementRuntimeData)
-  override lazy val unparser = new NadaUnparser(e.termRuntimeData) // DFDL v1.0 Section 16.1.4 - The occursCount expression is not evaluated.
-
-}
+//
+//package org.apache.daffodil.grammar.primitives
+//
+//import org.apache.daffodil.grammar._
+//import org.apache.daffodil.dsom._
+//import org.apache.daffodil.processors.unparsers.NadaUnparser
+//import org.apache.daffodil.processors.parsers.OccursCountExpressionParser
+
+//
+//object INoWarn6 { ImplicitsSuppressUnusedImportWarning() }
+//
+//object ENoWarn6 { EqualitySuppressUnusedImportWarning() }
+//
+//object RepPrims {
+//  abstract class RepPrim(context: ElementBase, n: Long, r: => Gram)
+//    extends UnaryGram(context, r) {
+//    Assert.invariant(n > 0)
+//    lazy val rd = context.elementRuntimeData
+//    lazy val intN = n.toInt
+//    lazy val rParser = r.parser
+//    lazy val rUnparser = r.unparser
+//
+//  }
+//
+//  abstract class Rep3Arg(f: (ElementBase, Long, => Gram) => Gram) {
+//    def apply(context: ElementBase, n: Long, rr: => Gram) = {
+//      lazy val r = rr
+//      if (n == 0 || r.isEmpty) EmptyGram
+//      else f(context, n, r)
+//    }
+//  }
+//
+//  abstract class Rep2Arg(f: (ElementBase, => Gram) => Gram) {
+//    def apply(context: ElementBase, r: => Gram) = {
+//      lazy val rr = r
+//      if (rr.isEmpty) EmptyGram
+//      else f(context, r)
+//    }
+//  }
+//
+//  class RepExactlyNPrim(context: ElementBase, n: Long, r: => Gram) extends RepPrim(context, n, r) {
+//
+//    // Since this is Exactly N, there is no new point of uncertainty considerations here.
+//    override lazy val parser = new RepExactlyNParser(n, r.parser, context.elementRuntimeData)
+//    override lazy val unparser = new RepExactlyNUnparser(n, r.unparser, context.elementRuntimeData)
+//
+//  }
+//
+//  class RepAtMostTotalNPrim(context: ElementBase, n: Long, r: => Gram) extends RepPrim(context, n, r) {
+//
+//    override lazy val parser = new RepAtMostTotalNParser(n, r.parser, context.elementRuntimeData)
+//    override lazy val unparser = new RepAtMostTotalNUnparser(n, r.unparser, context.elementRuntimeData)
+//
+//  }
+//
+//  class RepExactlyTotalNPrim(context: ElementBase, n: Long, r: => Gram) extends RepPrim(context, n, r) {
+//
+//    override lazy val parser = new RepExactlyTotalNParser(n, r.parser, context.elementRuntimeData)
+//    override lazy val unparser = new RepExactlyTotalNUnparser(n, r.unparser, context.elementRuntimeData)
+//
+//  }
+//
+//  class RepUnboundedPrim(e: ElementBase, r: => Gram) extends RepPrim(e, 1, r) {
+//
+//    override lazy val parser = new RepUnboundedParser(e.occursCountKind, r.parser, e.elementRuntimeData)
+//    override lazy val unparser = new RepUnboundedUnparser(e.occursCountKind, r.unparser, e.elementRuntimeData)
+//  }
+//
+//  class RepAtMostOccursCountPrim(e: ElementBase, n: Long, r: => Gram)
+//    extends RepPrim(e, n, r) {
+//
+//    override lazy val parser = new RepAtMostOccursCountParser(r.parser, n, e.elementRuntimeData)
+//    override lazy val unparser = new RepAtMostOccursCountUnparser(r.unparser, n, e.elementRuntimeData)
+//
+//  }
+//
+//  class RepExactlyTotalOccursCountPrim(e: ElementBase, r: => Gram)
+//    extends RepPrim(e, 1, r) {
+//
+//    override lazy val parser = new RepExactlyTotalOccursCountParser(r.parser, e.elementRuntimeData)
+//
+//    /**
+//     * Unparser for this is exactly the same as unbounded case - we output all the occurrences in the infoset.
+//     */
+//    override lazy val unparser = new RepUnboundedUnparser(e.occursCountKind, r.unparser, e.elementRuntimeData)
+//
+//  }
+//}
+//
+//object RepExactlyN extends Rep3Arg(new RepExactlyNPrim(_, _, _))
+//
+//object RepAtMostTotalN extends Rep3Arg(new RepAtMostTotalNPrim(_, _, _))
+//
+//object RepUnbounded extends Rep2Arg(new RepUnboundedPrim(_, _))
+//
+//object RepExactlyTotalN extends Rep3Arg(new RepExactlyTotalNPrim(_, _, _))
+//
+//object RepAtMostOccursCount extends Rep3Arg(new RepAtMostOccursCountPrim(_, _, _))
+//
+//object RepExactlyTotalOccursCount extends Rep2Arg(new RepExactlyTotalOccursCountPrim(_, _))
+//
+//case class OccursCountExpression(e: ElementBase)
+//  extends Terminal(e, true) {
+//
+//  override lazy val parser = new OccursCountExpressionParser(e.occursCountEv, e.elementRuntimeData)
+//  override lazy val unparser = new NadaUnparser(e.termRuntimeData) // DFDL v1.0 Section 16.1.4 - The occursCount expression is not evaluated.
+//
+//}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala
new file mode 100644
index 000000000..53acb9449
--- /dev/null
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.grammar.primitives
+
+import org.apache.daffodil.grammar._
+import org.apache.daffodil.dsom._
+import org.apache.daffodil.processors.unparsers._
+import org.apache.daffodil.processors.parsers._
+import org.apache.daffodil.dpath.NodeInfo
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
+import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
+import org.apache.daffodil.schema.annotation.props.gen.LengthKind
+import org.apache.daffodil.schema.annotation.props.gen.Representation
+
+abstract class SequenceChild(
+  protected val sq: SequenceTermBase, child: Term, groupIndex: Int)
+  extends Terminal(child, true) {
+
+  protected def childParser = child.termContentBody.parser
+  protected def childUnparser = child.termContentBody.unparser
+
+  final override def parser = sequenceChildParser
+  final override def unparser = sequenceChildUnparser
+
+  protected def sequenceChildParser: SequenceChildParser
+  protected def sequenceChildUnparser: SequenceChildUnparser
+
+  def optSequenceChildParser: Option[SequenceChildParser] =
+    if (childParser.isEmpty) None else Some(parser)
+
+  def optSequenceChildUnparser: Option[SequenceChildUnparser] =
+    if (childUnparser.isEmpty) None else Some(unparser)
+
+  protected lazy val sepGram = sq.sequenceSeparator
+  protected lazy val sepParser = sepGram.parser
+  protected lazy val sepUnparser = sepGram.unparser
+
+  lazy val srd = sq.sequenceRuntimeData
+  lazy val trd = child.termRuntimeData
+
+  /**
+   * Used by unparsing algorithms that involve separator suppression for
+   * zero-length data.
+   */
+  final lazy val zeroLengthDetector: ZeroLengthDetector = {
+    val result: ZeroLengthDetector = child match {
+      case e: ElementBase => {
+        Assert.invariant(e.isRepresented)
+        import LengthKind._
+
+        lazy val couldBeZLSimpleType =
+          !e.hasDelimiters &&
+            e.isSimpleType &&
+            (e.lengthKind match {
+              case Delimited | EndOfParent => true
+              //
+              // When parsing, the pattern might not match zero-length data, but
+              // when unparsing we just output the data as it appears in the infoset.
+              // We don't check that it satisfies the pattern. So a zero-length
+              // string in the infoset will be zero-length when output.
+              //
+              case Pattern => true
+              case Explicit | Implicit => e.hasFixedLengthOf(0)
+              case Prefixed => false
+            }) &&
+            //
+            // Alignment stuff - can't be any aligning possible or we'd have
+            // to do a runtime check for whether things are aligned or not.
+            // In the unparser, that is a suspendable operation, since we may
+            // not know the bit position.
+            //
+            // Separated sequences where there's any alignment possibly needed
+            // are an obscure corner case we don't need to handle.
+            //
+            e.hasNoSkipRegions &&
+            (((e.impliedRepresentation eq Representation.Text) && e.hasTextAlignment) ||
+              // binary data is allowed to be delimited... so long as the
+              // separators are recognizably not confused with binary bytes.
+              ((e.impliedRepresentation eq Representation.Binary) && e.isKnownToBeAligned))
+
+        val hasNilZL = (e.isNillable && !e.hasNilValueRequiredSyntax)
+        val hasEmptyZL = (e.emptyIsAnObservableConcept && e.hasEmptyValueZLSyntax)
+        val hasStringZL = e.isSimpleType && (e.simpleType.primType eq NodeInfo.String) && (couldBeZLSimpleType || hasEmptyZL)
+        val hasHexBinaryZL = e.isSimpleType && (e.simpleType.primType eq NodeInfo.HexBinary) && (couldBeZLSimpleType || hasEmptyZL)
+        (hasNilZL, hasStringZL, hasHexBinaryZL) match {
+          case (true, false, false) => new NillableZeroLengthDetector
+          case (false, true, false) => new StringZeroLengthDetector
+          case (false, false, true) => new HexBinaryZeroLengthDetector
+          case (true, true, false) => new NillableStringZeroLengthDetector
+          case (true, false, true) => new NillableHexBinaryZeroLengthDetector
+          case (_, true, true) => Assert.invariantFailed("Can't be both String and HexBinary type")
+          case _ => new NeverZeroLengthDetector
+        }
+      }
+      case m: ModelGroup => {
+        new NeverZeroLengthDetector
+      }
+    }
+    result
+  }
+
+  /**
+   * Used when unparsing to determine which of several separator suppression
+   * algorithms is required.
+   *
+   * Relevant only if the enclosing sequence is separated.
+   */
+  final lazy val separatorSuppressionAlgorithm: SeparatorSuppressionAlgorithm = {
+    Assert.invariant(sq.hasSeparator)
+    import SeparatorSuppressionAlgorithm._
+    import OccursCountKind._
+    child match {
+      case e: ElementBase => {
+        if (e.isScalar) None
+        else e.occursCountKind match {
+          case Fixed | Expression => FixedOrExpression
+          case Parsed => new SuppressAnyEmpty(zeroLengthDetector)
+          case StopValue => Assert.notYetImplemented()
+          case Implicit => {
+            import SeparatorSuppressionPolicy._
+            sq.separatorSuppressionPolicy match {
+              case Never => ImplicitNeverOrNotPotentiallyTrailing
+              case AnyEmpty => new ImplicitSuppressAnyEmpty(zeroLengthDetector)
+              case _ if (!e.isPotentiallyTrailing) => ImplicitNeverOrNotPotentiallyTrailing
+              case _ => new ImplicitPotentiallyTrailing(zeroLengthDetector)
+            }
+          }
+        }
+      }
+      case m: ModelGroup => {
+        SeparatorSuppressionAlgorithm.None
+      }
+    }
+  }
+
+}
+
+class ScalarOrderedSequenceChild(sq: SequenceTermBase, term: Term, groupIndex: Int)
+  extends SequenceChild(sq, term, groupIndex) {
+
+  def sequenceChildParser: SequenceChildParser = sq.hasSeparator match {
+    case true => new ScalarOrderedSeparatedSequenceChildParser(
+      childParser, srd, trd, sepParser, sq.separatorPosition, sq.separatorSuppressionPolicy)
+    case false => new ScalarOrderedUnseparatedSequenceChildParser(childParser, srd, trd)
+  }
+  def sequenceChildUnparser: SequenceChildUnparser = sq.hasSeparator match {
+    case true => new ScalarOrderedSeparatedSequenceChildUnparser(
+      childUnparser, srd, trd, sepUnparser, sq.separatorPosition, sq.separatorSuppressionPolicy,
+      this.separatorSuppressionAlgorithm)
+    case false => new ScalarOrderedUnseparatedSequenceChildUnparser(childUnparser, srd, trd)
+  }
+}
+
+sealed abstract class ElementSequenceChild(
+  sq: SequenceTermBase,
+  protected val e: ElementBase, groupIndex: Int)
+  extends SequenceChild(sq, e, groupIndex) {
+
+  protected lazy val erd = e.elementRuntimeData
+}
+
+sealed trait RepUnparserMixin { self: ElementSequenceChild =>
+
+  protected def e: ElementBase
+
+  def sequenceChildUnparser: SequenceChildUnparser = sq.hasSeparator match {
+    case true => new RepOrderedSeparatedSequenceChildUnparser(
+      childUnparser, srd, erd, sepUnparser, sq.separatorPosition, sq.separatorSuppressionPolicy,
+      this.separatorSuppressionAlgorithm)
+    case false => new RepOrderedUnseparatedSequenceChildUnparser(childUnparser, srd, erd)
+  }
+}
+
+class RepOrderedExactlyNSequenceChild(sq: SequenceTermBase, e: ElementBase, groupIndex: Int, repeatCount: Long)
+  extends ElementSequenceChild(sq, e, groupIndex)
+  with RepUnparserMixin {
+
+  def sequenceChildParser: SequenceChildParser = sq.hasSeparator match {
+    case true => new RepOrderedExactlyNSeparatedSequenceChildParser(
+      childParser, srd, erd, sepParser, sq.separatorPosition, sq.separatorSuppressionPolicy)
+    case false => new RepOrderedExactlyNUnseparatedSequenceChildParser(childParser, srd, erd, repeatCount)
+  }
+
+}
+
+class RepOrderedExactlyTotalOccursCountSequenceChild(sq: SequenceTermBase, e: ElementBase, groupIndex: Int)
+  extends ElementSequenceChild(sq, e, groupIndex)
+  with RepUnparserMixin {
+
+  def sequenceChildParser: SequenceChildParser = sq.hasSeparator match {
+    case true => new RepOrderedExactlyTotalOccursCountSeparatedSequenceChildParser(
+      childParser, e.occursCountEv, srd, erd, sepParser, sq.separatorPosition, sq.separatorSuppressionPolicy)
+    case false => new RepOrderedExactlyTotalOccursCountUnseparatedSequenceChildParser(childParser, e.occursCountEv, srd, erd)
+  }
+}
+
+class RepOrderedWithMinMaxSequenceChild(sq: SequenceTermBase, e: ElementBase, groupIndex: Int)
+  extends ElementSequenceChild(sq, e, groupIndex)
+  with RepUnparserMixin {
+
+  def sequenceChildParser: SequenceChildParser = sq.hasSeparator match {
+    case true => new RepOrderedWithMinMaxSeparatedSequenceChildParser(
+      childParser, srd, erd, sepParser, sq.separatorPosition, sq.separatorSuppressionPolicy,
+      e.isPotentiallyTrailing, e.isDeclaredLastInSequence)
+    case false => new RepOrderedWithMinMaxUnseparatedSequenceChildParser(childParser, srd, erd)
+  }
+}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
new file mode 100644
index 000000000..30d50e362
--- /dev/null
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.grammar.primitives
+
+import org.apache.daffodil.grammar.Terminal
+import org.apache.daffodil.dsom._
+import org.apache.daffodil.processors.parsers._
+import org.apache.daffodil.processors.unparsers._
+import org.apache.daffodil.util.Misc
+
+abstract class SequenceCombinator(sq: SequenceTermBase, sequenceChildren: Seq[SequenceChild])
+  extends Terminal(sq, sequenceChildren.length > 0) {
+  val srd = sq.sequenceRuntimeData
+}
+
+sealed abstract class OrderedSequenceBase(sq: SequenceTermBase, sequenceChildren: Seq[SequenceChild])
+  extends SequenceCombinator(sq, sequenceChildren) {
+
+  override def toString() =
+    "<" + Misc.getNameFromClass(this) + ">" +
+      sequenceChildren.map { _.toString() }.mkString +
+      "</" + Misc.getNameFromClass(this) + ">"
+}
+
+class OrderedSequence(sq: SequenceTermBase, sequenceChildren: Seq[SequenceChild])
+  extends OrderedSequenceBase(sq, sequenceChildren) {
+
+  private lazy val sepGram = sq.sequenceSeparator
+  private lazy val sepParser = sepGram.parser
+  private lazy val sepUnparser = sepGram.unparser
+
+  override lazy val parser: Parser = sq.hasSeparator match {
+    case true => new OrderedSeparatedSequenceParser(srd,
+      sq.separatorSuppressionPolicy, sq.separatorPosition, sepParser,
+      sequenceChildren.flatMap { _.optSequenceChildParser })
+    case false =>
+      new OrderedUnseparatedSequenceParser(srd,
+        sequenceChildren.flatMap { _.optSequenceChildParser })
+  }
+  override lazy val unparser: Unparser = {
+    sq.checkHiddenSequenceIsDefaultableOrOVC
+    val childUnparsers = sequenceChildren.flatMap { _.optSequenceChildUnparser }
+    if (childUnparsers.isEmpty) new NadaUnparser(null)
+    else {
+      sq.hasSeparator match {
+        case true => new OrderedSeparatedSequenceUnparser(srd,
+          sq.separatorSuppressionPolicy, sq.separatorPosition, sepUnparser,
+          childUnparsers)
+        case false =>
+          new OrderedUnseparatedSequenceUnparser(srd,
+            childUnparsers)
+      }
+    }
+  }
+}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SpecifiedLength.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SpecifiedLength.scala
index 7ea95b864..82854c0f5 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SpecifiedLength.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SpecifiedLength.scala
@@ -29,21 +29,32 @@ import org.apache.daffodil.processors.parsers.SpecifiedLengthExplicitParser
 import org.apache.daffodil.processors.parsers.SpecifiedLengthImplicitParser
 import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.processors.parsers.Parser
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.util.Maybe._
 
 abstract class SpecifiedLengthCombinatorBase(val e: ElementBase, eGramArg: => Gram)
   extends Terminal(e, true) {
 
   lazy val eGram = eGramArg // once only
-  lazy val eParser = eGram.parser
+
+  final protected lazy val maybeEParser: Maybe[Parser] = {
+    val p = eGram.parser
+    if (p.isEmpty) Nope
+    else One(p)
+  }
+
   lazy val eUnparser = eGram.unparser
 
   def kind: String
 
   def toBriefXML(depthLimit: Int = -1): String = {
     if (depthLimit == 0) "..." else
-      "<SpecifiedLengthCombinator_" + kind + ">" +
-        eParser.toBriefXML(depthLimit - 1) +
-        "</SpecifiedLengthCombinator_" + kind + ">"
+      "<SpecifiedLengthCombinator_" + kind + (
+        if (maybeEParser.isEmpty) "/>"
+        else ">" +
+          maybeEParser.get.toBriefXML(depthLimit - 1) +
+          "</SpecifiedLengthCombinator_" + kind + ">"
+      )
   }
 
 }
@@ -71,7 +82,7 @@ class SpecifiedLengthPattern(e: ElementBase, eGram: => Gram)
   }
 
   override lazy val parser: Parser = new SpecifiedLengthPatternParser(
-    eParser,
+    maybeEParser,
     e.elementRuntimeData,
     pattern)
 
@@ -90,11 +101,16 @@ trait SpecifiedLengthExplicitImplicitUnparserMixin {
   def e: ElementBase
   def eUnparser: Unparser
 
-  lazy val unparser: Unparser = new SpecifiedLengthExplicitImplicitUnparser(
-    eUnparser,
-    e.elementRuntimeData,
-    e.unparseTargetLengthInBitsEv,
-    e.maybeUnparseTargetLengthInCharactersEv)
+  lazy val unparser: Unparser = {
+    val u = eUnparser
+    if (u.isEmpty) u
+    else
+      new SpecifiedLengthExplicitImplicitUnparser(
+        u,
+        e.elementRuntimeData,
+        e.unparseTargetLengthInBitsEv,
+        e.maybeUnparseTargetLengthInCharactersEv)
+  }
 }
 
 class SpecifiedLengthExplicit(e: ElementBase, eGram: => Gram, bitsMultiplier: Int)
@@ -106,7 +122,7 @@ class SpecifiedLengthExplicit(e: ElementBase, eGram: => Gram, bitsMultiplier: In
   lazy val kind = "Explicit_" + e.lengthUnits.toString
 
   lazy val parser: Parser = new SpecifiedLengthExplicitParser(
-    eParser,
+    maybeEParser,
     e.elementRuntimeData,
     e.lengthEv,
     bitsMultiplier)
@@ -122,7 +138,7 @@ class SpecifiedLengthImplicit(e: ElementBase, eGram: => Gram, nBits: Long)
   lazy val toBits = 1
 
   lazy val parser: Parser = new SpecifiedLengthImplicitParser(
-    eParser,
+    maybeEParser,
     e.elementRuntimeData,
     nBits)
 
@@ -135,7 +151,7 @@ class SpecifiedLengthExplicitCharacters(e: ElementBase, eGram: => Gram)
   val kind = "ExplicitCharacters"
 
   lazy val parser: Parser = new SpecifiedLengthExplicitCharactersParser(
-    eParser,
+    maybeEParser,
     e.elementRuntimeData,
     e.lengthEv)
 }
@@ -147,7 +163,7 @@ class SpecifiedLengthImplicitCharacters(e: ElementBase, eGram: => Gram, nChars:
   val kind = "ImplicitCharacters"
 
   lazy val parser: Parser = new SpecifiedLengthImplicitCharactersParser(
-    eParser,
+    maybeEParser,
     e.elementRuntimeData,
     nChars)
 }
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/api/TestAPI.scala b/daffodil-core/src/test/scala/org/apache/daffodil/api/TestAPI.scala
index dde6edf54..728389ca4 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/api/TestAPI.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/api/TestAPI.scala
@@ -30,7 +30,7 @@ class TestDFDLParser_New {
       <xs:element name="e1" dfdl:lengthKind="implicit" dfdl:terminator=".">
         <xs:complexType>
           <xs:sequence dfdl:separator=";" dfdl:terminator=";">
-            <xs:element name="s1" type="xs:int" dfdl:lengthKind="delimited" maxOccurs="100" minOccurs="0" dfdl:occursCountKind="implicit"/>
+            <xs:element name="s1" type="xs:int" dfdl:lengthKind="delimited" maxOccurs="4" minOccurs="0" dfdl:occursCountKind="implicit"/>
           </xs:sequence>
         </xs:complexType>
       </xs:element>)
@@ -38,4 +38,19 @@ class TestDFDLParser_New {
     val expected = <e1><s1>5</s1><s1>6</s1><s1>7</s1><s1>8</s1></e1>
     TestUtils.assertEqualsXMLElements(expected, actual)
   }
+
+  @Test def testParseOccursCountKindOfParsedDelimitedBySeparatorImplicitWithMaxOccurs2() {
+    val sch = SchemaUtils.dfdlTestSchema(
+      <dfdl:format ref="tns:GeneralFormat"/>,
+      <xs:element name="e1" dfdl:lengthKind="implicit" dfdl:terminator=".">
+        <xs:complexType>
+          <xs:sequence dfdl:separator=";" dfdl:terminator="!">
+            <xs:element name="s1" type="xs:int" dfdl:lengthKind="delimited" maxOccurs="100" minOccurs="0" dfdl:occursCountKind="implicit"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>)
+    val (_, actual) = TestUtils.testString(sch, "5;6;7;8!.")
+    val expected = <e1><s1>5</s1><s1>6</s1><s1>7</s1><s1>8</s1></e1>
+    TestUtils.assertEqualsXMLElements(expected, actual)
+  }
 }
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/api/TestAPI1.scala b/daffodil-core/src/test/scala/org/apache/daffodil/api/TestAPI1.scala
index 862a1be59..f60acf65b 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/api/TestAPI1.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/api/TestAPI1.scala
@@ -375,7 +375,7 @@ class TestDFDLParser {
       <xs:element name="e1" dfdl:lengthKind="implicit" dfdl:terminator=".">
         <xs:complexType>
           <xs:sequence dfdl:separator=";" dfdl:terminator=";">
-            <xs:element name="s1" type="xs:int" dfdl:lengthKind="delimited" minOccurs="0" dfdl:occursCountKind="parsed"/>
+            <xs:element name="s1" type="xs:int" dfdl:lengthKind="delimited" minOccurs="0" dfdl:occursCountKind="implicit" maxOccurs="4"/>
           </xs:sequence>
         </xs:complexType>
       </xs:element>)
@@ -386,6 +386,23 @@ class TestDFDLParser {
     TestUtils.assertEqualsXMLElements(expected, actual)
   }
 
+  @Test def testParseOccursCountKindOfParsedDelimitedBySeparator3() {
+    val sch = SchemaUtils.dfdlTestSchema(
+      <dfdl:format ref="tns:GeneralFormat"/>,
+      <xs:element name="e1" dfdl:lengthKind="implicit" dfdl:terminator=".">
+        <xs:complexType>
+          <xs:sequence dfdl:separator=";" dfdl:terminator="!">
+            <xs:element name="s1" type="xs:int" dfdl:lengthKind="delimited" minOccurs="0" dfdl:occursCountKind="parsed"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>)
+    val areTracing = false
+    val (_, actual) = TestUtils.testString(sch, "5;6;7;8!.", areTracing)
+    val expected = <e1><s1>5</s1><s1>6</s1><s1>7</s1><s1>8</s1></e1>
+
+    TestUtils.assertEqualsXMLElements(expected, actual)
+  }
+
   @Test def testBinaryIntMinusOne() {
     val sch = SchemaUtils.dfdlTestSchema(
       <dfdl:format representation="binary" byteOrder="bigEndian" binaryNumberRep="binary" ref="tns:GeneralFormat"/>,
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
index 9e5798f0b..8de747863 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
@@ -223,25 +223,25 @@ class TestDsomCompiler extends Logging {
     val root1 = e1f.forRoot()
     val e1 = root1.referencedElement
     e2f.forRoot()
-    val e3 = e3f.forRoot().referencedElement
+    val e3 = e3f.forRoot()
     assertEquals(
       ByteOrder.BigEndian.toString.toLowerCase(),
-      e1.formatAnnotation.asInstanceOf[DFDLElement].getProperty("byteOrder").toLowerCase())
-    val Seq(a1, a2) = e3.annotationObjs // third one has two annotations
+      e1.formatAnnotation.asInstanceOf[DFDLElement].getPropertyForUnitTest("byteOrder").toLowerCase())
+    val Seq(_, a2) = e3.referencedElement.annotationObjs // third one has two annotations
     assertTrue(a2.isInstanceOf[DFDLAssert]) // second annotation is newVariableInstance
-    assertEquals("implicit", a1.asInstanceOf[DFDLElement].getProperty("occursCountKind"))
+    assertEquals(OccursCountKind.Implicit.toString, e3.getProperty("occursCountKind"))
     // Explore local complex type def
     val seq = e1.sequence //... which is a sequence
     seq.formatAnnotation.asInstanceOf[DFDLSequence] //...annotated with...
     assertEquals(YesNo.No, seq.initiatedContent) // initiatedContent="no"
 
     val Seq(e1a: DFDLElement) = e1.annotationObjs
-    assertEquals("UTF-8", e1a.getProperty("encoding"))
+    assertEquals("UTF-8", e1a.getPropertyForUnitTest("encoding"))
 
     // Explore global simple type defs
     val Seq(st1, _, _, _) = sd.globalSimpleTypeDefs // there are two.
     val Seq(b1, b2, _, b4) = st1.forElement(e1).annotationObjs // first one has 4 annotations
-    assertEquals(AlignmentUnits.Bytes.toString.toLowerCase, b1.asInstanceOf[DFDLSimpleType].getProperty("alignmentUnits")) // first has alignmentUnits
+    assertEquals(AlignmentUnits.Bytes.toString.toLowerCase, b1.asInstanceOf[DFDLSimpleType].getPropertyForUnitTest("alignmentUnits")) // first has alignmentUnits
     assertEquals("tns:myVar1", b2.asInstanceOf[DFDLSetVariable].ref) // second is setVariable with a ref
     assertEquals("yadda yadda yadda", b4.asInstanceOf[DFDLAssert].message) // fourth is an assert with yadda message
 
@@ -249,7 +249,7 @@ class TestDsomCompiler extends Logging {
     val Seq(df1, _) = sd.defineFormats // there are two
     val def1 = df1.asInstanceOf[DFDLDefineFormat]
     assertEquals("def1", def1.name) // first is named "def1"
-    assertEquals(Representation.Text.toString.toLowerCase, def1.formatAnnotation.getProperty("representation")) // has representation="text"
+    assertEquals(Representation.Text.toString.toLowerCase, def1.formatAnnotation.getPropertyForUnitTest("representation")) // has representation="text"
 
     // Explore define variables
     val Seq(dv1, _) = sd.defineVariables // there are two
@@ -331,8 +331,7 @@ class TestDsomCompiler extends Logging {
     val Seq(sd) = sch.schemaDocuments
 
     val Seq(ge1f, _, _, _, _, _) = sd.globalElementDecls // Obtain global element nodes
-    val ge1 = ge1f.forRoot().referencedElement
-    val Seq(a1: DFDLElement) = ge1.annotationObjs
+    val a1 = ge1f.forRoot()
 
     assertEquals(true, a1.verifyPropValue("occursCountKind", "parsed"))
     assertEquals(true, a1.verifyPropValue("lengthKind", "pattern"))
@@ -408,29 +407,29 @@ class TestDsomCompiler extends Logging {
 
     // Explore global element decl
     val Seq(e1f, e2f, e3f, _, _) = sd.globalElementDecls // there are 3 factories
-    val e1 = e1f.forRoot().referencedElement
+    val e1 = e1f.forRoot()
     e2f.forRoot()
     e3f.forRoot()
 
     val Seq(gs1f, _, gs3f, _) = sd.globalSimpleTypeDefs
 
-    val gs1 = gs1f.forElement(e1) // Global Simple Type - aType
+    val gs1 = gs1f.forElement(e1.referencedElement) // Global Simple Type - aType
 
     val baseQName = gs1.optRestriction.get.baseQName
 
     assertEquals("ex", baseQName.prefix.get)
     assertEquals("aaType", baseQName.local)
 
-    assertTrue(gs1.term.verifyPropValue("alignmentUnits", "bytes")) // SimpleType - Local
+    assertTrue(gs1.formatAnnotation.verifyPropValue("alignmentUnits", "bytes")) // SimpleType - Local
 
-    assertTrue(gs1.term.verifyPropValue("byteOrder", "bigEndian")) // SimpleType - Base
-    assertTrue(gs1.term.verifyPropValue("occursCountKind", "implicit")) // Default Format
-    assertTrue(gs1.term.verifyPropValue("representation", "text")) // Define Format - def1
-    assertTrue(gs1.term.verifyPropValue("encoding", "UTF-8")) // Define Format - def1
-    assertTrue(gs1.term.verifyPropValue("textStandardBase", "10")) // Define Format - def2
-    assertTrue(gs1.term.verifyPropValue("escapeSchemeRef", "tns:quotingScheme")) // Define Format - def2
+    assertTrue(e1.verifyPropValue("byteOrder", "bigEndian")) // SimpleType - Base
+    assertTrue(e1.verifyPropValue("occursCountKind", "implicit")) // Default Format
+    assertTrue(e1.verifyPropValue("representation", "text")) // Define Format - def1
+    assertTrue(e1.verifyPropValue("encoding", "UTF-8")) // Define Format - def1
+    assertTrue(e1.verifyPropValue("textStandardBase", "10")) // Define Format - def2
+    assertTrue(e1.verifyPropValue("escapeSchemeRef", "tns:quotingScheme")) // Define Format - def2
 
-    val gs3 = gs3f.forElement(e1) // Global SimpleType - aTypeError - overlapping base props
+    val gs3 = gs3f.forElement(e1.referencedElement) // Global SimpleType - aTypeError - overlapping base props
 
     // Tests overlapping properties
     // because these unit tests are outside the normal framework,
@@ -504,7 +503,7 @@ class TestDsomCompiler extends Logging {
     val Seq(ge1f) = sd.globalElementDecls // Obtain global element nodes
     val ge1 = ge1f.forRoot()
 
-    val f1 = ge1.formatAnnotation
+    val f1 = ge1
 
     assertTrue(f1.verifyPropValue("separatorPosition", "infix"))
     assertTrue(f1.verifyPropValue("lengthKind", "implicit"))
@@ -515,11 +514,9 @@ class TestDsomCompiler extends Logging {
     val seq = ct.sequence
 
     val Seq(e1: ElementBase, _: ElementBase) = seq.groupMembers
-
-    val e1f = e1.formatAnnotation.asInstanceOf[DFDLElement]
     //
-    assertTrue(e1f.verifyPropValue("initiator", ""))
-    assertTrue(e1f.verifyPropValue("representation", "text"))
+    assertTrue(e1.verifyPropValue("initiator", ""))
+    assertTrue(e1.verifyPropValue("representation", "text"))
 
     e1.lengthKind
   }
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestPropertyScoping.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestPropertyScoping.scala
index 97bddb685..b50c3cab4 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestPropertyScoping.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestPropertyScoping.scala
@@ -23,7 +23,7 @@ import org.junit.Assert._
 import org.apache.daffodil.util.LogLevel
 import org.apache.daffodil.util.Fakes
 
-class HasProps(xml: Node) extends DFDLNonDefaultFormatAnnotation(xml, Fakes.fakeElem)
+class HasProps(xml: Node) extends DFDLFormatAnnotation(xml, Fakes.fakeElem)
 
 class TestPropertyScoping {
   val x1 = new HasProps(<fake alignmentUnits="bytes"/>)
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/grammar/TestGrammar.scala b/daffodil-core/src/test/scala/org/apache/daffodil/grammar/TestGrammar.scala
index e1c977be6..a701fbad0 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/grammar/TestGrammar.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/grammar/TestGrammar.scala
@@ -24,6 +24,7 @@ import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.processors.parsers.Parser
 import org.junit.Test
 import org.apache.daffodil.util.Fakes
+import org.apache.daffodil.processors.unparsers.Unparser
 
 class TestGrammar extends GrammarMixin {
 
@@ -31,11 +32,10 @@ class TestGrammar extends GrammarMixin {
 
   final override protected def grammarContext = fakeTerm
 
-  case class Primitive1(e: Term, guard: Boolean = true) extends Terminal(e, guard) with HasNoUnparser {
+  case class Primitive1(e: Term, guard: Boolean = true) extends Terminal(e, guard) {
     def parser: Parser = Assert.notYetImplemented()
+    def unparser: Unparser = Assert.notYetImplemented()
   }
-  //  case class Primitive2(e: SchemaComponent, guard: Boolean = true) extends Terminal(e, guard)
-  //  case class Primitive3(e: SchemaComponent, guard: Boolean = true) extends Terminal(e, guard)
 
   @Test def testBasicTripleSequential() {
 
@@ -70,7 +70,6 @@ class TestGrammar extends GrammarMixin {
     assertFalse(triple.isEmpty)
 
     val exp = triple.gram
-    // println(exp)
     assertTrue(exp.name.contains("SeqComp"))
     assertTrue(exp.toString.contains("first"))
     assertFalse(exp.toString.contains("mid")) // spliced out.
@@ -90,7 +89,6 @@ class TestGrammar extends GrammarMixin {
     assertTrue(triple.isEmpty)
 
     val exp = triple.gram
-    // println(exp)
     assertFalse(exp.name.contains("SeqComp"))
     assertFalse(exp.toString.contains("first"))
     assertFalse(exp.toString.contains("mid")) // spliced out.
@@ -99,92 +97,4 @@ class TestGrammar extends GrammarMixin {
 
   }
 
-  @Test def testMultipleSpliceOuts() {
-
-    object first extends Primitive1(fakeTerm)
-    object mid extends Primitive1(fakeTerm, false)
-    object last extends Primitive1(fakeTerm, false)
-
-    lazy val triple = prod("triple") { first | (last ~ mid ~ first) | last }
-
-    assertFalse(triple.isEmpty)
-
-    val exp = triple.gram
-    // println(exp)
-    assertTrue(exp.name.contains("AltComp"))
-    assertTrue(exp.toString.contains("first"))
-    assertFalse(exp.toString.contains("mid")) // spliced out.
-    assertFalse(exp.toString.contains("last")) // spliced out.
-    assertTrue(exp.toString.contains(" | "))
-    assertFalse(exp.toString.contains(" (")) // no interior parens. There will be around the outside though.
-
-  }
-
-  @Test def testPrecedence1() {
-
-    object first extends Primitive1(fakeTerm)
-    object mid extends Primitive1(fakeTerm)
-    object last extends Primitive1(fakeTerm)
-
-    lazy val triple = prod("triple") { first | mid ~ last }
-
-    assertFalse(triple.isEmpty)
-
-    val exp = triple.gram
-    assertTrue(exp.name.contains("AltComp"))
-    assertTrue(exp.toString.contains("first"))
-    assertTrue(exp.toString.contains("mid"))
-    assertTrue(exp.toString.contains("last"))
-    assertTrue(exp.toString.contains(" | "))
-    assertTrue(exp.toString.contains(" ~ "))
-    //   assertTrue(exp.toString.contains(" | (")) // ~ binds tighter
-
-  }
-
-  @Test def testPrecedence2() {
-
-    object first extends Primitive1(fakeTerm)
-    object mid extends Primitive1(fakeTerm)
-    object last extends Primitive1(fakeTerm)
-
-    lazy val triple = prod("triple") { first ~ mid | last }
-
-    assertFalse(triple.isEmpty)
-
-    val exp = triple.gram
-    // println(exp)
-    assertTrue(exp.name.contains("AltComp"))
-    assertTrue(exp.toString.contains("first"))
-    assertTrue(exp.toString.contains("mid"))
-    assertTrue(exp.toString.contains("last"))
-    assertTrue(exp.toString.contains(" | "))
-    assertTrue(exp.toString.contains(" ~ "))
-    //   assertTrue(exp.toString.contains(") | ")) // ~ binds tighter
-
-  }
-
-  @Test def testProdsSpliceOut() {
-
-    object first extends Primitive1(fakeTerm)
-    object mid extends Primitive1(fakeTerm, false)
-    object last extends Primitive1(fakeTerm)
-
-    lazy val prod1 = prod("prod1") { first ~ mid | last }
-    lazy val prod2 = prod("prod2", false) { first ~ mid | last }
-    lazy val prod3 = prod("prod3") { first ~ mid | last }
-    lazy val prod4 = prod("prod4") { prod1 | (prod2 ~ prod3) }
-
-    assertFalse(prod4.isEmpty)
-
-    val exp = prod4.gram
-    assertTrue(exp.name.contains("AltComp"))
-    // assertTrue(exp.toString.contains("prod1"))
-    assertFalse(exp.toString.contains("prod2"))
-    assertFalse(exp.toString.contains("prod3"))
-    assertTrue(exp.toString.contains(" | "))
-    assertFalse(exp.toString.contains(" ~ "))
-    assertTrue(exp.toString.contains(" | "))
-
-  }
-
 }
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/util/TestUtils.scala b/daffodil-core/src/test/scala/org/apache/daffodil/util/TestUtils.scala
index 40b08f53d..88fedbe2c 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/util/TestUtils.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/util/TestUtils.scala
@@ -208,7 +208,9 @@ object TestUtils {
     val input = InputSourceDataInputStream(Channels.newInputStream(data))
     val actual = p.parse(input, outputter)
     if (actual.isProcessingError) {
-      val msgs = actual.getDiagnostics.map(_.getMessage()).mkString("\n")
+      val diags = actual.getDiagnostics
+      if (diags.length == 1) throw diags(0)
+      val msgs = diags.map(_.getMessage()).mkString("\n")
       throw new Exception(msgs)
     }
     (actual, outputter.getResult)
diff --git a/daffodil-io/src/main/scala/org/apache/daffodil/io/InputSourceDataInputStream.scala b/daffodil-io/src/main/scala/org/apache/daffodil/io/InputSourceDataInputStream.scala
index 3f093bc64..cc541b8e9 100644
--- a/daffodil-io/src/main/scala/org/apache/daffodil/io/InputSourceDataInputStream.scala
+++ b/daffodil-io/src/main/scala/org/apache/daffodil/io/InputSourceDataInputStream.scala
@@ -716,7 +716,7 @@ class InputSourceDataInputStreamCharIteratorState  {
 
 class InputSourceDataInputStreamCharIterator(dis: InputSourceDataInputStream) extends DataInputStream.CharIterator {
 
-  private var finfo : FormatInfo = _
+  private var finfo : FormatInfo = null
 
   override def reset(): Unit = {
     dis.cst.charIteratorState.clear()
diff --git a/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd b/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
index 2423f0c07..76a1af018 100644
--- a/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
+++ b/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
@@ -164,6 +164,7 @@
       <enumeration value="true"/> <!-- means same as onePass -->
       <enumeration value="onePass"/> <!--  parse, compare infoset, unparse - compare data -->
       <enumeration value="twoPass"/> <!-- parse, unparse, reparse - compare infoset -->
+      <enumeration value="threePass"/><!-- parse, unparse, reparse, reunparse, compare data -->
     </restriction>
   </simpleType>
   
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/exceptions/Assert.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/exceptions/Assert.scala
index 46a5c3c33..4f6472902 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/exceptions/Assert.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/exceptions/Assert.scala
@@ -20,7 +20,7 @@ package org.apache.daffodil.exceptions
 trait ThinThrowable { self: Throwable =>
   // Sometimes we want to use Exceptions/Throwables in try/catch as a form of
   // flow control (yeah, usually not that great of an idea), for example with
-  // ProcessingError and withParseErrorThrowing. Unfortunately, the problem
+  // ProcessingError. Unfortunately, the problem
   // with this is that Exceptions are pretty heavy to create, mostly do to the
   // building of stack traces. But, in cases where we use Exceptions for flow
   // control, we don't need all this extra baggage of the stack traces. So
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/schema/annotation/props/ByHandMixins.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/schema/annotation/props/ByHandMixins.scala
index 5423b24c8..77d2e16ab 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/schema/annotation/props/ByHandMixins.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/schema/annotation/props/ByHandMixins.scala
@@ -122,7 +122,7 @@ trait SeparatorSuppressionPolicyMixin
    * DFDL standard in this way, so this approach is better than the loader that rewrites. It
    * gives us more flexibility in warnings or error treatment of the old/deprecated names.
    */
-  lazy val separatorSuppressionPolicy = {
+  lazy val separatorSuppressionPolicy: SeparatorSuppressionPolicy = {
     val sp = getPropertyOption("separatorPolicy")
     val ssp = getPropertyOption("separatorSuppressionPolicy")
     (sp, ssp) match {
@@ -131,7 +131,10 @@ trait SeparatorSuppressionPolicyMixin
         SeparatorSuppressionPolicy(sspStr, this)
       }
       case (None, Some(sspStr)) => SeparatorSuppressionPolicy(sspStr, this)
-      case (None, None) => getProperty("separatorSuppressionPolicy") // which will SDE!
+      case (None, None) => {
+        getProperty("separatorSuppressionPolicy") // which will SDE!
+        Assert.impossible("Above is going to SDE")
+      }
       case (Some(spString), None) => {
         SDW(WarnID.DeprecatedPropertySeparatorPolicy, "Property separatorPolicy is deprecated. Use separatorSuppressionPolicy instead.")
         spString match {
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/schema/annotation/props/PropertyScoping.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/schema/annotation/props/PropertyScoping.scala
index c4b6bd4f8..1784f4b09 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/schema/annotation/props/PropertyScoping.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/schema/annotation/props/PropertyScoping.scala
@@ -193,7 +193,7 @@ trait FindPropertyMixin extends PropTypes {
   /**
    * For unit testing convenience, or for use when debugging.
    */
-  final def verifyPropValue(key: String, value: String): Boolean = {
+  def verifyPropValue(key: String, value: String): Boolean = {
     val prop = findPropertyOption(key)
     prop match {
       case Found(v, _, _, _) if (v == value) => true
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/util/Pool.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/util/Pool.scala
index 18d44d425..bf33ef199 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/util/Pool.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/util/Pool.scala
@@ -18,7 +18,6 @@
 package org.apache.daffodil.util
 
 import org.apache.daffodil.equality._
-import org.apache.daffodil.exceptions.Assert
 import scala.collection.mutable
 
 /**
@@ -78,7 +77,15 @@ trait Pool[T <: Poolable] {
     numOutstanding -= 1
     pool.push(thing)
     inUse -= thing
-    thing.setPoolDebugLabel(null)
+    // Do Not reset the pool debug label.
+    // That way if something is double-returned, we can look at the
+    // pool debug label to see what it previously was, as a clue to how
+    // it was erroneously double returned.
+    // thing.setPoolDebugLabel(null)
+  }
+  
+  final def isInUse(thing: T) = {
+    inUse.contains(thing)
   }
 
   /**
@@ -92,7 +99,8 @@ trait Pool[T <: Poolable] {
     if (!(numOutstanding =#= 0)) {
       val msg = "Pool " + Misc.getNameFromClass(this) + " leaked " + numOutstanding + " instance(s)." +
         "\n" + inUse.map { item => "poolDebugLabel = " + item.poolDebugLabel }.mkString("\n")
-      Assert.invariantFailed(msg)
+      System.err.println(msg)
+      // Assert.invariantFailed(msg)
     }
   }
 
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementKindUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementKindUnparsers.scala
index 08af74668..1f0f44eab 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementKindUnparsers.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementKindUnparsers.scala
@@ -21,12 +21,8 @@ import org.apache.daffodil.processors._
 import org.apache.daffodil.infoset._
 import org.apache.daffodil.processors.RuntimeData
 import org.apache.daffodil.util.Maybe._
-import org.apache.daffodil.api.ValidationMode
-import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.Maybe._
-import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.equality._
 
 class ComplexTypeUnparser(rd: RuntimeData, bodyUnparser: Unparser)
   extends CombinatorUnparser(rd) {
@@ -46,88 +42,6 @@ class ComplexTypeUnparser(rd: RuntimeData, bodyUnparser: Unparser)
   }
 }
 
-class SequenceCombinatorUnparser(ctxt: ModelGroupRuntimeData, childUnparsers: Vector[Unparser])
-  extends CombinatorUnparser(ctxt)
-  with ToBriefXMLImpl {
-
-  override lazy val runtimeDependencies: Seq[Evaluatable[AnyRef]] = Nil
-
-  override def nom = "Sequence"
-
-  // Sequences of nothing (no initiator, no terminator, nothing at all) should
-  // have been optimized away
-  Assert.invariant(childUnparsers.length > 0)
-
-  // Since some of the grammar terms might have folded away to EmptyGram,
-  // the number of unparsers here may be different from the number of
-  // children of the sequence group.
-  Assert.invariant(ctxt.groupMembers.length >= childUnparsers.length)
-
-  override lazy val childProcessors: Seq[Processor] = childUnparsers
-
-  def unparse(start: UState): Unit = {
-
-    start.groupIndexStack.push(1L) // one-based indexing
-
-    var index = 0
-    var doUnparser = false
-    val limit = childUnparsers.length
-    while (index < limit) {
-      doUnparser = false
-      val childUnparser = childUnparsers(index)
-      val childRD = childUnparser.context
-
-      childRD match {
-        case erd: ElementRuntimeData if !erd.isRequired => {
-          // it's not a required element, so we check to see if we have a matching
-          // incoming infoset event
-          if (start.inspect) {
-            val ev = start.inspectAccessor
-            if (ev.isStart) {
-              val eventNQN = ev.node.namedQName
-              if (eventNQN =:= erd.namedQName) {
-                doUnparser = true
-              }
-            } else if (ev.isEnd && ev.isComplex) {
-              val c = ev.asComplex
-              //ok. We've peeked ahead and found the end of the complex element
-              //that this sequence is the model group of.
-              val optParentRD = ctxt.immediateEnclosingElementRuntimeData
-              optParentRD match {
-                case Some(e: ElementRuntimeData) =>
-                  Assert.invariant(c.runtimeData.namedQName =:= e.namedQName)
-                case _ =>
-                  Assert.invariantFailed("Not end element for this sequence's containing element. Event %s, optParentRD %s.".format(
-                    ev, optParentRD))
-              }
-            } else {
-              Assert.invariantFailed("Not a start event: " + ev)
-            }
-          }
-        }
-        case _ => {
-          // since only elements can be optional, anything else is non-optional
-          doUnparser = true
-        }
-      }
-      if (doUnparser) {
-        childUnparser.unparse1(start)
-      }
-      index += 1
-      //
-      // Note: the invariant is that unparsers move over 1 within their group themselves
-      // we do not do the moving over here as we are the caller of the unparser.
-      //
-    }
-    start.groupIndexStack.pop()
-    //
-    // this is establishing the invariant that unparsers (in this case the sequence unparser)
-    // moves over within its containing group. The caller of an unparser does not do this move.
-    //
-    start.moveOverOneGroupIndexOnly()
-  }
-}
-
 class ChoiceCombinatorUnparser(mgrd: ModelGroupRuntimeData, eventUnparserMap: Map[ChoiceBranchEvent, Unparser])
   extends CombinatorUnparser(mgrd)
   with ToBriefXMLImpl {
@@ -240,71 +154,71 @@ class DynamicEscapeSchemeUnparser(escapeScheme: EscapeSchemeUnparseEv, ctxt: Ter
   }
 }
 
-class ArrayCombinatorUnparser(erd: ElementRuntimeData, bodyUnparser: Unparser)
-  extends CombinatorUnparser(erd) {
-  override def nom = "Array"
-  override lazy val runtimeDependencies = Nil
-  override lazy val childProcessors = Seq(bodyUnparser)
-
-  def unparse(state: UState) {
-    state.arrayIndexStack.push(1L) // one-based indexing
-    state.occursBoundsStack.push(state.tunable.maxOccursBounds)
-
-    var event = state.advanceOrError
-    Assert.invariant(event.isStart && event.node.isInstanceOf[DIArray])
-
-    bodyUnparser.unparse1(state)
-
-    event = state.advanceOrError
-    if (!(event.isEnd && event.node.isInstanceOf[DIArray])) {
-      UnparseError(One(erd.schemaFileLocation), One(state.currentLocation), "Expected array end event for %s, but received %s.", erd.namedQName, event)
-    }
-
-    val shouldValidate =
-      (state.dataProc.isDefined) && state.dataProc.value.getValidationMode != ValidationMode.Off
-
-    val actualOccurs = state.arrayIndexStack.pop()
-    state.occursBoundsStack.pop()
-
-    if (shouldValidate) {
-      (erd.minOccurs, erd.maxOccurs) match {
-        case (Some(minOccurs), Some(maxOccurs)) => {
-          val isUnbounded = maxOccurs == -1
-          val occurrence = actualOccurs - 1
-          if (isUnbounded && occurrence < minOccurs)
-            state.validationError("%s occurred '%s' times when it was expected to be a " +
-              "minimum of '%s' and a maximum of 'UNBOUNDED' times.", erd.diagnosticDebugName,
-              occurrence, minOccurs)
-          else if (!isUnbounded && (occurrence < minOccurs || occurrence > maxOccurs))
-            state.validationError("%s occurred '%s' times when it was expected to be a " +
-              "minimum of '%s' and a maximum of '%s' times.", erd.diagnosticDebugName,
-              occurrence, minOccurs, maxOccurs)
-        }
-        case _ => // ok
-      }
-    }
-  }
-}
-
-class OptionalCombinatorUnparser(erd: ElementRuntimeData, bodyUnparser: Unparser)
-  extends CombinatorUnparser(erd) {
-  override def nom = "Optional"
-  override lazy val childProcessors = Seq(bodyUnparser)
-
-  override lazy val runtimeDependencies = Nil
-
-  def unparse(state: UState) {
-
-    state.arrayIndexStack.push(1L) // one-based indexing
-    state.occursBoundsStack.push(1L)
-
-    val event = state.inspectOrError
-    Assert.invariant(event.isStart && !event.node.isInstanceOf[DIArray])
-
-    bodyUnparser.unparse1(state)
-
-    state.arrayIndexStack.pop()
-    state.occursBoundsStack.pop()
-  }
-}
+//class ArrayCombinatorUnparser(erd: ElementRuntimeData, bodyUnparser: Unparser)
+//  extends CombinatorUnparser(erd) {
+//  override def nom = "Array"
+//  override lazy val runtimeDependencies = Nil
+//  override lazy val childProcessors = Seq(bodyUnparser)
+//
+//  def unparse(state: UState) {
+//    state.arrayIndexStack.push(1L) // one-based indexing
+//    state.occursBoundsStack.push(state.tunable.maxOccursBounds)
+//
+//    var event = state.advanceOrError
+//    Assert.invariant(event.isStart && event.node.isInstanceOf[DIArray])
+//
+//    bodyUnparser.unparse1(state)
+//
+//    event = state.advanceOrError
+//    if (!(event.isEnd && event.node.isInstanceOf[DIArray])) {
+//      UnparseError(One(erd.schemaFileLocation), One(state.currentLocation), "Expected array end event for %s, but received %s.", erd.namedQName, event)
+//    }
+//
+//    val shouldValidate =
+//      (state.dataProc.isDefined) && state.dataProc.value.getValidationMode != ValidationMode.Off
+//
+//    val actualOccurs = state.arrayIndexStack.pop()
+//    state.occursBoundsStack.pop()
+//
+//    if (shouldValidate) {
+//      (erd.minOccurs, erd.maxOccurs) match {
+//        case (Some(minOccurs), Some(maxOccurs)) => {
+//          val isUnbounded = maxOccurs == -1
+//          val occurrence = actualOccurs - 1
+//          if (isUnbounded && occurrence < minOccurs)
+//            state.validationError("%s occurred '%s' times when it was expected to be a " +
+//              "minimum of '%s' and a maximum of 'UNBOUNDED' times.", erd.diagnosticDebugName,
+//              occurrence, minOccurs)
+//          else if (!isUnbounded && (occurrence < minOccurs || occurrence > maxOccurs))
+//            state.validationError("%s occurred '%s' times when it was expected to be a " +
+//              "minimum of '%s' and a maximum of '%s' times.", erd.diagnosticDebugName,
+//              occurrence, minOccurs, maxOccurs)
+//        }
+//        case _ => // ok
+//      }
+//    }
+//  }
+//}
+//
+//class OptionalCombinatorUnparser(erd: ElementRuntimeData, bodyUnparser: Unparser)
+//  extends CombinatorUnparser(erd) {
+//  override def nom = "Optional"
+//  override lazy val childProcessors = Seq(bodyUnparser)
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  def unparse(state: UState) {
+//
+//    state.arrayIndexStack.push(1L) // one-based indexing
+//    state.occursBoundsStack.push(1L)
+//
+//    val event = state.inspectOrError
+//    Assert.invariant(event.isStart && !event.node.isInstanceOf[DIArray])
+//
+//    bodyUnparser.unparse1(state)
+//
+//    state.arrayIndexStack.pop()
+//    state.occursBoundsStack.pop()
+//  }
+//}
 
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
index 7ebc9aa76..bfce1961d 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
@@ -55,8 +55,6 @@ class ElementUnspecifiedLengthUnparser(
 
 trait RepMoveMixin {
   def move(start: UState) {
-    val grIndex = start.groupIndexStack.pop()
-    start.groupIndexStack.push(grIndex + 1)
     val childIndex = start.childIndexStack.pop()
     start.childIndexStack.push(childIndex + 1)
   }
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/LayeredSequenceUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/LayeredSequenceUnparser.scala
index ee456e30f..6240fe104 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/LayeredSequenceUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/LayeredSequenceUnparser.scala
@@ -17,13 +17,14 @@
 
 package org.apache.daffodil.processors.unparsers
 
-import org.apache.daffodil.processors.{ LayerTransformerEv, ModelGroupRuntimeData }
+import org.apache.daffodil.processors.LayerTransformerEv
 import org.apache.daffodil.io.DirectOrBufferedDataOutputStream
+import org.apache.daffodil.processors.SequenceRuntimeData
 
-class LayeredSequenceUnparser(ctxt: ModelGroupRuntimeData,
+class LayeredSequenceUnparser(ctxt: SequenceRuntimeData,
   layerTransformerEv: LayerTransformerEv,
-  childUnparser: Unparser)
-  extends SequenceCombinatorUnparser(ctxt, Vector(childUnparser)) {
+  childUnparser: SequenceChildUnparser)
+  extends OrderedUnseparatedSequenceUnparser(ctxt, Seq(childUnparser)) {
 
   override lazy val runtimeDependencies = Seq(layerTransformerEv)
 
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/NadaUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/NadaUnparser.scala
index eaca97ca5..64d22ddc0 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/NadaUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/NadaUnparser.scala
@@ -21,6 +21,9 @@ import org.apache.daffodil.processors.RuntimeData
 
 class NadaUnparser(override val context: RuntimeData)
   extends PrimUnparser {
+  
+  override def isEmpty = true
+  
   override def toString = "Nada"
 
   override lazy val runtimeDependencies = Nil
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/NilEmptyCombinatorUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/NilEmptyCombinatorUnparsers.scala
index 018a24cad..5481643f0 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/NilEmptyCombinatorUnparsers.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/NilEmptyCombinatorUnparsers.scala
@@ -21,12 +21,12 @@ import org.apache.daffodil.processors.ElementRuntimeData
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.util.Maybe
 
-case class SimpleNilOrEmptyOrValueUnparser(ctxt: ElementRuntimeData,
-  nilUnparser: Unparser, emptyUnparser: Unparser, valueUnparser: Unparser) extends CombinatorUnparser(ctxt) {
+case class SimpleNilOrValueUnparser(ctxt: ElementRuntimeData,
+  nilUnparser: Unparser, valueUnparser: Unparser) extends CombinatorUnparser(ctxt) {
 
   override lazy val runtimeDependencies = Nil
 
-  override lazy val childProcessors = Seq(nilUnparser, emptyUnparser, valueUnparser)
+  override lazy val childProcessors = Seq(nilUnparser, valueUnparser)
 
   def unparse(state: UState): Unit = {
     Assert.invariant(Maybe.WithNulls.isDefined(state.currentInfosetNode))
@@ -39,38 +39,6 @@ case class SimpleNilOrEmptyOrValueUnparser(ctxt: ElementRuntimeData,
     // because _isNilled has not been set yet. Rather than having to deal with
     // suspending, only check isNilled for non-OVC elements.
     if (ctxt.outputValueCalcExpr.isEmpty && inode.isNilled) nilUnparser.unparse1(state)
-    else if (inode.isEmpty) emptyUnparser.unparse1(state)
-    else valueUnparser.unparse1(state)
-  }
-}
-
-case class SimpleNilOrValueUnparser(ctxt: ElementRuntimeData,
-  nilUnparser: Unparser, valueUnparser: Unparser) extends CombinatorUnparser(ctxt) {
-
-  override lazy val runtimeDependencies = Nil
-
-  override lazy val childProcessors = Seq(nilUnparser, valueUnparser)
-
-  def unparse(state: UState): Unit = {
-    Assert.invariant(Maybe.WithNulls.isDefined(state.currentInfosetNode))
-    val inode = state.currentInfosetNode.asSimple
-    // see comment above for why this OVC check is necessary
-    if (ctxt.outputValueCalcExpr.isEmpty && inode.isNilled) nilUnparser.unparse1(state)
-    else valueUnparser.unparse1(state)
-  }
-}
-
-case class SimpleEmptyOrValueUnparser(ctxt: ElementRuntimeData,
-  emptyUnparser: Unparser, valueUnparser: Unparser) extends CombinatorUnparser(ctxt) {
-
-  override lazy val runtimeDependencies = Nil
-
-  override lazy val childProcessors = Seq(emptyUnparser, valueUnparser)
-
-  def unparse(state: UState): Unit = {
-    Assert.invariant(Maybe.WithNulls.isDefined(state.currentInfosetNode))
-    val inode = state.currentInfosetNode.asSimple
-    if (inode.isEmpty) emptyUnparser.unparse1(state)
     else valueUnparser.unparse1(state)
   }
 }
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/OptionalInfixSepUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/OptionalInfixSepUnparser.scala
index 2e8b11d6b..1ddf9f69f 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/OptionalInfixSepUnparser.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/OptionalInfixSepUnparser.scala
@@ -18,10 +18,13 @@
 package org.apache.daffodil.processors.unparsers
 
 import org.apache.daffodil.processors.TermRuntimeData
+import org.apache.daffodil.exceptions.Assert
 
 class OptionalInfixSepUnparser(contextArg: TermRuntimeData,
   sepUnparser: Unparser)
   extends CombinatorUnparser(contextArg) {
+  
+  Assert.invariant(!sepUnparser.isEmpty)
 
   override lazy val runtimeDependencies = Nil
 
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SeparatedSequenceUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SeparatedSequenceUnparsers.scala
new file mode 100644
index 000000000..54a98083d
--- /dev/null
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SeparatedSequenceUnparsers.scala
@@ -0,0 +1,423 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.processors.unparsers
+
+import org.apache.daffodil.equality.TypeEqual
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.processors.{ ElementRuntimeData, SequenceRuntimeData, TermRuntimeData }
+import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
+import org.apache.daffodil.schema.annotation.props.gen.{ SeparatorPosition }
+import org.apache.daffodil.infoset.DIElement
+
+/**
+ * DFDL Spec. section 14.2.3 specifies only a few different behaviors
+ * for separator suppression. Each has an algorithm.
+ */
+sealed trait SeparatorSuppressionAlgorithm extends Serializable {
+
+  /**
+   * Determines if we should suppress a zero length element and
+   * separator.
+   *
+   * Checks if the length is zero if necessary to decide.
+   *
+   * Returns Suppress or IfTrailing when the element is, in fact, zero length,
+   * and the algorithm wants those to be suppressed.
+   * Returns DoNotSuppress otherwise.
+   */
+  def shouldSuppressIfZeroLength(state: UState, infosetElement: DIElement): SeparatorSuppressionAction
+
+  def shouldDoExtraSeparators = false
+
+  def checkArrayPos(state: UState, maxRepeats: Long): Boolean = true
+
+}
+
+object SeparatorSuppressionAlgorithm {
+  type Type = SeparatorSuppressionAlgorithm
+  import SeparatorSuppressionAction._
+
+  object None extends Type {
+    def shouldSuppressIfZeroLength(state: UState, infosetElement: DIElement) = Assert.usageError("not to be called.")
+  }
+  object FixedOrExpression extends Type {
+    def shouldSuppressIfZeroLength(state: UState, infosetElement: DIElement) = DoNotSuppress
+  }
+
+  class SuppressAnyEmpty(zeroLengthDetector: ZeroLengthDetector) extends Type {
+    def shouldSuppressIfZeroLength(state: UState, infosetElement: DIElement) = {
+      val isZL = zeroLengthDetector.isZeroLength(infosetElement)
+      if (isZL) Suppress
+      else DoNotSuppress
+    }
+  }
+
+  trait CheckArrayPosMixin { self: SeparatorSuppressionAlgorithm =>
+    override def checkArrayPos(state: UState, maxRepeats: Long): Boolean = {
+      state.arrayPos <= maxRepeats
+    }
+  }
+
+  class ImplicitSuppressAnyEmpty(zeroLengthDetector: ZeroLengthDetector)
+    extends SuppressAnyEmpty(zeroLengthDetector)
+    with CheckArrayPosMixin
+
+  object ImplicitNeverOrNotPotentiallyTrailing extends Type
+    with CheckArrayPosMixin {
+    def shouldSuppressIfZeroLength(state: UState, infosetElement: DIElement) = DoNotSuppress
+
+    override def shouldDoExtraSeparators = true
+
+  }
+
+  class ImplicitPotentiallyTrailing(zeroLengthDetector: ZeroLengthDetector) extends Type
+    with CheckArrayPosMixin {
+    def shouldSuppressIfZeroLength(state: UState, infosetElement: DIElement) = {
+      val isZL = zeroLengthDetector.isZeroLength(infosetElement)
+      if (isZL) IfTrailing
+      else DoNotSuppress
+    }
+  }
+}
+
+sealed trait SeparatorSuppressionAction extends Serializable
+object SeparatorSuppressionAction {
+  type Type = SeparatorSuppressionAction
+  case object Suppress extends Type
+  case object DoNotSuppress extends Type
+  case object IfTrailing extends Type
+}
+
+trait Separated { self: SequenceChildUnparser =>
+
+  def sep: Unparser
+  def spos: SeparatorPosition
+  def ssp: SeparatorSuppressionPolicy
+  def ssAlgorithm: SeparatorSuppressionAlgorithm
+
+  val childProcessors = Seq(childUnparser, sep)
+}
+
+class ScalarOrderedSeparatedSequenceChildUnparser(
+  childUnparser: Unparser,
+  srd: SequenceRuntimeData,
+  trd: TermRuntimeData,
+  val sep: Unparser,
+  val spos: SeparatorPosition,
+  val ssp: SeparatorSuppressionPolicy,
+  val ssAlgorithm: SeparatorSuppressionAlgorithm)
+  extends SequenceChildUnparser(childUnparser, srd, trd)
+  with Separated {
+
+  override def unparse(state: UState) = childUnparser.unparse1(state)
+}
+
+class RepOrderedSeparatedSequenceChildUnparser(
+  childUnparser: Unparser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData,
+  val sep: Unparser,
+  val spos: SeparatorPosition,
+  val ssp: SeparatorSuppressionPolicy, // need for diagnostics perhaps
+  val ssAlgorithm: SeparatorSuppressionAlgorithm)
+  extends RepeatingChildUnparser(childUnparser, srd, erd)
+  with Separated {
+
+  override def checkArrayPos(state: UState) = ssAlgorithm.checkArrayPos(state, maxRepeats(state))
+}
+
+class OrderedSeparatedSequenceUnparser(
+  rd: SequenceRuntimeData,
+  ssp: SeparatorSuppressionPolicy,
+  spos: SeparatorPosition,
+  sep: Unparser,
+  childUnparsersArg: Seq[SequenceChildUnparser])
+  extends OrderedSequenceUnparserBase(rd, childUnparsersArg) {
+
+  private val childUnparsers = childUnparsersArg.asInstanceOf[Seq[SequenceChildUnparser with Separated]]
+
+  /**
+   * True if requires special treatment in the unparse processing loop, as occurrences
+   * of later sequence children can influence whether possible trailing separators
+   * from earlier sequence children are actually trailing or not.
+   */
+  private type IPT = SeparatorSuppressionAlgorithm.ImplicitPotentiallyTrailing
+
+  private val hasTrailingSeparatorSuppression = {
+    childUnparsers.last.ssAlgorithm.isInstanceOf[IPT]
+  }
+
+  /**
+   * Unparses one occurrence.
+   */
+  protected def unparseOne(
+    unparser: SequenceChildUnparser,
+    trd: TermRuntimeData,
+    state: UState): Unit = {
+
+    if (trd.isRepresented) {
+      if ((spos eq SeparatorPosition.Prefix)) {
+        sep.unparse1(state)
+      } else if ((spos eq SeparatorPosition.Infix) && state.groupPos > 1) {
+        sep.unparse1(state)
+      }
+    }
+
+    unparser.unparse1(state)
+
+    if ((spos eq SeparatorPosition.Postfix) && trd.isRepresented) {
+      sep.unparse1(state)
+    }
+  }
+
+  /**
+   * Unparses a zero-length occurrence, without the separator. This is so that
+   * any statements or other side-effects (discriminators, setVariable, etc.)
+   * will occur.
+   */
+  private def unparseZeroLengthWithoutSeparatorForSideEffect(
+    unparser: SequenceChildUnparser,
+    trd: TermRuntimeData,
+    state: UState): Unit = {
+    //
+    // Unfortunately there's no way to confirm that this produced zero length
+    // because of the possible buffering going on in the unparser.
+    // We'd have to depend on intricate details of the unparser behavior to do this,
+    // and that's unwise from separation-of-concerns perspective.
+    //
+    unparser.unparse1(state)
+  }
+
+  /**
+   * Unparses the separator only.
+   *
+   * Does not deals with infix boundary condition, because
+   * the counting of the potential trailing separators takes
+   * this into account.
+   */
+  private def unparseJustSeparator(state: UState): Unit = {
+    sep.unparse1(state)
+  }
+
+  /**
+   * Returns 1, or 0 if infix separator, and this is the first thing
+   * in the sequence meaning there is no separator for it.
+   *
+   * However, if we're not doing trailing separator suppression, always
+   * returns 0.
+   */
+  private def suppressedTrailingSeparatorIncrement(unparser: SequenceChildUnparser with Separated, state: UState): Int = {
+    Assert.usage(unparser.trd.isRepresented)
+    val notIPT = !unparser.ssAlgorithm.isInstanceOf[IPT]
+    val result =
+      if (notIPT)
+        0
+      else {
+        val infixAndFirst = (spos eq SeparatorPosition.Infix) && state.groupPos == 1
+        if (infixAndFirst)
+          0
+        else
+          1
+      }
+    result
+  }
+
+  /**
+   * Unparses an entire sequence, including both scalar and array/optional children.
+   */
+  protected def unparse(state: UState): Unit = {
+
+    state.groupIndexStack.push(1L) // one-based indexing
+
+    var index = 0
+    var doUnparser = false
+    val limit = childUnparsers.length
+
+    var potentialTrailingSeparatorCount: Int = 0
+
+    // This state var just lets us check some important
+    // invariants about potentially trailing, e.g., once
+    // you hit it, it sticks until the end of the group.
+    //
+    var haveSeenPotentiallyTrailingSeparators = false
+
+    while (index < limit) {
+      val childUnparser = childUnparsers(index)
+      val trd = childUnparser.trd
+
+      //
+      // Unparsing an ordered sequence depends on the incoming
+      // stream of infoset events matching up with the order that
+      // they are expected as the unparser recurses through the
+      // child term unparsers.
+      //
+      childUnparser match {
+        case unparser: RepOrderedSeparatedSequenceChildUnparser => {
+          val erd = unparser.erd
+          var numOccurrences = 0
+          val maxReps = unparser.maxRepeats(state)
+          //
+          // The number of occurrances we unparse is always exactly driven
+          // by the number of infoset events for the repeating/optional element.
+          //
+          // For RepUnparser - array/optional case - in all cases we should get a
+          // startArray event. If we don't then
+          // the element must be entirely optional, so we get no events for it
+          // at all.
+          //
+          val ssAlgorithm = unparser.ssAlgorithm
+
+          if (state.inspect) {
+            val ev = state.inspectAccessor
+            val isArray = erd.isArray
+            if (ev.isStart && (isArray || erd.isOptional)) {
+              val eventNQN = ev.node.namedQName
+              if (eventNQN =:= erd.namedQName) {
+
+                //
+                // Note: leaving in some ofthese println, since debugger for unparsing is so inadequate currently.
+                // This is the only way to figure out what is going on.
+                //
+                // System.err.println("Starting unparse of array/opt %s. Array Index Stack is: %s".format(
+                //   erd.namedQName, state.arrayIndexStack))
+                //
+
+                // StartArray for this unparser's array element
+                //
+                unparser.startArray(state)
+                while ({
+                  doUnparser = unparser.shouldDoUnparser(unparser, state)
+                  doUnparser
+                }) {
+                  val suppressionAction =
+                    ssAlgorithm.shouldSuppressIfZeroLength(
+                      state,
+                      state.inspectAccessor.asElement)
+                  import SeparatorSuppressionAction._
+                  suppressionAction match {
+                    case DoNotSuppress => {
+                      //
+                      // If there are pending potentially trailing separators,
+                      // then we've just proven that they are NOT actually trailing
+                      // So we output them all.
+                      //
+                      while (potentialTrailingSeparatorCount > 0) {
+                        Assert.invariant(haveSeenPotentiallyTrailingSeparators)
+                        Assert.invariant(ssAlgorithm.isInstanceOf[IPT]) // sticks once we hit one
+                        unparseJustSeparator(state)
+                        potentialTrailingSeparatorCount -= 1
+                      }
+
+                      if (state.dataProc.isDefined) state.dataProc.get.beforeRepetition(state, this)
+                      // System.err.println("Starting unparse of occurrence of %s. Array Index Stack is: %s".format(
+                      //   erd.namedQName, state.arrayIndexStack))
+
+                      unparseOne(unparser, erd, state)
+                      numOccurrences += 1
+
+                      state.moveOverOneArrayIndexOnly()
+                      // System.err.println("Finished unparse of occurrence of %s. Array Index Stack is: %s".format(
+                      //   erd.namedQName, state.arrayIndexStack))
+
+                      state.moveOverOneGroupIndexOnly() // array elements are always represented.
+
+                      if (state.dataProc.isDefined) state.dataProc.get.afterRepetition(state, this)
+                    }
+                    case Suppress => {
+                      unparseZeroLengthWithoutSeparatorForSideEffect(unparser, trd, state)
+                      state.moveOverOneArrayIndexOnly()
+                      state.moveOverOneGroupIndexOnly() // array elements are always represented.
+                    }
+                    case IfTrailing => {
+                      Assert.invariant(hasTrailingSeparatorSuppression)
+                      haveSeenPotentiallyTrailingSeparators = true // sticks once we've hit one.
+                      unparseZeroLengthWithoutSeparatorForSideEffect(unparser, trd, state)
+                      state.moveOverOneArrayIndexOnly()
+                      state.moveOverOneGroupIndexOnly() // array elements are always represented
+                      potentialTrailingSeparatorCount += suppressedTrailingSeparatorIncrement(unparser, state)
+                    }
+                  }
+                }
+                //
+                // For maxOccurs bounded, and never or not potentially trailing
+                //
+                if (ssAlgorithm.shouldDoExtraSeparators && maxReps > numOccurrences) {
+                  var numExtraSeps = erd.maxOccurs - numOccurrences
+                  while (numExtraSeps > 0) {
+                    unparseJustSeparator(state)
+                    numExtraSeps -= 1
+                  }
+                }
+                // System.err.println("Finished unparse of array/opt %s. Array Index Stack is: %s, maxReps %s, numOccurrences %s".format(
+                //   erd.namedQName, state.arrayIndexStack, maxReps, numOccurrences))
+                unparser.checkOccursCount(state, unparser, numOccurrences, maxReps)
+                unparser.endArray(erd, state)
+              } else {
+                //
+                // start array for some other array. Not this one. So we
+                // don't unparse anything here, and we'll go on to the next
+                // sequence child, which hopefully will be a matching array.
+                //
+                Assert.invariant(erd.minOccurs == 0L)
+              }
+
+            } else if (ev.isStart) {
+              Assert.invariant(!ev.erd.isArray && !erd.isOptional)
+              //
+              // start of scalar.
+              // That has to be for a different element later in the sequence
+              // since this one has a RepUnparser (i.e., is NOT scalar)
+              val eventNQN = ev.node.namedQName
+              Assert.invariant(eventNQN != erd.namedQName)
+            } else {
+              //              if (!(ev.isEnd && ev.isComplex))
+              //                Assert.invariantFailed("Expected end of complex. Was " + ev)
+              // System.err.println("End event: " + ev)
+            }
+          } else {
+            // no event (state.inspect returned false)
+            Assert.invariantFailed("No event for unparsing.")
+          }
+        }
+        //
+        case scalarUnparser => {
+          //
+          // Note that once we've encountered a trailing separator situation,
+          // all subsequent sequence children must also be that, otherwise
+          // the first one wouldn't have been in trailing position to begin with.
+          //
+          // So that means we can never find ourself encountering
+          // a need to output potentially trailing separators here.
+          //
+          Assert.invariant(!haveSeenPotentiallyTrailingSeparators)
+          Assert.invariant(potentialTrailingSeparatorCount == 0)
+          unparseOne(scalarUnparser, trd, state)
+          // only move over in group if the scalar "thing" is an element
+          // that is represented.
+          trd match {
+            case erd: ElementRuntimeData if (!erd.isRepresented) => // ok, skip group advance
+            case _ => state.moveOverOneGroupIndexOnly()
+          }
+        }
+      }
+      index += 1
+    }
+    state.groupIndexStack.pop()
+  }
+
+}
+
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceChildUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceChildUnparsers.scala
new file mode 100644
index 000000000..ed6af85cb
--- /dev/null
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceChildUnparsers.scala
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.processors.unparsers
+
+import org.apache.daffodil.processors.Success
+import org.apache.daffodil.processors.SequenceRuntimeData
+import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.processors.TermRuntimeData
+import org.apache.daffodil.api.ValidationMode
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DIArray
+import org.apache.daffodil.equality._
+import org.apache.daffodil.processors.parsers.MinMaxRepeatsMixin
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
+
+/**
+ * base for unparsers for the children of sequences.
+ *
+ * There is one sequence child unparser for each child (declared) of the sequence.
+ *
+ * These do not iterate over multiple recurring instances. That iteration happens
+ * in the caller. These unparse only a single occurrence when the child unparser
+ * is for an array/optional element.
+ */
+abstract class SequenceChildUnparser(
+  val childUnparser: Unparser,
+  val srd: SequenceRuntimeData,
+  val trd: TermRuntimeData)
+  extends CombinatorUnparser(srd) {
+
+  override def runtimeDependencies = Nil
+}
+
+/**
+ * Base for unparsers of array/optional elements.
+ *
+ * The unparse() method unparses exactly one occurrance, does NOT iterate over
+ * all the occurrences.
+ */
+abstract class RepeatingChildUnparser(
+  override val childUnparser: Unparser,
+  override val srd: SequenceRuntimeData,
+  val erd: ElementRuntimeData)
+  extends SequenceChildUnparser(childUnparser, srd, erd)
+  with MinMaxRepeatsMixin {
+
+  /**
+   * Unparse exactly one occurrence of an array/optional element.
+   *
+   * Iterating for arrays/optionals is done in the caller.
+   */
+  override protected def unparse(state: UState): Unit = {
+    childUnparser.unparse1(state)
+  }
+
+  override lazy val runtimeDependencies = Nil
+
+  override def toString = "RepUnparser(" + childUnparser.toString + ")"
+
+  override def toBriefXML(depthLimit: Int = -1): String = {
+    if (depthLimit == 0) "..." else
+      "<RepUnparser name='" + erd.name + "'>" + childUnparser.toBriefXML(depthLimit - 1) +
+        "</RepUnparser>"
+  }
+
+  /**
+   * Sets up for the start of an array. Pulls an event, which must be a start-array
+   * event.
+   */
+  def startArray(state: UState): Unit = {
+    //
+    // The Infoset events don't create an array start/end event for a
+    // truly optional (0..1) element.
+    //
+    // But an expression might still refer to dfdl:occursIndex() and we want that
+    // to be 1, not wherever an enclosing parent array is.
+    //
+    state.arrayIndexStack.push(1L) // one-based indexing
+
+    val ev = state.inspectAccessor
+    if (ev.erd.isArray) {
+      // only pull start array event for a true array, not an optional.
+      val event = state.advanceOrError
+      Assert.invariant(event.isStart && event.node.isInstanceOf[DIArray])
+      // pull the next event, so that nothing else sees or deals with array start events
+      state.inspect
+    }
+  }
+
+  /**
+   * Ends an array. Pulls an event which must be an end-array event.
+   * Validates array dimensions if validation has been requested.
+   */
+  def endArray(currentArrayERD: ElementRuntimeData, state: UState): Unit = {
+    if (currentArrayERD.isArray) {
+      // only pull end array event for a true array, not an optional
+      val event = state.advanceOrError
+      if (!(event.isEnd && event.node.isInstanceOf[DIArray])) {
+        UE(state, "Expected array end event for %s, but received %s.", erd.namedQName, event)
+      }
+    }
+
+    // However, we pop the arrayIndexStack for either true arrays or optionals.
+    val actualOccurs = state.arrayIndexStack.pop()
+
+    if (state.processorStatus ne Success) return
+
+    val shouldValidate =
+      state.dataProc.isDefined && state.dataProc.value.getValidationMode != ValidationMode.Off
+
+    if (shouldValidate) {
+      val minO = erd.minOccurs
+      val maxO = erd.maxOccurs
+      val isUnbounded = maxO == -1
+      val occurrence = actualOccurs - 1
+
+      if (isUnbounded && occurrence < minO)
+        state.validationError("%s occurred '%s' times when it was expected to be a " +
+          "minimum of '%s' and a maximum of 'UNBOUNDED' times.", erd.diagnosticDebugName,
+          occurrence, minO)
+      else if (!isUnbounded && (occurrence < minO || occurrence > maxO))
+        state.validationError("%s occurred '%s' times when it was expected to be a " +
+          "minimum of '%s' and a maximum of '%s' times.", erd.diagnosticDebugName,
+          occurrence, minO, maxO)
+      else {
+        //ok
+      }
+    }
+  }
+
+  /**
+   * Determines if the incoming event matches the current term, so we
+   * should run its unparser.
+   *
+   * If the term is an element and the event is a start element,
+   * then true if the incoming element event namedQName matches the expected element namedQName.
+   * Always true if the term is a model-group and the event is a start element.
+   * If the event is not a start, it must be an endArray for the enclosing complex element, and
+   * the answer is false.
+   */
+  def shouldDoUnparser(unparser: RepeatingChildUnparser, state: UState): Boolean = {
+    val childRD = unparser.trd
+    val res =
+      childRD match {
+        case erd: ElementRuntimeData => {
+          // check to see if we have a matching
+          // incoming infoset event
+          if (state.inspect) {
+            val ev = state.inspectAccessor
+            if (ev.isStart) {
+              val eventNQN = ev.node.namedQName
+              if (eventNQN =:= erd.namedQName) {
+                true
+              } else {
+                // System.err.println("Stopping occurrences(1) of %s due to event %s".format(erd.namedQName, ev))
+                false // event not a start for this element
+              }
+            } else if (ev.isEnd && ev.isComplex) {
+              val c = ev.asComplex
+              //ok. We've peeked ahead and found the end of the complex element
+              //that this sequence is the model group of.
+              val optParentRD = srd.immediateEnclosingElementRuntimeData
+              // FIXME: there's no reason to walk backpointer to immediateEnclosingElementRuntimeData
+              // as we just want that element's name, and we could precompute that and
+              // include it on the SequenceChildUnparser for this
+              optParentRD match {
+                case Some(e: ElementRuntimeData) => {
+                  Assert.invariant(c.runtimeData.namedQName =:= e.namedQName)
+                  // System.err.println("Stopping occurrences(2) of %s due to event %s".format(erd.namedQName, ev))
+                  false
+                }
+                case _ =>
+                  Assert.invariantFailed("Not end element for this sequence's containing element. Event %s, optParentRD %s.".format(
+                    ev, optParentRD))
+              }
+            } else {
+              // end of simple element. We shouldUnparse on the start event.
+              // System.err.println("Stopping occurrences(3) of %s due to event %s".format(erd.namedQName, ev))
+              false
+            }
+          } else {
+            // was no event, so no unparse
+            // System.err.println("Stopping occurrences of(4) %s due to No infoset event".format(erd.namedQName))
+            false
+          }
+        }
+        case _ => {
+          // since only elements can be optional, anything else is non-optional
+          true
+        }
+      }
+    val chk: Boolean =
+      if (res) {
+        val check = unparser.checkArrayPos(state)
+        if (!check) {
+          // System.err.println("Stopping occurrences(5) of %s due to array pos %s".format(erd.namedQName, state.arrayPos))
+        }
+        check
+      } else
+        false
+    chk
+  }
+
+  /**
+   * True if arrayPos is less than maxOccurs, but only if we care about
+   * maxOccurs. Always true if occursCountKind is not one where we
+   * bound occurrences with maxOccurs.
+   *
+   */
+  def checkArrayPos(state: UState) = true
+
+  /**
+   * For OccursCountKind 'implicit', we need to check for arrayPos in range
+   * and enforce the min/maxOccurs bounds.
+   */
+  def checkOccursCount(state: UState,
+    unparser: RepeatingChildUnparser,
+    numOccurrences: Int, maxReps: Long): Unit = {
+    import OccursCountKind._
+
+    val minReps = unparser.minRepeats(state)
+    val ev = state.inspectAccessor
+    val erd = unparser.erd
+
+    if (numOccurrences < minReps) {
+      //
+      // Defaultable feature not yet implemented.
+      //
+      // Assert.invariant(!erd.isDefaultable) // should have handled this elsewhere
+      //
+      UE(state, "Expected %s additional %s elements, but received %s.", minReps - numOccurrences, erd.namedQName, ev)
+    }
+    //
+    // Now if there is an unspecified number of occurrences
+    // and we're supposed to respect min and maxOccurs
+    // (Per DFDL Spec 16.1)
+    //
+    val ock = erd.maybeOccursCountKind.get
+    // System.err.println("Checking for events consistent with Array index:\n ==> Array Index Stack is:" + state.arrayIndexStack)
+    val arrPos = state.arrayPos - 1 // because we advance after each unparse so this is the position of the next (non-existing) occurrence
+
+    Assert.invariant(arrPos <= maxReps || !(ock eq Implicit))
+
+    //
+    // check that if we could consume more (didn't end due to maxReps)
+    // Then we ended with whatever's next NOT being another occurrence of this
+    // same element.
+    //
+    if (arrPos < maxReps &&
+      minReps < maxReps &&
+      (ock ne Implicit)) {
+      if (state.inspect) {
+        val ev = state.inspectAccessor
+        if (ev.isStart && ev.node.namedQName == erd)
+          // This is the error we get if there are more events in the infoset event stream
+          // for an array, than are allowed by maxOccurs.
+          UE(state, "More than maxOccurs %s occurrences of %s in Infoset input: Expected no more events for %s, but received %s.", maxReps, erd.namedQName, ev)
+      }
+    }
+  }
+}
+
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceUnparserBases.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceUnparserBases.scala
new file mode 100644
index 000000000..ebb9afced
--- /dev/null
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceUnparserBases.scala
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.processors.unparsers
+
+import org.apache.daffodil.processors.Evaluatable
+import org.apache.daffodil.processors.SequenceRuntimeData
+import org.apache.daffodil.exceptions.Assert
+
+abstract class OrderedSequenceUnparserBase(srd: SequenceRuntimeData, childUnparsers: Seq[SequenceChildUnparser])
+  extends CombinatorUnparser(srd) {
+
+  override def nom = "Sequence"
+
+  override lazy val runtimeDependencies: Seq[Evaluatable[AnyRef]] = Nil
+
+  override lazy val childProcessors = childUnparsers
+
+  // Sequences of nothing (no initiator, no terminator, nothing at all) should
+  // have been optimized away
+  Assert.invariant(childUnparsers.length > 0)
+
+  // Since some of the grammar terms might have folded away to EmptyGram,
+  // the number of unparsers here may be different from the number of
+  // children of the sequence group.
+  Assert.invariant(srd.groupMembers.length >= childUnparsers.length - 1) // minus 1 for the separator unparser
+}
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceUnparsers.scala
new file mode 100644
index 000000000..1579a58fc
--- /dev/null
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SequenceUnparsers.scala
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//
+//package org.apache.daffodil.processors.unparsers
+//
+//import org.apache.daffodil.processors.Evaluatable
+//import org.apache.daffodil.processors.ElementRuntimeData
+//import org.apache.daffodil.processors.RuntimeData
+//import org.apache.daffodil.processors.Processor
+//import org.apache.daffodil.schema.annotation.props.gen.SeparatorPosition
+//import org.apache.daffodil.exceptions.Assert
+//import org.apache.daffodil.equality._
+//import org.apache.daffodil.processors.SequenceRuntimeData
+//import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
+//import org.apache.daffodil.processors.TermRuntimeData
+//
+//sealed abstract class OrderedSequenceUnparserBase(ctxt: SequenceRuntimeData, childUnparsers: Seq[Unparser])
+//  extends CombinatorUnparser(ctxt) {
+//  override def nom = "Sequence"
+//
+//  // Sequences of nothing (no initiator, no terminator, nothing at all) should
+//  // have been optimized away
+//  Assert.invariant(childUnparsers.length > 0)
+//
+//  // Since some of the grammar terms might have folded away to EmptyGram,
+//  // the number of unparsers here may be different from the number of
+//  // children of the sequence group.
+//  Assert.invariant(ctxt.groupMembers.length >= childUnparsers.length - 1) // minus 1 for the separator unparser
+//
+//  override lazy val childProcessors: Seq[Processor] = childUnparsers
+//
+//  def unparse(start: UState): Unit = {
+//
+//    start.groupIndexStack.push(1L) // one-based indexing
+//    unparseChildren(start)
+//    start.groupIndexStack.pop()
+//    //
+//    // this is establishing the invariant that unparsers (in this case the sequence unparser)
+//    // moves over within its containing group. The caller of an unparser does not do this move.
+//    //
+//    start.moveOverOneGroupIndexOnly()
+//  }
+//
+//  protected def unparseChildren(start: UState): Unit
+//
+//  protected final def shouldDoUnparser(childRD: RuntimeData, start: UState): Boolean = {
+//    childRD match {
+//      case erd: ElementRuntimeData if !erd.isRequired => {
+//        // it's not a required element, so we check to see if we have a matching
+//        // incoming infoset event
+//        if (start.inspect) {
+//          val ev = start.inspectAccessor
+//          if (ev.isStart) {
+//            val eventNQN = ev.node.namedQName
+//            if (eventNQN =:= erd.namedQName) {
+//              true
+//            } else {
+//              false // event not a start for this element
+//            }
+//          } else if (ev.isEnd && ev.isComplex) {
+//            val c = ev.asComplex
+//            //ok. We've peeked ahead and found the end of the complex element
+//            //that this sequence is the model group of.
+//            val optParentRD = ctxt.immediateEnclosingElementRuntimeData
+//            optParentRD match {
+//              case Some(e: ElementRuntimeData) => {
+//                Assert.invariant(c.runtimeData.namedQName =:= e.namedQName)
+//                false
+//              }
+//              case _ =>
+//                Assert.invariantFailed("Not end element for this sequence's containing element. Event %s, optParentRD %s.".format(
+//                  ev, optParentRD))
+//            }
+//          } else {
+//            Assert.invariantFailed("Not a start event: " + ev)
+//          }
+//        } else {
+//          // was no element, so no unparse
+//          false
+//        }
+//      }
+//      case _ => {
+//        // since only elements can be optional, anything else is non-optional
+//        true
+//      }
+//    }
+//  }
+//}
+//
+///*
+// * Temporarily these next two classes are identical, but as we break out the separator
+// * functionality from being built into the child unparsers, these will diverge.
+// * The unseparated variant will stay like it is, but the separated one should be
+// * distinct.
+// */
+//class OrderedUnseparatedSequenceUnparser(ctxt: SequenceRuntimeData, childUnparsers: Seq[SequenceChildUnparser])
+//  extends OrderedSequenceUnparserBase(ctxt, childUnparsers) {
+//
+//  override lazy val runtimeDependencies: Seq[Evaluatable[AnyRef]] = Nil
+//
+//  protected def unparseChildren(start: UState): Unit = {
+//
+//    var index = 0
+//    var doUnparser = false
+//    val limit = childUnparsers.length
+//    while (index < limit) {
+//      val childUnparser = childUnparsers(index)
+//      val childRD = childUnparser.context
+//
+//      doUnparser = shouldDoUnparser(childRD, start)
+//
+//      if (doUnparser) {
+//        childUnparser.unparse1(start)
+//      }
+//      index += 1
+//      //
+//      // Note: the invariant is that unparsers move over 1 within their group themselves
+//      // we do not do the moving over here as we are the caller of the unparser.
+//      //
+//    }
+//  }
+//}
+//
+//trait Repeating { self: SequenceChildUnparser => }
+//trait Scalar { self: SequenceChildUnparser => }
+//
+//abstract class SequenceChildUnparser(
+//  val srd: SequenceRuntimeData,
+//  val trd: TermRuntimeData,
+//  override val childProcessors: Seq[Unparser])
+//  extends CombinatorUnparser(trd) {
+//  override def unparse(state: UState): Unit = ???
+//  override def runtimeDependencies = Nil
+//}
+//
+//abstract class UnseparatedSequenceChildUnparser(
+//  srd: SequenceRuntimeData,
+//  trd: TermRuntimeData,
+//  childUnparsers: Seq[Unparser])
+//  extends SequenceChildUnparser(srd, trd, childUnparsers)
+//
+//class ScalarOrderedRequiredUnseparatedSequenceChildUnparser(
+//  childUnparser: Unparser,
+//  srd: SequenceRuntimeData,
+//  trd: TermRuntimeData)
+//  extends UnseparatedSequenceChildUnparser(srd, trd, Seq(childUnparser)) with Scalar
+//
+//class RepOrderedExactlyNUnseparatedSequenceChildUnparser(
+//  childUnparser: Unparser,
+//  srd: SequenceRuntimeData,
+//  erd: ElementRuntimeData)
+//  extends UnseparatedSequenceChildUnparser(srd, erd, Seq(childUnparser)) with Repeating
+//
+//class RepOrderedExactlyTotalOccursCountUnseparatedSequenceChildUnparser(
+//  childUnparser: Unparser,
+//  ocUnparser: Unparser,
+//  srd: SequenceRuntimeData,
+//  erd: ElementRuntimeData)
+//  extends UnseparatedSequenceChildUnparser(srd, erd, Seq(childUnparser)) with Repeating
+//
+//class RepOrderedWithMinMaxUnseparatedSequenceChildUnparser(
+//  childUnparser: Unparser,
+//  srd: SequenceRuntimeData,
+//  erd: ElementRuntimeData)
+//  extends UnseparatedSequenceChildUnparser(srd, erd, Seq(childUnparser)) with Repeating
+//
+//class OrderedSeparatedSequenceUnparser(ctxt: SequenceRuntimeData,
+//  spos: SeparatorPosition,
+//  sep: Unparser,
+//  childUnparsers: Seq[SequenceChildUnparser])
+//  extends OrderedSequenceUnparserBase(ctxt, childUnparsers :+ sep) {
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  protected def unparseChildren(start: UState): Unit = {
+//
+//    var prefixDone = false
+//    var atLeastOneUnparsed = false
+//
+//    var index = 0
+//    var doUnparser = false
+//
+//    val limit = childUnparsers.length
+//    while (index < limit) {
+//      val child = childUnparsers(index)
+//      val trd = child.trd
+//      val childUnparser = child
+//      val childRD = childUnparser.context
+//      doUnparser = shouldDoUnparser(childRD, start)
+//
+//      if (doUnparser) {
+//        // unparse prefix sep if any
+//        if ((spos eq SeparatorPosition.Prefix) && !prefixDone && trd.isRepresented) {
+//          prefixDone = true
+//          sep.unparse1(start)
+//        }
+//        // except for the first position of the group, unparse an infix separator
+//        if (index != 0 && trd.isRequiredScalar && trd.isRepresented) {
+//          sep.unparse1(start)
+//        }
+//        childUnparser.unparse1(start)
+//        if (trd.isRepresented)
+//          atLeastOneUnparsed = true
+//      }
+//      index += 1
+//      if (index == limit && (spos eq SeparatorPosition.Postfix) && atLeastOneUnparsed) {
+//        sep.unparse1(start)
+//      }
+//      //
+//      // Note: the invariant is that unparsers move over 1 within their group themselves
+//      // we do not do the moving over here as we are the caller of the unparser.
+//      //
+//    }
+//  }
+//}
+//
+//abstract class SeparatedSequenceChildUnparser(
+//  srd: SequenceRuntimeData,
+//  trd: TermRuntimeData,
+//  childUnparsers: Seq[Unparser],
+//  val sep: Unparser,
+//  val spos: SeparatorPosition,
+//  val ssp: SeparatorSuppressionPolicy)
+//  extends SequenceChildUnparser(srd, trd, childUnparsers :+ sep)
+//
+//class ScalarOrderedRequiredSeparatedSequenceChildUnparser(
+//  childUnparser: Unparser,
+//  srd: SequenceRuntimeData,
+//  trd: TermRuntimeData,
+//  sep: Unparser,
+//  spos: SeparatorPosition,
+//  ssp: SeparatorSuppressionPolicy)
+//  extends SeparatedSequenceChildUnparser(srd, trd, Seq(childUnparser), sep, spos, ssp) with Scalar
+//
+//class RepOrderedExactlyNSequenceSeparatedChildUnparser(
+//  childUnparser: Unparser,
+//  srd: SequenceRuntimeData,
+//  erd: ElementRuntimeData,
+//  sep: Unparser,
+//  spos: SeparatorPosition,
+//  ssp: SeparatorSuppressionPolicy)
+//  extends SeparatedSequenceChildUnparser(srd, erd, Seq(childUnparser), sep, spos, ssp) with Repeating
+//
+//class RepOrderedExactlyTotalOccursCountSeparatedSequenceChildUnparser(
+//  childUnparser: Unparser,
+//  ocUnparser: Unparser,
+//  srd: SequenceRuntimeData,
+//  erd: ElementRuntimeData,
+//  sep: Unparser,
+//  spos: SeparatorPosition,
+//  ssp: SeparatorSuppressionPolicy)
+//  extends SeparatedSequenceChildUnparser(srd, erd, Seq(childUnparser), sep, spos, ssp) with Repeating
+//
+//class RepOrderedWithMinMaxSeparatedSequenceChildUnparser(
+//  childUnparser: Unparser,
+//  srd: SequenceRuntimeData,
+//  erd: ElementRuntimeData,
+//  sep: Unparser,
+//  spos: SeparatorPosition,
+//  ssp: SeparatorSuppressionPolicy)
+//  extends SeparatedSequenceChildUnparser(srd, erd, Seq(childUnparser), sep, spos, ssp) with Repeating
+//
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLength2.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLength2.scala
index c82c03deb..24f1d73e0 100644
--- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLength2.scala
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/SpecifiedLength2.scala
@@ -391,7 +391,7 @@ sealed trait NeedValueAndTargetLengthMixin {
             paddingLengthInBits
           }
           case c: DIComplex =>
-            ???
+            ??? // FIXME: This code was left incomplete - JIRA DAFFODIL-1952
         }
       } else {
         0L // must be delimited, so we don't pad unless there's a minLength, which
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/UnseparatedSequenceUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/UnseparatedSequenceUnparsers.scala
new file mode 100644
index 000000000..58020b5a5
--- /dev/null
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/UnseparatedSequenceUnparsers.scala
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.processors.unparsers
+
+import org.apache.daffodil.processors.{ SequenceRuntimeData, TermRuntimeData }
+import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.equality._
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
+
+trait Unseparated { self: SequenceChildUnparser =>
+
+  val childProcessors = Seq(childUnparser)
+}
+
+class ScalarOrderedUnseparatedSequenceChildUnparser(
+  childUnparser: Unparser,
+  srd: SequenceRuntimeData,
+  trd: TermRuntimeData)
+  extends SequenceChildUnparser(childUnparser, srd, trd)
+  with Unseparated {
+
+  override protected def unparse(state: UState) = childUnparser.unparse1(state)
+}
+
+class RepOrderedUnseparatedSequenceChildUnparser(
+  childUnparser: Unparser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData)
+  extends RepeatingChildUnparser(childUnparser, srd, erd)
+  with Unseparated {
+
+  private val ock = erd.maybeOccursCountKind.get
+
+  override def checkArrayPos(state: UState): Boolean = {
+    if (ock eq OccursCountKind.Implicit)
+      state.arrayPos <= maxRepeats(state)
+    else
+      true
+  }
+}
+
+class OrderedUnseparatedSequenceUnparser(rd: SequenceRuntimeData, childUnparsers: Seq[SequenceChildUnparser])
+  extends OrderedSequenceUnparserBase(rd, childUnparsers) {
+
+  /**
+   * Unparses one iteration of an array/optional element
+   */
+  protected def unparseOne(
+    unparser: SequenceChildUnparser,
+    trd: TermRuntimeData,
+    state: UState): Unit = {
+
+    unparser.unparse1(state)
+  }
+
+  /**
+   * Unparses an entire sequence, including both scalar and array/optional children.
+   */
+  protected def unparse(state: UState): Unit = {
+
+    state.groupIndexStack.push(1L) // one-based indexing
+
+    var index = 0
+    var doUnparser = false
+    val limit = childUnparsers.length
+    while (index < limit) {
+      val childUnparser = childUnparsers(index)
+      val trd = childUnparser.trd
+
+      //
+      // Unparsing an ordered sequence depends on the incoming
+      // stream of infoset events matching up with the order that
+      // they are expected as the unparser recurses through the
+      // child term unparsers.
+      //
+      childUnparser match {
+        case unparser: RepeatingChildUnparser => {
+          val erd = unparser.erd
+          var numOccurrences = 0
+          val maxReps = unparser.maxRepeats(state)
+          val minReps = unparser.minRepeats(state)
+
+          //
+          // The number of occurrances we unparse is always exactly driven
+          // by the number of infoset events for the repeating/optional element.
+          //
+          // For RepUnparser - array/optional case - in all cases we should get a
+          // startArray event. If we don't then
+          // the element must be entirely optional, so we get no events for it
+          // at all.
+          //
+          if (state.inspect) {
+            val ev = state.inspectAccessor
+            val isArr = ev.isArray
+            if (ev.isStart && (isArr || ev.erd.isOptional)) {
+              val eventNQN = ev.node.namedQName
+              if (eventNQN =:= erd.namedQName) {
+                //
+                // StartArray for this unparser's array element
+                //
+                if (isArr) unparser.startArray(state)
+                while ({
+                  doUnparser = unparser.shouldDoUnparser(unparser, state)
+                  doUnparser
+                }) {
+                  if (isArr) if (state.dataProc.isDefined) state.dataProc.get.beforeRepetition(state, this)
+
+                  unparseOne(unparser, erd, state)
+                  numOccurrences += 1
+                  state.moveOverOneArrayIndexOnly()
+                  state.moveOverOneGroupIndexOnly() // array elements are always represented.
+
+                  if (isArr) if (state.dataProc.isDefined) state.dataProc.get.afterRepetition(state, this)
+                }
+                if (isArr) {
+                  unparser.checkOccursCount(state, unparser, numOccurrences, maxReps)
+                  unparser.endArray(erd, state)
+                }
+              } else {
+                //
+                // start array but not for the expected array,
+                // rather for some other array. Not this one. So we
+                // don't unparse anything here, and we'll go on to the next
+                // sequence child, which hopefully will be a matching array.
+                //
+                // minReps has to be 0, meaning it is allowed to have zero
+                // occurrences (not necessarily valid, but allowed),
+                // because we got zero instances of this array
+                //
+                Assert.invariant(minReps == 0L)
+              }
+            } else if (ev.isStart) {
+              Assert.invariant(!isArr && !ev.erd.isOptional)
+              //
+              // start of scalar.
+              // That has to be for a different element later in the sequence
+              // since this one has a RepUnparser (i.e., is NOT scalar)
+              val eventNQN = ev.node.namedQName
+              Assert.invariant(eventNQN != erd.namedQName)
+            } else {
+              Assert.invariant(ev.isEnd && ev.isComplex)
+            }
+          } else {
+            // no event (state.inspect returned false)
+            Assert.invariantFailed("No event for unparing.")
+          }
+        }
+        //
+        case scalarUnparser => {
+          unparseOne(scalarUnparser, trd, state)
+          // only move over in group if the scalar "thing" is an element
+          // that is represented.
+          scalarUnparser.trd match {
+            case erd: ElementRuntimeData if (!erd.isRepresented) => // ok, skip group advance
+            case _ => state.moveOverOneGroupIndexOnly()
+          }
+        }
+      }
+      index += 1
+      //
+      // Note: the invariant is that unparsers move over 1 within their group themselves
+      // we do not do the moving over here as we are the caller of the unparser.
+      //
+    }
+
+    state.groupIndexStack.pop()
+    //
+    // this is establishing the invariant that unparsers (in this case the sequence unparser)
+    // moves over within its containing group. The caller of an unparser does not do this move.
+    //
+    // state.moveOverOneGroupIndexOnly() // move past this sequence itself, next group child it ITS parent.
+  }
+
+}
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ZeroLengthDetector.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ZeroLengthDetector.scala
new file mode 100644
index 000000000..2e5f64bd5
--- /dev/null
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ZeroLengthDetector.scala
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.processors.unparsers
+
+import org.apache.daffodil.infoset.DIElement
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.infoset.DISimple
+import org.apache.daffodil.dpath.NodeInfo
+
+/**
+ * Rapidly determines if an Infoset Element will have zero length when unparsed.
+ *
+ * This is required for proper separator suppression in sequence unparsers.
+ *
+ * The specific concrete sub-class is selected based on a compile time analysis
+ * of whether the element can have zero length at all, and if so, under
+ * what conditions.
+ */
+sealed trait ZeroLengthDetector
+  extends Serializable {
+  def isZeroLength(diElement: DIElement): Boolean
+}
+
+/**
+ * Applies to both simple and complex types that are nillable.
+ */
+sealed trait NillableZeroLengthMixin { self: ZeroLengthDetector =>
+  protected def isNillableZeroLength(diElement: DIElement): Boolean = {
+    Assert.invariant(diElement.erd.isNillable)
+    diElement.isNilled
+  }
+}
+/**
+ * Use when the characteristics of the nil representation are such that
+ * unparsing a nilled element will result in zero length.
+ */
+class NillableZeroLengthDetector
+  extends ZeroLengthDetector
+  with NillableZeroLengthMixin {
+  override def isZeroLength(diElement: DIElement) = isNillableZeroLength(diElement)
+}
+
+sealed trait StringZeroLengthMixin { self: ZeroLengthDetector =>
+  protected def isStringZeroLength(diElement: DIElement): Boolean = {
+    val opt = diElement.erd.optPrimType
+    Assert.invariant(opt.isDefined & (opt.get eq NodeInfo.String))
+    val result =
+      if (diElement.isNilled)
+        false // must not be zero length nil. If it was zero length nil, we wouldn't be at this code.
+      else {
+        diElement match {
+          case st: DISimple => {
+            Assert.invariant(st.hasValue)
+            val str = st.dataValueAsString
+            val len = str.length()
+            len == 0
+          }
+          case _ => Assert.invariantFailed("Not a simple type")
+        }
+      }
+    result
+  }
+}
+
+/**
+ * Use when the element is of simple type string, not nillable.
+ */
+class StringZeroLengthDetector
+  extends ZeroLengthDetector
+  with StringZeroLengthMixin {
+  override def isZeroLength(diElement: DIElement) = isStringZeroLength(diElement)
+
+}
+
+sealed trait HexBinaryZeroLengthMixin { self: ZeroLengthDetector =>
+  protected def isHexBinaryZeroLength(diElement: DIElement): Boolean = {
+    val opt = diElement.erd.optPrimType
+    Assert.invariant(opt.isDefined & (opt.get eq NodeInfo.HexBinary))
+    val result =
+      if (diElement.isNilled)
+        false // must not be zero length nil. If it was zero length nil, we wouldn't be at this code.
+      else {
+        diElement match {
+          case st: DISimple => {
+            Assert.invariant(st.hasValue)
+            val arr = st.dataValue.asInstanceOf[Array[Byte]]
+            val len = arr.length
+            len == 0
+          }
+          case _ => Assert.invariantFailed("Not a simple type")
+        }
+      }
+    result
+  }
+}
+
+/**
+ * Use when the element is of simple type hexBinary, not nillable.
+ */
+class HexBinaryZeroLengthDetector
+  extends ZeroLengthDetector
+  with HexBinaryZeroLengthMixin {
+  override def isZeroLength(diElement: DIElement) = isHexBinaryZeroLength(diElement)
+}
+
+/**
+ * Use when analysis shows the element can never be zero length.
+ */
+class NeverZeroLengthDetector
+  extends ZeroLengthDetector {
+  override def isZeroLength(diElement: DIElement) = false
+}
+
+/**
+ * Use for nillable strings when they can be zero length two different ways.
+ */
+class NillableStringZeroLengthDetector
+  extends ZeroLengthDetector
+  with NillableZeroLengthMixin
+  with StringZeroLengthMixin {
+  override def isZeroLength(diElement: DIElement) =
+    isStringZeroLength(diElement) ||
+      isNillableZeroLength(diElement)
+}
+
+/**
+ * Use for nillable hexBinary when they can be zero length two different ways.
+ */
+class NillableHexBinaryZeroLengthDetector
+  extends ZeroLengthDetector
+  with NillableZeroLengthMixin
+  with HexBinaryZeroLengthMixin {
+  override def isZeroLength(diElement: DIElement) =
+    isHexBinaryZeroLength(diElement) ||
+      isNillableZeroLength(diElement)
+}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
index 670026ce2..06479573d 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
@@ -197,11 +197,10 @@ class InteractiveDebugger(runner: InteractiveDebuggerRunner, eCompilers: Express
     val interesting = parser match {
       case _: ComplexTypeParser => false
       case _: SeqCompParser => false
-      case _: SequenceCombinatorParser => false
-      case _: AltCompParser => false
-      case _: RepParser => false
+      case _: RepeatingChildParser => false
       case _: OptionalInfixSepParser => false
       case _: ConvertTextCombinatorParser => false
+      case _: CombinatorParser => false
       case _ => true
     }
     interesting
@@ -1181,7 +1180,7 @@ class InteractiveDebugger(runner: InteractiveDebuggerRunner, eCompilers: Express
                         |multiple times to display multiple pieces of information.
                         |
                         |Example: info data infoset""".stripMargin
-      override val subcommands = Seq(InfoArrayIndex, InfoBitLimit, InfoBitPosition, InfoBreakpoints, InfoChildIndex, InfoData, InfoDelimiterStack, InfoDiff, InfoDiscriminator, InfoDisplays, InfoFoundDelimiter, InfoGroupIndex, InfoInfoset, InfoOccursBounds, InfoParser, InfoUnparser, InfoPath)
+      override val subcommands = Seq(InfoArrayIndex, InfoBitLimit, InfoBitPosition, InfoBreakpoints, InfoChildIndex, InfoData, InfoDelimiterStack, InfoDiff, InfoDiscriminator, InfoDisplays, InfoFoundDelimiter, InfoGroupIndex, InfoInfoset, InfoParser, InfoUnparser, InfoPath)
 
       override def validate(args: Seq[String]) {
         if (args.size == 0) {
@@ -1539,17 +1538,17 @@ class InteractiveDebugger(runner: InteractiveDebuggerRunner, eCompilers: Express
         }
       }
 
-      object InfoOccursBounds extends DebugCommand with DebugCommandValidateZeroArgs {
-        val name = "occursBounds"
-        override lazy val short = "ob"
-        val desc = "display the current occurs bounds"
-        val longDesc = desc
-        def act(args: Seq[String], prestate: StateForDebugger, state: ParseOrUnparseState, processor: Processor): DebugState.Type = {
-          if (state.occursBoundsStack.isEmpty) debugPrintln("%s: occurs bounds not set".format(name))
-          else debugPrintln("%s: %d".format(name, state.occursBoundsStack.top))
-          DebugState.Pause
-        }
-      }
+//      object InfoOccursBounds extends DebugCommand with DebugCommandValidateZeroArgs {
+//        val name = "occursBounds"
+//        override lazy val short = "ob"
+//        val desc = "display the current occurs bounds"
+//        val longDesc = desc
+//        def act(args: Seq[String], prestate: StateForDebugger, state: ParseOrUnparseState, processor: Processor): DebugState.Type = {
+//          if (state.occursBoundsStack.isEmpty) debugPrintln("%s: occurs bounds not set".format(name))
+//          else debugPrintln("%s: %d".format(name, state.occursBoundsStack.top))
+//          DebugState.Pause
+//        }
+//      }
 
       abstract class InfoProcessorBase extends DebugCommand with DebugCommandValidateZeroArgs {
         val desc = "display the current Daffodil " + name
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetInputter.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetInputter.scala
index ae2799940..1a941b350 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetInputter.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetInputter.scala
@@ -417,10 +417,7 @@ case object EndKind extends InfosetEventKind { override def toString = "end" }
  */
 class InfosetAccessor private (var kind: InfosetEventKind, var node: DINode) extends Accessor[InfosetAccessor] {
   def namedQName = node.namedQName
-  def erd: ElementRuntimeData = node match {
-    case a: DIArray => a.parent.runtimeData
-    case e: DIElement => e.erd
-  }
+  def erd: ElementRuntimeData = node.erd
 
   override def toString = {
     val evLbl = if (kind eq null) "NullKind" else kind.toString
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorBases.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorBases.scala
index a7db50406..ffc94a109 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorBases.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorBases.scala
@@ -32,6 +32,9 @@ object Processor {
   private def ensureCompiled(proc: Processor) {
     if (!proc.isInitialized) {
       proc.isInitialized = true
+      //      proc.childProcessors.foreach { cp =>
+      //        Assert.invariant(!cp.isEmpty)
+      //      }
       proc.runtimeDependencies.foreach { ensureCompiled }
       proc.childProcessors.foreach { ensureCompiled }
     }
@@ -70,6 +73,8 @@ trait Processor
    * interact with the data stream.
    */
   def isPrimitive: Boolean
+
+  def isEmpty: Boolean
 }
 
 /**
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
index ba76920aa..3d78c3c7f 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
@@ -437,7 +437,7 @@ abstract class ParseOrUnparseState protected (
   def groupPos: Long
   def arrayPos: Long
   def childPos: Long
-  def occursBoundsStack: MStackOfLong
+  //  def occursBoundsStack: MStackOfLong
 
   def hasInfoset: Boolean
 
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/Runtime.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/Runtime.scala
index fa115586e..4b6cadc3c 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/Runtime.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/Runtime.scala
@@ -239,7 +239,7 @@ class DataProcessor(val ssrd: SchemaSetRuntimeData)
       Assert.invariant(state.mpstate.arrayIndexStack.length == 1)
       Assert.invariant(state.mpstate.groupIndexStack.length == 1)
       Assert.invariant(state.mpstate.childIndexStack.length == 1)
-      Assert.invariant(state.mpstate.occursBoundsStack.length == 1)
+      // Assert.invariant(state.mpstate.occursBoundsStack.length == 1)
     } catch {
       // technically, runtime shouldn't throw. It's really too heavyweight a construct. And "failure"
       // when parsing isn't exceptional, it's routine behavior. So ought not be implemented via an
@@ -370,7 +370,7 @@ class DataProcessor(val ssrd: SchemaSetRuntimeData)
     Assert.invariant(state.arrayIndexStack.length == 1)
     Assert.invariant(state.groupIndexStack.length == 1)
     Assert.invariant(state.childIndexStack.length == 1)
-    Assert.invariant(state.occursBoundsStack.length == 1)
+    //    Assert.invariant(state.occursBoundsStack.length == 1)
     Assert.invariant(state.currentInfosetNodeStack.isEmpty)
     Assert.invariant(state.escapeSchemeEVCache.isEmpty)
     //
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
index 7a299982d..17af8881a 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
@@ -55,6 +55,7 @@ import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.util.OKOrError
 import java.util.regex.Matcher
 import org.apache.daffodil.api.DaffodilTunables
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
 
 /*
  * NOTE: Any time you add a member to one of these objects, you must modify at least 3 places.
@@ -129,6 +130,9 @@ sealed abstract class TermRuntimeData(
     case _ => false
   }
 
+  def isRequiredScalar: Boolean
+  def isArray: Boolean
+
   /**
    * At some point TermRuntimeData is a ResolvesQNames which requires tunables:
    *
@@ -618,8 +622,9 @@ final class ElementRuntimeData(
   @TransientParam targetNamespaceArg: => NS,
   @TransientParam thisElementsNamespaceArg: => NS,
   @TransientParam optSimpleTypeRuntimeDataArg: => Option[SimpleTypeRuntimeData],
-  @TransientParam minOccursArg: => Option[Int],
-  @TransientParam maxOccursArg: => Option[Int],
+  @TransientParam minOccursArg: => Long,
+  @TransientParam maxOccursArg: => Long,
+  @TransientParam maybeOccursCountKindArg: => Maybe[OccursCountKind],
   @TransientParam nameArg: => String,
   @TransientParam targetNamespacePrefixArg: => String,
   @TransientParam thisElementsNamespacePrefixArg: => String,
@@ -659,6 +664,8 @@ final class ElementRuntimeData(
     maybeCheckByteAndBitOrderEvArg,
     maybeCheckBitOrderAndCharsetEvArg) {
 
+  override def isRequiredScalar = !isArray && isRequired
+
   lazy val parent = parentArg
   lazy val parentTerm = parentTermArg
   lazy val children = childrenArg
@@ -678,14 +685,15 @@ final class ElementRuntimeData(
   lazy val optSimpleTypeRuntimeData = optSimpleTypeRuntimeDataArg
   lazy val minOccurs = minOccursArg
   lazy val maxOccurs = maxOccursArg
+  lazy val maybeOccursCountKind = maybeOccursCountKindArg
   lazy val name = nameArg
   lazy val targetNamespacePrefix = targetNamespacePrefixArg
   lazy val thisElementsNamespacePrefix = thisElementsNamespacePrefixArg
   lazy val isHidden = isHiddenArg
   lazy val isNillable = isNillableArg
-  lazy val isArray = isArrayArg
+  override lazy val isArray = isArrayArg
   lazy val isOptional = isOptionalArg
-  lazy val isRequired = isRequiredArg
+  lazy val isRequired = isRequiredArg // if true, no uncertainty about number of occurrences.
   lazy val namedQName = namedQNameArg
   lazy val impliedRepresentation = impliedRepresentationArg
   lazy val optDefaultValue = optDefaultValueArg
@@ -715,6 +723,7 @@ final class ElementRuntimeData(
     optSimpleTypeRuntimeData
     minOccurs
     maxOccurs
+    maybeOccursCountKind
     name
     targetNamespacePrefix
     thisElementsNamespacePrefix
@@ -789,6 +798,9 @@ sealed abstract class ModelGroupRuntimeData(
     maybeCheckByteAndBitOrderEvArg,
     maybeCheckBitOrderAndCharsetEvArg) {
 
+  final override def isRequiredScalar = true
+  final override def isArray = false
+
   lazy val variableMap = variableMapArg
   lazy val encInfo = encInfoArg
   lazy val schemaFileLocation = schemaFileLocationArg
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/DelimiterParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/DelimiterParsers.scala
index accad28d0..4b1dc6d52 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/DelimiterParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/DelimiterParsers.scala
@@ -132,7 +132,9 @@ class DelimiterTextParser(
     if (foundDelimiter.isDefined) {
       if (!containsLocalMatch(foundDelimiter.get.matchedDFAs, start)) {
         // It was a remote delimiter but we should have found a local one.
-        PE(start, "Found out of scope delimiter: %s", Misc.remapStringToVisibleGlyphs(foundDelimiter.get.matchedDelimiterValue.get))
+        PE(start, "Found out of scope delimiter: '%s' '%s'",
+          foundDelimiter.get.matchedDFAs(0).lookingFor,
+          Misc.remapStringToVisibleGlyphs(foundDelimiter.get.matchedDelimiterValue.get))
         return
       }
 
@@ -158,7 +160,14 @@ class DelimiterTextParser(
           return
         } else {
           // no match and no ES in delims
-          PE(start, "Delimiter not found.")
+          //
+          // FIXME: this was just doing start.mpstate.delimiters.last, assuming that would be the matching
+          // delim, but it isn't in some tests. It's a terminator when the delimiterType is initiator.
+          //
+          // val optDelim = start.mpstate.delimiters.find{ d => d.delimType == delimiterType }
+          val optDelim = Some(start.mpstate.delimiters.last)
+          Assert.invariant(optDelim.isDefined)
+          PE(start, "%s '%s' not found.", delimiterType.toString, optDelim.get.lookingFor)
           return
         }
       }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementCombinator1.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementCombinator1.scala
index adbc77d6f..08f1f1ccc 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementCombinator1.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementCombinator1.scala
@@ -229,7 +229,6 @@ class ElementParser(
     eAfterParser) {
 
   def move(start: PState) {
-    start.mpstate.moveOverOneGroupIndexOnly
     start.mpstate.moveOverOneElementChildOnly
     ()
   }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementKindParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementKindParsers.scala
index fecd7d61e..147dac948 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementKindParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementKindParsers.scala
@@ -17,16 +17,8 @@
 
 package org.apache.daffodil.processors.parsers
 
-import org.apache.daffodil.api.ValidationMode
-import org.apache.daffodil.processors.ChoiceDispatchKeyEv
-import org.apache.daffodil.processors.DelimiterParseEv
-import org.apache.daffodil.processors.ElementRuntimeData
-import org.apache.daffodil.processors.EscapeSchemeParseEv
-import org.apache.daffodil.processors.RuntimeData
-import org.apache.daffodil.processors.Success
+import org.apache.daffodil.processors._
 import org.apache.daffodil.util.LogLevel
-import org.apache.daffodil.processors.TermRuntimeData
-import org.apache.daffodil.processors.Evaluatable
 
 class ComplexTypeParser(rd: RuntimeData, bodyParser: Parser)
   extends CombinatorParser(rd) {
@@ -120,43 +112,6 @@ class DynamicEscapeSchemeParser(escapeScheme: EscapeSchemeParseEv,
   }
 }
 
-class SequenceCombinatorParser(rd: TermRuntimeData, bodyParser: Parser)
-  extends CombinatorParser(rd) {
-  override def nom = "Sequence"
-
-  override lazy val runtimeDependencies: Seq[Evaluatable[AnyRef]] = Nil
-
-  override lazy val childProcessors = Seq(bodyParser)
-
-  def parse(start: PState): Unit = {
-    start.mpstate.groupIndexStack.push(1L) // one-based indexing
-
-    bodyParser.parse1(start)
-
-    start.mpstate.groupIndexStack.pop()
-    start.mpstate.moveOverOneGroupIndexOnly()
-    ()
-  }
-}
-
-/**
- * This is essentially just a wrapper around the bodyParser, which is an
- * AltCompParser. This is only here to maintain symmetry with the unparse side,
- * which has a more complicated unparser that differs from an AltCompUnparser.
- */
-class ChoiceCombinatorParser(rd: TermRuntimeData, bodyParser: Parser)
-  extends CombinatorParser(rd) {
-  override def nom = "Choice"
-
-  override lazy val runtimeDependencies = Nil
-
-  override lazy val childProcessors = Seq(bodyParser)
-
-  def parse(start: PState): Unit = {
-    bodyParser.parse1(start)
-  }
-}
-
 class ChoiceDispatchCombinatorParser(rd: TermRuntimeData, dispatchKeyEv: ChoiceDispatchKeyEv, dispatchBranchKeyMap: Map[String, Parser])
   extends CombinatorParser(rd) {
   override def nom = "ChoiceDispatch"
@@ -197,50 +152,50 @@ class ChoiceDispatchCombinatorParser(rd: TermRuntimeData, dispatchKeyEv: ChoiceD
   }
 }
 
-class ArrayCombinatorParser(erd: ElementRuntimeData, bodyParser: Parser)
-  extends CombinatorParser(erd) {
-  override def nom = "Array"
-  override lazy val childProcessors = Seq(bodyParser)
-
-  override lazy val runtimeDependencies = Nil
-
-  def parse(start: PState): Unit = {
-
-    start.mpstate.arrayIndexStack.push(1L) // one-based indexing
-    start.mpstate.occursBoundsStack.push(start.tunable.maxOccursBounds)
-
-    bodyParser.parse1(start)
-
-    val actualOccurs = start.mpstate.arrayIndexStack.pop()
-    start.mpstate.occursBoundsStack.pop()
-
-    if (start.processorStatus ne Success) return
-
-    val shouldValidate =
-      start.dataProc.isDefined && start.dataProc.value.getValidationMode != ValidationMode.Off
-
-    if (shouldValidate && erd.minOccurs.isDefined && erd.maxOccurs.isDefined) {
-      val minO = erd.minOccurs.get
-      val maxO = erd.maxOccurs.get
-      val isUnbounded = maxO == -1
-      val occurrence = actualOccurs - 1
-
-      if (isUnbounded && occurrence < minO)
-        start.validationError("%s occurred '%s' times when it was expected to be a " +
-          "minimum of '%s' and a maximum of 'UNBOUNDED' times.", erd.diagnosticDebugName,
-          occurrence, minO)
-      else if (!isUnbounded && (occurrence < minO || occurrence > maxO))
-        start.validationError("%s occurred '%s' times when it was expected to be a " +
-          "minimum of '%s' and a maximum of '%s' times.", erd.diagnosticDebugName,
-          occurrence, minO, maxO)
-      else {
-        //ok
-      }
-    }
-  }
-}
-
-// This follows the same behavior as Arrays for parsing
-class OptionalCombinatorParser(erd: ElementRuntimeData, bodyParser: Parser) extends ArrayCombinatorParser(erd, bodyParser) {
-  override def nom = "Optional"
-}
+//class ArrayCombinatorParser(erd: ElementRuntimeData, bodyParser: Parser)
+//  extends CombinatorParser(erd) {
+//  override def nom = "Array"
+//  override lazy val childProcessors = Seq(bodyParser)
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  def parse(start: PState): Unit = {
+//
+//    start.mpstate.arrayIndexStack.push(1L) // one-based indexing
+//    start.mpstate.occursBoundsStack.push(start.tunable.maxOccursBounds)
+//
+//    bodyParser.parse1(start)
+//
+//    val actualOccurs = start.mpstate.arrayIndexStack.pop()
+//    start.mpstate.occursBoundsStack.pop()
+//
+//    if (start.processorStatus ne Success) return
+//
+//    val shouldValidate =
+//      start.dataProc.isDefined && start.dataProc.value.getValidationMode != ValidationMode.Off
+//
+//    if (shouldValidate && erd.minOccurs.isDefined && erd.maxOccurs.isDefined) {
+//      val minO = erd.minOccurs.get
+//      val maxO = erd.maxOccurs.get
+//      val isUnbounded = maxO == -1
+//      val occurrence = actualOccurs - 1
+//
+//      if (isUnbounded && occurrence < minO)
+//        start.validationError("%s occurred '%s' times when it was expected to be a " +
+//          "minimum of '%s' and a maximum of 'UNBOUNDED' times.", erd.diagnosticDebugName,
+//          occurrence, minO)
+//      else if (!isUnbounded && (occurrence < minO || occurrence > maxO))
+//        start.validationError("%s occurred '%s' times when it was expected to be a " +
+//          "minimum of '%s' and a maximum of '%s' times.", erd.diagnosticDebugName,
+//          occurrence, minO, maxO)
+//      else {
+//        //ok
+//      }
+//    }
+//  }
+//}
+//
+//// This follows the same behavior as Arrays for parsing
+//class OptionalCombinatorParser(erd: ElementRuntimeData, bodyParser: Parser) extends ArrayCombinatorParser(erd, bodyParser) {
+//  override def nom = "Optional"
+//}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/LayeredSequenceParser.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/LayeredSequenceParser.scala
index 1d23a1257..8522217a0 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/LayeredSequenceParser.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/LayeredSequenceParser.scala
@@ -17,13 +17,13 @@
 
 package org.apache.daffodil.processors.parsers
 
-import org.apache.daffodil.processors.TermRuntimeData
+import org.apache.daffodil.processors.SequenceRuntimeData
 import org.apache.daffodil.processors.LayerTransformerEv
 
-class LayeredSequenceParser(rd: TermRuntimeData,
+class LayeredSequenceParser(rd: SequenceRuntimeData,
   layerTransformerEv: LayerTransformerEv,
-  bodyParser: Parser)
-  extends SequenceCombinatorParser(rd, bodyParser) {
+  bodyParser: SequenceChildParser)
+  extends OrderedUnseparatedSequenceParser(rd, Seq(bodyParser)) {
   override def nom = "LayeredSequence"
 
   override lazy val runtimeDependencies = Seq(layerTransformerEv)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/NilEmptyCombinatorParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/NilEmptyCombinatorParsers.scala
index 77ff2a651..4e9766afc 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/NilEmptyCombinatorParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/NilEmptyCombinatorParsers.scala
@@ -19,14 +19,8 @@ package org.apache.daffodil.processors.parsers
 
 import org.apache.daffodil.processors.TermRuntimeData
 
-case class SimpleNilOrEmptyOrValueParser(ctxt: TermRuntimeData, nilParser: Parser, emptyParser: Parser, valueParser: Parser)
-  extends AltCompParser(ctxt, Seq(nilParser, emptyParser, valueParser))
-
 case class SimpleNilOrValueParser(ctxt: TermRuntimeData, nilParser: Parser, valueParser: Parser)
-  extends AltCompParser(ctxt, Seq(nilParser, valueParser))
-
-case class SimpleEmptyOrValueParser(ctxt: TermRuntimeData, emptyParser: Parser, valueParser: Parser)
-  extends AltCompParser(ctxt, Seq(emptyParser, valueParser))
+  extends ChoiceParser(ctxt, Seq(nilParser, valueParser))
 
 case class ComplexNilOrContentParser(ctxt: TermRuntimeData, emptyParser: Parser, contentParser: Parser)
-  extends AltCompParser(ctxt, Seq(emptyParser, contentParser))
+  extends ChoiceParser(ctxt, Seq(emptyParser, contentParser))
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/OptionalInfixSepParser.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/OptionalInfixSepParser.scala
index e9584df95..d37cd51db 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/OptionalInfixSepParser.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/OptionalInfixSepParser.scala
@@ -18,10 +18,13 @@
 package org.apache.daffodil.processors.parsers
 
 import org.apache.daffodil.processors.TermRuntimeData
+import org.apache.daffodil.exceptions.Assert
 
 class OptionalInfixSepParser(ctxt: TermRuntimeData, sepParser: Parser)
   extends CombinatorParser(ctxt) {
 
+  Assert.invariant(!sepParser.isEmpty)
+
   override lazy val nom = "OptionalInfixSep"
   override lazy val childProcessors = Seq(sepParser)
   override lazy val runtimeDependencies = Nil
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
index 205f2f3c7..6efcf09df 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
@@ -28,10 +28,8 @@ import org.apache.daffodil.api.DataLocation
 import org.apache.daffodil.api.Diagnostic
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.infoset.DIComplex
-import org.apache.daffodil.infoset.DIComplexState
 import org.apache.daffodil.infoset.DIElement
 import org.apache.daffodil.infoset.DISimple
-import org.apache.daffodil.infoset.DISimpleState
 import org.apache.daffodil.infoset.Infoset
 import org.apache.daffodil.infoset.InfosetDocument
 import org.apache.daffodil.infoset.InfosetOutputter
@@ -60,6 +58,8 @@ import org.apache.daffodil.util.Maybe.One
 import org.apache.daffodil.util.MaybeULong
 import org.apache.daffodil.util.Pool
 import org.apache.daffodil.util.Poolable
+import org.apache.daffodil.infoset.DIComplexState
+import org.apache.daffodil.infoset.DISimpleState
 
 object MPState {
 
@@ -89,13 +89,13 @@ object MPState {
       arrayIndexStackMark = mp.arrayIndexStack.mark
       groupIndexStackMark = mp.groupIndexStack.mark
       childIndexStackMark = mp.childIndexStack.mark
-      occursBoundsStackMark = mp.occursBoundsStack.mark
+      // occursBoundsStackMark = mp.occursBoundsStack.mark
     }
     def restoreInto(mp: MPState) {
       mp.arrayIndexStack.reset(this.arrayIndexStackMark)
       mp.groupIndexStack.reset(this.groupIndexStackMark)
       mp.childIndexStack.reset(this.childIndexStackMark)
-      mp.occursBoundsStack.reset(this.occursBoundsStackMark)
+      // mp.occursBoundsStack.reset(this.occursBoundsStackMark)
     }
   }
 }
@@ -104,6 +104,8 @@ class MPState private () {
 
   val arrayIndexStack = MStackOfLong()
   def moveOverOneArrayIndexOnly() = arrayIndexStack.push(arrayIndexStack.pop + 1)
+  def moveBackOneArrayIndexOnly() = arrayIndexStack.push(arrayIndexStack.pop - 1)
+
   def arrayPos = arrayIndexStack.top
 
   val groupIndexStack = MStackOfLong()
@@ -114,25 +116,32 @@ class MPState private () {
   // stack. Can we get rid of it?
   val childIndexStack = MStackOfLong()
   def moveOverOneElementChildOnly() = childIndexStack.push(childIndexStack.pop + 1)
-  def childPos = childIndexStack.top
-
-  val occursBoundsStack = MStackOfLong()
-  def updateBoundsHead(ob: Long) = {
-    occursBoundsStack.pop()
-    occursBoundsStack.push(ob)
+  def childPos = {
+    val res = childIndexStack.top
+    Assert.invariant(res >= 1)
+    res
   }
-  def occursBounds = occursBoundsStack.top
+
+  //  val occursBoundsStack = MStackOfLong()
+  //  def updateBoundsHead(ob: Long) = {
+  //    occursBoundsStack.pop()
+  //    occursBoundsStack.push(ob)
+  //  }
+  //  def occursBounds = occursBoundsStack.top
 
   val delimiters = new mutable.ArrayBuffer[DFADelimiter]
   val delimitersLocalIndexStack = MStackOfInt()
 
   val escapeSchemeEVCache = new MStackOfMaybe[EscapeSchemeParserHelper]
 
+  //var wasAnyArrayElementNonZeroLength = false
+  //var wasLastArrayElementZeroLength = true
+
   private def init {
     arrayIndexStack.push(1L)
     groupIndexStack.push(1L)
     childIndexStack.push(1L)
-    occursBoundsStack.push(1L)
+    // occursBoundsStack.push(1L)
     delimitersLocalIndexStack.push(-1)
   }
 }
@@ -172,7 +181,7 @@ final class PState private (
   override def groupPos = mpstate.groupPos
   override def arrayPos = mpstate.arrayPos
   override def childPos = mpstate.childPos
-  override def occursBoundsStack = mpstate.occursBoundsStack
+  // override def occursBoundsStack = mpstate.occursBoundsStack
 
   private val markPool = new PState.MarkPool
 
@@ -183,6 +192,10 @@ final class PState private (
     m
   }
 
+  def isInUse(m: PState.Mark) = {
+    markPool.isInUse(m)
+  }
+
   def reset(m: PState.Mark) {
     // threadCheck()
     m.restoreInto(this)
@@ -332,6 +345,13 @@ object PState {
    */
   class Mark extends Poolable {
 
+    override def toString() = {
+      if (disMark ne null)
+        "Mark(bitPos0b = " + bitPos0b + " requestorId = " + poolDebugLabel + ")"
+      else
+        "Mark(uninitialized" + " requestorId = " + poolDebugLabel + ")"
+    }
+
     def bitPos0b = disMark.bitPos0b
 
     val simpleElementState = DISimpleState()
@@ -355,6 +375,7 @@ object PState {
       diagnostics = null
       delimitedParseResult = Nope
       mpStateMark.clear()
+      // DO NOT clear requestorId. It is there to help us debug if we try to repeatedly reset/discard a mark already discarded.
     }
 
     def captureFrom(ps: PState, requestorID: String) {
@@ -371,12 +392,16 @@ object PState {
       this.mpStateMark.captureFrom(ps.mpstate)
     }
 
-    def restoreInto(ps: PState) {
+    def restoreInfoset(ps: PState) = {
       val e = ps.thisElement
       e match {
         case s: DISimple => simpleElementState.restoreInto(e)
         case c: DIComplex => complexElementState.restoreInto(e)
       }
+    }
+
+    def restoreInto(ps: PState) {
+      restoreInfoset(ps)
       ps.dataInputStream.reset(this.disMark)
       ps.setVariableMap(this.variableMap)
       ps._processorStatus = this.processorStatus
@@ -420,7 +445,7 @@ object PState {
     val diagnostics = Nil
     val mutablePState = MPState()
     val tunables = dataProc.getTunables()
-    
+
     dis.cst.setPriorBitOrder(root.defaultBitOrder)
     val newState = new PState(doc.asInstanceOf[DIElement], dis, output, variables, diagnostics, mutablePState,
       dataProc.asInstanceOf[DataProcessor], Nope, tunables)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ParseErrors.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ParseErrors.scala
index 176297523..ce0364819 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ParseErrors.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ParseErrors.scala
@@ -48,12 +48,12 @@ class AssertionFailed(rd: SchemaFileLocation, state: PState, msg: String, detail
   }
 }
 
-class ParseAlternativeFailed(rd: SchemaFileLocation, state: PState, val errors: Seq[Diagnostic])
+class ChoiceBranchFailed(rd: SchemaFileLocation, state: PState, val errors: Seq[Diagnostic])
   extends ParseError(One(rd), One(state.currentLocation), "Alternative failed. Reason(s): %s", errors)
 
-class AltParseFailed(rd: SchemaFileLocation, state: PState,
-                     diags: Seq[Diagnostic])
-  extends ParseError(One(rd), One(state.currentLocation), "All alternatives failed. Reason(s): %s", diags) {
+class EntireChoiceFailed(rd: SchemaFileLocation, state: PState,
+  diags: Seq[Diagnostic])
+  extends ParseError(One(rd), One(state.currentLocation), "All choice alternatives failed. Reason(s): %s", diags) {
 
   override def getLocationsInSchemaFiles: Seq[LocationInSchemaFile] = diags.flatMap { _.getLocationsInSchemaFiles }
 
@@ -84,24 +84,11 @@ class GeneralParseFailure(msg: String) extends Diagnostic(Nope, Nope, Nope, Mayb
 }
 
 /**
- * Mix this into parsers that have deep algorithms that are spread over multiple classes.
+ * Mixin for signaling Schema Definition Errors at runtime.
  *
- * These allow one to bend the rule about parsers not throwing ParseError so that
- * if you are inside a parser, but you are way down a bunch of calls away from the parser itself
- * you can throw, and it will be intercepted and proper behavior (not throwing, but returning
- * a failed status) will result.
- *
- * Use like this:
- * @example {{{
- * withParseErrorThrowing(pstate) { // something enclosing like the parser
- * ...
- *   // calls something which calls something which eventually calls
- *       PE(context, bitOffset % 8 == 0, "must be byte boundary, not bit %s", bitOffset)
- * ...
- * }
- * }}}
+ * Some SDE cannot be detected until runtime. Classes that need to signal them
+ * mixin this trait.
  */
-
 trait DoSDEMixin {
 
   protected final def doSDE(e: Throwable, state: ParseOrUnparseState) = {
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/Parser.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/Parser.scala
index 595710f24..23e0a5127 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/Parser.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/Parser.scala
@@ -49,6 +49,8 @@ import org.apache.daffodil.processors.PrimProcessorNoData
 sealed trait Parser
   extends Processor {
 
+  def isEmpty = false // override in NadaParser
+
   protected def parserName = Misc.getNameFromClass(this)
 
   def PE(pstate: PState, s: String, args: Any*) = {
@@ -133,17 +135,19 @@ trait TextPrimParser
 /**
  * Parser which does "Nada" (Nothing in Spanish)
  *
- * Used for optitonality in some cases, but is usually recognized and
+ * Used for optionality in some cases, but is usually recognized and
  * optimized out.
  */
 final class NadaParser(override val context: RuntimeData)
   extends PrimParserNoData {
   override def runtimeDependencies: Seq[Evaluatable[AnyRef]] = Nil
 
+  override def isEmpty = true
+
   override def toString = "Nada"
 
   override def parse(start: PState): Unit = {
-    // do nothing
+    Assert.abort("NadaParsers are all supposed to optimize out!")
   }
 }
 
@@ -175,12 +179,12 @@ final class SeqCompParser(context: RuntimeData, val childParsers: Array[Parser])
 
 }
 
-class AltCompParser(ctxt: RuntimeData, val childParsers: Seq[Parser])
+class ChoiceParser(ctxt: RuntimeData, val childParsers: Seq[Parser])
   extends CombinatorParser(ctxt) {
   override lazy val runtimeDependencies = Nil
   override lazy val childProcessors = childParsers
 
-  override def nom = "alt"
+  override def nom = "choice"
 
   def parse(pstate: PState): Unit = {
     var pBefore: PState.Mark = null
@@ -197,7 +201,7 @@ class AltCompParser(ctxt: RuntimeData, val childParsers: Seq[Parser])
         parser = childParsers(i)
         i += 1
         log(LogLevel.Debug, "Trying choice alternative: %s", parser)
-        pBefore = pstate.mark("AltCompParser1")
+        pBefore = pstate.mark("ChoiceParser1")
         try {
           parser.parse1(pstate)
         } catch {
@@ -218,7 +222,7 @@ class AltCompParser(ctxt: RuntimeData, val childParsers: Seq[Parser])
           //
           // capture diagnostics
           //
-          val diag = new ParseAlternativeFailed(context.schemaFileLocation, pstate, pstate.diagnostics)
+          val diag = new ChoiceBranchFailed(context.schemaFileLocation, pstate, pstate.diagnostics)
           diagnostics = diag +: diagnostics
           //
           // check for discriminator evaluated to true.
@@ -229,7 +233,7 @@ class AltCompParser(ctxt: RuntimeData, val childParsers: Seq[Parser])
             // consume this discriminator status result (so it doesn't ripple upward)
             // and return the failed state with all the diagnostics.
             //
-            val allDiags = new AltParseFailed(context.schemaFileLocation, pstate, diagnostics.reverse)
+            val allDiags = new EntireChoiceFailed(context.schemaFileLocation, pstate, diagnostics.reverse)
             pstate.discard(pBefore) // because disc set, we don't unwind side effects on input stream & infoset
             pBefore = null
             pstate.setFailed(allDiags)
@@ -250,18 +254,23 @@ class AltCompParser(ctxt: RuntimeData, val childParsers: Seq[Parser])
       if (returnFlag == false) {
         Assert.invariant(i == limit)
         // Out of alternatives. All of them failed.
-        val allDiags = new AltParseFailed(context.schemaFileLocation, pstate, diagnostics.reverse)
+        val allDiags = new EntireChoiceFailed(context.schemaFileLocation, pstate, diagnostics.reverse)
         pstate.setFailed(allDiags)
-        log(LogLevel.Debug, "All AltParser alternatives failed.")
+        log(LogLevel.Debug, "All Choice alternatives failed.")
       }
 
       pstate.popDiscriminator
     } catch {
       // Similar try/catch/finally logic for returning marks is also used in
-      // the RepAtMostTotalNParser and RepUnboundedParser. The logic isn't
+      // the Sequence parser base. The logic isn't
       // easily factored out so it is duplicated. Changes made here should also
       // be made there. Only these parsers deal with taking marks, so this logic
       // should not be needed elsewhere.
+      //
+      // TODO: Refactor by hoisting this logic into CombinatorParser using same
+      // technique as in SequenceParserBase's tryParseDetectMarkLeaks and parseOne
+      // methods. That way this code really can live in exactly one place.
+      //
       case t: Throwable => {
         if (pBefore != null) {
           markLeakCausedByException = true
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/RepParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/RepParsers.scala
index e012db81e..4b627ab72 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/RepParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/RepParsers.scala
@@ -14,398 +14,437 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.daffodil.processors.parsers
-
-import java.lang.{ Long => JLong }
-import java.io.StringWriter
-import java.io.PrintWriter
-
-import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
-import org.apache.daffodil.equality.ViewEqual
-import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.exceptions.UnsuppressableException
-import org.apache.daffodil.processors.ElementRuntimeData
-import org.apache.daffodil.processors.Evaluatable
-import org.apache.daffodil.processors.Failure
-import org.apache.daffodil.processors.Success
-import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
-import org.apache.daffodil.util.LogLevel
-import org.apache.daffodil.util.Numbers
-import org.apache.daffodil.processors.TermRuntimeData
-
-abstract class RepParser(n: Long, rParser: Parser, context: ElementRuntimeData, baseName: String)
-  extends CombinatorParser(context) {
-
-  override lazy val runtimeDependencies = Nil
-
-  override lazy val childProcessors = Seq(rParser)
-
-  val intN = n.toInt
-
-  def checkN(pstate: PState, n: Long): Boolean = {
-    if (n > pstate.tunable.maxOccursBounds) {
-      // TODO: how can we go after bigger than max int bytes? We have 64-bit computers
-      // after all....
-      PE(pstate, "Occurs count %s exceeds implementation maximum of %s.", n, pstate.tunable.maxOccursBounds)
-      false
-    } else true
-  }
-
-  final def parse(pstate: PState): Unit = {
-    if (!checkN(pstate, n)) return
-    parseAllRepeats(pstate)
-    // pstate.mpstate.clearDelimitedText
-  }
-
-  protected def parseAllRepeats(pstate: PState): Unit
-
-  override def toString = "Rep" + baseName + "(" + rParser.toString + ")"
-
-  override def toBriefXML(depthLimit: Int = -1): String = {
-    if (depthLimit == 0) "..." else
-      "<Rep" + baseName + " name='" + context.name + "' n='" + n + "'>" + rParser.toBriefXML(depthLimit - 1) +
-        "</Rep" + baseName + ">"
-  }
-}
-
-/**
- * This object is so that we can share the iteration idioms between situations
- * where we know N statically, and where dynamic evaluation computes N.
- *
- * In these cases, there are no new points of uncertainty because computed or
- * otherwise, we know N.
- */
-object Rep {
-  def loopExactlyTotalN(intN: Int, rParser: Parser, pstate: PState, context: TermRuntimeData, iParser: Parser): Unit = {
-    while (pstate.mpstate.arrayPos <= intN) {
-      if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, iParser)
-      rParser.parse1(pstate)
-      if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, iParser)
-      if (pstate.processorStatus ne Success) {
-        return // fail if we don't get them all
-      }
-      pstate.mpstate.moveOverOneArrayIndexOnly
-    }
-  }
-}
-
-class RepExactlyNParser(n: Long, rParser: Parser, context: ElementRuntimeData)
-  extends RepParser(n, rParser, context, "ExactlyN") {
-
-  def parseAllRepeats(pstate: PState): Unit = {
-    var i = 0
-    while (i < intN) {
-      i += 1
-      if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, rParser)
-      rParser.parse1(pstate)
-      if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, rParser)
-      if (pstate.processorStatus ne Success) {
-        val cause = pstate.processorStatus.asInstanceOf[Failure].cause
-        PE(pstate, "Failed to populate %s[%s].  Expected %s item(s). Cause: %s.",
-          context.prefixedName, pstate.mpstate.arrayPos, n,
-          cause) // they all must succeed, otherwise we fail here.
-        return
-      }
-      pstate.mpstate.moveOverOneArrayIndexOnly
-    }
-  }
-}
-
-class RepAtMostTotalNParser(n: Long, rParser: Parser, erd: ElementRuntimeData)
-  extends RepParser(n, rParser, erd, "AtMostTotalN") {
-
-  def parseAllRepeats(initialState: PState): Unit = {
-    var startState: PState.Mark = null
-    var priorState: PState.Mark = null
-    var markLeakCausedByException = false
-
-    try {
-      if (initialState.mpstate.arrayPos <= intN) {
-        startState = initialState.mark("RepAtMostTotalNParser1")
-        priorState = initialState.mark("RepAtMostTotalNParser2")
-        val pstate = initialState
-        var returnFlag = false
-        while (!returnFlag && (pstate.mpstate.arrayPos <= intN)) {
-          // Since each one could fail, each is a new point of uncertainty.
-
-          pstate.pushDiscriminator
-
-          if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
-
-          try {
-            rParser.parse1(pstate)
-          } catch {
-            case sde: SchemaDefinitionDiagnosticBase => {
-              pstate.discard(startState)
-              startState = null
-              priorState = null
-              throw sde
-            }
-          }
-
-          if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
-
-          if (pstate.processorStatus ne Success) {
-            //
-            // Did not succeed
-            //
-            // Was a discriminator set?
-            //
-            if (pstate.discriminator == true) {
-              // we fail the whole RepUnbounded, because there was a discriminator set
-              // before the failure.
-              pstate.reset(startState)
-              startState = null
-              priorState = null
-
-              // no need discard priorState, that is implicitly discarded by resetting the startState
-              returnFlag = true
-            } else {
-              //
-              // backout any element appended as part of this attempt.
-              //
-              pstate.reset(priorState)
-              pstate.discard(startState)
-              priorState = null
-              startState = null
-
-              returnFlag = true // success at prior state.
-            }
-          } else {
-            //
-            // Success
-            //
-            pstate.discard(priorState)
-            priorState = pstate.mark("RepAtMostTotalNParser3")
-            pstate.mpstate.moveOverOneArrayIndexOnly
-            returnFlag = false
-          }
-
-          pstate.popDiscriminator
-        }
-        if (returnFlag == false) {
-          // we exited the loop due to arrayPos hitting the upper limit
-          pstate.discard(priorState)
-          pstate.discard(startState)
-          priorState = null
-          startState = null
-        }
-      }
-    } catch {
-      // Similar try/catch/finally logic for returning marks is also used in
-      // the AltCompParser and RepUnboundedParser. The logic isn't
-      // easily factored out so it is duplicated. Changes made here should also
-      // be made there. Only these parsers deal with taking marks, so this logic
-      // should not be needed elsewhere.
-      case t: Throwable => {
-        if (priorState != null || startState != null) {
-          markLeakCausedByException = true
-          if (!t.isInstanceOf[SchemaDefinitionDiagnosticBase] && !t.isInstanceOf[UnsuppressableException]) {
-            val stackTrace = new StringWriter()
-            t.printStackTrace(new PrintWriter(stackTrace))
-            Assert.invariantFailed("Exception thrown with mark not returned: " + t + "\nStackTrace:\n" + stackTrace)
-          }
-        }
-        throw t
-      }
-    } finally {
-      var markLeak = false;
-      if (priorState != null) {
-        initialState.discard(priorState)
-        markLeak = true;
-      }
-      if (startState != null) {
-        initialState.discard(startState)
-        markLeak = true;
-      }
-
-      if (markLeak && !markLeakCausedByException) {
-        // likely a logic bug, throw assertion
-        Assert.invariantFailed("mark not returned, likely a logic bug")
-      }
-    }
-  }
-}
-
-class RepExactlyTotalNParser(n: Long, rParser: Parser, context: ElementRuntimeData)
-  extends RepParser(n, rParser, context, "ExactlyTotalN") {
-
-  def parseAllRepeats(pstate: PState): Unit = {
-    Rep.loopExactlyTotalN(intN, rParser, pstate, context, this)
-
-    if (pstate.processorStatus ne Success) {
-      PE(pstate, "Failed to populate %s[%s].  Expected %s item(s).",
-        context.prefixedName, pstate.mpstate.arrayPos, n) // they all must succeed, otherwise we fail here.
-    }
-  }
-}
-
-class RepUnboundedParser(occursCountKind: OccursCountKind.Value, rParser: Parser, erd: ElementRuntimeData)
-  extends RepParser(-1, rParser, erd, "Unbounded") {
-
-  def parseAllRepeats(initialState: PState): Unit = {
-    var startState: PState.Mark = null
-    var priorState: PState.Mark = null
-    var markLeakCausedByException = false
-
-    Assert.invariant(initialState.processorStatus eq Success)
-
-    try {
-      val pstate = initialState
-      startState = initialState.mark("RepUnboundedParser1")
-      priorState = initialState.mark("RepUnboundedParser2")
-      var returnFlag = false
-      while (!returnFlag && (pstate.processorStatus eq Success)) {
-
-        // Every parse is a new point of uncertainty.
-        pstate.pushDiscriminator
-        if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
-
-        try {
-          rParser.parse1(pstate)
-        } catch {
-          case sde: SchemaDefinitionDiagnosticBase => {
-            pstate.discard(startState)
-            startState = null
-            priorState = null
-            throw sde
-          }
-        }
-
-        if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
-        if (pstate.processorStatus ne Success) {
-          //
-          // Did not succeed
-          //
-          // Was a discriminator set?
-          //
-          if (pstate.discriminator == true) {
-            // we fail the whole RepUnbounded, because there was a discriminator set
-            // before the failure.
-            pstate.reset(startState)
-            startState = null
-            priorState = null
-            // no need discard priorState, that is implicitly discarded by resetting the startState
-          } else {
-            //
-            // no discriminator, so suppress the failure. Loop terminated with prior element.
-            //
-
-            log(LogLevel.Debug, "Failure suppressed. This is normal termination of a occursCountKind='parsed' array.")
-            pstate.reset(priorState)
-            pstate.discard(startState)
-            startState = null
-            priorState = null
-          }
-          returnFlag = true
-        } else {
-          // Success
-          // Need to check for forward progress
-          if (pstate.bitPos =#= priorState.bitPos0b) {
-            pstate.discard(priorState) // didn't move, but might have assigned variables, have to undo those.
-            pstate.discard(startState)
-            startState = null
-            priorState = null
-            PE(pstate,
-              "RepUnbounded - No forward progress at byte %s. Attempt to parse %s " +
-                "succeeded but consumed no data.\nPlease re-examine your schema to correct this infinite loop.",
-              pstate.bytePos, erd.diagnosticDebugName)
-            returnFlag = true
-          } else {
-            pstate.discard(priorState)
-            priorState = pstate.mark("RepUnboundedParser3")
-            pstate.mpstate.moveOverOneArrayIndexOnly
-            returnFlag = false
-          }
-        }
-        pstate.popDiscriminator
-      }
-      Assert.invariant(returnFlag == true)
-    } catch {
-      // Similar try/catch/finally logic for returning marks is also used in
-      // the AltCompParser and RepAtMostTotalNParser. The logic isn't
-      // easily factored out so it is duplicated. Changes made here should also
-      // be made there. Only these parsers deal with taking marks, so this logic
-      // should not be needed elsewhere.
-      case t: Throwable => {
-        if (priorState != null || startState != null) {
-          markLeakCausedByException = true
-          if (!t.isInstanceOf[SchemaDefinitionDiagnosticBase] && !t.isInstanceOf[UnsuppressableException]) {
-            val stackTrace = new StringWriter()
-            t.printStackTrace(new PrintWriter(stackTrace))
-            Assert.invariantFailed("Exception thrown with mark not returned: " + t + "\nStackTrace:\n" + stackTrace)
-          }
-        }
-        throw t
-      }
-    } finally {
-      var markLeak = false;
-      if (priorState != null) {
-        initialState.discard(priorState)
-        markLeak = true;
-      }
-      if (startState != null) {
-        initialState.discard(startState)
-        markLeak = true;
-      }
-
-      if (markLeak && !markLeakCausedByException) {
-        // likely a logic bug, throw assertion
-        Assert.invariantFailed("mark not returned, likely a logic bug")
-      }
-    }
-  }
-}
-
-class OccursCountExpressionParser(occursCountEv: Evaluatable[JLong],
-  override val context: ElementRuntimeData)
-  extends PrimParserNoData {
-  override lazy val runtimeDependencies = Nil
-
-  override lazy val childProcessors = Nil
-
-  def parse(pstate: PState): Unit = {
-    val oc = occursCountEv.evaluate(pstate)
-    val ocLong = Numbers.asLong(oc)
-    if (ocLong < 0 ||
-      ocLong > pstate.tunable.maxOccursBounds) {
-      PE(pstate, "Evaluation of occursCount expression %s returned out of range value %s.", occursCountEv, ocLong)
-      return
-    }
-    pstate.mpstate.updateBoundsHead(ocLong)
-  }
-
-  override def toString = toBriefXML() // "OccursCount(" + e.occursCount.prettyExpr + ")"
-
-  override def toBriefXML(depthLimit: Int = -1) = {
-    "<OccursCount>" + occursCountEv.toString + "</OccursCount>"
-  }
-}
-
-class RepAtMostOccursCountParser(rParser: Parser, intN: Long, erd: ElementRuntimeData)
-  extends RepParser(intN, rParser, erd, "AtMostOccursCount") {
-  def parseAllRepeats(pstate: PState): Unit = {
-    // repeat either n times, or occursCount times if that's less than n.
-    val n = math.min(pstate.mpstate.occursBounds, erd.minOccurs.get)
-    Rep.loopExactlyTotalN(intN.toInt, rParser, pstate, erd, this)
-    if (pstate.processorStatus ne Success) {
-      PE(pstate, "Failed to populate %s[%s].  Expected at most %s items.",
-        erd.prefixedName, pstate.mpstate.arrayPos, n) // they all must succeed, otherwise we fail here.
-      return
-    }
-  }
-}
-
-class RepExactlyTotalOccursCountParser(rParser: Parser, erd: ElementRuntimeData)
-  extends RepParser(-1, rParser, erd, "ExactlyTotalOccursCount") {
-  def parseAllRepeats(pstate: PState): Unit = {
-    val ocInt = pstate.mpstate.occursBounds.toInt
-    Rep.loopExactlyTotalN(ocInt, rParser, pstate, erd, this)
-    if (pstate.processorStatus ne Success) {
-      PE(pstate, "Failed to populate %s[%s].  Expected %s item(s).",
-        erd.prefixedName, pstate.mpstate.arrayPos, ocInt) // they all must succeed, otherwise we fail here.
-      return
-    }
-  }
-}
+//
+//package org.apache.daffodil.processors.parsers
+//
+//import java.lang.{ Long => JLong }
+//
+//import org.apache.daffodil.processors.{ ElementRuntimeData, Evaluatable }
+//import org.apache.daffodil.util.Numbers
+
+//trait RepParser { self: SequenceChildParser =>
+//
+//  def rParser: Parser
+//  def srd: SequenceRuntimeData
+//  def erd: ElementRuntimeData
+//  def baseName: String
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  def checkN(pstate: PState, n: Long): Boolean = {
+//    if (n > pstate.tunable.maxOccursBounds) {
+//      PE(pstate, "Occurs count %s exceeds implementation maximum of %s.", n, pstate.tunable.maxOccursBounds)
+//      false
+//    } else true
+//  }
+//
+//  override def toString = "Rep" + baseName + "(" + rParser.toString + ")"
+//
+//  override def toBriefXML(depthLimit: Int = -1): String = {
+//    if (depthLimit == 0) "..." else
+//      "<Rep" + baseName + " name='" + erd.name + "'>" + rParser.toBriefXML(depthLimit - 1) +
+//        "</Rep" + baseName + ">"
+//  }
+//
+//  def startArray(state: PState): Unit = {
+//
+//    state.mpstate.arrayIndexStack.push(1L) // one-based indexing
+//    state.mpstate.occursBoundsStack.push(state.tunable.maxOccursBounds)
+//  }
+//
+//  def endArray(state: PState): Unit = {
+//    val actualOccurs = state.mpstate.arrayIndexStack.pop()
+//    state.mpstate.occursBoundsStack.pop()
+//
+//    if (state.processorStatus ne Success) return
+//
+//    val shouldValidate =
+//      state.dataProc.isDefined && state.dataProc.value.getValidationMode != ValidationMode.Off
+//
+//    if (shouldValidate && erd.minOccurs.isDefined && erd.maxOccurs.isDefined) {
+//      val minO = erd.minOccurs.get
+//      val maxO = erd.maxOccurs.get
+//      val isUnbounded = maxO == -1
+//      val occurrence = actualOccurs - 1
+//
+//      if (isUnbounded && occurrence < minO)
+//        state.validationError("%s occurred '%s' times when it was expected to be a " +
+//          "minimum of '%s' and a maximum of 'UNBOUNDED' times.", erd.diagnosticDebugName,
+//          occurrence, minO)
+//      else if (!isUnbounded && (occurrence < minO || occurrence > maxO))
+//        state.validationError("%s occurred '%s' times when it was expected to be a " +
+//          "minimum of '%s' and a maximum of '%s' times.", erd.diagnosticDebugName,
+//          occurrence, minO, maxO)
+//      else {
+//        //ok
+//      }
+//    }
+//  }
+//}
+//
+//abstract class RepUnseparatedParser(
+//  val repeatCount: Long,
+//  val rParser: Parser,
+//  srd: SequenceRuntimeData,
+//  val erd: ElementRuntimeData,
+//  val baseName: String)
+//  extends UnseparatedSequenceChildParser(srd, erd, Seq(rParser)) with RepParser {
+//
+//  override protected def parse(pstate: PState): Unit = {
+//    startArray(pstate)
+//    parseAllRepeats(pstate)
+//    endArray(pstate)
+//  }
+//
+//  protected def parseAllRepeats(pstate: PState): Unit
+//}
+//
+///**
+// * This object is so that we can share the iteration idioms between situations
+// * where we know N statically, and where dynamic evaluation computes N.
+// *
+// * In these cases, there are no new points of uncertainty because computed or
+// * otherwise, we know N.
+// */
+//object Rep {
+//  def loopExactlyTotalN(intN: Long, rParser: Parser, pstate: PState, context: TermRuntimeData, iParser: Parser): Unit = {
+//    while (pstate.mpstate.arrayPos <= intN) {
+//      if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, iParser)
+//      rParser.parse1(pstate)
+//      if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, iParser)
+//      if (pstate.processorStatus ne Success) {
+//        return // fail if we don't get them all
+//      }
+//      pstate.mpstate.moveOverOneArrayIndexOnly
+//    }
+//  }
+//}
+//
+//class RepExactlyNParser(repeatCount: Long, rParser: Parser, sContext: SequenceRuntimeData, eContext: ElementRuntimeData)
+//  extends RepUnseparatedParser(repeatCount, rParser, sContext, eContext, "ExactlyN") {
+//
+//  /**
+//   * Overridden for bounds check.
+//   */
+//  override protected def parse(pstate: PState): Unit = {
+//    if (!checkN(pstate, repeatCount)) return
+//    super.parse(pstate)
+//  }
+//
+//  def parseAllRepeats(pstate: PState): Unit = {
+//    var i = 0
+//    while (i < repeatCount) {
+//      i += 1
+//      if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, rParser)
+//      rParser.parse1(pstate)
+//      if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, rParser)
+//      if (pstate.processorStatus ne Success) {
+//        val cause = pstate.processorStatus.asInstanceOf[Failure].cause
+//        PE(pstate, "Failed to populate %s[%s].  Expected %s item(s). Cause: %s.",
+//          eContext.prefixedName, pstate.mpstate.arrayPos, repeatCount,
+//          cause) // they all must succeed, otherwise we fail here.
+//        return
+//      }
+//      pstate.mpstate.moveOverOneArrayIndexOnly
+//    }
+//  }
+//}
+//
+//class RepAtMostTotalNParser(repeatCount: Long, rParser: Parser, srd: SequenceRuntimeData, erd: ElementRuntimeData)
+//  extends RepUnseparatedParser(repeatCount, rParser, srd, erd, "AtMostTotalN") {
+//
+//  def parseAllRepeats(initialState: PState): Unit = {
+//    var startState: PState.Mark = null
+//    var priorState: PState.Mark = null
+//    var markLeakCausedByException = false
+//
+//    try {
+//      if (initialState.mpstate.arrayPos <= repeatCount) {
+//        startState = initialState.mark("RepAtMostTotalNParser1")
+//        priorState = initialState.mark("RepAtMostTotalNParser2")
+//        val pstate = initialState
+//        var returnFlag = false
+//        while (!returnFlag && (pstate.mpstate.arrayPos <= repeatCount)) {
+//          // Since each one could fail, each is a new point of uncertainty.
+//
+//          pstate.pushDiscriminator
+//
+//          if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
+//
+//          try {
+//            rParser.parse1(pstate)
+//          } catch {
+//            case sde: SchemaDefinitionDiagnosticBase => {
+//              pstate.discard(startState)
+//              startState = null
+//              priorState = null
+//              throw sde
+//            }
+//          }
+//
+//          if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
+//
+//          if (pstate.processorStatus ne Success) {
+//            //
+//            // Did not succeed
+//            //
+//            // Was a discriminator set?
+//            //
+//            if (pstate.discriminator == true) {
+//              // we fail the whole RepUnbounded, because there was a discriminator set
+//              // before the failure.
+//              pstate.reset(startState)
+//              startState = null
+//              priorState = null
+//
+//              // no need discard priorState, that is implicitly discarded by resetting the startState
+//              returnFlag = true
+//            } else {
+//              //
+//              // backout any element appended as part of this attempt.
+//              //
+//              pstate.reset(priorState)
+//              pstate.discard(startState)
+//              priorState = null
+//              startState = null
+//
+//              returnFlag = true // success at prior state.
+//            }
+//          } else {
+//            //
+//            // Success
+//            //
+//            pstate.discard(priorState)
+//            priorState = pstate.mark("RepAtMostTotalNParser3")
+//            pstate.mpstate.moveOverOneArrayIndexOnly
+//            returnFlag = false
+//          }
+//
+//          pstate.popDiscriminator
+//        }
+//        if (returnFlag == false) {
+//          // we exited the loop due to arrayPos hitting the upper limit
+//          pstate.discard(priorState)
+//          pstate.discard(startState)
+//          priorState = null
+//          startState = null
+//        }
+//      }
+//    } catch {
+//      // Similar try/catch/finally logic for returning marks is also used in
+//      // the AltCompParser and RepUnboundedParser. The logic isn't
+//      // easily factored out so it is duplicated. Changes made here should also
+//      // be made there. Only these parsers deal with taking marks, so this logic
+//      // should not be needed elsewhere.
+//      case t: Throwable => {
+//        if (priorState != null || startState != null) {
+//          markLeakCausedByException = true
+//          if (!t.isInstanceOf[SchemaDefinitionDiagnosticBase] && !t.isInstanceOf[UnsuppressableException]) {
+//            val stackTrace = new StringWriter()
+//            t.printStackTrace(new PrintWriter(stackTrace))
+//            Assert.invariantFailed("Exception thrown with mark not returned: " + t + "\nStackTrace:\repeatCount" + stackTrace)
+//          }
+//        }
+//        throw t
+//      }
+//    } finally {
+//      var markLeak = false;
+//      if (priorState != null) {
+//        initialState.discard(priorState)
+//        markLeak = true;
+//      }
+//      if (startState != null) {
+//        initialState.discard(startState)
+//        markLeak = true;
+//      }
+//
+//      if (markLeak && !markLeakCausedByException) {
+//        // likely a logic bug, throw assertion
+//        Assert.invariantFailed("mark not returned, likely a logic bug")
+//      }
+//    }
+//  }
+//}
+//
+//class RepExactlyTotalNParser(repeatCount: Long, rParser: Parser, srd: SequenceRuntimeData, erd: ElementRuntimeData)
+//  extends RepUnseparatedParser(repeatCount, rParser, srd, erd, "ExactlyTotalN") {
+//
+//  def parseAllRepeats(pstate: PState): Unit = {
+//    Rep.loopExactlyTotalN(repeatCount, rParser, pstate, erd, this)
+//
+//    if (pstate.processorStatus ne Success) {
+//      PE(pstate, "Failed to populate %s[%s].  Expected %s item(s).",
+//        erd.prefixedName, pstate.mpstate.arrayPos, repeatCount) // they all must succeed, otherwise we fail here.
+//    }
+//  }
+//}
+//
+//class RepUnboundedParser(occursCountKind: OccursCountKind.Value, rParser: Parser, srd: SequenceRuntimeData, erd: ElementRuntimeData)
+//  extends RepUnseparatedParser(-1, rParser, srd, erd, "Unbounded") {
+//
+//  def parseAllRepeats(initialState: PState): Unit = {
+//    var startState: PState.Mark = null
+//    var priorState: PState.Mark = null
+//    var markLeakCausedByException = false
+//
+//    Assert.invariant(initialState.processorStatus eq Success)
+//
+//    try {
+//      val pstate = initialState
+//      startState = initialState.mark("RepUnboundedParser1")
+//      priorState = initialState.mark("RepUnboundedParser2")
+//      var returnFlag = false
+//      while (!returnFlag && (pstate.processorStatus eq Success)) {
+//
+//        // Every parse is a new point of uncertainty.
+//        pstate.pushDiscriminator
+//        if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
+//
+//        try {
+//          rParser.parse1(pstate)
+//        } catch {
+//          case sde: SchemaDefinitionDiagnosticBase => {
+//            pstate.discard(startState)
+//            startState = null
+//            priorState = null
+//            throw sde
+//          }
+//        }
+//
+//        if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
+//        if (pstate.processorStatus ne Success) {
+//          //
+//          // Did not succeed
+//          //
+//          // Was a discriminator set?
+//          //
+//          if (pstate.discriminator == true) {
+//            // we fail the whole RepUnbounded, because there was a discriminator set
+//            // before the failure.
+//            pstate.reset(startState)
+//            startState = null
+//            priorState = null
+//            // no need discard priorState, that is implicitly discarded by resetting the startState
+//          } else {
+//            //
+//            // no discriminator, so suppress the failure. Loop terminated with prior element.
+//            //
+//
+//            log(LogLevel.Debug, "Failure suppressed. This is normal termination of a occursCountKind='parsed' array.")
+//            pstate.reset(priorState)
+//            pstate.discard(startState)
+//            startState = null
+//            priorState = null
+//          }
+//          returnFlag = true
+//        } else {
+//          // Success
+//          // Need to check for forward progress
+//          if (pstate.bitPos =#= priorState.bitPos0b) {
+//            pstate.discard(priorState) // didn't move, but might have assigned variables, have to undo those.
+//            pstate.discard(startState)
+//            startState = null
+//            priorState = null
+//            PE(pstate,
+//              "RepUnbounded - No forward progress at byte %s. Attempt to parse %s " +
+//                "succeeded but consumed no data.\nPlease re-examine your schema to correct this infinite loop.",
+//              pstate.bytePos, erd.diagnosticDebugName)
+//            returnFlag = true
+//          } else {
+//            pstate.discard(priorState)
+//            priorState = pstate.mark("RepUnboundedParser3")
+//            pstate.mpstate.moveOverOneArrayIndexOnly
+//            returnFlag = false
+//          }
+//        }
+//        pstate.popDiscriminator
+//      }
+//      Assert.invariant(returnFlag == true)
+//    } catch {
+//      // Similar try/catch/finally logic for returning marks is also used in
+//      // the AltCompParser and RepAtMostTotalNParser. The logic isn't
+//      // easily factored out so it is duplicated. Changes made here should also
+//      // be made there. Only these parsers deal with taking marks, so this logic
+//      // should not be needed elsewhere.
+//      case t: Throwable => {
+//        if (priorState != null || startState != null) {
+//          markLeakCausedByException = true
+//          if (!t.isInstanceOf[SchemaDefinitionDiagnosticBase] && !t.isInstanceOf[UnsuppressableException]) {
+//            val stackTrace = new StringWriter()
+//            t.printStackTrace(new PrintWriter(stackTrace))
+//            Assert.invariantFailed("Exception thrown with mark not returned: " + t + "\nStackTrace:\n" + stackTrace)
+//          }
+//        }
+//        throw t
+//      }
+//    } finally {
+//      var markLeak = false;
+//      if (priorState != null) {
+//        initialState.discard(priorState)
+//        markLeak = true;
+//      }
+//      if (startState != null) {
+//        initialState.discard(startState)
+//        markLeak = true;
+//      }
+//
+//      if (markLeak && !markLeakCausedByException) {
+//        // likely a logic bug, throw assertion
+//        Assert.invariantFailed("mark not returned, likely a logic bug")
+//      }
+//    }
+//  }
+//}
+//
+//class OccursCountExpressionParser(occursCountEv: Evaluatable[JLong],
+//  override val context: ElementRuntimeData)
+//  extends PrimParserNoData {
+//  override lazy val runtimeDependencies = Seq(occursCountEv)
+//
+//  override lazy val childProcessors = Nil
+//
+//  override def parse(pstate: PState): Unit = {
+//    val oc = occursCountEv.evaluate(pstate)
+//    val ocLong = Numbers.asLong(oc)
+//    if (ocLong < 0 ||
+//      ocLong > pstate.tunable.maxOccursBounds) {
+//      PE(pstate, "Evaluation of occursCount expression %s returned out of range value %s.", occursCountEv, ocLong)
+//      return
+//    }
+//    pstate.mpstate.updateBoundsHead(ocLong)
+//  }
+//
+//  override def toString = toBriefXML() // "OccursCount(" + e.occursCount.prettyExpr + ")"
+//
+//  override def toBriefXML(depthLimit: Int = -1) = {
+//    "<OccursCount>" + occursCountEv.toString + "</OccursCount>"
+//  }
+//}
+
+//class RepAtMostOccursCountParser(rParser: Parser, intN: Long, srd: SequenceRuntimeData, erd: ElementRuntimeData)
+//  extends RepUnseparatedParser(intN, rParser, srd, erd, "AtMostOccursCount") {
+//  def parseAllRepeats(pstate: PState): Unit = {
+//    // repeat either n times, or occursCount times if that's less than n.
+//    val n = math.min(pstate.mpstate.occursBounds, erd.minOccurs.get)
+//    Rep.loopExactlyTotalN(intN.toInt, rParser, pstate, erd, this)
+//    if (pstate.processorStatus ne Success) {
+//      PE(pstate, "Failed to populate %s[%s].  Expected at most %s items.",
+//        erd.prefixedName, pstate.mpstate.arrayPos, n) // they all must succeed, otherwise we fail here.
+//      return
+//    }
+//  }
+//}
+//
+//class RepExactlyTotalOccursCountParser(rParser: Parser, ocParser: Parser, srd: SequenceRuntimeData, erd: ElementRuntimeData)
+//  extends RepUnseparatedParser(-1, rParser, srd, erd, "ExactlyTotalOccursCount") {
+//  def parseAllRepeats(pstate: PState): Unit = {
+//    ocParser.parse1(pstate)
+//    val ocInt = pstate.mpstate.occursBounds.toInt
+//    Rep.loopExactlyTotalN(ocInt, rParser, pstate, erd, this)
+//    if (pstate.processorStatus ne Success) {
+//      PE(pstate, "Failed to populate %s[%s].  Expected %s item(s).",
+//        erd.prefixedName, pstate.mpstate.arrayPos, ocInt) // they all must succeed, otherwise we fail here.
+//      return
+//    }
+//  }
+//}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceParsers.scala
new file mode 100644
index 000000000..aa445cc1a
--- /dev/null
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceParsers.scala
@@ -0,0 +1,541 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.processors.parsers
+
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.processors._
+import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
+import org.apache.daffodil.schema.annotation.props.gen.SeparatorPosition
+import ArrayIndexStatus._
+import org.apache.daffodil.dpath.NodeInfo
+
+trait Separated { self: SequenceChildParser =>
+  // import ArrayIndexStatus._
+
+  def sep: Parser
+  def spos: SeparatorPosition
+  def ssp: SeparatorSuppressionPolicy
+
+  val childProcessors = Seq(sep, childParser)
+}
+
+sealed trait RepeatingSeparatedPoU extends Separated { self: RepeatingChildParser =>
+
+  private lazy val shouldRemoveZLStringHexBinaryValue_ =
+    false && // disable this feature as many test in daffodil-core depend on NOT removing these empty strings.
+      isPotentiallyTrailing &&
+      isDeclaredLastInSequence &&
+      (
+        (ssp eq SeparatorSuppressionPolicy.TrailingEmpty) ||
+        (ssp eq SeparatorSuppressionPolicy.TrailingEmptyStrict)
+      )
+
+  /**
+   * Tells us if we should remove a successfully parsed zero-length string
+   * or hexBinary from the infoset, because it is optional, so even though
+   * zero length may parse successfully and return an empty string or hexbinary
+   * normal value, the optionality of the element wins out over the empty-string value, and
+   * we don't put the element into the infoset as an array child.
+   */
+  final def shouldRemoveZLStringHexBinaryValue(ais: ArrayIndexStatus, erd: ElementRuntimeData): Boolean = {
+    shouldRemoveZLStringHexBinaryValue_
+  }
+
+  /**
+   *  Only needed for separated sequences, but in order to avoid code duplication
+   *  we use this "fat interface" approach, and have these here by default.
+   *
+   *  Override in separated, hasPoU case.
+   */
+  def isPotentiallyTrailing: Boolean
+
+  /**
+   *  Only needed for separated sequences, but in order to avoid code duplication
+   *  we use this "fat interface" approach, and have these here by default.
+   *
+   *  Override in separated, hasPoU case.
+   */
+  def isDeclaredLastInSequence: Boolean
+
+  /**
+   * True for cases where we should deal with trailing separator toleration.
+   */
+  private lazy val shouldSuppressZLDelimitedParseFailures_ = {
+    //
+    // A complex type that fails to parse can't fail on zero length.
+    // It can be successful on zero length, but if it fails, something will
+    // have to have been scanned/examined from the input data.
+    //
+    val result =
+      if (erd.isComplexType) false
+      else {
+        Assert.invariant(erd.isSimpleType)
+        val ty = erd.optPrimType.get
+        ty match {
+          //
+          // String and HexBinary, if they FAIL, given ZL, then they must have
+          // assertions that cause them to fail because otherwise they would always
+          // parse successfully on ZL.
+          // So that means these aren't ever ZL failures
+          //
+          case NodeInfo.String => false
+          case NodeInfo.HexBinary => false
+          //
+          // For non hexbinary or string, if it fails, and the length is zero,
+          // that's the case where we should suppress the failure.
+          case other => {
+            // but only if the element decl is potentially trailing
+            {
+              isPotentiallyTrailing && // and only if it is declared last in its sequence.
+                // isDeclaredLastInSequence &&
+                (
+                  (ssp eq SeparatorSuppressionPolicy.TrailingEmpty) ||
+                  (ssp eq SeparatorSuppressionPolicy.TrailingEmptyStrict)
+                )
+            }
+          }
+
+        }
+      }
+    result
+  }
+
+  /**
+   * True for cases where we should deal with trailing separator toleration.
+   *
+   * Combines the runtime information needed with static/schema-compile-time information
+   * about the Sequence child.
+   *
+   * This is applicable only to OPTIONAL elements (as in between min/maxOccurs, i.e.,
+   * has variable occurrences, and speculative parsing/PoU.
+   */
+  final def shouldSuppressZLDelimitedParseFailure(pstate: PState,
+    hasZLParseAttempt: Boolean): Boolean = {
+    val shouldSuppress =
+      shouldSuppressZLDelimitedParseFailures_ && {
+        Assert.invariant(erd.isSimpleType)
+        hasZLParseAttempt
+      }
+    shouldSuppress
+  }
+}
+
+final class ScalarOrderedSeparatedSequenceChildParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  trd: TermRuntimeData,
+  val sep: Parser,
+  val spos: SeparatorPosition,
+  val ssp: SeparatorSuppressionPolicy)
+  extends SequenceChildParser(childParser, srd, trd)
+  with Separated {
+
+  override def parse(state: PState) = childParser.parse1(state)
+
+}
+
+final class RepOrderedExactlyNSeparatedSequenceChildParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData,
+  val sep: Parser,
+  val spos: SeparatorPosition,
+  val ssp: SeparatorSuppressionPolicy)
+  extends OccursCountExactParser(childParser, srd, erd)
+  with Separated
+
+final class RepOrderedExactlyTotalOccursCountSeparatedSequenceChildParser(
+  childParser: Parser,
+  ocEv: OccursCountEv,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData,
+  val sep: Parser,
+  val spos: SeparatorPosition,
+  val ssp: SeparatorSuppressionPolicy)
+  extends OccursCountExpressionParser(childParser, srd, erd, ocEv)
+  with Separated
+
+final class RepOrderedWithMinMaxSeparatedSequenceChildParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData,
+  override val sep: Parser,
+  override val spos: SeparatorPosition,
+  override val ssp: SeparatorSuppressionPolicy,
+  override val isPotentiallyTrailing: Boolean,
+  override val isDeclaredLastInSequence: Boolean)
+  extends OccursCountMinMaxParser(childParser, srd, erd)
+  with RepeatingSeparatedPoU {
+
+}
+
+final class OrderedSeparatedSequenceParser(rd: SequenceRuntimeData,
+  ssp: SeparatorSuppressionPolicy,
+  spos: SeparatorPosition,
+  sep: Parser,
+  childrenArg: Seq[SequenceChildParser])
+  extends OrderedSequenceParserBase(rd, childrenArg) {
+
+  override lazy val childProcessors: Seq[Parser] = sep +: childrenArg.asInstanceOf[Seq[Parser]]
+
+  /**
+   * Parses (1) one iteration of an array with fixed/expression occurs count.
+   * (2) a model group (3) a scalar element.
+   *
+   * Returns a status indicating success/failure and the nature of that success/failure.
+   *
+   * No backtracking supported.
+   */
+  final protected def parseOneWithoutPoU(
+    parserArg: SequenceChildParser,
+    trd: TermRuntimeData,
+    pstate: PState): ParseAttemptStatus = {
+
+    val parser = parserArg.asInstanceOf[SequenceChildParser with Separated]
+
+    val finalStatus: ParseAttemptStatus = {
+      // parse prefix sep if any
+      val prefixSepSuccessful =
+        if ((spos eq SeparatorPosition.Prefix) && trd.isRepresented) {
+          sep.parse1(pstate)
+          pstate.processorStatus eq Success
+        } else
+          true
+
+      if (!prefixSepSuccessful) {
+        failedSeparator(pstate, "prefix", trd)
+        ParseAttemptStatus.Failed_EntireArray
+      } else {
+        // except for the first position of the group, parse an infix separator
+
+        val infixSepSuccessful =
+          if ((spos eq SeparatorPosition.Infix) && pstate.mpstate.groupPos > 1 && trd.isRepresented) {
+            sep.parse1(pstate)
+            pstate.processorStatus eq Success
+          } else
+            true
+
+        if (!infixSepSuccessful) {
+          failedSeparator(pstate, "infix", trd)
+          ParseAttemptStatus.Failed_EntireArray
+        } else {
+          //
+          // now we parse the child
+          //
+          if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
+
+          parser.parse1(pstate)
+
+          if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
+
+          val childSuccessful = pstate.processorStatus eq Success
+
+          val res: ParseAttemptStatus = {
+            if (!childSuccessful) {
+              ParseAttemptStatus.Failed_EntireArray
+            } else {
+              Assert.invariant(childSuccessful)
+              // parse postfix sep if any
+              val postfixSepSuccessful =
+                if ((spos eq SeparatorPosition.Postfix) && trd.isRepresented) {
+                  sep.parse1(pstate)
+                  pstate.processorStatus eq Success
+                } else
+                  true
+
+              if (!postfixSepSuccessful) {
+                failedSeparator(pstate, "postfix", trd)
+                ParseAttemptStatus.Failed_EntireArray
+              } else {
+
+                //
+                // successful parse of required element. Zero length or not.
+                // note that anyEmpty doesn't apply in this case, and
+                // that separatorSuppressionPolicy property should be ignored.
+                //
+                ParseAttemptStatus.Success_LengthUndetermined
+                // returning lengthUndeterined indicates that because this was a
+                // required element, treat it just like it had content,
+                // even if it was zero length
+
+              } // end if postfix success/fail
+            } // child if child success/fail
+          }
+          res
+        } // end if infix
+      } // end if prefix
+    }
+    finalStatus
+  }
+
+  /**
+   * Parses one iteration of an array/optional element, and returns
+   * a status indicating success/failure and the nature of that success/failure.
+   */
+  final protected def parseOneWithPoU(
+    parserArg: RepeatingChildParser,
+    erd: ElementRuntimeData,
+    pstate: PState,
+    priorState: PState.Mark,
+    ais: GoArrayIndexStatus,
+    isBounded: Boolean): ParseAttemptStatus = {
+
+    val parser = parserArg.asInstanceOf[RepeatingChildParser with RepeatingSeparatedPoU]
+
+    val finalStatus: ParseAttemptStatus = {
+
+      val bitPosBeforeSeparator = pstate.bitPos0b
+
+      // parse prefix sep if any
+      val prefixSepSuccessful =
+        if (spos eq SeparatorPosition.Prefix) {
+          sep.parse1(pstate)
+          pstate.processorStatus eq Success
+        } else
+          true
+
+      if (!prefixSepSuccessful) {
+        failedSeparator(pstate, "prefix", erd)
+        processFailedSeparatorWithPoU(pstate)
+      } else {
+        // except for the first position of the group, parse an infix separator
+
+        val isInfix = spos eq SeparatorPosition.Infix
+
+        val infixSepShouldBePresent =
+          pstate.mpstate.groupPos > 1
+
+        val infixSepSuccessful =
+          if (isInfix && infixSepShouldBePresent) {
+            sep.parse1(pstate)
+            pstate.processorStatus eq Success
+          } else
+            true
+
+        //
+        // captures corner case when there is no separator because it's infix,
+        // and this optional/array element was first in the group
+        // so we don't put an infix separator in.
+        //
+        val wasInfixSepSkippedForInitialElement =
+          isInfix && !infixSepShouldBePresent
+
+        if (!infixSepSuccessful) {
+          failedSeparator(pstate, "infix", erd)
+          processFailedSeparatorWithPoU(pstate)
+        } else {
+          //
+          // now we parse the child
+          //
+          val prevBitPosBeforeChild = pstate.bitPos0b
+
+          pstate.pushDiscriminator
+
+          if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
+
+          parser.parse1(pstate)
+
+          if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
+
+          val childSuccessful = pstate.processorStatus eq Success
+          val childFailure = !childSuccessful // just makes later logic easier to read
+
+          val bitPosAfterChildAttempt = pstate.bitPos0b
+
+          val hasZLChildAttempt = prevBitPosBeforeChild == bitPosAfterChildAttempt
+          val hasZLChildSuccess = childSuccessful && hasZLChildAttempt
+
+          /**
+           * This is what the DFDL Spec v1.0 calls the "absent" representation.
+           * (Section 9.2.4). This is a kind of missing representation (section 9.2.6)
+           */
+          val isRepresentationAbsent = childFailure && hasZLChildAttempt
+
+          val postfixSepSuccessful =
+            if ((spos eq SeparatorPosition.Postfix) && (
+              childSuccessful ||
+              isRepresentationAbsent)) {
+              // parse postfix sep if any
+              sep.parse1(pstate)
+              pstate.processorStatus eq Success
+            } else
+              true
+
+          val bitPosAfterSeparator = pstate.bitPos0b
+
+          if (!postfixSepSuccessful) {
+            failedSeparator(pstate, "postfix", erd)
+            processFailedSeparatorWithPoU(pstate)
+          } else {
+
+            //
+            // At this point we know the separator (wherever located) was
+            // successfully parsed, and we're past where separators are concerned
+            // so the separator was successful.
+            //
+            val hasMadeForwardProgress = bitPosAfterSeparator > bitPosBeforeSeparator
+
+            Assert.invariant(hasMadeForwardProgress || wasInfixSepSkippedForInitialElement || postfixSepSuccessful)
+
+            val res = {
+              if (childFailure) {
+                if (pstate.discriminator == true) {
+                  ParseAttemptStatus.Failed_WithDiscriminatorSet
+                } else {
+                  Assert.invariant(pstate.discriminator == false)
+                  ais match {
+                    case ArrayIndexStatus.Required => {
+                      //
+                      // failure of required element is handled by caller.
+                      //
+                      ParseAttemptStatus.Failed_SpeculativeParse
+                    }
+                    case opt: OptionalArrayIndexStatus => {
+                      //
+                      // failure of optional element
+                      //
+                      if (!wasInfixSepSkippedForInitialElement &&
+                        isRepresentationAbsent &&
+                        parser.shouldSuppressZLDelimitedParseFailure(pstate, hasZLChildAttempt)) {
+                        //
+                        // optional element failed, but for tolerating excess
+                        // trailing separators, we want to keep the separator.
+                        // But we must remove the speculated element.
+                        //
+                        // This will not work right if the separator and terminator are/can-be the same,
+                        // as we'll never find the terminator after a failure that happens
+                        // to have zero-length. We'll find the "separator", and fail to parse
+                        // but we'll suppress this failure in the case where we're supposed
+                        // to tolerate trailing additional separators. So we succeed, consume
+                        // the "separator", and the separator will never be reconsidered as the terminator.
+                        //
+                        // However, solving for "separator can be equal to terminator", so as to issue
+                        // an SDE is pretty difficult. It has to be done in an Evaluatable, so that
+                        // the delimiters can be run-time computed. Since delimiters can have
+                        // things like characters class entities in them, deciding this is quite hard.
+                        //
+                        // In general, the ambiguity this creates is a "user-beware" situation
+                        // and the right thing for the runtime to do is make sure a trace/debug
+                        // session can help the user isolate what is actually happening.
+                        //
+
+                        // backtrack away this speculative element and any variable side-effects
+                        pstate.reset(priorState)
+                        // but that resets the position to before the separator
+                        // so we set position to after the separator
+                        pstate.dataInputStream.setBitPos0b(bitPosAfterSeparator)
+                        //
+                        // use special return status that indicates we've taken care of the
+                        // priorState and repositioning after a skipped separator.
+                        //
+                        ParseAttemptStatus.Success_SkippedSeparator
+                      } else {
+                        //
+                        // optional element failed but separator was found (or it's the first of an infix-separated array)
+                        // this is regular speculative parse failure to find the element.
+                        //
+                        ParseAttemptStatus.Failed_SpeculativeParse
+                      }
+                    }
+                  }
+                }
+              } else {
+                Assert.invariant(childSuccessful)
+
+                val result: ParseAttemptStatus = ais match {
+                  case Required => {
+                    //
+                    // Success on a required element.
+                    // We don't actually care if it is zero length or non-zero length.
+                    //
+                    ParseAttemptStatus.Success_LengthUndetermined
+                  }
+                  case _: OptionalArrayIndexStatus => {
+                    //
+                    // Now we have to analyze the cases where ZL matters and needs special handling
+                    //
+                    if (hasZLChildSuccess) {
+                      val shouldRemoveZLElement = parser.shouldRemoveZLStringHexBinaryValue(ais, erd)
+                      if (shouldRemoveZLElement) {
+                        //
+                        // It's an optional element, type is string/hexBinary and length is zero
+                        // so we don't want to add it to the infoset
+                        //
+                        // Note: This does seem to be correct interpretation of the DFDL v1.0 spec.
+                        // However, the language is very subtle. Hopefully it gets clarified.
+                        //
+                        // However, we do want to keep trying to parse more, as they could be trailing separators.
+                        // that are to be tolerated.
+                        //
+                        // So we don't backtrack here. We just remove the accumulated element.
+                        //
+                        // Note that we do NOT backout variable side-effects that occurred while parsing
+                        // and also a discriminator could be set to true.
+                        // So while we are suppressing adding the element to the infoset,
+                        // we're not suppressing side-effects that occurred during its parsing.
+                        //
+                        priorState.restoreInfoset(pstate)
+                      }
+                    } // end if ZL success
+                    ParseAttemptStatus.Success_NotZeroLength // NotZeroLength due to separator
+                  }
+                }
+                result
+              } // end if child success/fail
+            } // end val res
+            pstate.popDiscriminator
+            res
+          } // end if postfix
+        } // end if infix
+      } // end if prefix
+    } // end val finalStatus
+    finalStatus
+  }
+
+  override protected def zeroLengthSpecialChecks(pstate: PState, wasLastChildZeroLength: Boolean): Unit = {
+    if ((pstate.processorStatus eq Success) && wasLastChildZeroLength) {
+      if (ssp eq SeparatorSuppressionPolicy.TrailingEmptyStrict)
+        PE(pstate, "Empty trailing elements are not allowed when dfdl:separatorSuppressionPolicy='trailingEmptyStrict'")
+    }
+  }
+
+  /**
+   * Sets PState status to failure when separator is not found.
+   * Used for BOTH PoU and non-PoU
+   */
+  private def failedSeparator(pstate: PState, kind: String, trd: TermRuntimeData): Unit = {
+    val cause = pstate.processorStatus.asInstanceOf[Failure].cause
+    trd match {
+      case erd: ElementRuntimeData if (erd.isArray) =>
+        PE(pstate, "Failed to populate %s[%s]. Missing %s separator. Cause: %s",
+          erd.prefixedName, pstate.mpstate.arrayPos, kind, cause)
+      case _ =>
+        PE(pstate, "Failed to parse %s separator. Cause: %s.", kind, cause)
+    }
+  }
+
+  /**
+   * Handles backtracking for PoU case of failed separator.
+   */
+  private def processFailedSeparatorWithPoU(pstate: PState): ParseAttemptStatus = {
+    if (pstate.discriminator == true) {
+      ParseAttemptStatus.Failed_WithDiscriminatorSet
+    } else {
+      ParseAttemptStatus.Failed_SpeculativeParse
+    }
+  }
+}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildBases.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildBases.scala
new file mode 100644
index 000000000..b2e79e590
--- /dev/null
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildBases.scala
@@ -0,0 +1,466 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.processors.parsers
+
+import org.apache.daffodil.processors.Evaluatable
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.processors.Success
+import org.apache.daffodil.processors.SequenceRuntimeData
+import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.processors.TermRuntimeData
+import org.apache.daffodil.api.ValidationMode
+import org.apache.daffodil.processors.Failure
+import org.apache.daffodil.processors.OccursCountEv
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
+import org.apache.daffodil.processors.ParseOrUnparseState
+
+/**
+ * Enables various sub-kinds of success/failure of a parse to be distinguished
+ * easily. These are statuses of parsing of an occurrence of an array/optional
+ * element, or when implied, the entire array/optional that contains that occurrence.
+ * This applies to both specified and speculative number of occurrences.
+ */
+sealed trait ParseAttemptStatus {
+  def isSuccess: Boolean = false
+}
+sealed trait SuccessParseAttemptStatus extends ParseAttemptStatus {
+  override def isSuccess = true
+}
+sealed trait FailedParseAttemptStatus extends ParseAttemptStatus {
+  override def isSuccess = false
+}
+
+object ParseAttemptStatus {
+
+  /**
+   * State that we initialize the variable to. Only exists until the first
+   * parse attempt.
+   */
+  case object Uninitialized extends ParseAttemptStatus
+
+  /**
+   * The parse succeeded. The parse consumed no bits - i.e., was zero length.
+   */
+  case object Success_ZeroLength extends SuccessParseAttemptStatus
+
+  /**
+   * The parse succeeded. The parse consumed a separator that is being skipped.
+   *
+   * This is used only by separated sequences, and only for optional occurrences
+   * when a separator is being passed over and ignored, without an occurrence
+   * being added to the infoset.
+   */
+  case object Success_SkippedSeparator extends SuccessParseAttemptStatus
+
+  /**
+   * The parse succeeded. The parse consumed some bits - was not zero length.
+   */
+  case object Success_NotZeroLength extends SuccessParseAttemptStatus
+
+  /**
+   * The parse succeeded. We did not keep track of whether it consumed bits or not.
+   */
+  case object Success_LengthUndetermined extends SuccessParseAttemptStatus
+
+  /**
+   * The parse succeeded. We have reached the end of the variable occurrences.
+   *
+   * Ultimately all parses of variable-occurrence/PoU elements must end with
+   * either Success_EndOfArray, or FailedWholeArray status. However, in some cases
+   * a failure of an occurrence gets turned into a Success_EndOfArray (at a
+   * prior occurrence) or a FailedWholeArray.
+   */
+  case object Success_EndOfArray extends SuccessParseAttemptStatus
+
+  /**
+   * The parse failed, and a discriminator was set, indicating that the
+   * PoU was resolved first, and subsequently a failure occurred.
+   */
+  case object Failed_WithDiscriminatorSet extends FailedParseAttemptStatus
+
+  /**
+   * The parse failed. This was a forward-speculative parse, and it failed.
+   */
+  case object Failed_SpeculativeParse extends FailedParseAttemptStatus
+
+  /**
+   * The parse failed. This was a forward speculative parse, and it failed, but furthermore,
+   * no forward progress was made.
+   *
+   * This status is only created by unseparated sequences.
+   */
+  case object Failed_NoForwardProgress extends FailedParseAttemptStatus
+
+  /**
+   * The parse failed. The entire array/optional element failed.
+   *
+   * When the number of occurrences is specified, then any failure results in
+   * a failure of the entire array.
+   *
+   * When the number of occurrences is determined by speculative parsing,
+   * then in some cases a failure of an occurrence gets turned into a
+   * Success_EndOfArray (at a prior occurrence) or a Failed_WholeArray.
+   */
+  case object Failed_EntireArray extends FailedParseAttemptStatus
+
+}
+
+/**
+ * An encapsulating parser for a term parser that is a child of a sequence.
+ *
+ * This class provides support for the iteration of the sequence over the occurrences
+ * of the children, which must distinguish scalars from optional and array elements,
+ * and must distinguish situations with specified numbers of occurrences from
+ * those with points-of-uncertainty.
+ */
+abstract class SequenceChildParser(
+  val childParser: Parser,
+  val srd: SequenceRuntimeData,
+  val trd: TermRuntimeData)
+  extends CombinatorParser(srd) {
+
+  override def runtimeDependencies: Seq[Evaluatable[AnyRef]] = Nil
+}
+
+/**
+ * Base for SequenceChildParsers that are repeating.
+ *
+ * This mixes in the interface. Implementations of this enable the
+ * driver loop in OrderedSequenceParserBase to iterate over the occurrences
+ * with a common interation pattern.
+ */
+abstract class RepeatingChildParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  val erd: ElementRuntimeData,
+  baseName: String)
+  extends SequenceChildParser(childParser, srd, erd)
+  with MinMaxRepeatsMixin {
+
+  def hasPoU: Boolean
+
+  /**
+   *  Invokes the child parser. Once, only. Does NOT do iterations of it.
+   */
+  override protected def parse(pstate: PState): Unit = {
+    childParser.parse1(pstate)
+    //
+    // This is retained because tests look for this wording in error messages.
+    // It isn't really necessary to re-encapsulate the failure like this, but
+    // we otherwise have to chase down tests that depend on this wording.
+    //
+    if (pstate.processorStatus ne Success) {
+      val cause = pstate.processorStatus.asInstanceOf[Failure].cause
+      PE(pstate, "Failed to populate %s[%s]. Cause: %s.",
+        erd.prefixedName, pstate.mpstate.arrayPos, cause)
+      return
+    }
+  }
+
+  /**
+   * Tells us whether to attempt another array element at the current index,
+   * and how we should interpret the existence of an element
+   * or empty/zero-length based on the array index.
+   *
+   * NOTE: must be stateless. State must be passed in, and returned for
+   * assignment to a loop var, or held in pstate.
+   */
+  def arrayIndexStatus(minRepeats: Long, maxRepeats: Long,
+    pstate: PState,
+    resultOfPriorTry: ParseAttemptStatus): ArrayIndexStatus = {
+    import ParseAttemptStatus._
+    import ArrayIndexStatus._
+    val result =
+      if (pstate.processorStatus ne Success)
+        Failed
+      else
+        resultOfPriorTry match {
+          case Success_EndOfArray => Done
+          case _: SuccessParseAttemptStatus | Uninitialized =>
+            if (pstate.arrayPos <= minRepeats)
+              Required
+            else if (pstate.arrayPos < maxRepeats)
+              OptionalMiddle
+            else if (pstate.arrayPos == maxRepeats)
+              OptionalLast
+            else
+              Done
+          // case FailedSpeculativeParse => Assert.invariantFailed("Should already be handled.")
+          case _: FailedParseAttemptStatus => Failed
+        }
+    result
+  }
+
+  override def toString = "Rep" + baseName + "(" + childParser.toString + ")"
+
+  override def toBriefXML(depthLimit: Int = -1): String = {
+    if (depthLimit == 0) "..." else
+      "<Rep" + baseName + " name='" + erd.name + "'>" + childParser.toBriefXML(depthLimit - 1) +
+        "</Rep" + baseName + ">"
+  }
+
+  /**
+   * Do things that are done at the start of an array-element.
+   *
+   * This applies to both variable-occurrence and fixed-occurrence array elements,
+   * as well as optional elements.
+   *
+   * This applies for optional elements as well because expressions can access them
+   * by way of index: e.g., fn:exists( optElement[dfdl:currentIndex()]  )
+   *
+   * This makes more sense if you consider that an "optional" element (minOccurs 0,
+   * maxOccurs 1) when occursCountKind is 'parsed' is treated as an array with
+   * an unbounded number of possible occurrences. Similarly, if occursCountKind is
+   * 'expression', then minOccurs/maxOccurs are ignored (used only for validation), and
+   * there can be more than 1 occurrence.
+   */
+  def startArray(state: PState): Unit = {
+
+    state.mpstate.arrayIndexStack.push(1L) // one-based indexing
+    //    state.mpstate.occursBoundsStack.push(state.tunable.maxOccursBounds)
+  }
+
+  /**
+   * Do things that must be done at the end of an array.
+   *
+   * This applies to both variable-occurrence and fixed-occurrence array elements,
+   * as well as optional elements.
+   *
+   * This applies for optional elements as well because expressions can access them
+   * by way of index: e.g., fn:exists( optElement[dfdl:currentIndex()]  )
+   */
+  def endArray(state: PState): Unit = {
+    val actualOccurs = state.mpstate.arrayIndexStack.pop()
+    //    state.mpstate.occursBoundsStack.pop()
+
+    if (state.processorStatus eq Success) {
+
+      val shouldValidate =
+        state.dataProc.isDefined && state.dataProc.value.getValidationMode != ValidationMode.Off
+
+      if (shouldValidate) {
+        val minO = erd.minOccurs
+        val maxO = erd.maxOccurs
+        val isUnbounded = maxO == -1
+        val occurrence = actualOccurs - 1
+
+        if (isUnbounded && occurrence < minO)
+          state.validationError("%s occurred '%s' times when it was expected to be a " +
+            "minimum of '%s' and a maximum of 'UNBOUNDED' times.", erd.diagnosticDebugName,
+            occurrence, minO)
+        else if (!isUnbounded && (occurrence < minO || occurrence > maxO))
+          state.validationError("%s occurred '%s' times when it was expected to be a " +
+            "minimum of '%s' and a maximum of '%s' times.", erd.diagnosticDebugName,
+            occurrence, minO, maxO)
+        else {
+          //ok
+        }
+      }
+    }
+  }
+
+}
+
+/**
+ * Indicates the status of an array index vis a vis whether the
+ * element occurrence at that index is required, optional, etc.
+ */
+sealed trait ArrayIndexStatus
+
+/**
+ * Indicates that parsing of an element occurrence for that index
+ * should be attempted.
+ */
+sealed trait GoArrayIndexStatus extends ArrayIndexStatus
+
+/**
+ * Indicates that the parsing of an element occurrence for that index
+ * should be attempted, and that the index is for an optional occurrence.
+ */
+sealed trait OptionalArrayIndexStatus extends GoArrayIndexStatus
+
+/**
+ * Indicates that the parsing of an element occurence for that index should
+ * not be attempted.
+ */
+sealed trait StopArrayIndexStatus extends ArrayIndexStatus
+
+/**
+ * Object to provide namespace for these constant values.
+ */
+object ArrayIndexStatus {
+
+  /**
+   * Indicates the array element occurrence index is less than or equal to
+   * minOccurs, and so is required. However, for occursCountKind 'parsed' or 'stopValue'
+   * this is never returned, as the min/max bounds are only advisory
+   * for validation purposes in that case.
+   */
+  case object Required extends GoArrayIndexStatus
+
+  /**
+   * Indicates that the array element index is minOccurs or greater, and strictly less than maxOccurs.
+   *
+   * When maxOccurs is unbounded, this is always returned.
+   */
+  case object OptionalMiddle extends OptionalArrayIndexStatus
+
+  /**
+   * Indicates that the array element index is maxOccurs exactly, for any
+   * element which has bounded occurrences.
+   *
+   * This is needed so we can decide NOT to consume a separator if we
+   * fail on a zero-length string. This is used in some situations where we
+   * tolerate redundant separators.
+   */
+  case object OptionalLast extends OptionalArrayIndexStatus
+
+  /**
+   * Indicates that pstate status is failed, that is, we
+   * are unable to continue parsing. No parse attempt should be done for this
+   * index.
+   */
+  case object Failed extends StopArrayIndexStatus
+
+  /**
+   * Indicates that we are done iterating, and should stop parsing more
+   * array. Used to indicate that the end of the array was identified
+   * by speculative parsing.
+   */
+  case object Done extends StopArrayIndexStatus
+}
+
+/**
+ * Parser is for a non-scalar with a specific number of occurrences.
+ *
+ * There are no points-of-uncertainty (PoU).
+ */
+abstract class OccursCountExactParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData)
+  extends RepeatingChildParser(childParser, srd, erd, "ExactN") {
+
+  final override def isBoundedMax(max: Long) = true
+
+  final override def minRepeats(pstate: ParseOrUnparseState) = maxRepeats(pstate)
+
+  final override def maxRepeats(pstate: ParseOrUnparseState): Long = erd.maxOccurs match {
+    case -1 => Long.MaxValue
+    case _ => erd.maxOccurs
+  }
+
+  final override def hasPoU = false
+}
+
+/**
+ * Parser is for a non-scalar with a specific number of occurrences given by
+ * an occursCount expression.
+ *
+ * There are no points-of-uncertainty (PoU).
+ */
+abstract class OccursCountExpressionParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData,
+  val occursCountEv: OccursCountEv)
+  extends RepeatingChildParser(childParser, srd, erd, "Expression") {
+
+  final override def hasPoU = false
+
+  final override lazy val runtimeDependencies = Seq(occursCountEv)
+
+  final override def isBoundedMax(max: Long) = true
+
+  final override def minRepeats(pstate: ParseOrUnparseState) = maxRepeats(pstate)
+
+  final override def maxRepeats(pstate: ParseOrUnparseState): Long = {
+    val ocInt = occursCountEv.evaluate(pstate)
+    ocInt
+  }
+}
+
+/**
+ * Trait shared by both repeating sequence child parsers and unparsers
+ */
+trait MinMaxRepeatsMixin {
+
+  def erd: ElementRuntimeData
+
+  private val ock = erd.maybeOccursCountKind.get
+
+  private val minRepeats_ = {
+    val mr =
+      if (ock eq OccursCountKind.Parsed) 0
+      else erd.minOccurs
+    mr
+  }
+
+  /**
+   * The digestion of minOccurs with the occursCountKind results in minRepeats.
+   * For example, when occursCountKind is parsed, then minRepeats is 0, regardless
+   * of the value of minOccurs.
+   */
+  def minRepeats(state: ParseOrUnparseState): Long = minRepeats_
+
+  /**
+   * True if the loop has a finite upper bound on number of iterations.
+   * Meaning either it's specified occurrence count, or
+   * for speculative parsing cases, it's not OCK parsed, or OCK implicit with
+   * maxOccurs unbounded.
+   */
+  private val maxRepeats_ = {
+    if (ock eq OccursCountKind.Parsed) Long.MaxValue
+    else if (erd.maxOccurs == -1) Long.MaxValue
+    else erd.maxOccurs
+  }
+
+  /**
+   * The digestion of maxOccurs with the occursCountKind results in maxRepeats.
+   * For example, when occursCountKind is parsed, then maxRepeats is -1 (meaning unbounded)
+   * regardless of the value of maxOccurs.
+   */
+  def maxRepeats(state: ParseOrUnparseState): Long = maxRepeats_
+
+  private val isBoundedMax_ = maxRepeats_ < Long.MaxValue
+
+  def isBoundedMax(maxRepeats: Long) = isBoundedMax_
+
+}
+
+/**
+ * Base class for parsers for terms which are parsed speculatively.
+ *
+ * These may respect min/maxOccurs, or may not depending on the occursCountKind.
+ * (e.g., parsed uses 0 for min, unbounded for max, implicit does use the
+ * min and max occurs values.)
+ */
+abstract class OccursCountMinMaxParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData)
+  extends RepeatingChildParser(childParser, srd, erd, "MinMax") {
+
+  Assert.invariant(erd.maybeOccursCountKind.isDefined)
+
+  private val ock = erd.maybeOccursCountKind.get
+
+  Assert.invariant(ock == OccursCountKind.Implicit ||
+    ock == OccursCountKind.Parsed)
+
+  final override def hasPoU = true
+}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala
new file mode 100644
index 000000000..b86107be6
--- /dev/null
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala
@@ -0,0 +1,380 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.processors.parsers
+
+import org.apache.daffodil.processors.Evaluatable
+import java.io.PrintWriter
+import org.apache.daffodil.exceptions.UnsuppressableException
+import java.io.StringWriter
+import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.processors.Success
+import org.apache.daffodil.processors.SequenceRuntimeData
+import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.processors.TermRuntimeData
+import org.apache.daffodil.processors.Failure
+
+abstract class OrderedSequenceParserBase(
+  srd: SequenceRuntimeData,
+  protected val childParsers: Seq[SequenceChildParser])
+  extends CombinatorParser(srd) {
+  override def nom = "Sequence"
+
+  override lazy val runtimeDependencies: Seq[Evaluatable[AnyRef]] = Nil
+
+  override lazy val childProcessors: Seq[Parser] = childParsers
+
+  /**
+   * Parses (1) one iteration of an array with fixed/expression occurs count.
+   * (2) a model group (3) a scalar element.
+   *
+   * Returns a status indicating success/failure and the nature of that success/failure.
+   *
+   * No backtracking supported.
+   */
+  protected def parseOneWithoutPoU(
+    parserArg: SequenceChildParser,
+    trd: TermRuntimeData,
+    pstate: PState): ParseAttemptStatus
+
+  /**
+   * Parses one iteration of an array/optional element, and returns
+   * a status indicating success/failure and the nature of that success/failure.
+   *
+   * Supports speculative parsing via backtracking.
+   */
+  protected def parseOneWithPoU(
+    parser: RepeatingChildParser,
+    erd: ElementRuntimeData,
+    pstate: PState,
+    priorState: PState.Mark,
+    ais: GoArrayIndexStatus,
+    isBounded: Boolean): ParseAttemptStatus
+
+  protected def zeroLengthSpecialChecks(pstate: PState, wasLastChildZeroLength: Boolean): Unit
+
+  final protected def checkN(pstate: PState): Boolean = {
+    if (pstate.arrayPos > pstate.tunable.maxOccursBounds) {
+      PE(pstate, "Occurs count %s exceeds implementation maximum of %s.", pstate.arrayPos, pstate.tunable.maxOccursBounds)
+      false
+    } else true
+  }
+
+  /**
+   * This parse method is used for both separated and unseparated sequences.
+   */
+  override protected def parse(pstate: PState): Unit = {
+    val children = childParsers
+
+    var scpIndex = 0
+    pstate.mpstate.groupIndexStack.push(1L) // one-based indexing
+
+    val limit = children.length
+
+    var wasLastChildZeroLength = false
+
+    //
+    // This loop iterates over the children terms of the sequence
+    //
+    while ((scpIndex < limit) && (pstate.processorStatus eq Success)) {
+      val child = children(scpIndex)
+      child match {
+        case parser: RepeatingChildParser => {
+          //
+          // The sequence child is an array/repeating element (or ooptional
+          // element as the runtime doesn't distinguish them.)
+          //
+          //
+          val min = parser.minRepeats(pstate)
+          val max = parser.maxRepeats(pstate)
+          val isBounded = parser.isBoundedMax(max)
+          val erd = parser.trd.asInstanceOf[ElementRuntimeData]
+
+          parser.startArray(pstate)
+
+          //
+          // There are two kinds of loops. Arrays which have points of uncertainty (PoU)
+          // where speculative parsing is used to determine how many occurrences,
+          // and specified-number of occurrences, where a number is known or is computed.
+          //
+          parser.hasPoU match {
+            case true => {
+              //
+              // This case for array/optionals where the number of occurences is
+              // determined by speculative parsing. OCK=implicit with min/maxOccurs
+              // different, or OCK=parsed.
+              //
+
+              //
+              // The beforeArrayState will be assigned the priorState before the whole array
+              // This is the same object as the priorState before the first
+              // occurrence.
+              //
+              var beforeArrayState: PState.Mark = null
+
+              var resultOfTry: ParseAttemptStatus = ParseAttemptStatus.Uninitialized
+
+              var ais: ArrayIndexStatus = null
+              var goAIS: GoArrayIndexStatus = null
+
+              var isFirstIteration = true
+
+              while ({
+                ais = parser.arrayIndexStatus(min, max, pstate, resultOfTry)
+                ais match {
+                  case go: GoArrayIndexStatus => { goAIS = go; true }
+                  case _ => false
+                }
+              }) {
+
+                //
+                // Saved state before an individual occurrence.
+                //
+                // On the first iteration this is the same as the beforeArrayState
+                // and by "same" we mean same object in the 'eq' sense.
+                //
+                // If we are in a second or subsequent iteration then an invariant is
+                // that this is NOT the same as the beforeArrayState.
+                //
+                // These should not leak as we iterate the occurrences.
+                // The lifetime of these is the parse attempt for a single occurrence
+                // only.
+                //
+                val priorState =
+                  if (isFirstIteration) {
+                    beforeArrayState = pstate.mark("before all occurrences")
+                    beforeArrayState
+                  } else {
+                    pstate.mark("before second/subsequent occurrence")
+                  }
+
+                checkN(pstate) // check if arrayIndex exceeds tunable limit.
+
+                var markLeakCausedByException = false
+                var wasThrow = true
+                try {
+                  resultOfTry =
+                    parseOneWithPoU(parser, erd, pstate, priorState, goAIS, isBounded)
+                  wasThrow = false
+                  //
+                  // Now we handle the result of the parse attempt.
+                  //
+
+                  // check for consistency - failure comes with a PE in the PState.
+                  Assert.invariant((pstate.processorStatus eq Success) ||
+                    resultOfTry.isInstanceOf[FailedParseAttemptStatus])
+
+                  resultOfTry match {
+                    //
+                    // These statuses for whole array/optional are not used
+                    // for PoU occurrences.
+                    //
+                    case ParseAttemptStatus.Failed_EntireArray |
+                      ParseAttemptStatus.Success_EndOfArray =>
+                      Assert.invariantFailed("not valid return status for a PoU array/optional.")
+
+                    case ParseAttemptStatus.Success_SkippedSeparator => {
+                      //
+                      // In the case of separated sequences when we skip just the separator,
+                      // the parseWithOnePoU method has handled the reset to priorState
+                      // and advance past the separator. It has to, as it knows
+                      // how long the separator was.
+                      //
+                      wasLastChildZeroLength = true
+                    }
+                    case _: SuccessParseAttemptStatus => {
+                      pstate.mpstate.moveOverOneGroupIndexOnly()
+                      //
+                      // Here we leave beforeArrayState alone. May still
+                      // need it later.
+                      //
+                      wasLastChildZeroLength = resultOfTry eq ParseAttemptStatus.Success_ZeroLength
+                    }
+
+                    case ParseAttemptStatus.Failed_WithDiscriminatorSet => {
+                      // Just allow the failure to propagate.
+                    }
+
+                    case ParseAttemptStatus.Failed_SpeculativeParse => {
+                      // We failed.
+                      goAIS match {
+                        case ArrayIndexStatus.Required => {
+                          //
+                          // Did we reach minOccurs? I.e., did we fail on a required element?
+                          // if so, then we failed the whole array
+                          //
+                          // Grab the cause, restore the state prior to the whole array,
+                          // then re-assert the failure cause.
+                          //
+                          val Failure(cause) = pstate.processorStatus
+
+                          //
+                          // Discarding has to be done before resetting of an outer/earlier mark
+                          // because the InputDataStream marks are unwound in a stack manner. I.e., resetting
+                          // to an earlier one implicitly discards any nested within that.
+                          //
+                          // This was causing a problem when we didn't discard priorState until later, since it
+                          // would then try to discard the InputDataStream's mark, and find it had already been
+                          // discarded.
+                          //
+                          if (!isFirstIteration) pstate.discard(priorState)
+                          pstate.reset(beforeArrayState)
+                          pstate.setFailed(cause)
+                          resultOfTry = ParseAttemptStatus.Failed_EntireArray
+                        }
+                        case _: OptionalArrayIndexStatus => {
+                          //
+                          // We failed on an optional element.
+                          // Means we back out and succeed on prior
+                          // (which might be none - could be no occurrences at all)
+                          //
+                          pstate.reset(priorState)
+                          //
+                          // The above doesn't reset the array index back to the prior, because that is
+                          // advanced at the bottom of the loop before the priorState is captured for this
+                          // iteration, so the array index needs to back up by 1.
+                          //
+                          // We're done with the array, but the arrayPos still has to be correct for validation
+                          // purposes - it is used to measure how many occurrences.
+                          //
+                          pstate.mpstate.moveBackOneArrayIndexOnly()
+                          Assert.invariant(pstate.processorStatus eq Success)
+                          resultOfTry = ParseAttemptStatus.Success_EndOfArray
+                        }
+                      }
+                    }
+
+                    case ParseAttemptStatus.Failed_NoForwardProgress => {
+                      // Just allow the failure to propagate.
+                    }
+
+                    case other => Assert.invariantFailed("Unexpected parse attempt status: " + other)
+                  }
+
+                } catch {
+                  // Similar try/catch/finally logic for returning marks is also used in
+                  // the Choice parser. The logic isn't
+                  // easily factored out so it is duplicated. Changes made here should also
+                  // be made there. Only these parsers deal with taking marks, so this logic
+                  // should not be needed elsewhere.
+                  case t: Throwable => {
+                    if (pstate.isInUse(priorState)) {
+                      markLeakCausedByException = true
+                      if (!t.isInstanceOf[SchemaDefinitionDiagnosticBase] && !t.isInstanceOf[UnsuppressableException]) {
+                        val stackTrace = new StringWriter()
+                        t.printStackTrace(new PrintWriter(stackTrace))
+                        Assert.invariantFailed("Exception thrown with mark not returned: " + t + "\nStackTrace:\n" + stackTrace)
+                      }
+                    }
+                    throw t
+                  }
+                }
+                // if it wasn't reset, we discard priorState here.
+                if (!isFirstIteration && pstate.isInUse(priorState)) {
+                  pstate.discard(priorState)
+                }
+
+                //
+                // advance array position.
+                // Done unconditionally, as some failures get converted into successes
+                //
+                // If ultimately this is a real failure, then mothing cares about this, it is
+                // about to get poppped/cleared anyway.
+                //
+                pstate.mpstate.moveOverOneArrayIndexOnly()
+                isFirstIteration = false
+
+              } // end while for each repeat
+
+              // if it wasn't reset or discarded, discard here.
+              if (pstate.isInUse(beforeArrayState)) {
+                pstate.discard(beforeArrayState)
+              }
+
+            } // end match case hasPoU = true
+
+            case false => {
+              //
+              // This case for array/optionals where the number of occurences is
+              // specified or fixed. dfdl:occursCountKind='expression' or 'fixed'
+              // or 'implicit' when minOccurs = maxOccurs.
+              //
+
+              var resultOfTry: ParseAttemptStatus = ParseAttemptStatus.Uninitialized
+              var ais: ArrayIndexStatus = null
+              var goAIS: GoArrayIndexStatus = null
+
+              while ({
+                ais = parser.arrayIndexStatus(min, max, pstate, resultOfTry)
+                ais match {
+                  case go: GoArrayIndexStatus => { goAIS = go; true }
+                  case _ => false
+                }
+              }) {
+
+                checkN(pstate)
+                resultOfTry = parseOneWithoutPoU(parser, parser.trd, pstate)
+                resultOfTry match {
+                  case ParseAttemptStatus.Success_EndOfArray => // ok, success will move on to next sequence child.
+                  case _: SuccessParseAttemptStatus => {
+                    pstate.mpstate.moveOverOneGroupIndexOnly() // advance group position
+                    pstate.mpstate.moveOverOneArrayIndexOnly() // advance array position
+                  }
+                  case _: FailedParseAttemptStatus => // ok, failure will propagate from pstate.
+                  case ParseAttemptStatus.Uninitialized =>
+                    Assert.invariantFailed("Cannot be uninitialized")
+                }
+                wasLastChildZeroLength = resultOfTry eq ParseAttemptStatus.Success_ZeroLength
+              } // end while for each occurrence
+            } // end match case hasPoU == false
+          } // end match hasPoU
+          parser.endArray(pstate)
+        } // end match case RepeatingChildParser
+
+        //
+        // This case for scalar parsers. This includes both scalar elements, and
+        // model group terms (choices, or sequences that are children of a sequence).
+        // A model group term is considered scalar
+        // in that they cannot be repeating at all in DFDL v1.0.
+        //
+        case scalarParser => {
+          val resultOfTry = parseOneWithoutPoU(scalarParser, scalarParser.trd, pstate)
+          if (resultOfTry.isSuccess) {
+            // only move over in group if the scalar "thing" is an element
+            // that is represented.
+            if (scalarParser.trd.isRepresented) {
+              // allows for non-represented elements, and if we add it to DFDL
+              // a concept of non-represented model groups - model groups containing
+              // only statement annotations for example, or only non-represented elements.
+              pstate.mpstate.moveOverOneGroupIndexOnly()
+            }
+          }
+          // in failure case, pstate indicates failure of this scalar, and
+          // we will exit the loop for the sequence's children.
+          wasLastChildZeroLength = resultOfTry eq ParseAttemptStatus.Success_ZeroLength
+        } // end match case scalar parser
+      } // end match
+      scpIndex += 1
+    } // end while for each sequence child parser
+
+    zeroLengthSpecialChecks(pstate, wasLastChildZeroLength)
+
+    pstate.mpstate.groupIndexStack.pop()
+    ()
+  }
+}
+
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SpecifiedLengthParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SpecifiedLengthParsers.scala
index b4b55d8ba..5785f52b2 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SpecifiedLengthParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SpecifiedLengthParsers.scala
@@ -28,15 +28,16 @@ import org.apache.daffodil.util.MaybeULong
 import passera.unsigned.ULong
 import org.apache.daffodil.equality._
 import java.lang.{ Long => JLong }
+import org.apache.daffodil.util.Maybe
 
-sealed abstract class SpecifiedLengthParserBase(eParser: Parser,
+sealed abstract class SpecifiedLengthParserBase(maybeEParser: Maybe[Parser],
   erd: ElementRuntimeData)
   extends CombinatorParser(erd)
   with CaptureParsingValueLength {
 
   override lazy val runtimeDependencies = Nil
 
-  override lazy val childProcessors = Seq(eParser)
+  override lazy val childProcessors = maybeEParser.toSeq
 
   override def charsetEv = Assert.invariantFailed("Specified Length parsers should not capture value length using the charset")
 
@@ -61,7 +62,8 @@ sealed abstract class SpecifiedLengthParserBase(eParser: Parser,
 
     val startingBitPos0b = dis.bitPos0b
     val isLimitOk: Boolean = dis.withBitLengthLimit(nBits) {
-      eParser.parse1(pState)
+      if (maybeEParser.isDefined) 
+        maybeEParser.get.parse1(pState)
     }
     Assert.invariant(isLimitOk)
 
@@ -88,10 +90,10 @@ sealed abstract class SpecifiedLengthParserBase(eParser: Parser,
 }
 
 class SpecifiedLengthPatternParser(
-  eParser: Parser,
+  maybeEParser: Maybe[Parser],
   erd: ElementRuntimeData,
   pattern: java.util.regex.Pattern)
-  extends SpecifiedLengthParserBase(eParser, erd) {
+  extends SpecifiedLengthParserBase(maybeEParser, erd) {
 
   object withMatcher extends OnStack[Matcher](pattern.matcher(""))
 
@@ -114,11 +116,11 @@ class SpecifiedLengthPatternParser(
 }
 
 class SpecifiedLengthExplicitParser(
-  eParser: Parser,
+  maybeEParser: Maybe[Parser],
   erd: ElementRuntimeData,
   lengthEv: Evaluatable[JLong],
   toBits: Int)
-  extends SpecifiedLengthParserBase(eParser, erd) {
+  extends SpecifiedLengthParserBase(maybeEParser, erd) {
 
   final override def getBitLength(s: PState): MaybeULong = {
     val nBytesAsAny = lengthEv.evaluate(s)
@@ -128,10 +130,10 @@ class SpecifiedLengthExplicitParser(
 }
 
 class SpecifiedLengthImplicitParser(
-  eParser: Parser,
+  maybeEParser: Maybe[Parser],
   erd: ElementRuntimeData,
   nBits: Long)
-  extends SpecifiedLengthParserBase(eParser, erd) {
+  extends SpecifiedLengthParserBase(maybeEParser, erd) {
 
   final override def getBitLength(s: PState): MaybeULong = MaybeULong(nBits)
 }
@@ -150,9 +152,9 @@ class SpecifiedLengthImplicitParser(
  * characters, as we're going to recursively descend and parse it into the complex structure.
  */
 sealed abstract class SpecifiedLengthCharactersParserBase(
-  eParser: Parser,
+  maybeEParser: Maybe[Parser],
   erd: ElementRuntimeData)
-  extends SpecifiedLengthParserBase(eParser, erd) {
+  extends SpecifiedLengthParserBase(maybeEParser, erd) {
 
   private def maybeBitPosAfterNChars(start: PState, nChars: Long): MaybeULong = {
     val dis = start.dataInputStream
@@ -193,20 +195,20 @@ sealed abstract class SpecifiedLengthCharactersParserBase(
 }
 
 final class SpecifiedLengthImplicitCharactersParser(
-  eParser: Parser,
+  maybeEParser: Maybe[Parser],
   erd: ElementRuntimeData,
   nChars: Long)
-  extends SpecifiedLengthCharactersParserBase(eParser, erd) {
+  extends SpecifiedLengthCharactersParserBase(maybeEParser, erd) {
 
   override def getCharLength(s: PState) = nChars
 
 }
 
 final class SpecifiedLengthExplicitCharactersParser(
-  eParser: Parser,
+  maybeEParser: Maybe[Parser],
   erd: ElementRuntimeData,
   lengthEv: Evaluatable[JLong])
-  extends SpecifiedLengthCharactersParserBase(eParser, erd) {
+  extends SpecifiedLengthCharactersParserBase(maybeEParser, erd) {
 
   def getCharLength(s: PState): Long = {
     val nChars = lengthEv.evaluate(s)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/StringLengthParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/StringLengthParsers.scala
index 5d9455016..d1ca18830 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/StringLengthParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/StringLengthParsers.scala
@@ -27,7 +27,7 @@ import org.apache.daffodil.processors.CharsetEv
 /**
  * Specifically designed to be used inside one of the SpecifiedLength parsers.
  * override
- * This grabs a string as long as it coverride an get, depending on the SpecifiedLength context
+ * This grabs a string as long as it can get, depending on the SpecifiedLength context
  * to constrain how much it can get.
  */
 final class StringOfSpecifiedLengthParser(
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnseparatedSequenceParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnseparatedSequenceParsers.scala
new file mode 100644
index 000000000..b39269530
--- /dev/null
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnseparatedSequenceParsers.scala
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.processors.parsers
+
+import org.apache.daffodil.processors.{ SequenceRuntimeData, Success, TermRuntimeData }
+import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.processors.Failure
+import org.apache.daffodil.processors.OccursCountEv
+
+trait Unseparated { self: SequenceChildParser =>
+
+  val childProcessors = Seq(childParser)
+}
+
+class ScalarOrderedUnseparatedSequenceChildParser(
+  override val childParser: Parser,
+  override val srd: SequenceRuntimeData,
+  override val trd: TermRuntimeData)
+  extends SequenceChildParser(childParser, srd, trd) with Unseparated {
+
+  override protected def parse(state: PState) = childParser.parse1(state)
+}
+
+class RepOrderedExactlyNUnseparatedSequenceChildParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData,
+  val repeatCount: Long)
+  extends OccursCountExactParser(childParser, srd, erd)
+  with Unseparated
+
+class RepOrderedExactlyTotalOccursCountUnseparatedSequenceChildParser(
+  childParser: Parser,
+  ocEv: OccursCountEv,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData)
+  extends OccursCountExpressionParser(childParser, srd, erd, ocEv)
+  with Unseparated
+
+class RepOrderedWithMinMaxUnseparatedSequenceChildParser(
+  childParser: Parser,
+  srd: SequenceRuntimeData,
+  erd: ElementRuntimeData) // pass -2 to force unbounded behavior
+  extends OccursCountMinMaxParser(childParser, srd, erd)
+  with Unseparated
+
+class OrderedUnseparatedSequenceParser(rd: SequenceRuntimeData, childParsersArg: Seq[SequenceChildParser])
+  extends OrderedSequenceParserBase(rd, childParsersArg) {
+
+  /**
+   * Parses (1) one iteration of an array with fixed/expression occurs count.
+   * (2) a model group (3) a scalar element.
+   *
+   * Returns a status indicating success/failure and the nature of that success/failure.
+   *
+   * No backtracking supported.
+   */
+  override protected def parseOneWithoutPoU(
+    parser: SequenceChildParser,
+    trd: TermRuntimeData,
+    pstate: PState): ParseAttemptStatus = {
+
+    if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
+
+    parser.parse1(pstate)
+
+    if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
+
+    val childSuccessful = pstate.processorStatus eq Success
+
+    val res: ParseAttemptStatus = pstate.processorStatus match {
+      case Success => {
+
+        Assert.invariant(childSuccessful)
+        //
+        // successful parse of required element. Zero length or not.
+        //
+        ParseAttemptStatus.Success_LengthUndetermined
+      }
+      case _ => {
+        //
+        // There are no PoU for this case, so a failure fails everything.
+        //
+        ParseAttemptStatus.Failed_EntireArray
+      }
+    }
+    res
+  }
+
+  /**
+   * Parses one iteration of an array/optional element, and returns
+   * a status indicating success/failure and the nature of that success/failure.
+   *
+   * Does not modify priorState.
+   */
+  override protected def parseOneWithPoU(
+    parser: RepeatingChildParser,
+    erd: ElementRuntimeData,
+    pstate: PState,
+    priorStateArg: PState.Mark,
+    aisArg: GoArrayIndexStatus,
+    isBounded: Boolean): ParseAttemptStatus = {
+
+    Assert.invariant(erd.isArray || erd.isOptional) // not a PoU otherwise.
+
+    pstate.pushDiscriminator
+
+    if (pstate.dataProc.isDefined) pstate.dataProc.get.beforeRepetition(pstate, this)
+
+    val posBefore = pstate.bitPos0b
+
+    parser.parse1(pstate)
+
+    if (pstate.dataProc.isDefined) pstate.dataProc.get.afterRepetition(pstate, this)
+
+    val res: ParseAttemptStatus =
+      pstate.processorStatus match {
+        case Success => {
+          if (posBefore == pstate.bitPos0b) {
+            if (isBounded) {
+              // ok to have no forward progress, so long as iterations are bounded
+              ParseAttemptStatus.Success_ZeroLength
+            } else {
+              //
+              // success but no forward progress in unbounded case
+              // This is the parser equivalent of an infinite loop.
+              //
+              PE(pstate,
+                "Repeating or Optional Element - No forward progress at byte %s. Attempt to parse %s " +
+                  "succeeded but consumed no data.\nPlease re-examine your schema to correct this infinite loop.",
+                pstate.bytePos, erd.diagnosticDebugName)
+              ParseAttemptStatus.Failed_NoForwardProgress
+            }
+          } else {
+            // ordinary success
+            ParseAttemptStatus.Success_NotZeroLength
+          }
+        }
+        case _: Failure => {
+          if (pstate.discriminator == true) {
+            ParseAttemptStatus.Failed_WithDiscriminatorSet
+          } else {
+            ParseAttemptStatus.Failed_SpeculativeParse
+          }
+        }
+      }
+    pstate.popDiscriminator
+    res
+  }
+
+  override protected def zeroLengthSpecialChecks(pstate: PState, wasLastChildZeroLength: Boolean): Unit = {
+    // Nothing for unseparated sequences
+  }
+}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/RepUnparsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/RepUnparsers.scala
index 3effbd577..1e4c789a5 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/RepUnparsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/RepUnparsers.scala
@@ -14,146 +14,146 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.daffodil.processors.unparsers
-
-import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.processors.ElementRuntimeData
-import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
-import org.apache.daffodil.processors.TermRuntimeData
-
-abstract class RepUnparser(n: Long, rUnparser: Unparser, context: ElementRuntimeData, baseName: String)
-  extends CombinatorUnparser(context) {
-
-  override lazy val childProcessors = Seq(rUnparser)
-
-  val intN = n.toInt
-
-  def checkN(ustate: UState, n: Long) {
-    if (n > ustate.tunable.maxOccursBounds) {
-      // TODO: how can we go after bigger than max int bytes? We have 64-bit computers
-      // after all....
-      UE(ustate, "Occurs count %s exceeds implementation maximum of %s.", n, ustate.tunable.maxOccursBounds)
-    }
-  }
-
-  final def unparse(ustate: UState): Unit = {
-    checkN(ustate, n)
-    unparseAllRepeats(ustate)
-  }
-
-  protected def unparseAllRepeats(ustate: UState): Unit
-
-  override def toString = "Rep" + baseName + "(" + rUnparser.toString + ")"
-
-  override def toBriefXML(depthLimit: Int = -1): String = {
-    if (depthLimit == 0) "..." else
-      "<Rep" + baseName + ">" + rUnparser.toBriefXML(depthLimit - 1) +
-        "</Rep" + baseName + ">"
-  }
-}
-
-/**
- * This object is so that we can share the iteration idioms between situations
- * where we know N statically, and where dynamic evaluation computes N.
- *
- * In these cases, there are no new points of uncertainty because computed or
- * otherwise, we know N.
- */
-object Rep {
-  def loopExactlyTotalN(intN: Int, rUnparser: Unparser, ustate: UState, context: TermRuntimeData, iParser: Unparser): Unit = {
-    while (ustate.arrayPos <= intN && !ustate.isInspectArrayEnd) {
-      // Debugger.beforeRepetition(ustate, iParser)
-      rUnparser.unparse1(ustate)
-      // Debugger.afterRepetition(ustate, iParser)
-      ustate.moveOverOneArrayIndexOnly
-    }
-  }
-}
-
-class RepExactlyNUnparser(n: Long, rUnparser: Unparser, context: ElementRuntimeData)
-  extends RepUnparser(n, rUnparser, context, "ExactlyN") {
-
-  override lazy val runtimeDependencies = Nil
-
-  def unparseAllRepeats(ustate: UState) {
-    1 to intN foreach { _ =>
-      {
-        // Debugger.beforeRepetition(pResult, this)
-        rUnparser.unparse1(ustate)
-        // Debugger.afterRepetition(pResult, this)
-        ustate.moveOverOneArrayIndexOnly
-      }
-    }
-  }
-}
-
-class RepAtMostTotalNUnparser(n: Long, rUnparser: Unparser, erd: ElementRuntimeData)
-  extends RepUnparser(n, rUnparser, erd, "AtMostTotalN") {
-
-  override lazy val runtimeDependencies = Nil
-
-  def unparseAllRepeats(ustate: UState): Unit = {
-    while (ustate.arrayPos <= intN && !ustate.isInspectArrayEnd) {
-      // Debugger.beforeRepetition(ustate, this)
-      rUnparser.unparse1(ustate)
-      if (ustate.isInspectArrayEnd) return
-      // Debugger.afterRepetition(ustate, this)
-      ustate.moveOverOneArrayIndexOnly
-    }
-  }
-}
-
-class RepExactlyTotalNUnparser(n: Long, rUnparser: Unparser, context: ElementRuntimeData)
-  extends RepUnparser(n, rUnparser, context, "ExactlyTotalN") {
-
-  override lazy val runtimeDependencies = Nil
-
-  def unparseAllRepeats(ustate: UState) {
-    Rep.loopExactlyTotalN(intN, rUnparser, ustate, context, this)
-  }
-}
-
-/**
- * This is a bit tricky: Since we are streaming the elements to the unparser,
- * it will receive a DIArray element, but the length of that DIArray element at the
- * time it is received, will probably be 0 because the child elements (not even
- * one of them) will have been pulled yet. So we cannot just measure how big the array
- * is and iterate that many times. Rather, we have to iterate until we come to
- * an End(DIArray) event.
- *
- * This requires the ability to look ahead into the input stream by 1, see if it
- * is EndArray, and if so consume it and end the iteration.
- */
-class RepUnboundedUnparser(occursCountKind: OccursCountKind.Value, rUnparser: Unparser, erd: ElementRuntimeData)
-  extends RepUnparser(-1, rUnparser, erd, "Unbounded") {
-
-  override lazy val runtimeDependencies = Nil
-
-  def unparseAllRepeats(ustate: UState) {
-    Assert.invariant(ustate.currentInfosetNodeMaybe.isDefined)
-    while (!ustate.isInspectArrayEnd) {
-      // Debugger.beforeRepetition(ustate, this)
-      rUnparser.unparse1(ustate)
-      // Debugger.afterRepetition(ustate, this)
-      ustate.moveOverOneArrayIndexOnly
-    }
-  }
-}
-
-//
-// Unparsers don't evaluate or use expression values. The number of occurrences is the number
-// in the infoset (augmented up to minOccurs with default values when appropriate)
-//
-
-class RepAtMostOccursCountUnparser(rUnparser: Unparser, intN: Long, erd: ElementRuntimeData)
-  extends RepUnparser(intN, rUnparser, erd, "AtMostOccursCount") {
-
-  override lazy val runtimeDependencies = Nil
-
-  def unparseAllRepeats(ustate: UState) {
-    // repeat either n times, or occursCount times if that's less than n.
-    // val n = math.min(ustate.occursBounds, erd.minOccurs.get)
-    Rep.loopExactlyTotalN(intN.toInt, rUnparser, ustate, erd, this)
-  }
-}
+//
+//package org.apache.daffodil.processors.unparsers
+//
+//import org.apache.daffodil.exceptions.Assert
+//import org.apache.daffodil.processors.ElementRuntimeData
+//import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
+//import org.apache.daffodil.processors.TermRuntimeData
+//
+//abstract class RepUnparser(n: Long, rUnparser: Unparser, context: ElementRuntimeData, baseName: String)
+//  extends CombinatorUnparser(context) {
+//
+//  override lazy val childProcessors = Seq(rUnparser)
+//
+//  val intN = n.toInt
+//
+//  def checkN(ustate: UState, n: Long) {
+//    if (n > ustate.tunable.maxOccursBounds) {
+//      // TODO: how can we go after bigger than max int bytes? We have 64-bit computers
+//      // after all....
+//      UE(ustate, "Occurs count %s exceeds implementation maximum of %s.", n, ustate.tunable.maxOccursBounds)
+//    }
+//  }
+//
+//  final def unparse(ustate: UState): Unit = {
+//    checkN(ustate, n)
+//    unparseAllRepeats(ustate)
+//  }
+//
+//  protected def unparseAllRepeats(ustate: UState): Unit
+//
+//  override def toString = "Rep" + baseName + "(" + rUnparser.toString + ")"
+//
+//  override def toBriefXML(depthLimit: Int = -1): String = {
+//    if (depthLimit == 0) "..." else
+//      "<Rep" + baseName + ">" + rUnparser.toBriefXML(depthLimit - 1) +
+//        "</Rep" + baseName + ">"
+//  }
+//}
+//
+///**
+// * This object is so that we can share the iteration idioms between situations
+// * where we know N statically, and where dynamic evaluation computes N.
+// *
+// * In these cases, there are no new points of uncertainty because computed or
+// * otherwise, we know N.
+// */
+//object Rep {
+//  def loopExactlyTotalN(intN: Int, rUnparser: Unparser, ustate: UState, context: TermRuntimeData, iParser: Unparser): Unit = {
+//    while (ustate.arrayPos <= intN && !ustate.isInspectArrayEnd) {
+//      // Debugger.beforeRepetition(ustate, iParser)
+//      rUnparser.unparse1(ustate)
+//      // Debugger.afterRepetition(ustate, iParser)
+//      ustate.moveOverOneArrayIndexOnly
+//    }
+//  }
+//}
+//
+//class RepExactlyNUnparser(n: Long, rUnparser: Unparser, context: ElementRuntimeData)
+//  extends RepUnparser(n, rUnparser, context, "ExactlyN") {
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  def unparseAllRepeats(ustate: UState) {
+//    1 to intN foreach { _ =>
+//      {
+//        // Debugger.beforeRepetition(pResult, this)
+//        rUnparser.unparse1(ustate)
+//        // Debugger.afterRepetition(pResult, this)
+//        ustate.moveOverOneArrayIndexOnly
+//      }
+//    }
+//  }
+//}
+//
+//class RepAtMostTotalNUnparser(n: Long, rUnparser: Unparser, erd: ElementRuntimeData)
+//  extends RepUnparser(n, rUnparser, erd, "AtMostTotalN") {
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  def unparseAllRepeats(ustate: UState): Unit = {
+//    while (ustate.arrayPos <= intN && !ustate.isInspectArrayEnd) {
+//      // Debugger.beforeRepetition(ustate, this)
+//      rUnparser.unparse1(ustate)
+//      if (ustate.isInspectArrayEnd) return
+//      // Debugger.afterRepetition(ustate, this)
+//      ustate.moveOverOneArrayIndexOnly
+//    }
+//  }
+//}
+//
+//class RepExactlyTotalNUnparser(n: Long, rUnparser: Unparser, context: ElementRuntimeData)
+//  extends RepUnparser(n, rUnparser, context, "ExactlyTotalN") {
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  def unparseAllRepeats(ustate: UState) {
+//    Rep.loopExactlyTotalN(intN, rUnparser, ustate, context, this)
+//  }
+//}
+//
+///**
+// * This is a bit tricky: Since we are streaming the elements to the unparser,
+// * it will receive a DIArray element, but the length of that DIArray element at the
+// * time it is received, will probably be 0 because the child elements (not even
+// * one of them) will have been pulled yet. So we cannot just measure how big the array
+// * is and iterate that many times. Rather, we have to iterate until we come to
+// * an End(DIArray) event.
+// *
+// * This requires the ability to look ahead into the input stream by 1, see if it
+// * is EndArray, and if so consume it and end the iteration.
+// */
+//class RepUnboundedUnparser(occursCountKind: OccursCountKind.Value, rUnparser: Unparser, erd: ElementRuntimeData)
+//  extends RepUnparser(-1, rUnparser, erd, "Unbounded") {
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  def unparseAllRepeats(ustate: UState) {
+//    Assert.invariant(ustate.currentInfosetNodeMaybe.isDefined)
+//    while (!ustate.isInspectArrayEnd) {
+//      // Debugger.beforeRepetition(ustate, this)
+//      rUnparser.unparse1(ustate)
+//      // Debugger.afterRepetition(ustate, this)
+//      ustate.moveOverOneArrayIndexOnly
+//    }
+//  }
+//}
+//
+////
+//// Unparsers don't evaluate or use expression values. The number of occurrences is the number
+//// in the infoset (augmented up to minOccurs with default values when appropriate)
+////
+//
+//class RepAtMostOccursCountUnparser(rUnparser: Unparser, intN: Long, erd: ElementRuntimeData)
+//  extends RepUnparser(intN, rUnparser, erd, "AtMostOccursCount") {
+//
+//  override lazy val runtimeDependencies = Nil
+//
+//  def unparseAllRepeats(ustate: UState) {
+//    // repeat either n times, or occursCount times if that's less than n.
+//    // val n = math.min(ustate.occursBounds, erd.minOccurs.get)
+//    Rep.loopExactlyTotalN(intN.toInt, rUnparser, ustate, erd, this)
+//  }
+//}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
index 2d71eb0aa..d3785fb93 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
@@ -384,7 +384,7 @@ class UStateForSuspension(
   override def moveOverOneElementChildOnly() = die
   override def childPos = 0 // was die, but this is called when copying state during debugging.
 
-  override def occursBoundsStack = die
+  // override def occursBoundsStack = die
 
   override def pushDelimiters(node: DelimiterStackUnparseNode) = die
   override def popDelimiters() = die
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UnparseError.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UnparseError.scala
index 52cd22801..04e0ebaa4 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UnparseError.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UnparseError.scala
@@ -23,6 +23,7 @@ import org.apache.daffodil.util.Maybe._
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.Maybe._
 import org.apache.daffodil.exceptions.SchemaFileLocation
+import org.apache.daffodil.exceptions.Assert
 
 class UnparseAlternativeFailed(rd: TermRuntimeData, loc: DataLocation, val errors: Seq[Diagnostic])
   extends UnparseError(One(rd.schemaFileLocation), One(loc), Maybe.Nope, Maybe("Alternative failed. Reason(s): %s"), errors)
@@ -30,7 +31,7 @@ class UnparseAlternativeFailed(rd: TermRuntimeData, loc: DataLocation, val error
 object UnparseError {
   def apply(rd: Maybe[SchemaFileLocation], loc: Maybe[DataLocation], formatString: String, args: Any*) = {
     val ue = new UnparseError(rd, loc, Maybe.Nope, Maybe(formatString), args: _*)
-    throw ue
+    Assert.toss(ue)
   }
 }
 
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/Unparser.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/Unparser.scala
index 9442a67e2..ce7e29ef6 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/Unparser.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/Unparser.scala
@@ -140,25 +140,6 @@ trait SuspendableUnparser
   }
 }
 
-// No-op, in case an optimization lets one of these sneak thru.
-// TODO: make this fail, and test optimizer sufficiently to know these
-// do NOT get through.
-final class EmptyGramUnparser(override val context: TermRuntimeData = null) extends PrimUnparserNoData {
-
-  override lazy val runtimeDependencies = Nil
-
-  def unparse(ustate: UState) {
-    Assert.invariantFailed("EmptyGramUnparsers are all supposed to optimize out!")
-  }
-
-  override def isEmpty = true
-
-  override lazy val childProcessors = Nil
-
-  override def toBriefXML(depthLimit: Int = -1) = "<empty/>"
-  override def toString = toBriefXML()
-}
-
 final class ErrorUnparser(override val context: TermRuntimeData = null) extends PrimUnparserNoData {
 
   override lazy val runtimeDependencies = Nil
diff --git a/daffodil-tdml/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala b/daffodil-tdml/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index f34a2fb6a..06d967091 100644
--- a/daffodil-tdml/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -115,6 +115,13 @@ case object OnePassRoundTrip extends RoundTrip
  */
 case object TwoPassRoundTrip extends RoundTrip
 
+/**
+ * Unparse doesn't produce original data, parsing it doesn't produce the
+ * same infoset, but an equivalent infoset which if unparsed, reproduces
+ * the first unparse output.
+ */
+case object ThreePassRoundTrip extends RoundTrip
+
 private[tdml] object DFDLTestSuite {
 
   /**
@@ -125,6 +132,8 @@ private[tdml] object DFDLTestSuite {
       case "false" | "none" => NoRoundTrip
       case "true" | "onePass" => OnePassRoundTrip
       case "twoPass" => TwoPassRoundTrip
+      case "threePass" => ThreePassRoundTrip
+      case other => Assert.invariantFailed("String '%s' not valid for round trip".format(other))
     }
 
   type CompileResult = Either[Seq[Diagnostic], (Seq[Diagnostic], DFDL.DataProcessor)]
@@ -790,7 +799,7 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
 
     val testDataLength = lengthLimitInBits
     val outputter = new TDMLInfosetOutputter()
-    
+
     val dis = InputSourceDataInputStream(new ByteArrayInputStream(testData))
     if (testDataLength % 8 != 0) {
       // Only set the bit limit if the length is not a multiple of 8. In that
@@ -872,6 +881,44 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
     unparseResult
   }
 
+  private def doTwoPassRoundTripExpectSuccess(
+    processor: DFDL.DataProcessor,
+    firstPassInfosetOutputter: TDMLInfosetOutputter, // outputter from prior parse.
+    firstParseTestData: Array[Byte],
+    testInfoset: Infoset,
+    passesLabel: String = "Two-Pass"): (TDMLInfosetOutputter, DFDL.ParseResult, Array[Byte], Long) = {
+    val outStream = new java.io.ByteArrayOutputStream()
+    val unparseResult: UnparseResult = doOnePassRoundTripUnparseExpectSuccess(processor, outStream, firstPassInfosetOutputter)
+    val isUnparseOutputDataMatching =
+      try {
+        VerifyTestCase.verifyUnparserTestData(new ByteArrayInputStream(firstParseTestData), outStream)
+        true
+      } catch {
+        case e: TDMLException => {
+          false
+          //
+          // We got the failure we expect for a two-pass test on the unparse.
+          //
+        }
+      }
+    if (isUnparseOutputDataMatching) {
+      val msg = ("Expected data from first unparse of %s to NOT match original input, but it did match." +
+        "\nShould this really be a %s test?").format(passesLabel, passesLabel)
+      throw new TDMLException(msg)
+    }
+    // Try parse again, consuming the canonicalized data from the prior unparse.
+    val reParseTestData = outStream.toByteArray
+    val reParseTestDataLength = unparseResult.resultState.bitPos0b
+    // verify enough bytes for the bits.
+    val fullBytesNeeded = (reParseTestDataLength + 7) / 8
+    if (reParseTestData.length != fullBytesNeeded) {
+      throw new TDMLException("Unparse result data was was %d bytes, but the result length (%d bits) requires %d bytes.".format(
+        reParseTestData.length, reParseTestDataLength, fullBytesNeeded))
+    }
+    val (outputter, actual) = doParseExpectSuccess(reParseTestData, testInfoset, processor, reParseTestDataLength)
+    (outputter, actual, reParseTestData, reParseTestDataLength)
+  }
+
   def runParseExpectSuccess(processor: DFDL.DataProcessor,
     dataToParse: InputStream,
     lengthLimitInBits: Long,
@@ -899,65 +946,90 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
     // if we get here, the parse test passed. If we don't get here then some exception was
     // thrown either during the run of the test or during the comparison.
 
-      roundTrip match {
-        case NoRoundTrip => {
-          // done. Do nothing else.
-        }
-        case OnePassRoundTrip => {
-          val outStream = new java.io.ByteArrayOutputStream()
+    roundTrip match {
+      case NoRoundTrip => {
+        // done. Do nothing else.
+      }
+      case OnePassRoundTrip => {
+        val outStream = new java.io.ByteArrayOutputStream()
 
-          doOnePassRoundTripUnparseExpectSuccess(processor, outStream, firstPassInfosetOutputter)
+        doOnePassRoundTripUnparseExpectSuccess(processor, outStream, firstPassInfosetOutputter)
 
-          // It has to work, as this is one pass round trip. We expect it to unparse
-          // directly back to the original input form.
+        // It has to work, as this is one pass round trip. We expect it to unparse
+        // directly back to the original input form.
 
-          VerifyTestCase.verifyUnparserTestData(new ByteArrayInputStream(firstParseTestData), outStream)
-        }
-        case TwoPassRoundTrip => {
-          //
-          // In two-pass, the unparse comparison of data from first unparse
-          // to the original input data MUST fail.
-          // We need to unparse, then parse again to have the comparison work
-          // thereby showing that while the output data is different, it is
-          // equivalent in that re-parsing that data produces the same infoset
-          // that parsing the original data did.
-          //
-          val outStream = new java.io.ByteArrayOutputStream()
-          val unparseResult: UnparseResult = doOnePassRoundTripUnparseExpectSuccess(processor, outStream, firstPassInfosetOutputter)
-          val isUnparseOutputDataMatching =
-            try {
-              VerifyTestCase.verifyUnparserTestData(new ByteArrayInputStream(firstParseTestData), outStream)
-              true
-            } catch {
-              case e: TDMLException => {
-                false
-                //
-                // We got the failure we expect for a two-pass test on the unparse.
-                //
-              }
+        VerifyTestCase.verifyUnparserTestData(new ByteArrayInputStream(firstParseTestData), outStream)
+      }
+      case TwoPassRoundTrip => {
+        //
+        // In two-pass, the unparse comparison of data from first unparse
+        // to the original input data MUST fail.
+        // We need to unparse, then parse again to have the comparison work
+        // thereby showing that while the output data is different, it is
+        // equivalent in that re-parsing that data produces the same infoset
+        // that parsing the original data did.
+        //
+
+        val (outputter, actual, _, reParseTestDataLength) =
+          doTwoPassRoundTripExpectSuccess(
+            processor,
+            firstPassInfosetOutputter,
+            firstParseTestData,
+            testInfoset)
+        verifyParseResults(processor, actual, testInfoset, outputter)
+        verifyLeftOverData(actual, reParseTestDataLength)
+        // if it doesn't pass, it will throw out of here.
+      }
+      case ThreePassRoundTrip => {
+        //
+        // In three-pass, the unparse comparison of data from first unparse
+        // to the original input data MUST fail.
+        // We need to unparse, then parse again and the infoset comparison
+        // must ALSO fail.
+        // Then we unparse again, and get same data as the first unparse.
+        // At that point we're in steady state.
+        //
+        // This mode is needed due to asymmetric separator suppression policies
+        // like anyEmpty which allow a separator for a zero-length optional element to
+        // appear in the data, but when unparsing will not output this separator,
+        // so when reparsed, the infoset won't have the element.
+        //
+        val (secondPassInfosetOutputter, secondPassActual, reParseTestData, reParseTestDataLength) =
+          doTwoPassRoundTripExpectSuccess(
+            processor,
+            firstPassInfosetOutputter,
+            firstParseTestData,
+            testInfoset,
+            "Three-Pass")
+        val isUnparseOutputDataMatching =
+          try {
+            verifyParseResults(processor, actual, testInfoset, secondPassInfosetOutputter)
+            verifyLeftOverData(secondPassActual, reParseTestDataLength)
+            true
+          } catch {
+            case e: TDMLException => {
+              false
+              //
+              // We got the failure we expect for a three-pass test on the reparse.
+              //
             }
-          if (isUnparseOutputDataMatching) {
-            throw new TDMLException("Expected data from first unparse of Two-Pass to NOT match original input, but it did match." +
-              "\nShould this really be a Two-Pass test?")
-          }
-          // Try parse again, consuming the canonicalized data from the prior unparse.
-          val reParseTestData = outStream.toByteArray
-          val reParseTestDataLength = unparseResult.resultState.bitPos0b
-          // verify enough bytes for the bits.
-          val fullBytesNeeded = (reParseTestDataLength + 7) / 8
-          if (reParseTestData.length != fullBytesNeeded) {
-            throw new TDMLException("Unparse result data was was %d bytes, but the result length (%d bits) requires %d bytes.".format(
-              reParseTestData.length, reParseTestDataLength, fullBytesNeeded))
           }
-          val (outputter, actual) = doParseExpectSuccess(reParseTestData, testInfoset, processor, reParseTestDataLength)
-          verifyParseResults(processor, actual, testInfoset, outputter)
-          verifyLeftOverData(actual, reParseTestDataLength)
-          // if it doesn't pass, it will throw out of here.
+        if (isUnparseOutputDataMatching) {
+          throw new TDMLException("Expected infoset from reparse of Three-Pass to NOT match original infoset, but it did match." +
+            "\nShould this really be a Three-Pass test?")
         }
+        //
+        // So now we do the third pass unparse and compare this output with the
+        // first unparsed output.
+        //
+        // We get to reuse the one-pass code here.
+        val thirdPassOutStream = new java.io.ByteArrayOutputStream()
+        doOnePassRoundTripUnparseExpectSuccess(processor, thirdPassOutStream, firstPassInfosetOutputter)
+        VerifyTestCase.verifyUnparserTestData(new ByteArrayInputStream(reParseTestData), thirdPassOutStream)
       }
     }
   }
-
+}
 
 case class UnparserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
   extends TestCase(ptc, parentArg) {
@@ -1178,7 +1250,12 @@ object VerifyTestCase {
 
     val expectedForCompare = XMLUtils.removeAttributes(XMLUtils.convertPCDataToText(expected))
 
-    XMLUtils.compareAndReport(expectedForCompare, actualForCompare)
+    try {
+      XMLUtils.compareAndReport(expectedForCompare, actualForCompare)
+    } catch {
+      case e: Exception =>
+        throw new TDMLException(e)
+    }
   }
 
   def verifyUnparserTestData(expectedData: InputStream, actualOutStream: java.io.ByteArrayOutputStream) {
@@ -1275,7 +1352,7 @@ object VerifyTestCase {
     val finfo = new FormatInfoForTDMLDecode
     val cb = CharBuffer.allocate(256)
     val sb = new StringBuilder(256)
-    while( { val numDecoded = decoder.decode(dis, finfo, cb); numDecoded > 0 } ) {
+    while ({ val numDecoded = decoder.decode(dis, finfo, cb); numDecoded > 0 }) {
       cb.flip()
       sb.append(cb)
       cb.clear()
@@ -1314,6 +1391,8 @@ object VerifyTestCase {
       if (str.length <= maxTextCharsToShow) str
       else str.substring(0, maxTextCharsToShow) + "..."
     }
+    val actualCharsToShow = if (actualText.length == 0) "" else " for '" + trimToMax(actualText) + "'"
+    val expectedCharsToShow = if (expectedText.length == 0) "" else " for '" + trimToMax(expectedText) + "'"
     if (actualText.length != expectedText.length) {
       val actualCharsToShow = if (actualText.length == 0) "" else " for '" + trimToMax(actualText) + "'"
       val expectedCharsToShow = if (expectedText.length == 0) "" else " for '" + trimToMax(expectedText) + "'"
@@ -1325,7 +1404,8 @@ object VerifyTestCase {
     pairs.foreach {
       case ((expected, actual), index) =>
         if (expected != actual) {
-          val msg = "Unparsed data differs at character %d. Expected '%s'. Actual was '%s'".format(index, expected, actual)
+          val msg = "Unparsed data differs at character %d. Expected '%s'. Actual was '%s'. Expected data %s, actual data %s".format(
+            index, expected, actual, expectedCharsToShow, actualCharsToShow)
           throw new TDMLException(msg)
         }
     }
diff --git a/daffodil-tdml/src/test/scala/org/apache/daffodil/tdml/TestTDMLRoundTrips.scala b/daffodil-tdml/src/test/scala/org/apache/daffodil/tdml/TestTDMLRoundTrips.scala
index 051043df3..4028393e4 100644
--- a/daffodil-tdml/src/test/scala/org/apache/daffodil/tdml/TestTDMLRoundTrips.scala
+++ b/daffodil-tdml/src/test/scala/org/apache/daffodil/tdml/TestTDMLRoundTrips.scala
@@ -105,41 +105,70 @@ class TestTDMLRoundTrips {
     assertTrue(m.toLowerCase.contains("unparsed data differs"))
   }
 
+  def needsTwoPassesOnlyTDML(passesEnum: String) =
+    <ts:testSuite xmlns:dfdl={ dfdl } xmlns:xs={ xsd } xmlns:ex={ example } xmlns:ts={ tdml } suiteName="theSuiteName">
+      <ts:defineSchema name="s">
+        <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+        <dfdl:format ref="ex:GeneralFormat"/>
+        <xs:element name="r" dfdl:lengthKind="implicit">
+          <xs:complexType>
+            <xs:sequence dfdl:separator="; ,">
+              <xs:element name="foo" type="xs:string" dfdl:lengthKind="delimited"/>
+              <xs:element name="bar" type="xs:string" dfdl:lengthKind="delimited"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </ts:defineSchema>
+      <ts:parserTestCase ID="test1" name="test1" root="r" model="s" roundTrip={ passesEnum }>
+        <ts:infoset>
+          <ts:dfdlInfoset>
+            <ex:r>
+              <foo>foo</foo>
+              <bar>bar</bar>
+            </ex:r>
+          </ts:dfdlInfoset>
+        </ts:infoset>
+        <ts:document>foo,bar</ts:document>
+      </ts:parserTestCase>
+    </ts:testSuite>
+
   /**
    * A test defined to show that we need two-passes, so that we re-parse
    * the canonical data from the unparse and then get a matching infoset.
    */
   @Test def testTwoPass1() {
 
-    val testSuite = <ts:testSuite xmlns:dfdl={ dfdl } xmlns:xs={ xsd } xmlns:ex={ example } xmlns:ts={ tdml } suiteName="theSuiteName">
-                      <ts:defineSchema name="s">
-                        <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
-                        <dfdl:format ref="ex:GeneralFormat"/>
-                        <xs:element name="r" dfdl:lengthKind="implicit">
-                          <xs:complexType>
-                            <xs:sequence dfdl:separator="; ,">
-                              <xs:element name="foo" type="xs:string" dfdl:lengthKind="delimited"/>
-                              <xs:element name="bar" type="xs:string" dfdl:lengthKind="delimited"/>
-                            </xs:sequence>
-                          </xs:complexType>
-                        </xs:element>
-                      </ts:defineSchema>
-                      <ts:parserTestCase ID="test1" name="test1" root="r" model="s" roundTrip="twoPass">
-                        <ts:infoset>
-                          <ts:dfdlInfoset>
-                            <ex:r>
-                              <foo>foo</foo>
-                              <bar>bar</bar>
-                            </ex:r>
-                          </ts:dfdlInfoset>
-                        </ts:infoset>
-                        <ts:document>foo,bar</ts:document>
-                      </ts:parserTestCase>
-                    </ts:testSuite>
+    val testSuite = needsTwoPassesOnlyTDML("twoPass")
     lazy val ts = new DFDLTestSuite(testSuite)
     ts.runOneTest("test1")
   }
 
+  def nPassNotNeededTDML(passesEnum: String) =
+    <ts:testSuite xmlns:dfdl={ dfdl } xmlns:xs={ xsd } xmlns:ex={ example } xmlns:ts={ tdml } suiteName="theSuiteName">
+      <ts:defineSchema name="s">
+        <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+        <dfdl:format ref="ex:GeneralFormat"/>
+        <xs:element name="r" dfdl:lengthKind="implicit">
+          <xs:complexType>
+            <xs:sequence dfdl:separator=",">
+              <xs:element name="foo" type="xs:string" dfdl:lengthKind="delimited"/>
+              <xs:element name="bar" type="xs:string" dfdl:lengthKind="delimited"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </ts:defineSchema>
+      <ts:parserTestCase ID="test1" name="test1" root="r" model="s" roundTrip={ passesEnum }>
+        <ts:infoset>
+          <ts:dfdlInfoset>
+            <ex:r>
+              <foo>foo</foo>
+              <bar>bar</bar>
+            </ex:r>
+          </ts:dfdlInfoset>
+        </ts:infoset>
+        <ts:document>foo,bar</ts:document>
+      </ts:parserTestCase>
+    </ts:testSuite>
   /**
    * A test defined to show that when we say we need two passes, if the
    * unparse data in fact matches the original (i.e., we didn't really need two passes)
@@ -149,32 +178,7 @@ class TestTDMLRoundTrips {
    * or two-pass, and label the test accordingly.
    */
   @Test def testTwoPassNotNeeded1() {
-
-    val testSuite = <ts:testSuite xmlns:dfdl={ dfdl } xmlns:xs={ xsd } xmlns:ex={ example } xmlns:ts={ tdml } suiteName="theSuiteName">
-                      <ts:defineSchema name="s">
-                        <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
-                        <dfdl:format ref="ex:GeneralFormat"/>
-                        <xs:element name="r" dfdl:lengthKind="implicit">
-                          <xs:complexType>
-                            <xs:sequence dfdl:separator=",">
-                              <xs:element name="foo" type="xs:string" dfdl:lengthKind="delimited"/>
-                              <xs:element name="bar" type="xs:string" dfdl:lengthKind="delimited"/>
-                            </xs:sequence>
-                          </xs:complexType>
-                        </xs:element>
-                      </ts:defineSchema>
-                      <ts:parserTestCase ID="test1" name="test1" root="r" model="s" roundTrip="twoPass">
-                        <ts:infoset>
-                          <ts:dfdlInfoset>
-                            <ex:r>
-                              <foo>foo</foo>
-                              <bar>bar</bar>
-                            </ex:r>
-                          </ts:dfdlInfoset>
-                        </ts:infoset>
-                        <ts:document>foo,bar</ts:document>
-                      </ts:parserTestCase>
-                    </ts:testSuite>
+    val testSuite = nPassNotNeededTDML("twoPass")
     lazy val ts = new DFDLTestSuite(testSuite)
     val e = intercept[TDMLException] {
       ts.runOneTest("test1")
@@ -188,7 +192,6 @@ class TestTDMLRoundTrips {
    * the canonical data from the unparse and then still do not get a matching infoset,
    * but unparsing that infoset finally does give us matching unparsed data.
    */
-  /*
   @Test def testThreePass1() {
     val testSuite = <ts:testSuite xmlns:dfdl={ dfdl } xmlns:xs={ xsd } xmlns:xsi={ xsi } xmlns:fn={ fn } xmlns:ex={ example } xmlns:ts={ tdml } suiteName="theSuiteName">
                       <ts:defineSchema name="s" elementFormDefault="unqualified">
@@ -196,9 +199,9 @@ class TestTDMLRoundTrips {
                         <dfdl:format ref="ex:GeneralFormat"/>
                         <xs:element name="r" dfdl:lengthKind="implicit">
                           <xs:complexType>
-                            <xs:sequence dfdl:separator=",">
-                              <xs:element name="foo" nillable="true" type="xs:string" dfdl:lengthKind="delimited" dfdl:useNilForDefault="yes" dfdl:nilKind="literalValue" dfdl:nilValue="%ES; nil" dfdl:outputValueCalc="{ ../bar }"/>
-                              <xs:element name="bar" type="xs:string" dfdl:inputValueCalc="{ if (fn:nilled(../foo)) then '' else 'foo' }"/>
+                            <xs:sequence dfdl:separator="," dfdl:separatorSuppressionPolicy="anyEmpty">
+                              <xs:element name="foo" type="xs:string" dfdl:lengthKind="delimited"/>
+                              <xs:element name="bar" type="xs:string" dfdl:lengthKind="delimited" minOccurs="0" dfdl:occursCountKind="implicit"/>
                             </xs:sequence>
                           </xs:complexType>
                         </xs:element>
@@ -212,11 +215,43 @@ class TestTDMLRoundTrips {
                             </ex:r>
                           </ts:dfdlInfoset>
                         </ts:infoset>
-                        <ts:document></ts:document>
+                        <ts:document>foo,</ts:document>
                       </ts:parserTestCase>
                     </ts:testSuite>
     lazy val ts = new DFDLTestSuite(testSuite)
     ts.runOneTest("test1")
   }
-  */
+
+  /**
+   * A test defined to show that when we say we need three passes, if the
+   * unparse data in fact matches the original (i.e., we didn't
+   * even really need two passes, that it is detected and reported.
+   */
+  @Test def testThreePassNotNeeded1() {
+    val testSuite = nPassNotNeededTDML("threePass")
+    lazy val ts = new DFDLTestSuite(testSuite)
+    val e = intercept[TDMLException] {
+      ts.runOneTest("test1")
+    }
+    val m = e.getMessage()
+    assertTrue(m.toLowerCase.contains("should this really be a three-pass test"))
+  }
+
+  /**
+   * A test defined to show that when we say we need three passes, if the
+   * reparsed unparse data in fact matches the original infoset (i.e., we didn't
+   * even really need three passes, two would have been enough),
+   * that it is detected and reported.
+   */
+  @Test def testThreePassNotNeeded2() {
+
+    val testSuite = needsTwoPassesOnlyTDML("threePass")
+    lazy val ts = new DFDLTestSuite(testSuite)
+    val e = intercept[TDMLException] {
+      ts.runOneTest("test1")
+    }
+    val m = e.getMessage()
+    assertTrue(m.toLowerCase.contains("should this really be a three-pass test"))
+  }
+
 }
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/alignment_bytes_12.dfdl.xsd b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/alignment_bytes_12.dfdl.xsd
index bf2224925..fe474ef88 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/alignment_bytes_12.dfdl.xsd
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/alignment_bytes_12.dfdl.xsd
@@ -31,7 +31,7 @@
 					alignment="1" alignmentUnits="bytes" fillByte="f" leadingSkip="0" trailingSkip="0"
 					ignoreCase="no" lengthKind="implicit" sequenceKind="ordered"
 					initiatedContent="no"	textPadKind="none" textTrimKind="none" textStringJustification="left"
-					occursCountKind="implicit"	
+					occursCountKind="implicit" separatorSuppressionPolicy="trailingEmpty"
                     bitOrder="mostSignificantBitFirst"
 					/>
 				
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpabol101.dfdl.xsd b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpabol101.dfdl.xsd
index 7f9712e60..21ec46b35 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpabol101.dfdl.xsd
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpabol101.dfdl.xsd
@@ -26,7 +26,7 @@
 			<dfdl:format initiator="" terminator="" leadingSkip="0" trailingSkip="0" truncateSpecifiedLengthString="no"  separator="" textBidi="no" floating="no"   ref="booleanText" escapeSchemeRef=""
 				encodingErrorPolicy="replace" encoding="utf-8" byteOrder="bigEndian" lengthUnits="characters"
 				textOutputMinLength="1" alignment="1" alignmentUnits="bytes"
-				fillByte="f"  occursCountKind="implicit" ignoreCase="no"
+				fillByte="f"  occursCountKind="implicit" ignoreCase="no" separatorSuppressionPolicy="trailingEmpty"
 				lengthKind="delimited" sequenceKind="ordered" initiatedContent="no" />
 
 		</xs:appinfo>
@@ -135,4 +135,4 @@
 	
 	
 
-</xs:schema>
\ No newline at end of file
+</xs:schema>
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaflsaln101_01.dfdl.xsd b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaflsaln101_01.dfdl.xsd
index da2cfdf32..cf8adb062 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaflsaln101_01.dfdl.xsd
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaflsaln101_01.dfdl.xsd
@@ -29,7 +29,7 @@
 	<xs:annotation>
 		<xs:appinfo source="http://www.ogf.org/dfdl/">
 			<dfdl:format representation="text" 
-            initiator="" terminator="" leadingSkip="0" trailingSkip="0" 
+      initiator="" terminator="" leadingSkip="0" trailingSkip="0" separatorSuppressionPolicy="trailingEmpty"
 			truncateSpecifiedLengthString="no"  separator="" textBidi="no" floating="no"   
 			ref="rdefFormat" encoding="ascii" byteOrder="bigEndian" bitOrder="mostSignificantBitFirst"
 			ignoreCase="yes" textStringJustification="left" occursCountKind="implicit"
@@ -142,4 +142,4 @@
 			</xs:sequence>
 		</xs:complexType>
 	</xs:element>
-</xs:schema>
\ No newline at end of file
+</xs:schema>
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc121_01.dfdl.xsd b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc121_01.dfdl.xsd
index 16206cd32..6a145acb4 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc121_01.dfdl.xsd
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc121_01.dfdl.xsd
@@ -30,7 +30,7 @@
 		
 		<xs:appinfo source="http://www.ogf.org/dfdl/">
 			<dfdl:format initiator="" terminator="" leadingSkip="0" trailingSkip="0" truncateSpecifiedLengthString="no"  separator="" textBidi="no" floating="no"    encodingErrorPolicy="replace" encoding="utf-8" 
-				lengthUnits="bytes" lengthKind="implicit"
+				lengthUnits="bytes" lengthKind="implicit" separatorSuppressionPolicy="trailingEmpty"
 				initiatedContent="no" sequenceKind="ordered" 
 				alignment="1" alignmentUnits="bytes" fillByte="f" occursCountKind="implicit"
 				bitOrder="mostSignificantBitFirst" representation="binary"
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc83_01.dfdl.xsd b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc83_01.dfdl.xsd
index 1af10b609..e1d2674a5 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc83_01.dfdl.xsd
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc83_01.dfdl.xsd
@@ -33,7 +33,7 @@
 	<xs:annotation>
 		<xs:appinfo source="http://www.ogf.org/dfdl/">
 			<dfdl:format initiator="" terminator="" leadingSkip="0" trailingSkip="0" 
-				truncateSpecifiedLengthString="no"  separator=""  
+				truncateSpecifiedLengthString="no"  separator="" separatorSuppressionPolicy="trailingEmpty"
 				textBidi="no" floating="no"   encodingErrorPolicy="replace" encoding="ASCII" representation="text"
 				byteOrder="bigEndian" bitOrder="mostSignificantBitFirst" initiatedContent="no" sequenceKind="ordered"
 				ignoreCase="no" textPadKind="none" textTrimKind="none"
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc83_02.dfdl.xsd b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc83_02.dfdl.xsd
index e26cb24ce..ad226be2c 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc83_02.dfdl.xsd
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/dpaspc83_02.dfdl.xsd
@@ -28,7 +28,7 @@
 	<xs:annotation>
 		<xs:appinfo source="http://www.ogf.org/dfdl/">
 			<dfdl:format initiator="" terminator="" leadingSkip="0" trailingSkip="0" 
-				truncateSpecifiedLengthString="no"  separator=""  
+				truncateSpecifiedLengthString="no"  separator=""  separatorSuppressionPolicy="trailingEmpty"
 				textBidi="no" floating="no"   encodingErrorPolicy="replace" 
 				encoding="ASCII" representation="text"
 				byteOrder="bigEndian" bitOrder="mostSignificantBitFirst" 
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/syntax_entities_6.dfdl.xsd b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/syntax_entities_6.dfdl.xsd
index d70eb87ca..d63fa83fc 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/syntax_entities_6.dfdl.xsd
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/ibm-contributed/syntax_entities_6.dfdl.xsd
@@ -36,7 +36,7 @@
 		<xs:appinfo source="http://www.ogf.org/dfdl/">
 			<dfdl:defineFormat name="rdefFormat">
 				<dfdl:format initiatedContent="no" initiator="" terminator="" leadingSkip="0" trailingSkip="0" separator="" textBidi="no" floating="no"   encoding="ascii" byteOrder="bigEndian" bitOrder="mostSignificantBitFirst"
-					ignoreCase="no" outputNewLine="%LF;"
+					ignoreCase="no" outputNewLine="%LF;" separatorSuppressionPolicy="trailingEmpty"
 					truncateSpecifiedLengthString="no" decimalSigned="yes" alignment="1"
 					alignmentUnits="bytes" fillByte="1" occursCountKind="implicit" escapeSchemeRef=""
 					representation="text" lengthUnits="characters" lengthKind="explicit" 
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/tresys-contributed/AM.dfdl.xsd b/daffodil-test-ibm1/src/test/resources/test-suite/tresys-contributed/AM.dfdl.xsd
index fb0f49b0d..206393058 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/tresys-contributed/AM.dfdl.xsd
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/tresys-contributed/AM.dfdl.xsd
@@ -39,9 +39,6 @@
 
   <group name="arrayGroup">
     <sequence>
-    <!-- 
-    TBD: WHAT SHOULD THE occursCountKind BE??
-     -->
       <element name="array" type="xsd:unsignedByte" maxOccurs="unbounded" dfdl:occursCountKind='implicit'
         dfdl:representation="binary" dfdl:lengthKind="implicit" /> <!-- unsignedByte because it is compared with numbers > 127 -->
     </sequence>
diff --git a/daffodil-test-ibm1/src/test/resources/test-suite/tresys-contributed/AM.tdml b/daffodil-test-ibm1/src/test/resources/test-suite/tresys-contributed/AM.tdml
index 3dc62b3c9..06c1c58c8 100644
--- a/daffodil-test-ibm1/src/test/resources/test-suite/tresys-contributed/AM.tdml
+++ b/daffodil-test-ibm1/src/test/resources/test-suite/tresys-contributed/AM.tdml
@@ -17,8 +17,16 @@
 -->
 
 <testSuite suiteName="AM" xmlns="http://www.ibm.com/xmlns/dfdl/testData"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ct="http://w3.ibm.com/xmlns/dfdl/ctInfoset"
-  xsi:schemaLocation="http://www.ibm.com/xmlns/dfdl/testData /xsd/tdml.xsd">
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+  defaultConfig="cfg_largeArray">
+  
+  <defineConfig name="cfg_largeArray">
+    <daf:tunables xmlns="http://www.w3.org/2001/XMLSchema"
+      xmlns:xs="http://www.w3.org/2001/XMLSchema">
+      <daf:maxOccursBounds>50000</daf:maxOccursBounds>
+    </daf:tunables>
+  </defineConfig>
 
   <parserTestCase name="AM000" root="mimeType" model="AM.dfdl.xsd"
     description="MIME type detect - hiddenGroupRef, discriminators, and inputValueCalc" roundTrip="false">
@@ -60,8 +68,8 @@
  3169 5a70 a729 7435 79a2 35a7 a279 aab9 ad33 796e 2eaa 46a9 6a39 7da9 6a7d a84c
  2660 e995 9eae 9512 4fa9 b0ea 6990 f109 90e0 03e9 f4f1 6990 f105 912c 0669 44f1
  2991 0c12 738c 1743 5699 c141 4938 9184 1929 5ae2 ee53 82b9 4154 3544 ec00 8500
- ecb9 1bd6 2053 3b00
- ]]></documentPart>
+ ecb9 1bd6 2053 3b00 
+  ]]></documentPart>
     </document>
     <infoset>
       <dfdlInfoset>
@@ -74,6 +82,44 @@
       </dfdlInfoset>
     </infoset>
   </parserTestCase>
+  <!-- <![CDATA[
+   0909 0a0a 0f0a 0f0f 1111 1211 1212 1414 1614 1616 1717 1917 1919 1a1a 1b1a 1b1b
+ 1d1d 201d 2020 2222 2522 2525 2727 2827 2828 2929 2c29 2c2c 2d2d 2f2d 2f2f 3030
+ 3230 3232 3535 3635 3636 3737 3837 3838 3939 3a39 3a3a 3b3b 3c3b 3c3c 3e3e 3f3e
+ 3f3f 4040 4140 4141 4242 4442 4444 4646 4746 4747 4848 4948 4949 4c4c 4d4c 4d4d
+ 4e4e 504e 5050 5757 5857 5858 5a5a 5b5a 5b5b 5c5c 5e5c 5e5e 5f5f 605f 6060 6666
+ 6866 6868 6969 6d69 6d6d 7070 7b70 7b7b 7d7d 807d 8080 8383 8c83 8c8c 9090 9390
+ 9393 9595 9895 9898 9a9a 9b9a 9b9b 9e9e 9f9e 9f9f a3a3 ada3 adad aeae b3ae b3b3
+ b8b8 bfb8 bfbf c5c5 cac5 caca cccc cdcc cdcd cfcf d9cf d9d9 dada deda dede dfdf
+ e5df e5e5 e6e6 ece6 ecec efef f1ef f1f1 f3f3 f9f3 f9f9 fefe fffe ffff ffff ffff
+ ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
+ ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
+ ffff ffff ffff ffff ffff ffff 21ff 11fe 7243 6165 6574 2064 6977 6874 4720 4d49
+ 0050 002c 0000 6400 6400 0000 fe07 6480 8382 8584 8786 8988 8b8a 8d8c 8f8e 9190
+ 9392 9594 9796 9998 9b9a 9d9c 9f9e a1a0 a3a2 a5a4 a7a6 9aa8 575f 424c 4c42 5f57
+ b3a9 5f88 324c 0012 1200 4c32 b4b2 64c0 1ab6 c5ba 1a00 c1be 57b4 c631 31c6 ca57
+ 4ab3 ce0e 0ec5 d24a 3ea9 c6d6 da3e 35a8 c5dd 6332 a6e0 e332 18ba e760 3ca5 00ea
+ 5a0f a4ee 0143 4ff1 a3f5 0653 45f1 44fb 4171 cf10 4046 1f51 cde2 1838 43aa 123c
+ 410c 88bd 22f7 27e2 f113 583e a4f4 1e23 8d88 7e9d 4bc4 0bf0 2664 f128 4400 9933
+ 4b09 23ca 332c 5989 8f10 cc47 1b4c c5e2 89b8 4489 153c 2f3c 88b9 22e7 a5a8 f114
+ 1852 d4ad dd4c a5ce 4693 1bc4 7501 44d2 1575 46ab aa92 aa8e 4856 c74d fd3d 08ea
+ 3aa9 64a5 0d1d 5755 6d34 b323 e3fe bad0 045d 9bb7 b9dc d689 6b8e 378b 5d51 776b
+ 1afb db0a ac6d 4360 c75c d579 c626 164b 562b 78b2 e311 eae9 acb8 beca 0150 a272
+ ae81 0a02 a026 f108 4462 148c 522e 4ea0 6311 e944 a9d3 b757 bd7e a09a 043a 67a9
+ 5e9b db2d eef5 b9d8 c77d 5158 87c3 5892 be8c 2928 2071 f3a5 d0e7 4ba3 65d7 c8e1
+ 4496 2eb6 df4c bdce f3fb d71a 5d0f e749 bcbd f2f9 c23a 6217 eb92 fbbc cff7 484f
+ 2439 be04 fbfd 84dd c7d0 1fcf 7ebf ec43 27f5 7ba0 15ff de32 0880 2776 21df e4b6
+ e094 d083 57a5 2dcb e811 8032 1000 6866 848c b1d8 4422 4610 d138 1144 d039 4250
+ 3069 d0a0 0a02 a1bd 0288 2870 20c0 8b82 d9a9 0e36 ac6e 38cd 8a42 ca2b 63a6 b18a
+ 08ad 6f83 9030 01f0 ba04 da90 84c0 da7a 6610 618d 1187 97f2 8133 2945 5e88 f0dd
+ e565 5320 531a 95a5 165d 65f3 5894 a35a 96e5 8464 cba9 8798 e939 940c 265b cdd6
+ 6862 6192 3759 d598 41c9 263c 39d4 9ec8 e8ea a7e0 0430 f3c4 a0c3 a457 c504 47a0
+ 84a4 a0c5 a8f0 0123 7e65 69ba 078c 9283 42a1 283c 5a64 33a6 6e67 26a9 6c00 660a
+ 3169 5a70 a729 7435 79a2 35a7 a279 aab9 ad33 796e 2eaa 46a9 6a39 7da9 6a7d a84c
+ 2660 e995 9eae 9512 4fa9 b0ea 6990 f109 90e0 03e9 f4f1 6990 f105 912c 0669 44f1
+ 2991 0c12 738c 1743 5699 c141 4938 9184 1929 5ae2 ee53 82b9 4154 3544 ec00 8500
+ ecb9 1bd6 2053 3b00 
+ ]]> -->
 
   <parserTestCase name="AM001" root="mimeType" model="AM.dfdl.xsd"
     description="hiddenGroupRef, discriminators, and inputValueCalc" roundTrip="false">
diff --git a/daffodil-test-ibm1/src/test/scala/org/apache/daffodil/TresysTests3.scala b/daffodil-test-ibm1/src/test/scala/org/apache/daffodil/TresysTests3.scala
index 12b8d2fab..1536ecd10 100644
--- a/daffodil-test-ibm1/src/test/scala/org/apache/daffodil/TresysTests3.scala
+++ b/daffodil-test-ibm1/src/test/scala/org/apache/daffodil/TresysTests3.scala
@@ -65,8 +65,10 @@ class TresysTests3 {
   //
   // NOTE: AM.dfdl.xsd isn't a valid schema because it has an array in a hidden
   // group. Because everything inside a hidden group must be either default or
-  // OVC, and arrays can't have either, they cannot be in hidden groups. It is
-  // not worth fixing this test to work at the moment.
+  // OVC, and arrays can't have either, they cannot be in hidden groups.
+  // This is fixed by specifying daffodil-specific property
+  // daf:parseUnparsePolicy="parseOnly", which suppresses the check for this
+  // constraint.
 
   @Test def test_AM000() { runnerAM.runOneTest("AM000") }
   @Test def test_AM001() { runnerAM.runOneTest("AM001") }
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section00/general/testUnparserBitOrderOVC.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section00/general/testUnparserBitOrderOVC.tdml
index 20d069ee6..62a86a73c 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section00/general/testUnparserBitOrderOVC.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section00/general/testUnparserBitOrderOVC.tdml
@@ -34,7 +34,8 @@
   
   <tdml:defineSchema name="s1" elementFormDefault="unqualified">
 
-    <dfdl:format textPadKind='none' lengthKind="explicit" lengthUnits="bits" alignmentUnits="bits" alignment="1"
+    <dfdl:format ref="ex:GeneralFormat"
+      textPadKind='none' lengthKind="explicit" lengthUnits="bits" alignmentUnits="bits" alignment="1"
       fillByte="%#rFF;" representation="binary" binaryNumberRep="binary"
       leadingSkip="0" trailingSkip="0" initiator="" terminator="" separator="" 
       ignoreCase="yes" sequenceKind="ordered" encoding="ascii" initiatedContent="no"
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
index 9682d4568..6261c7e68 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
@@ -32,7 +32,7 @@
 
   <tdml:defineSchema name="SDE">
 
-    <dfdl:format ref="ex:GeneralFormat" />
+    <dfdl:format ref="ex:GeneralFormat" occursCountKind="implicit"/>
 
     <xs:element name="matrix">
       <xs:complexType>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml
index 675c192a9..ec2e9c7e8 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section02/validation_errors/Validation.tdml
@@ -1321,8 +1321,8 @@
 
     <tdml:document>1,2</tdml:document>
     <tdml:errors>
-      <tdml:error>Parse Error: Failed to populate ex:e[3]</tdml:error>
-      <tdml:error>Expected 3 item(s)</tdml:error>
+      <tdml:error>Parse Error</tdml:error>
+      <tdml:error>Failed to populate ex:e[3]</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
 
@@ -1687,7 +1687,7 @@
 
       <!-- Final Error -->
       <tdml:error>Parse Error</tdml:error>
-      <tdml:error>All alternatives failed</tdml:error>
+      <tdml:error>All choice alternatives failed</tdml:error>
       
       <!-- Failure for branch1:e2  -->
       <tdml:error>Parse Error</tdml:error>
@@ -1697,7 +1697,7 @@
       <tdml:error>Parse Error</tdml:error>
       <!-- <tdml:error>Alternative failed. Reason(s): List(Parse Error: Init('C') - branch2: Delimiter not found!</tdml:error> -->
       <tdml:error>branch2</tdml:error>
-      <tdml:error>Delimiter not found</tdml:error>
+      <tdml:error>Initiator 'C' not found</tdml:error>
     </tdml:errors>
 
     <tdml:validationErrors>
@@ -1746,7 +1746,7 @@
 
       <!-- Final Error -->
       <tdml:error>Parse Error</tdml:error>
-      <tdml:error>All alternatives failed</tdml:error>
+      <tdml:error>All choice alternatives failed</tdml:error>
       
       <!-- Failure for branch1:e2  -->
       <tdml:error>Parse Error</tdml:error>
@@ -1755,7 +1755,7 @@
       <!-- Failure for branch2  -->
       <tdml:error>Parse Error</tdml:error>
       <tdml:error>branch2</tdml:error>
-      <tdml:error>Delimiter not found</tdml:error>
+      <tdml:error>Initiator 'C' not found</tdml:error>
     </tdml:errors>
   
   </tdml:parserTestCase>
@@ -1774,7 +1774,7 @@
 
       <!-- Final Error -->
       <tdml:error>Parse Error</tdml:error>
-      <tdml:error>All alternatives failed</tdml:error>
+      <tdml:error>All choice alternatives failed</tdml:error>
       
       <!-- Failure for branch1:e2  -->
       <tdml:error>Parse Error</tdml:error>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/Facets.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/Facets.tdml
index 49a129ec3..1b2d1c24d 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/Facets.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/Facets.tdml
@@ -807,7 +807,11 @@
 
     <tdml:errors>
       <tdml:error>Schema Definition Error</tdml:error>
-      <tdml:error>occursCountKind='fixed' requires minOccurs to equal maxOccurs</tdml:error>
+      <tdml:error>occursCountKind='fixed'</tdml:error>
+      <tdml:error>require</tdml:error>
+      <tdml:error>equal</tdml:error>
+      <tdml:error>minOccurs</tdml:error>
+      <tdml:error>maxOccurs</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
 
@@ -3804,9 +3808,7 @@
 
     <tdml:errors>
       <tdml:error>Parse Error: Failed to populate ex:array[1].</tdml:error>
-      <tdml:error>Expected 1 item(s)</tdml:error>
       <tdml:error>Parse Error: Failed to populate ex:data[1].</tdml:error>
-      <tdml:error>Expected 3 item(s)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -3870,7 +3872,6 @@
 
     <tdml:errors>
       <tdml:error>Parse Error: Failed to populate ex:array[2].</tdml:error>
-      <tdml:error>Expected 3 item(s)</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>  
   
@@ -5290,7 +5291,7 @@
     model="enumSchema" description="Section 5 - Facets - enumeration - DFDL-5-054R">
     <tdml:document>crow</tdml:document>
       <tdml:errors>
-        <tdml:error>All alternatives failed</tdml:error>
+        <tdml:error>All choice alternatives failed</tdml:error>
       </tdml:errors>
   </tdml:parserTestCase>
   
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/Boolean.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/Boolean.tdml
index 4eaf5c686..67dff1b39 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/Boolean.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/Boolean.tdml
@@ -377,6 +377,21 @@
       </tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
+  
+  <tdml:parserTestCase name="textBoolean_0a" root="textList" model="boolean"
+    description="Text boolean"
+    roundTrip="onePass">
+    <tdml:document><![CDATA[yes;a;]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <textList xmlns="http://www.example.org/example1">
+          <x>true</x>
+          <y>false</y>
+        </textList>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+  
 
   <tdml:unparserTestCase name="textBoolean_unparse_0" root="textList" model="boolean"
     description="Text boolean">
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml
index 61cf5698b..7809980ed 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml
@@ -6777,6 +6777,21 @@
     </tdml:infoset>
 </tdml:parserTestCase>
   
+  <tdml:parserTestCase name="hexBinary_Delimited_01a"
+    root="hb_root01" model="HexBinary"
+    description="Section 5 Simple Types - hexBinary - DFDL-5-025R" roundTrip="twoPass">
+    <tdml:document>123.456.789.</tdml:document>
+    <tdml:infoset>
+        <tdml:dfdlInfoset>
+            <hb_root01>
+        <text>313233</text>
+        <text>343536</text>
+        <text>373839</text>
+      </hb_root01>
+        </tdml:dfdlInfoset>
+    </tdml:infoset>
+</tdml:parserTestCase>
+
   <!--
     Test name: hexBinary_Delimited_02
     Schema: HexBinary
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/Entities.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/Entities.tdml
index e6336a29f..7afe65db1 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/Entities.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/Entities.tdml
@@ -961,7 +961,7 @@ is multiple bytes in UTF-8 encoding that is used"
       <tdml:documentPart type="byte">00 41 00 0A 00 0A 00 42 00 0A 00 0A</tdml:documentPart>
     </tdml:document>
     <tdml:errors>
-      <tdml:error>␊␊</tdml:error>
+      <tdml:error>%NL;%NL;</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.tdml
index a119182e1..f11101927 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/charClassEntities.tdml
@@ -435,8 +435,8 @@
     description="Hexadecimal code point used in document tag - DFDL-6-044R">
 
     <!-- this fails to parse the first data row because it has too many elements.
-         The backtracking unwinds and you get an array element with zero entries, but
-         of course all the data is not used up. So the error is Left over data.  -->
+         At the point where it expects the NL (postfix sep), it instead finds 
+         the comma for another row element.  -->
     <document><![CDATA[last,first,middle,DOB
 jones,robert,brandon,1988-03-24,extra,extra
 johnson,john,henry,1986-01-23
@@ -444,7 +444,7 @@ jonesington,david,frederick,1986-02-19
 ]]></document>
    <errors>
      <error>Parse error</error>
-     <error>Expected 1 item</error>
+     <error>postfix separator</error>
    </errors>
   </parserTestCase>
   
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_IBM.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_IBM.dfdl.xsd
index 346c4b5f9..17c8b0d3a 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_IBM.dfdl.xsd
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_IBM.dfdl.xsd
@@ -69,7 +69,8 @@
   </xsd:element>
   <xsd:annotation>
     <xsd:appinfo source="http://www.ogf.org/dfdl/">
-      <dfdl:format ref="tns:GeneralPurposeFormat" />
+      <dfdl:format ref="tns:GeneralPurposeFormat" 
+      separatorSuppressionPolicy="trailingEmpty"/>
     </xsd:appinfo>
   </xsd:annotation>
 </xsd:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_IBM_invalid.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_IBM_invalid.dfdl.xsd
index 2b2b8dfd2..f2cb64de2 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_IBM_invalid.dfdl.xsd
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_IBM_invalid.dfdl.xsd
@@ -68,7 +68,8 @@
   </xsd:element>
   <xsd:annotation>
     <xsd:appinfo source="http://www.ogf.org/dfdl/">
-      <dfdl:format ref="tns:GeneralPurposeFormat" />
+      <dfdl:format ref="tns:GeneralPurposeFormat" 
+      separatorSuppressionPolicy="trailingEmpty"/>
     </xsd:appinfo>
   </xsd:annotation>
 </xsd:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_invalid.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_invalid.dfdl.xsd
index ec4db70c7..814110b32 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_invalid.dfdl.xsd
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_invalid.dfdl.xsd
@@ -107,7 +107,8 @@
 
   <xsd:annotation>
     <xsd:appinfo source="http://www.ogf.org/dfdl/">
-      <dfdl:format ref="tns:GeneralPurposeFormat" />
+      <dfdl:format ref="tns:GeneralPurposeFormat"
+        separatorSuppressionPolicy="trailingEmpty" />
     </xsd:appinfo>
   </xsd:annotation>
 </xsd:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_invalid_2.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_invalid_2.dfdl.xsd
index 51cb5fa4d..d32656d97 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_invalid_2.dfdl.xsd
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/ABC_invalid_2.dfdl.xsd
@@ -79,7 +79,8 @@
 
   <xsd:annotation>
     <xsd:appinfo source="http://www.ogf.org/dfdl/">
-      <dfdl:format ref="tns:GeneralPurposeFormat" />
+      <dfdl:format ref="tns:GeneralPurposeFormat"
+        separatorSuppressionPolicy="trailingEmpty" />
     </xsd:appinfo>
   </xsd:annotation>
 </xsd:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_A_03.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_A_03.dfdl.xsd
index f81d21b1e..b1c2dc358 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_A_03.dfdl.xsd
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_A_03.dfdl.xsd
@@ -44,7 +44,8 @@
         textCalendarPadCharacter="%SP;" textNumberJustification="right"
         textNumberPadCharacter="%SP;" textNumberRep="standard" textOutputMinLength="0"
         textPadKind="none" textStringPadCharacter="%SP;" textTrimKind="none"
-        trailingSkip="0" truncateSpecifiedLengthString="no" />
+        trailingSkip="0" truncateSpecifiedLengthString="no" 
+        emptyValueDelimiterPolicy="none"/>
     </xs:appinfo>
   </xs:annotation>
   
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section07/discriminators/discriminator.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section07/discriminators/discriminator.tdml
index b26670016..26101a4cb 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section07/discriminators/discriminator.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section07/discriminators/discriminator.tdml
@@ -466,7 +466,7 @@
     <tdml:document><![CDATA[1234]]></tdml:document>
     <tdml:errors>
       <tdml:error>Parse Error</tdml:error>
-      <tdml:error>All Alternatives Failed</tdml:error>
+      <tdml:error>All Choice Alternatives Failed</tdml:error>
       <tdml:error>Insufficient</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
@@ -546,6 +546,10 @@
               <xs:sequence>
                 <xs:annotation>
                   <xs:appinfo source="http://www.ogf.org/dfdl/">
+                    <!-- NOTE That this discriminator executes regardless of whether the 
+                    sequence content (int element) below parses successfully. So if that int parse fails, 
+                    the discriminator still will be true, and we will NOT backtrack to have zero occurrences
+                    of the ints array. -->
                     <dfdl:discriminator testKind="expression" test='{ fn:true() }' />
                   </xs:appinfo>
                 </xs:annotation>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section07/escapeScheme/escapeScenarios.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section07/escapeScheme/escapeScenarios.tdml
index 30fa58b37..04818affb 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section07/escapeScheme/escapeScenarios.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section07/escapeScheme/escapeScenarios.tdml
@@ -23,7 +23,8 @@
   defaultRoundTrip="true">
 
   <defineSchema name="es1">
-    <dfdl:format ref="tns:GeneralFormat" lengthKind="delimited" />
+    <dfdl:format ref="tns:GeneralFormat" lengthKind="delimited" 
+        occursCountKind="implicit"/>
 
     <dfdl:defineEscapeScheme name="scenario1">
       <dfdl:escapeScheme escapeCharacter='/'
@@ -76,7 +77,7 @@
       <dfdlInfoset>
         <e_infix>
           <x>foo</x>
-	  <y>bar</y>
+	      <y>bar</y>
 	</e_infix>
       </dfdlInfoset>
     </infoset>
@@ -146,14 +147,15 @@
   </parserTestCase>
   
   <parserTestCase name="scenario1_7" model="es1"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo;</document>
     <infoset>
       <dfdlInfoset>
         <e_infix>
           <x>foo</x>
-	  <y></y>
-	</e_infix>
+          <y/>
+	    </e_infix>
       </dfdlInfoset>
     </infoset>
   </parserTestCase>
@@ -191,7 +193,8 @@
   </parserTestCase>
   
   <parserTestCase name="scenario1_9" model="es1"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo/;;</document>
     <infoset>
       <dfdlInfoset>
@@ -216,7 +219,8 @@
   </parserTestCase>
   
   <parserTestCase name="scenario1_10" model="es1"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo//;</document>
     <infoset>
       <dfdlInfoset>
@@ -468,7 +472,8 @@
   </parserTestCase>
   
   <parserTestCase name="scenario2_10" model="es2"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo$;</document>
     <infoset>
       <dfdlInfoset>
@@ -513,7 +518,8 @@
   </parserTestCase>
   
   <parserTestCase name="scenario2_12" model="es2"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo$/$;</document>
     <infoset>
       <dfdlInfoset>
@@ -583,6 +589,7 @@
     <document>foo$$$//$;</document>
     <errors>
       <error>Parse Error</error>
+      <error>Terminator '$;' not found</error>
     </errors>
   </parserTestCase>
 
@@ -751,7 +758,8 @@
   </parserTestCase>
   
   <parserTestCase name="scenario3_10" model="es3"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo/;</document>
     <infoset>
       <dfdlInfoset>
@@ -822,7 +830,8 @@
   </parserTestCase>
   
   <parserTestCase name="scenario3_13" model="es3"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo$//;</document>
     <infoset>
       <dfdlInfoset>
@@ -1027,7 +1036,8 @@
   </parserTestCase>
   
   <parserTestCase name="scenario4_8" model="es4"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo/;</document>
     <infoset>
       <dfdlInfoset>
@@ -1093,7 +1103,8 @@
   </parserTestCase>
   
   <parserTestCase name="scenario4_11" model="es4"
-    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix">
+    description="Section 13 - escapeCharacter - DFDL-13-029R" root="e_infix"
+    roundTrip="threePass">
     <document>foo///;</document>
     <infoset>
       <dfdlInfoset>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/delimiter_properties/DelimiterProperties.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section12/delimiter_properties/DelimiterProperties.tdml
index ea8b239f0..368f6bf98 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/delimiter_properties/DelimiterProperties.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/delimiter_properties/DelimiterProperties.tdml
@@ -643,7 +643,8 @@
     <tdml:document><![CDATA[$A$$]]></tdml:document>
     <tdml:errors>
     <tdml:error>Parse Error</tdml:error>
-    <tdml:error>Found out of scope delimiter: $$</tdml:error>
+    <tdml:error>Found out of scope delimiter</tdml:error>
+    <tdml:error>$$</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -652,7 +653,8 @@
     <tdml:document><![CDATA[A$$B$$]]></tdml:document>
     <tdml:errors>
     <tdml:error>Parse Error</tdml:error>
-    <tdml:error>Found out of scope delimiter: $$</tdml:error>
+    <tdml:error>Found out of scope delimiter</tdml:error>
+    <tdml:error>$$</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -660,7 +662,8 @@
     model="ReqFieldMissingAndSepIsPrefixOfTerminator">
     <tdml:document><![CDATA[A$$B$$]]></tdml:document>
     <tdml:errors>
-    <tdml:error>Found out of scope delimiter: $$</tdml:error>
+    <tdml:error>Found out of scope delimiter</tdml:error>
+    <tdml:error>$$</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/AB.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/AB.dfdl.xsd
index da862e002..e5430d2bd 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/AB.dfdl.xsd
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/AB.dfdl.xsd
@@ -37,7 +37,7 @@
         representation="text" lengthKind="delimited"
         nilValueDelimiterPolicy="both" emptyValueDelimiterPolicy="none"
         documentFinalTerminatorCanBeMissing="yes" initiatedContent="no"
-        separatorSuppressionPolicy="anyEmpty" separatorPosition="infix" textTrimKind="none" />
+        separatorSuppressionPolicy="trailingEmpty" separatorPosition="infix" textTrimKind="none" />
     </appinfo>
   </annotation>
   <!-- Parsing of CSV -->
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/AB.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/AB.tdml
index 0cd78da3d..04880fcd7 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/AB.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/AB.tdml
@@ -217,7 +217,8 @@
   </parserTestCase>
 
   <parserTestCase name="AB005" root="matrix_02" model="AB.dfdl.xsd"
-    description="CSV-style tests - data stream is scanned for element's enclosing construct's separator.  separatorPosition is postfix.  Sequence has is nil elements. - DFDL-12-043R">
+    description="CSV-style tests - data stream is scanned for element's enclosing construct's separator.  separatorPosition is postfix.  Sequence has is nil elements. - DFDL-12-043R"
+    roundTrip="threePass">
 
     <document>
       <documentPart type="text"><![CDATA[0,1,2,3,4
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/DelimitedTests.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/DelimitedTests.tdml
index 682646bd5..afded89fb 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/DelimitedTests.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/lengthKind/DelimitedTests.tdml
@@ -180,16 +180,19 @@
 
     <xs:element name="NS_13">
       <xs:complexType>
-        <xs:sequence dfdl:separator=","
-          dfdl:separatorPosition="infix">
+        <xs:sequence>
           <xs:sequence>
+            <!-- this first sequence exists just to make the assert run 
+             before the rest of the sequence. -->
           	<xs:annotation>
               <xs:appinfo source="http://www.ogf.org/dfdl/">
                 <dfdl:assert>{fn:true()}</dfdl:assert>
               </xs:appinfo>
           	</xs:annotation>
           </xs:sequence>
-          <xs:element name="e2" type="xs:int" maxOccurs="unbounded" dfdl:textNumberPattern="#####" />
+          <xs:sequence dfdl:separator="," dfdl:separatorPosition="infix">
+            <xs:element name="e2" type="xs:int" maxOccurs="unbounded" dfdl:textNumberPattern="#####" />
+          </xs:sequence>
         </xs:sequence>
       </xs:complexType>
     </xs:element>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/ockImplicit.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/ockImplicit.tdml
index af19cfacd..6e2fbb41c 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/ockImplicit.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/ockImplicit.tdml
@@ -574,8 +574,7 @@
     <tdml:errors>
       <tdml:error>Failed to populate</tdml:error>
       <tdml:error>ex:a[2]</tdml:error>
-      <tdml:error>Expected 2 item(s)</tdml:error>
-      <tdml:error>Delimiter not found</tdml:error>
+      <tdml:error>Separator ',' not found</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   
@@ -609,8 +608,7 @@
     <tdml:errors>
       <tdml:error>Failed to populate</tdml:error>
       <tdml:error>ex:a[2]</tdml:error>
-      <tdml:error>Expected 2 item(s)</tdml:error>
-      <tdml:error>Delimiter not found</tdml:error>
+      <tdml:error>Initiator ')' not found</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
 
@@ -679,7 +677,8 @@
   -->
 
   <tdml:parserTestCase name="ockImplicit8" root="r6"
-    model="s1" description="Section 14.2.2">
+    model="s1" description="Section 14.2.2"
+    roundTrip="threePass">
     <tdml:document><![CDATA[(23),(25),48]]></tdml:document>
     <tdml:infoset>
       <tdml:dfdlInfoset>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice.tdml
index 7d3da3c4d..b2658887c 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice.tdml
@@ -301,7 +301,7 @@
       <tdml:error>float</tdml:error>
       <tdml:error>int</tdml:error>
       <tdml:error>Alternative failed</tdml:error>
-      <tdml:error>All alternatives failed</tdml:error>
+      <tdml:error>All choice alternatives failed</tdml:error>
 
     </tdml:errors>
 
@@ -1913,7 +1913,7 @@ it sure is/
     <tdml:document><![CDATA[1;5;foo]]></tdml:document>
     <tdml:errors>
       <tdml:error>Parse Error</tdml:error>
-      <tdml:error>All alternatives failed</tdml:error>
+      <tdml:error>All choice alternatives failed</tdml:error>
       <tdml:error>Choice dispatch branch failed</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section16/array_optional_elem/ArrayOptionalElem.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section16/array_optional_elem/ArrayOptionalElem.tdml
index 339afa085..136148a78 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section16/array_optional_elem/ArrayOptionalElem.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section16/array_optional_elem/ArrayOptionalElem.tdml
@@ -68,7 +68,7 @@
     <xs:element name="root2">
       <xs:complexType>
         <xs:sequence dfdl:separator="," dfdl:separatorPosition="infix">
-          <xs:element name="e1" type="xs:int" minOccurs="1" maxOccurs="10" />
+          <xs:element name="e1" type="xs:int" minOccurs="1" maxOccurs="10" dfdl:occursCountKind="implicit"/>
         </xs:sequence>
       </xs:complexType>
     </xs:element>
@@ -633,4 +633,180 @@
     </tdml:infoset>
   </tdml:parserTestCase>
 
+  <tdml:defineSchema name="array-ockImplicitSeparators.dfdl.xsd" elementFormDefault="unqualified">
+
+    <dfdl:format lengthKind="delimited" lengthUnits="bytes"
+      ref="ex:GeneralFormat" encoding="UTF-8" separator="" initiator="" terminator=""
+      occursCountKind="implicit" ignoreCase="no" textNumberRep="standard"
+      representation="text" />
+
+    <xs:element name="te_root">
+      <xs:complexType>
+        <xs:sequence dfdl:separator=":"
+          dfdl:separatorPosition="infix" dfdl:separatorSuppressionPolicy="trailingEmpty"
+          dfdl:sequenceKind="ordered">
+          <xs:element name="a" type="xs:int"/>
+          <xs:element name="b" type="xs:int" minOccurs="0" />
+          <xs:element name="c" type="xs:int" minOccurs="0" />
+          <xs:element name="d" type="xs:int" minOccurs="0" />
+          <xs:element name="e" type="xs:int" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>
+
+    <xs:element name="ts_root">
+      <xs:complexType>
+        <xs:sequence dfdl:separator=":"
+          dfdl:separatorPosition="infix" dfdl:separatorSuppressionPolicy="trailingEmptyStrict"
+          dfdl:sequenceKind="ordered">
+          <xs:element name="a" type="xs:int"/>
+          <xs:element name="b" type="xs:int" minOccurs="0" />
+          <xs:element name="c" type="xs:int" minOccurs="0" />
+          <xs:element name="d" type="xs:int" minOccurs="0" />
+          <xs:element name="e" type="xs:int" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>
+
+  </tdml:defineSchema>
+
+  <tdml:parserTestCase name="occursCountKindImplicitSeparators01a" root="te_root"
+    model="array-ockImplicitSeparators.dfdl.xsd"
+    roundTrip="false">
+
+    <tdml:document><![CDATA[1::::::]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:te_root>
+          <a>1</a>
+        </ex:te_root>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+  
+    <tdml:parserTestCase name="occursCountKindImplicitSeparators01b" root="ts_root"
+    model="array-ockImplicitSeparators.dfdl.xsd"
+    roundTrip="false">
+
+    <tdml:document><![CDATA[1::::]]></tdml:document>
+    <tdml:errors>
+        <tdml:error>strict</tdml:error>
+    </tdml:errors>
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="occursCountKindImplicitSeparators02" root="te_root"
+    model="array-ockImplicitSeparators.dfdl.xsd"
+    roundTrip="false">
+
+    <tdml:document><![CDATA[1::3::5]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:te_root>
+          <a>1</a>
+          <c>3</c>
+          <e>5</e>
+        </ex:te_root>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="occursCountKindImplicitSeparators03" root="te_root"
+    model="array-ockImplicitSeparators.dfdl.xsd"
+    roundTrip="twoPass">
+
+    <tdml:document><![CDATA[1:2:3::]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:te_root>
+          <a>1</a>
+          <b>2</b>
+          <c>3</c>
+        </ex:te_root>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase name="occursCountKindImplicitSeparatorsUnparser" root="te_root"
+    model="array-ockImplicitSeparators.dfdl.xsd"
+    roundTrip="false">
+
+    <tdml:document><![CDATA[1:3:5]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:te_root>
+          <a>1</a>
+          <c>3</c>
+          <e>5</e>
+        </ex:te_root>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase name="occursCountKindImplicitSeparators04" root="ts_root"
+    model="array-ockImplicitSeparators.dfdl.xsd"
+    roundTrip="true">
+
+    <tdml:document><![CDATA[1:2:3::]]></tdml:document>
+    <tdml:errors>
+      <tdml:error>trailingEmptyStrict</tdml:error>
+    </tdml:errors>
+  </tdml:parserTestCase>
+
+  <tdml:defineSchema name="nestedSequence" elementFormDefault="unqualified">
+
+    <dfdl:format lengthKind="delimited" lengthUnits="bytes"
+      ref="ex:GeneralFormat" encoding="UTF-8" separator="" initiator="" terminator=""
+      occursCountKind="implicit" ignoreCase="no" textNumberRep="standard"
+      representation="text" />
+
+    <dfdl:defineFormat name="listFormat">
+      <dfdl:format separator="||%NL;" separatorPosition="postfix" separatorSuppressionPolicy="trailingEmptyStrict"/>
+    </dfdl:defineFormat>
+
+    <dfdl:defineFormat name="parameters">
+      <dfdl:format sequenceKind="ordered" separator="|" separatorPosition="prefix" separatorSuppressionPolicy="trailingEmptyStrict"/>
+    </dfdl:defineFormat>
+
+    <xs:complexType name="listObject">
+      <xs:sequence dfdl:ref="parameters">
+        <xs:element name="param1" type="xs:string"/>
+        <xs:element name="param2" type="xs:string"/>
+        <xs:element name="param3" type="xs:string" minOccurs="0" maxOccurs="4" dfdl:occursCountKind="implicit"/>
+      </xs:sequence>
+    </xs:complexType>
+
+    <xs:element name="nestedRoot">
+      <xs:complexType>
+        <xs:sequence dfdl:ref="listFormat">
+          <xs:element name="list1" type="listObject" dfdl:initiator="BEGIN"/>
+          <xs:element name="list2" type="listObject" dfdl:initiator="BEGIN"/>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>
+
+  </tdml:defineSchema>
+
+  <tdml:parserTestCase name="occursCountKindImplicitSeparators05" root="nestedRoot"
+    model="nestedSequence"
+    roundTrip="true">
+
+    <tdml:document><![CDATA[BEGIN|this|is||
+BEGIN|of|nested||
+]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:nestedRoot>
+          <list1>
+            <param1>this</param1>
+            <param2>is</param2>
+          </list1>
+          <list2>
+            <param1>of</param1>
+            <param2>nested</param2>
+          </list2>
+        </ex:nestedRoot>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
 </tdml:testSuite>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section16/array_optional_elem/UnparseArrayFixedOptionalElem.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section16/array_optional_elem/UnparseArrayFixedOptionalElem.tdml
index 80aca3a30..e772f243b 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section16/array_optional_elem/UnparseArrayFixedOptionalElem.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section16/array_optional_elem/UnparseArrayFixedOptionalElem.tdml
@@ -154,10 +154,10 @@
     </tdml:infoset>
     <tdml:errors>
       <tdml:error>Unparse Error</tdml:error>
-      <tdml:error>Expected element start event</tdml:error>
+      <tdml:error>Expected</tdml:error>
+      <tdml:error>additional</tdml:error>
       <tdml:error>opt</tdml:error>
       <tdml:error>received array end event</tdml:error>
-      <tdml:error>r1a</tdml:error>
     </tdml:errors>
 
   </tdml:unparserTestCase>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
index 86a890184..30e797790 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
@@ -8943,7 +8943,7 @@
       truncateSpecifiedLengthString="no" ignoreCase="no" representation="text"
       lengthKind="delimited" nilValueDelimiterPolicy="both"
       emptyValueDelimiterPolicy="none" documentFinalTerminatorCanBeMissing="yes"
-      initiatedContent="no" separatorSuppressionPolicy="never" separatorPosition="infix" />
+      initiatedContent="no" separatorSuppressionPolicy="anyEmpty" separatorPosition="infix" />
 
     <xs:element name="choice">
       <xs:complexType>
diff --git a/daffodil-test/src/test/scala-debug/org/apache/daffodil/section07/discriminators/TestDiscriminators3.scala b/daffodil-test/src/test/scala-debug/org/apache/daffodil/section07/discriminators/TestDiscriminators3.scala
new file mode 100644
index 000000000..c913451d5
--- /dev/null
+++ b/daffodil-test/src/test/scala-debug/org/apache/daffodil/section07/discriminators/TestDiscriminators3.scala
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.section07.discriminators
+
+import org.junit.Test
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+
+object TestDiscriminators3 {
+  val testDir = "/org/apache/daffodil/section07/discriminators/"
+  val runner = Runner(testDir, "discriminator.tdml")
+
+  @AfterClass def shutDown() {
+    runner.reset
+  }
+
+}
+
+class TestDiscriminators3 {
+
+  import TestDiscriminators3._
+
+  // DAFFODIL-1971
+  @Test def test_discrimExpression_04() = { runner.runOneTest("discrimExpression_04") }
+}
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestBoolean2.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestBoolean2.scala
index 01031fdd3..fb26cb26c 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestBoolean2.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestBoolean2.scala
@@ -44,6 +44,7 @@ class TestBoolean2 {
   @Test def test_binaryBoolean_sde_0() { runner.runOneTest("binaryBoolean_sde_0") }
   @Test def test_binaryBoolean_sde_1() { runner.runOneTest("binaryBoolean_sde_1") }
   @Test def test_textBoolean_0() { runner.runOneTest("textBoolean_0") }
+  @Test def test_textBoolean_0a() { runner.runOneTest("textBoolean_0a") }
   @Test def test_textBoolean_unparse_0() { runner.runOneTest("textBoolean_unparse_0") }
   @Test def test_textBoolean_1() { runner.runOneTest("textBoolean_1") }
   @Test def test_textBoolean_2() { runner.runOneTest("textBoolean_2") }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala
index c5a0ed44b..a0a77f8b2 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala
@@ -46,6 +46,7 @@ class TestSimpleTypes {
 
   @Test def test_hexBinary_01() { runner.runOneTest("hexBinary_01") } //roundTrip
   @Test def test_hexBinary_Delimited_01() { runner.runOneTest("hexBinary_Delimited_01") } //roundTrip
+  @Test def test_hexBinary_Delimited_01a() { runner.runOneTest("hexBinary_Delimited_01a") } //roundTrip
   @Test def test_hexBinary_Delimited_02() { runner.runOneTest("hexBinary_Delimited_02") } //roundTrip
   @Test def test_hexBinary_Delimited_03() { runner.runOneTest("hexBinary_Delimited_03") } //roundTrip
   @Test def test_hexBinary_Implicit_01() { runner.runOneTest("hexBinary_Implicit_01") } //roundTrip
@@ -57,7 +58,7 @@ class TestSimpleTypes {
   @Test def test_hexBinary_func() { runner.runOneTest("hexBinary_func") }
   @Test def test_hexBinary_func_neg() { runner.runOneTest("hexBinary_func_neg") }
 
-  // DFDL-1707 
+  // DFDL-1707
   @Test def test_hexBinary_bits_be_msbf() { runner.runOneTest("hexBinary_bits_be_msbf") }
   @Test def test_hexBinary_bits_le_msbf() { runner.runOneTest("hexBinary_bits_le_msbf") }
   @Test def test_hexBinary_bits_le_lsbf() { runner.runOneTest("hexBinary_bits_le_lsbf") }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section07/discriminators/TestDiscriminators.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section07/discriminators/TestDiscriminators3.scala
similarity index 97%
rename from daffodil-test/src/test/scala/org/apache/daffodil/section07/discriminators/TestDiscriminators.scala
rename to daffodil-test/src/test/scala/org/apache/daffodil/section07/discriminators/TestDiscriminators3.scala
index 43fd55479..728120fa3 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section07/discriminators/TestDiscriminators.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section07/discriminators/TestDiscriminators3.scala
@@ -65,8 +65,9 @@ class TestDiscriminators {
   @Test def test_discrimExpression_01() = { runner.runOneTest("discrimExpression_01") }
   @Test def test_discrimExpression_02() = { runner.runOneTest("discrimExpression_02") }
   @Test def test_discrimExpression_03() = { runner.runOneTest("discrimExpression_03") }
-  @Test def test_discrimExpression_04() = { runner.runOneTest("discrimExpression_04") }
 
+  // DAFFODIL-1971
+  // @Test def test_discrimExpression_04() = { runner.runOneTest("discrimExpression_04") }
 
   @Test def test_discrimFailStopsFollowingAssert1() { runner.runOneTest("discrimFailStopsFollowingAssert1") }
   @Test def test_discrimPEnotSDE1() { runner.runOneTest("discrimPEnotSDE1") }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section16/array_optional_elem/TestArrayOptionalElem.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section16/array_optional_elem/TestArrayOptionalElem.scala
index b2ec15725..b965dbd2c 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section16/array_optional_elem/TestArrayOptionalElem.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section16/array_optional_elem/TestArrayOptionalElem.scala
@@ -70,4 +70,12 @@ class TestArrayOptionalElem {
   @Test def test_arrays_16_01() { runner1.runOneTest("arrays_16_01") }
 
   @Test def test_backtrack1Text() = { rBack.runOneTest("backtrack1Text") }
+
+  @Test def test_occursCountKindImplicitSeparators01a() { runner.runOneTest("occursCountKindImplicitSeparators01a") }
+  @Test def test_occursCountKindImplicitSeparators01b() { runner.runOneTest("occursCountKindImplicitSeparators01b") }
+  @Test def test_occursCountKindImplicitSeparators02() { runner.runOneTest("occursCountKindImplicitSeparators02") }
+  @Test def test_occursCountKindImplicitSeparators03() { runner.runOneTest("occursCountKindImplicitSeparators03") }
+  @Test def test_occursCountKindImplicitSeparators04() { runner.runOneTest("occursCountKindImplicitSeparators04") }
+  @Test def test_occursCountKindImplicitSeparators05() { runner.runOneTest("occursCountKindImplicitSeparators05") }
+  @Test def test_occursCountKindImplicitSeparatorsUnparser() { runner.runOneTest("occursCountKindImplicitSeparatorsUnparser") }
 }
diff --git a/eclipse-projects/cli-test/.classpath b/eclipse-projects/cli-test/.classpath
index 2f78f2340..16e12b2a1 100644
--- a/eclipse-projects/cli-test/.classpath
+++ b/eclipse-projects/cli-test/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/cli/.classpath b/eclipse-projects/cli/.classpath
index 0c349f8ec..7ad97a8c4 100644
--- a/eclipse-projects/cli/.classpath
+++ b/eclipse-projects/cli/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/core-test/.classpath b/eclipse-projects/core-test/.classpath
index b5d9c5ed3..9a6d5eaea 100644
--- a/eclipse-projects/core-test/.classpath
+++ b/eclipse-projects/core-test/.classpath
@@ -1,92 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-        <!-- This file is updated by the UpdateEclipseClasspath app. -->
-        <classpathentry path="src/test/resources" kind="src"/><classpathentry path="src/test/scala" kind="src"/><classpathentry path="src/test/scala-debug" kind="src"/><classpathentry path="org.scala-ide.sdt.launching.SCALA_CONTAINER" kind="con"/><classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER" kind="con"/><classpathentry path="/daffodil-core" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-lib" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1-unittest" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-io" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1-unparser" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-macro-lib" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-lib-unittest" kind="src" combineaccessrules="false"/><classpathentry path="target/eclipse/classes" kind="output"/><!--
-***********
-*********** Entries below this comment are maintained using the UpdateEclipseClasspaths
-*********** Utility and should not be modified by hand or using the Eclipse
-*********** BuildPath... GUI dialog.
-***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar">
-            
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar" exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry>
-      </classpath>
\ No newline at end of file
+	<classpathentry kind="src" path="src/test/resources"/>
+	<classpathentry kind="src" path="src/test/scala"/>
+	<classpathentry kind="src" path="src/test/scala-debug"/>
+	<classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-core"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1-unittest"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-io"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1-unparser"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-macro-lib"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib-unittest"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar" sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar" sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar" sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar" sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar" sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar" sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar" sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar" sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar" sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar" sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar" sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar" sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar" sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar" sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar" sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar" sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar" sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar" sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar" sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar"/>
+	<classpathentry kind="output" path="target/eclipse/classes"/>
+</classpath>
diff --git a/eclipse-projects/core/.classpath b/eclipse-projects/core/.classpath
index 0bd58f016..53c75d12c 100644
--- a/eclipse-projects/core/.classpath
+++ b/eclipse-projects/core/.classpath
@@ -1,92 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-        <!-- This file is updated by the UpdateEclipseClasspath app. -->
-        <classpathentry path="src/main/scala" kind="src"/><classpathentry path="/daffodil-lib" kind="src" combineaccessrules="false"/><classpathentry path="org.scala-ide.sdt.launching.SCALA_CONTAINER" kind="con"/><classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER" kind="con"/><classpathentry path="/daffodil-io" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1-unparser" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-macro-lib" kind="src" combineaccessrules="false"/><classpathentry path="target/eclipse" kind="output"/><!--
-***********
-*********** Entries below this comment are maintained using the UpdateEclipseClasspaths
-*********** Utility and should not be modified by hand or using the Eclipse
-*********** BuildPath... GUI dialog.
-***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar">
-            
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar" exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry>
-      </classpath>
\ No newline at end of file
+	<classpathentry kind="src" path="src/main/scala"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib"/>
+	<classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-io"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1-unparser"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-macro-lib"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar" sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar" sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar" sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar" sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar" sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar" sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar" sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar" sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar" sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar" sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar" sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar" sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar" sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar" sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar" sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar" sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar" sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar" sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar" sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar"/>
+	<classpathentry kind="output" path="target/eclipse"/>
+</classpath>
diff --git a/eclipse-projects/io-lib/.classpath b/eclipse-projects/io-lib/.classpath
index 8a540471b..a42dc7703 100644
--- a/eclipse-projects/io-lib/.classpath
+++ b/eclipse-projects/io-lib/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/io-test/.classpath b/eclipse-projects/io-test/.classpath
index d7d90a526..6ac0b2176 100644
--- a/eclipse-projects/io-test/.classpath
+++ b/eclipse-projects/io-test/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/japi-test/.classpath b/eclipse-projects/japi-test/.classpath
index 1f6e504ba..97db6d6fd 100644
--- a/eclipse-projects/japi-test/.classpath
+++ b/eclipse-projects/japi-test/.classpath
@@ -1,92 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-        <!-- This file is updated by the UpdateEclipseClasspath app. -->
-        <classpathentry path="src/test/java" kind="src"/><classpathentry path="src/test/resources" kind="src"/><classpathentry path="org.scala-ide.sdt.launching.SCALA_CONTAINER" kind="con"/><classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER" kind="con"/><classpathentry path="/daffodil-japi" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-tdml" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-lib" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-core" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-lib-unittest" kind="src" combineaccessrules="false"/><classpathentry path="target/eclipse/classes" kind="output"/><!--
-***********
-*********** Entries below this comment are maintained using the UpdateEclipseClasspaths
-*********** Utility and should not be modified by hand or using the Eclipse
-*********** BuildPath... GUI dialog.
-***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar">
-            
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar" exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry>
-      </classpath>
\ No newline at end of file
+	<classpathentry kind="src" path="src/test/java"/>
+	<classpathentry kind="src" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-japi"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-tdml"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-core"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib-unittest"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar" sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar" sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar" sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar" sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar" sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar" sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar" sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar" sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar" sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar" sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar" sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar" sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar" sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar" sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar" sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar" sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar" sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar" sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar" sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-io"/>
+	<classpathentry kind="output" path="target/eclipse/classes"/>
+</classpath>
diff --git a/eclipse-projects/japi/.classpath b/eclipse-projects/japi/.classpath
index f25c20128..9128cd2bf 100644
--- a/eclipse-projects/japi/.classpath
+++ b/eclipse-projects/japi/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/lib-test/.classpath b/eclipse-projects/lib-test/.classpath
index 9296d8821..b3193eb02 100644
--- a/eclipse-projects/lib-test/.classpath
+++ b/eclipse-projects/lib-test/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/lib/.classpath b/eclipse-projects/lib/.classpath
index 33adf8547..3cb8bf0a1 100644
--- a/eclipse-projects/lib/.classpath
+++ b/eclipse-projects/lib/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/macro-lib/.classpath b/eclipse-projects/macro-lib/.classpath
index 172d4ff92..ac44685c0 100644
--- a/eclipse-projects/macro-lib/.classpath
+++ b/eclipse-projects/macro-lib/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/propgen/.classpath b/eclipse-projects/propgen/.classpath
index 97bb529d8..1b06bc89a 100644
--- a/eclipse-projects/propgen/.classpath
+++ b/eclipse-projects/propgen/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/runtime1-test/.classpath b/eclipse-projects/runtime1-test/.classpath
index c02667b8a..235f408c3 100644
--- a/eclipse-projects/runtime1-test/.classpath
+++ b/eclipse-projects/runtime1-test/.classpath
@@ -1,92 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-        <!-- This file is updated by the UpdateEclipseClasspath app. -->
-        <classpathentry path="src/test/scala" kind="src"/><classpathentry path="src/test/scala-debug" kind="src"/><classpathentry path="org.scala-ide.sdt.launching.SCALA_CONTAINER" kind="con"/><classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER" kind="con"/><classpathentry path="/daffodil-io" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-lib" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-macro-lib" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-lib-unittest" kind="src" combineaccessrules="false"/><classpathentry path="bin" kind="output"/><!--
-***********
-*********** Entries below this comment are maintained using the UpdateEclipseClasspaths
-*********** Utility and should not be modified by hand or using the Eclipse
-*********** BuildPath... GUI dialog.
-***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar">
-            
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar" exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry>
-      </classpath>
\ No newline at end of file
+	<classpathentry kind="src" path="src/test/scala"/>
+	<classpathentry kind="src" path="src/test/scala-debug"/>
+	<classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-io"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-macro-lib"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib-unittest"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar" sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar" sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar" sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar" sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar" sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar" sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar" sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar" sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar" sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar" sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar" sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar" sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar" sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar" sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar" sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar" sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar" sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar" sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar" sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/eclipse-projects/runtime1-unparser-test/.classpath b/eclipse-projects/runtime1-unparser-test/.classpath
index d8f11e5ec..c2b7c1deb 100644
--- a/eclipse-projects/runtime1-unparser-test/.classpath
+++ b/eclipse-projects/runtime1-unparser-test/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/runtime1-unparser/.classpath b/eclipse-projects/runtime1-unparser/.classpath
index 592ccd93b..41262fee1 100644
--- a/eclipse-projects/runtime1-unparser/.classpath
+++ b/eclipse-projects/runtime1-unparser/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/runtime1/.classpath b/eclipse-projects/runtime1/.classpath
index ebb59b3b8..4f9e15117 100644
--- a/eclipse-projects/runtime1/.classpath
+++ b/eclipse-projects/runtime1/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/sapi-test/.classpath b/eclipse-projects/sapi-test/.classpath
index 0ebb10ccf..d74c4e069 100644
--- a/eclipse-projects/sapi-test/.classpath
+++ b/eclipse-projects/sapi-test/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/sapi/.classpath b/eclipse-projects/sapi/.classpath
index 69a9e50af..2bc7fa291 100644
--- a/eclipse-projects/sapi/.classpath
+++ b/eclipse-projects/sapi/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/tdml-test/.classpath b/eclipse-projects/tdml-test/.classpath
index 8db558288..bfd7eb344 100644
--- a/eclipse-projects/tdml-test/.classpath
+++ b/eclipse-projects/tdml-test/.classpath
@@ -1,92 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-        <!-- This file is updated by the UpdateEclipseClasspath app. -->
-        <classpathentry path="src/test/resources" kind="src"/><classpathentry path="src/test/scala" kind="src"/><classpathentry path="src/test/scala-debug" kind="src"/><classpathentry path="org.scala-ide.sdt.launching.SCALA_CONTAINER" kind="con"/><classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER" kind="con"/><classpathentry path="/daffodil-core" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-lib" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-tdml" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-io" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-macro-lib" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-runtime1-unparser" kind="src" combineaccessrules="false"/><classpathentry path="/daffodil-lib-unittest" kind="src" combineaccessrules="false"/><classpathentry path="target/eclipse/classes" kind="output"/><!--
-***********
-*********** Entries below this comment are maintained using the UpdateEclipseClasspaths
-*********** Utility and should not be modified by hand or using the Eclipse
-*********** BuildPath... GUI dialog.
-***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar">
-            
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar" exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar" exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar" exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar" exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry>
-      </classpath>
\ No newline at end of file
+	<classpathentry kind="src" path="src/test/resources"/>
+	<classpathentry kind="src" path="src/test/scala"/>
+	<classpathentry kind="src" path="src/test/scala-debug"/>
+	<classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-core"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-tdml"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-io"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-macro-lib"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-runtime1-unparser"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-lib-unittest"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar" sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4.jar" sourcepath="lib_managed/srcs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.codehaus.woodstox/stax2-api/stax2-api-3.1.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8.jar" sourcepath="lib_managed/srcs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.jackson.core/jackson-core/jackson-core-2.8.8-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/bundles/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3.jar" sourcepath="lib_managed/srcs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.fasterxml.woodstox/woodstox-core/woodstox-core-5.0.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-resolver/xml-resolver/xml-resolver-1.2.jar" sourcepath="lib_managed/srcs/xml-resolver/xml-resolver/xml-resolver-1.2-sources.jar"/>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.novocode/junit-interface/junit-interface-0.11.jar" sourcepath="lib_managed/srcs/com.novocode/junit-interface/junit-interface-0.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.novocode/junit-interface/junit-interface-0.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xml-apis/xml-apis/xml-apis-1.4.01.jar" sourcepath="lib_managed/srcs/xml-apis/xml-apis/xml-apis-1.4.01-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xml-apis/xml-apis/xml-apis-1.4.01-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.hamcrest/hamcrest-core/hamcrest-core-1.3.jar" sourcepath="lib_managed/srcs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.hamcrest/hamcrest-core/hamcrest-core-1.3-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/jline/jline/jline-2.12.1.jar" sourcepath="lib_managed/srcs/jline/jline/jline-2.12.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/jline/jline/jline-2.12.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scala-sbt/test-interface/test-interface-1.0.jar" sourcepath="lib_managed/srcs/org.scala-sbt/test-interface/test-interface-1.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-sbt/test-interface/test-interface-1.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/net.sf.expectit/expectit-core/expectit-core-0.8.1.jar" sourcepath="lib_managed/srcs/net.sf.expectit/expectit-core/expectit-core-0.8.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/net.sf.expectit/expectit-core/expectit-core-0.8.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.fusesource.jansi/jansi/jansi-1.14.jar" sourcepath="lib_managed/srcs/org.fusesource.jansi/jansi/jansi-1.14-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.fusesource.jansi/jansi/jansi-1.14-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/com.ibm.icu/icu4j/icu4j-51.1.jar" sourcepath="lib_managed/srcs/com.ibm.icu/icu4j/icu4j-51.1-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/com.ibm.icu/icu4j/icu4j-51.1-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/commons-io/commons-io/commons-io-2.5.jar" sourcepath="lib_managed/srcs/commons-io/commons-io/commons-io-2.5-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/commons-io/commons-io/commons-io-2.5-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4.jar" sourcepath="lib_managed/srcs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scalacheck/scalacheck_2.12/scalacheck_2.12-1.13.4-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/junit/junit/junit-4.11.jar" sourcepath="lib_managed/srcs/junit/junit/junit-4.11-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/junit/junit/junit-4.11-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.rogach/scallop_2.12/scallop_2.12-3.1.2.jar" sourcepath="lib_managed/srcs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.rogach/scallop_2.12/scallop_2.12-3.1.2-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/xerces/xercesImpl/xercesImpl-2.10.0.jar" sourcepath="lib_managed/srcs/xerces/xercesImpl/xercesImpl-2.10.0-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/xerces/xercesImpl/xercesImpl-2.10.0-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="lib" path="lib_managed/jars/org.jdom/jdom2/jdom2-2.0.6.jar" sourcepath="lib_managed/srcs/org.jdom/jdom2/jdom2-2.0.6-sources.jar">
+		<attributes>
+			<attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.jdom/jdom2/jdom2-2.0.6-javadoc.jar!/"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry combineaccessrules="false" kind="src" path="/daffodil-io-unittest"/>
+	<classpathentry kind="output" path="target/eclipse/classes"/>
+</classpath>
diff --git a/eclipse-projects/tdml/.classpath b/eclipse-projects/tdml/.classpath
index d28c31c45..4f630b7ca 100644
--- a/eclipse-projects/tdml/.classpath
+++ b/eclipse-projects/tdml/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/test-ibm1/.classpath b/eclipse-projects/test-ibm1/.classpath
index 0154b4a67..c02032eec 100644
--- a/eclipse-projects/test-ibm1/.classpath
+++ b/eclipse-projects/test-ibm1/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/test-stdLayout/.classpath b/eclipse-projects/test-stdLayout/.classpath
index 68af6e915..a980da27e 100644
--- a/eclipse-projects/test-stdLayout/.classpath
+++ b/eclipse-projects/test-stdLayout/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/test/.classpath b/eclipse-projects/test/.classpath
index da70b3b91..8eafdfbfd 100644
--- a/eclipse-projects/test/.classpath
+++ b/eclipse-projects/test/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/eclipse-projects/tutorials/.classpath b/eclipse-projects/tutorials/.classpath
index c7a4a9c5d..bc8069dac 100644
--- a/eclipse-projects/tutorials/.classpath
+++ b/eclipse-projects/tutorials/.classpath
@@ -6,15 +6,7 @@
 *********** Utility and should not be modified by hand or using the Eclipse
 *********** BuildPath... GUI dialog.
 ***********
---><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-parser-combinators_2.12/scala-parser-combinators_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4.jar">
-            <attributes>
-                  <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.4-javadoc.jar!/"/>
-                </attributes>
-          </classpathentry><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
+--><classpathentry sourcepath="lib_managed/srcs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-sources.jar" exported="true" kind="lib" path="lib_managed/bundles/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6.jar">
             <attributes>
                   <attribute name="javadoc_location" value="jar:file:lib_managed/docs/org.scala-lang.modules/scala-xml_2.12/scala-xml_2.12-1.0.6-javadoc.jar!/"/>
                 </attributes>
diff --git a/test-stdLayout/src/test/resources/org1/testStdLayout.tdml b/test-stdLayout/src/test/resources/org1/testStdLayout.tdml
index 96e399314..0207ac37c 100644
--- a/test-stdLayout/src/test/resources/org1/testStdLayout.tdml
+++ b/test-stdLayout/src/test/resources/org1/testStdLayout.tdml
@@ -34,7 +34,7 @@
       <tdml:documentPart type="file">org1/test-outer-data1.txt</tdml:documentPart>
     </tdml:document>
     <tdml:errors>
-      <tdml:error>RepUnbounded - No forward progress</tdml:error>
+      <tdml:error>No forward progress</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
   


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services