override def parseOneWithSeparator()

in daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SeparatedParseHelper.scala [190:316]


  override def parseOneWithSeparator(
    pstate: PState,
    requiredOptional: RequiredOptionalStatus
  ): ParseAttemptStatus = {

    val prevBitPosBeforeChild = pstate.bitPos0b

    pstate.withPointOfUncertainty("PostfixSeparatorHelper", childParser.context) { pou =>
      childParser.parse1(pstate)
      val childSuccessful = pstate.processorStatus eq Success
      val childFailure = !childSuccessful // just makes later logic easier to read
      val bitPosAfterChildAttempt = pstate.bitPos0b
      val prh = scParser.parseResultHelper
      // This seems odd, but there are cases where after a failure
      // the bitPos has not yet been repositioned back to where it started.
      // This does happen for complex types.
      val hasZLChildAttempt = prevBitPosBeforeChild == bitPosAfterChildAttempt

      if (childSuccessful) {
        val dataOnlyRep =
          prh.computeParseAttemptStatus(
            scParser,
            prevBitPosBeforeChild,
            pstate,
            requiredOptional
          )
        sep.parse1(pstate)
        if (pstate.processorStatus eq Success) {
          // we got the postfix sep after successful parse of the data item
          // so whatever the status of the item was, that's the status overall.
          dataOnlyRep
        } else {
          // child successful, but
          // no postfix sep found.
          // capture failure reason, but reset position to before the child,
          // and remove any elements. That way this behaves like a prefix
          // or infix separator, where if you don't get the sep, then you
          // usually (except first one in infix case) don't run the child parser
          val failure = pstate.processorStatus.asInstanceOf[Failure]

          Assert.invariant(!pstate.isPointOfUncertaintyResolved(pou))
          pstate.resetToPointOfUncertainty(pou)

          pstate.setFailed(failure.cause)
          failedSeparator(pstate, "postfix")
          prh.computeFailedSeparatorParseAttemptStatus(
            scParser,
            prevBitPosBeforeChild,
            pstate,
            hasZLChildAttempt,
            requiredOptional
          )
        }
      } else {
        Assert.invariant(childFailure)
        // We might be tempted to just try the postfix sep now,
        // to see if the postfix sep is there immediately.
        // This is, however, problematic.
        //
        // We're depending on this item being an element with lengthKind="delimited"
        // which can't have a zero-length representation, so that if there is zero-data before
        // the postfix separator, we can declare the item to be absentRep.
        //
        // But what if the element is not lengthKind 'delimited'.
        // Or what if it has complex type? But has a non-zero-length structure where this
        // same delimiter is used at a more deeply nested depth?
        //
        // If the type is simple, and lengthKind 'delimited' we can proceed.
        // Otherwise we punt and call it missing.
        //
        if (isSimpleDelimited) {
          val failure = pstate.processorStatus.asInstanceOf[Failure]

          Assert.invariant(!pstate.isPointOfUncertaintyResolved(pou))
          pstate.resetToPointOfUncertainty(pou)

          sep.parse1(pstate)
          if (pstate.isSuccess) {
            val posAfterSep = pstate.bitPos0b
            // failed child, but success on postfix sep.
            // behave here just like a prefix separator that was then followed by a child failure
            pstate.setFailed(failure.cause)
            val pas =
              prh.computeParseAttemptStatus(
                scParser,
                prevBitPosBeforeChild,
                pstate,
                requiredOptional
              )
            val res = pas match {
              case AbsentRep => {
                pstate.dataInputStream.setBitPos0b(posAfterSep)
                MissingSeparator
              }
              case _ => pas
            }
            res
          } else {
            // the separator failed on ZL data
            // so no chance on a ZL representation here.
            val isZL = false
            prh.computeFailedSeparatorParseAttemptStatus(
              scParser,
              prevBitPosBeforeChild,
              pstate,
              isZL,
              requiredOptional
            )
          }
        } else {
          // not simple delimited. We really have no way of knowing
          // if trying to parse just the sep now makes any sense at all.
          // (ex: the child could be failing because it is fixed length, with asserts that check the value
          // that fail.)
          val isZL = false
          prh.computeFailedParseAttemptStatus(
            scParser,
            prevBitPosBeforeChild,
            pstate,
            isZL,
            requiredOptional
          )
        }
      }

    }
  }