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 #987

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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 @@ -216,8 +216,8 @@ trait ProvidesDFDLStatementMixin extends ThrowsSDE with HasTermCheck {

final lazy val patternStatements: Seq[DFDLStatement] = patternAsserts ++ patternDiscrims
jadams-tresys marked this conversation as resolved.
Show resolved Hide resolved

final lazy val lowPriorityStatements: Seq[DFDLStatement] =
setVariableStatements ++ nonPatternAsserts ++ nonPatternDiscrims
final lazy val expressionStatements: Seq[DFDLStatement] =
nonPatternAsserts ++ nonPatternDiscrims
jadams-tresys marked this conversation as resolved.
Show resolved Hide resolved

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 @@ -92,7 +92,11 @@ class SeqComp private (context: SchemaComponent, children: Seq[Gram])
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,
)
}

lazy val unparserChildren = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ trait HasStatementsGrammarMixin extends GrammarMixin { self: Term =>

// Includes setVariable as well as assert/discriminator statements that
jadams-tresys marked this conversation as resolved.
Show resolved Hide resolved
// are not testKind="pattern"
private lazy val lowPriorityStatementGrams = lowPriorityStatements.map { _.gram(self) }
private lazy val expressionStatementGrams = expressionStatements.map { _.gram(self) }

final lazy val dfdlLowPriorityStatementEvaluations =
prod("dfdlStatementEvaluations", lowPriorityStatementGrams.length > 0) {
lowPriorityStatementGrams.fold(mt) { _ ~ _ }
final lazy val dfdlExpressionStatementEvaluations =
prod("dfdlExpressionStatementEvaluations", expressionStatementGrams.length > 0) {
expressionStatementGrams.fold(mt) { _ ~ _ }
}

// assert/discriminator statements with testKind="pattern"
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 ~
dfdlExpressionStatementEvaluations ~ // 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 @@ -588,6 +588,24 @@ 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
jadams-tresys marked this conversation as resolved.
Show resolved Hide resolved
* 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): ProcessorResult = {
val priorProcessorStatus = processorStatus
setSuccess()
func(this)
val funcStatus = processorStatus
_processorStatus = priorProcessorStatus
funcStatus
}

def suspensions = Seq.empty
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,26 +227,31 @@ 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],
) extends CombinatorParser(context) {
override lazy val runtimeDependencies = Vector()
override def childProcessors = childParsers

override def nom = "seq"

val numChildParsers = childParsers.size
val discrimExpressions = childParsers.collect{ case ae: AssertExpressionEvaluationParser if (ae.discrim) => ae }
val nonDiscrimChildren = childParsers.diff(discrimExpressions)

def parse(pstate: PState): Unit = {
var i: Int = 0
while (i < numChildParsers) {
val parser = childParsers(i)
parser.parse1(pstate)
if (pstate.processorStatus ne Success)
return
i += 1
for (p <- nonDiscrimChildren) {
jadams-tresys marked this conversation as resolved.
Show resolved Hide resolved
if (pstate.processorStatus eq Success)
p.parse1(pstate)
}
}

discrimExpressions.foreach { d =>
if (pstate.processorStatus eq Success)
d.parse1(pstate)
else
pstate.withTempSuccess(d.parse1)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this order confirmed by the DFDL-WG? First we do all normal parsers, then the discriminator, and then assertions? And that the order has nothing to do with the order things are defined in the schema?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Confirmed in a lengthly workgroup discussion yesterday in fact.

}

class ChoiceParser(ctxt: RuntimeData, val childParsers: Vector[Parser])
Expand Down
Loading
Loading