Github user stevedlawrence commented on a diff in the pull request:

    https://github.com/apache/incubator-daffodil/pull/4#discussion_r153524759
  
    --- Diff: 
daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/parsers/Parser.scala
 ---
    @@ -189,76 +193,107 @@ class AltCompParser(context: RuntimeData, val 
childParsers: Seq[Parser])
     
       def parse(pstate: PState): Unit = {
         var pBefore: PState.Mark = null
    +    var markLeakCausedByException = false;
     
    -    pstate.pushDiscriminator
    -    var diagnostics: Seq[Diagnostic] = Nil
    -    var i = 0
    -    var parser: Parser = null
    -    val limit = childParsers.length
    -    var returnFlag = false
    -    while (!returnFlag && i < limit) {
    -      parser = childParsers(i)
    -      i += 1
    -      log(LogLevel.Debug, "Trying choice alternative: %s", parser)
    -      pBefore = pstate.mark("AltCompParser1")
    -      try {
    -        parser.parse1(pstate)
    -      } catch {
    -        case d: SchemaDefinitionDiagnosticBase => {
    -          pstate.discard(pBefore)
    -          throw d
    +    try {
    +      pstate.pushDiscriminator
    +      var diagnostics: Seq[Diagnostic] = Nil
    +      var i = 0
    +      var parser: Parser = null
    +      val limit = childParsers.length
    +      var returnFlag = false
    +      while (!returnFlag && i < limit) {
    +        parser = childParsers(i)
    +        i += 1
    +        log(LogLevel.Debug, "Trying choice alternative: %s", parser)
    +        pBefore = pstate.mark("AltCompParser1")
    +        try {
    +          parser.parse1(pstate)
    +        } catch {
    +          case d: SchemaDefinitionDiagnosticBase => {
    +            pstate.discard(pBefore)
    +            pBefore = null
    +            throw d
    +          }
             }
    -      }
    -      if (pstate.processorStatus eq Success) {
    -        log(LogLevel.Debug, "Choice alternative success: %s", parser)
    -        pstate.discard(pBefore)
    -        pBefore = null
    -        returnFlag = true
    -      } else {
    -        // If we get here, then we had a failure
    -        log(LogLevel.Debug, "Choice alternative failed: %s", parser)
    -        //
    -        // capture diagnostics
    -        //
    -        val diag = new ParseAlternativeFailed(context.schemaFileLocation, 
pstate, pstate.diagnostics)
    -        diagnostics = diag +: diagnostics
    -        //
    -        // check for discriminator evaluated to true.
    -        //
    -        if (pstate.discriminator == true) {
    -          log(LogLevel.Debug, "Failure, but discriminator true. Additional 
alternatives discarded.")
    -          // If so, then we don't run the next alternative, we
    -          // consume this discriminator status result (so it doesn't 
ripple upward)
    -          // and return the failed state with all the diagnostics.
    -          //
    -          val allDiags = new AltParseFailed(context.schemaFileLocation, 
pstate, diagnostics.reverse)
    -          pstate.discard(pBefore) // because disc set, we don't unwind 
side effects on input stream & infoset
    +        if (pstate.processorStatus eq Success) {
    +          log(LogLevel.Debug, "Choice alternative success: %s", parser)
    +          pstate.discard(pBefore)
               pBefore = null
    -          pstate.setFailed(allDiags)
               returnFlag = true
             } else {
    +          // If we get here, then we had a failure
    +          log(LogLevel.Debug, "Choice alternative failed: %s", parser)
               //
    -          // Here we have a failure, but no discriminator was set, so we 
try the next alternative.
    -          // Which means we just go around the loop
    +          // capture diagnostics
               //
    -          // But we have to unwind side-effects on input-stream, infoset, 
variables, etc.
    -          pstate.reset(pBefore)
    -          pBefore = null
    -          returnFlag = false
    +          val diag = new 
ParseAlternativeFailed(context.schemaFileLocation, pstate, pstate.diagnostics)
    +          diagnostics = diag +: diagnostics
    +          //
    +          // check for discriminator evaluated to true.
    +          //
    +          if (pstate.discriminator == true) {
    +            log(LogLevel.Debug, "Failure, but discriminator true. 
Additional alternatives discarded.")
    +            // If so, then we don't run the next alternative, we
    +            // consume this discriminator status result (so it doesn't 
ripple upward)
    +            // and return the failed state with all the diagnostics.
    +            //
    +            val allDiags = new AltParseFailed(context.schemaFileLocation, 
pstate, diagnostics.reverse)
    +            pstate.discard(pBefore) // because disc set, we don't unwind 
side effects on input stream & infoset
    +            pBefore = null
    +            pstate.setFailed(allDiags)
    +            returnFlag = true
    +          } else {
    +            //
    +            // Here we have a failure, but no discriminator was set, so we 
try the next alternative.
    +            // Which means we just go around the loop
    +            //
    +            // But we have to unwind side-effects on input-stream, 
infoset, variables, etc.
    +            pstate.reset(pBefore)
    +            pBefore = null
    +            returnFlag = false
    +          }
             }
           }
    -    }
    -    Assert.invariant(i <= limit)
    -    if (returnFlag == false) {
    -      Assert.invariant(i == limit)
    -      // Out of alternatives. All of them failed.
    -      val allDiags = new AltParseFailed(context.schemaFileLocation, 
pstate, diagnostics.reverse)
    -      pstate.setFailed(allDiags)
    -      log(LogLevel.Debug, "All AltParser alternatives failed.")
    -    }
    +      Assert.invariant(i <= limit)
    +      if (returnFlag == false) {
    +        Assert.invariant(i == limit)
    +        // Out of alternatives. All of them failed.
    +        val allDiags = new AltParseFailed(context.schemaFileLocation, 
pstate, diagnostics.reverse)
    +        pstate.setFailed(allDiags)
    +        log(LogLevel.Debug, "All AltParser alternatives failed.")
    +      }
     
    -    Assert.invariant(pBefore eq null)
    -    pstate.popDiscriminator
    +      pstate.popDiscriminator
    +    } catch {
    +      // Similar try/catch/finally logic for returning marks is also used 
in
    +      // the RepAtMostTotalNParser and RepUnboundedParser. The logic isn't
    +      // easily factored out so it is duplicated. Changes made here should 
also
    +      // be made there. Only these parsers deal with taking marks, so this 
logic
    +      // should not be needed elsewhere.
    +      case t: Throwable => {
    +        if (pBefore != null) {
    +          markLeakCausedByException = true
    +          if (!t.isInstanceOf[SchemaDefinitionDiagnosticBase] && 
!t.isInstanceOf[UnsuppressableException]) {
    +            val stackTrace = new StringWriter()
    +            t.printStackTrace(new PrintWriter(stackTrace))
    +            Assert.invariantFailed("Exception thrown with mark not 
returned: " + t + "\nStackTrace:\n" + stackTrace)
    +          }
    +        }
    +        throw t
    +      }
    +    } finally {
    +      var markLeak = false;
    +      if (pBefore != null) {
    +        pstate.discard(pBefore)
    --- End diff --
    
    It is not needed here just because this code is for cleaning up leaked 
marked (i.e. non-null values). Since nothing uses pBefore afterwards, setting 
to null isn't needed.


---

Reply via email to