Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evaluate assert/discriminator expressions after groupContent: WIP #987

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,6 @@
</xs:sequence>
</xs:complexType>
</xs:element>

</tdml:defineSchema>

<tdml:parserTestCase name="discrimExpression_01"
Expand Down Expand Up @@ -693,13 +692,11 @@
root="e3" model="discrimExpression"
description="Property Name: test - DFDL-7-076R">
<tdml:document><![CDATA[abc]]></tdml:document>
<tdml:infoset>
<tdml:dfdlInfoset>
<e3>
<string>abc</string>
</e3>
</tdml:dfdlInfoset>
</tdml:infoset>
<tdml:errors>
<tdml:error>Parse Error</tdml:error>
<tdml:error>Failed to populate ex:ints</tdml:error>
<tdml:error>Unable to parse xs:int from text: a</tdml:error>
</tdml:errors>
</tdml:parserTestCase>

<tdml:defineSchema name="choice3">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down