diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLStatementMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLStatementMixin.scala
index a00306938b..a7175b3233 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLStatementMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLStatementMixin.scala
@@ -217,7 +217,7 @@ trait ProvidesDFDLStatementMixin extends ThrowsSDE with HasTermCheck {
final lazy val patternStatements: Seq[DFDLStatement] = patternAsserts ++ patternDiscrims
final lazy val lowPriorityStatements: Seq[DFDLStatement] =
- setVariableStatements ++ nonPatternAsserts ++ nonPatternDiscrims
+ nonPatternAsserts ++ nonPatternDiscrims
final protected lazy val localStatements = this.annotationObjs.collect {
case st: DFDLStatement => st
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/Grammar.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/Grammar.scala
index 6a4c5d700b..7a9e84f57a 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/Grammar.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/Grammar.scala
@@ -23,6 +23,7 @@ object INoWarn { ImplicitsSuppressUnusedImportWarning() }
import org.apache.daffodil.core.compiler.ForParser
import org.apache.daffodil.core.compiler.ForUnparser
import org.apache.daffodil.core.dsom._
+import org.apache.daffodil.runtime1.processors.parsers.AssertExpressionEvaluationParser
import org.apache.daffodil.runtime1.processors.parsers.NadaParser
import org.apache.daffodil.runtime1.processors.parsers.SeqCompParser
import org.apache.daffodil.runtime1.processors.unparsers.SeqCompUnparser
@@ -89,10 +90,19 @@ class SeqComp private (context: SchemaComponent, children: Seq[Gram])
_.isInstanceOf[NadaParser]
}
+ lazy val assertExpressionChildren = parserChildren.filter {
+ _.isInstanceOf[AssertExpressionEvaluationParser]
+ }
+
final override lazy val parser = {
if (parserChildren.isEmpty) new NadaParser(context.runtimeData)
else if (parserChildren.length == 1) parserChildren.head
- else new SeqCompParser(context.runtimeData, parserChildren.toVector)
+ else
+ new SeqCompParser(
+ context.runtimeData,
+ parserChildren.toVector,
+ assertExpressionChildren.toVector,
+ )
}
lazy val unparserChildren = {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ModelGroupGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ModelGroupGrammarMixin.scala
index bb5b9c567b..bd32a449db 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ModelGroupGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ModelGroupGrammarMixin.scala
@@ -50,8 +50,10 @@ trait ModelGroupGrammarMixin
// See 9.5 Evaluation Order for Statement Annotations
dfdlPatternStatementEvaluations ~ // Assert and Discriminator statements with testKind="pattern"
dfdlScopeBegin ~ // newVariableInstance
- dfdlLowPriorityStatementEvaluations ~ // setVariable and the rest of the Assert and Discriminator statements
- groupLeftFraming ~ groupContentWithInitiatorTerminator ~ groupRightFraming ~ dfdlScopeEnd
+ dfdlSetVariableStatements ~
+ groupLeftFraming ~ groupContentWithInitiatorTerminator ~ groupRightFraming ~
+ dfdlLowPriorityStatementEvaluations ~ // The rest of the Assert and Discriminator statements
+ dfdlScopeEnd
}
private lazy val groupContentWithInitiatorTerminator =
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/TermGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/TermGrammarMixin.scala
index f3891d16da..fcb58cc7d9 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/TermGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/TermGrammarMixin.scala
@@ -48,6 +48,15 @@ trait TermGrammarMixin extends AlignedMixin with BitOrderMixin with TermRuntime1
newVarEnds.fold(mt) { _ ~ _ }
}
+ private lazy val setVars = this.setVariableStatements
+
+ private lazy val setVarGrams = setVars.map { _.gram(self) }
+
+ protected lazy val dfdlSetVariableStatements =
+ prod("dfdlSetVariableStatments", setVarGrams.length > 0) {
+ setVarGrams.fold(mt) { _ ~ _ }
+ }
+
/**
* Mandatory text alignment or mta
*
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala
index 8d6600ab51..a7f12c9778 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala
@@ -71,7 +71,9 @@ class OrderedSequence(sq: SequenceTermBase, sequenceChildrenArg: Seq[SequenceChi
// the mta parser differently to avoid this
private lazy val sepUnparser = sepGram.unparser
- lazy val sequenceChildren = sequenceChildrenArg.toVector
+ lazy val sequenceChildren = {
+ sequenceChildrenArg.toVector
+ }
override lazy val parser: Parser = sq.hasSeparator match {
case true =>
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ExpressionEvaluatingParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ExpressionEvaluatingParsers.scala
index fa35fa4b1d..03f66c98df 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ExpressionEvaluatingParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ExpressionEvaluatingParsers.scala
@@ -225,7 +225,6 @@ final class AssertExpressionEvaluationParser(
with AssertParserMixin {
def parse(start: PState): Unit = {
- Logger.log.debug(s"This is ${toString}")
//
// This now informs us of the success/failure of the expression
// evaluation via side-effect on the start state passed here.
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/PState.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/PState.scala
index adf085ff1c..5d4ab4fa8d 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/PState.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/PState.scala
@@ -61,6 +61,7 @@ import org.apache.daffodil.runtime1.processors.NonTermRuntimeData
import org.apache.daffodil.runtime1.processors.ParseOrUnparseState
import org.apache.daffodil.runtime1.processors.ProcessorResult
import org.apache.daffodil.runtime1.processors.RuntimeData
+import org.apache.daffodil.runtime1.processors.Success
import org.apache.daffodil.runtime1.processors.TermRuntimeData
import org.apache.daffodil.runtime1.processors.VariableInstance
import org.apache.daffodil.runtime1.processors.VariableMap
@@ -586,6 +587,23 @@ final class PState private (
}
}
+ /**
+ * This function is used for cases where a parse must be performed after there
+ * has already been a failed parse of an enclosing element/sequence. Most
+ * common example of this would be a choice branch containing a sequence with
+ * an annotated assert expression. According to 9.5.2 of the DFDL spec this
+ * assert expression needs to be parsed regardless of whether or not the
+ * enclosing sequence content parses or not as the assert expression may be
+ * used as a discriminator for the choice branch.
+ */
+ def withTempSuccess(func: (PState) => Unit): Unit = {
+ val priorProcessorStatus = processorStatus
+ setSuccess()
+ func(this)
+ if (processorStatus eq Success)
+ _processorStatus = priorProcessorStatus
+ }
+
def suspensions = Seq.empty
}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/Parser.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/Parser.scala
index d546b0869d..c508fc9e36 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/Parser.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/Parser.scala
@@ -178,8 +178,11 @@ abstract class CombinatorParser(override val context: RuntimeData)
extends Parser
with CombinatorProcessor
-final class SeqCompParser(context: RuntimeData, val childParsers: Vector[Parser])
- extends CombinatorParser(context) {
+final class SeqCompParser(
+ context: RuntimeData,
+ val childParsers: Vector[Parser],
+ testAssert: Vector[Parser],
+) extends CombinatorParser(context) {
override lazy val runtimeDependencies = Vector()
override def childProcessors = childParsers
@@ -192,8 +195,14 @@ final class SeqCompParser(context: RuntimeData, val childParsers: Vector[Parser]
while (i < numChildParsers) {
val parser = childParsers(i)
parser.parse1(pstate)
- if (pstate.processorStatus ne Success)
+ if (pstate.processorStatus ne Success) {
+ if (testAssert.nonEmpty) {
+ testAssert.foreach { ap =>
+ pstate.withTempSuccess(ap.parse1)
+ }
+ }
return
+ }
i += 1
}
}
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 93629b6858..4dfbeed986 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
@@ -655,7 +655,6 @@
-
-
-
-
- abc
-
-
-
+
+ Parse Error
+ Failed to populate ex:ints
+ Unable to parse xs:int from text: a
+
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/TestDiscriminators.scala
index c5051c0b2c..acc183a4de 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/TestDiscriminators.scala
@@ -79,7 +79,7 @@ class TestDiscriminators {
@Test def test_discrimExpression_03() = { runner.runOneTest("discrimExpression_03") }
// DAFFODIL-1971
- // @Test def test_discrimExpression_04() = { runner.runOneTest("discrimExpression_04") }
+ @Test def test_discrimExpression_04() = { runner.runOneTest("discrimExpression_04") }
@Test def test_discrimFailStopsFollowingAssert1(): Unit = {
runner.runOneTest("discrimFailStopsFollowingAssert1")