in daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SequenceParserBases.scala [440:530]
private def parseOneInstanceWithMaybePoU(
parser: SequenceChildParser,
pstate: PState,
roStatus: RequiredOptionalStatus,
maybePoU: Maybe[PState.Mark]
): (ArrayIndexStatus, ParseAttemptStatus) = {
var ais: ArrayIndexStatus = ArrayIndexStatus.Uninitialized
checkN(pstate, parser) // check if occursIndex exceeds tunable limit.
val priorPos = pstate.bitPos0b
var resultOfTry = parser.parseOne(pstate, roStatus)
val currentPos = pstate.bitPos0b
val isPoUResolved =
if (maybePoU.isDefined) pstate.isPointOfUncertaintyResolved(maybePoU.get)
else true
//
// 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 {
case _: SuccessParseAttemptStatus => { // ok
if (maybePoU.isDefined && !isPoUResolved) pstate.discardPointOfUncertainty(maybePoU.get)
}
case AbsentRep => {
if (maybePoU.isDefined) {
Assert.invariant(!isPoUResolved) // impossible for an absent rep to resolve the PoU
pstate.resetToPointOfUncertainty(
maybePoU.get
) // back out any side effects of the attempt to parse
}
pstate.dataInputStream.setBitPos0b(currentPos) // skip syntax such as a separator
}
case MissingSeparator if (pstate.isSuccess) => {
// missing separator with parse success indicates that we should end the sequence now
ais = Done
}
case _: FailedParseAttemptStatus => { // MissingSeparator with failure will match here
Assert.invariant(pstate.isFailure)
if (!isOrdered) {
if (isPoUResolved) {
// failed this unordered sequence branch, and the PoU was resolved
// so the unordered sequence failed. Change the resultOfTry to a
// special state indicated this so this failure will propogate up
resultOfTry = UnorderedSeqDiscriminatedFailure
} else {
// failed this unordered sequence branch, but nothing resolved the
// PoU. We need to just try the next branch from the PoU. So just
// reset to the PoU. The resultOfTry will be returned and will be
// acted on appropriately
pstate.resetToPointOfUncertainty(maybePoU.get)
}
} else if (
maybePoU.isDefined && !isPoUResolved &&
(roStatus.isInstanceOf[RequiredOptionalStatus.Optional])
) {
// we back up and finish the array at the prior element if any.
pstate.resetToPointOfUncertainty(maybePoU.get)
Assert.invariant(pstate.isSuccess)
} else {
parser.trd match {
case erd: ElementRuntimeData if (erd.isArray) => {
val cause = pstate.processorStatus.asInstanceOf[Failure].cause
parser.PE(
pstate,
"Failed to populate %s[%s]. Cause: %s",
erd.prefixedName,
pstate.mpstate.arrayIterationPos,
cause
)
}
case _ => // ok
}
}
ais = Done // exits the while loop for the array
}
case other => Assert.invariantFailed("Unexpected parse attempt status: " + other)
}
(ais, resultOfTry)
}