protected def parseRemainder()

in daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/dfa/TextDelimitedParser.scala [267:398]


  protected def parseRemainder(
    state: PState,
    input: DataInputStream,
    fieldEsc: DFAField,
    startBlock: DFADelimiter,
    endBlock: DFADelimiter,
    delimIter: DelimiterIterator,
    isDelimRequired: Boolean
  ): Maybe[ParseResult] = {

    val lmt = new LongestMatchTracker()

    val fieldRegister = state.dfaRegistersPool.getFromPool("parseRemainder")
    fieldRegister.reset(state, input, delimIter)

    var stillSearching: Boolean = true
    var foundBlockEnd: Boolean = false
    var beforeDelimiter: DataInputStream.MarkPos = DataInputStream.MarkPos.NoMarkPos
    while (stillSearching) {

      Assert.invariant(beforeDelimiter =#= DataInputStream.MarkPos.NoMarkPos)
      fieldEsc.run(fieldRegister)
      val dfaStatus = fieldRegister.status
      beforeDelimiter =
        input.markPos // at this point the input is one past the end of the field.
      fieldRegister.actionNum = 0

      dfaStatus match {
        case StateKind.EndOfData => stillSearching = false
        case StateKind.Failed => stillSearching = false
        case StateKind.Paused => {
          // Pick up where field left off, we are looking for the blockEnd.
          val endBlockRegister = state.dfaRegistersPool.getFromPool("parseRemainder2")
          endBlockRegister.reset(state, input, delimIter)
          endBlock.run(endBlockRegister)
          val endBlockStatus = endBlockRegister.status
          state.dfaRegistersPool.returnToPool(endBlockRegister)

          endBlockStatus match {
            case StateKind.Succeeded => {
              // Found the unescaped block end, now we need to
              // find any padding.
              this.removeRightPadding(state, input, delimIter)
              beforeDelimiter = input.markPos

              delimIter.reset()
              while (delimIter.hasNext()) {
                // Finally, we can look for the delimiter.
                val d = delimIter.next() // Pick up where end of block/padding left off
                val delimRegister = state.dfaRegistersPool.getFromPool("parseRemainder3")
                input.resetPos(beforeDelimiter)
                beforeDelimiter = input.markPos
                delimRegister.reset(state, input, delimIter)

                d.run(delimRegister)
                if (delimRegister.status == StateKind.Succeeded) {
                  lmt.successfulMatch(
                    delimRegister.matchStartPos,
                    delimRegister.delimString,
                    d,
                    delimIter.currentIndex
                  )
                }
                state.dfaRegistersPool.returnToPool(delimRegister)
              }
              foundBlockEnd = true
              stillSearching = false
            }
            case _ => {
              //
              // In this case we already found
              // a block start, (because we're in parseRemainder)
              // and we halted scanning because we found the start of a block end
              // However, it turns out not to be an entire block end.
              //
              // So we keep going. But we have to accumulate the
              // characters we were scrutinizing as the possible block end
              // into the field.
              //
              input.resetPos(beforeDelimiter)
              beforeDelimiter = DataInputStream.MarkPos.NoMarkPos
              fieldRegister.resetChars(state)

              // resume field parse
              //
              // This resumes the field dfa by moving it onto the next rule
              // This assumes that the field dfa will resume properly using
              // it's existing state, so long as the input is repositioned properly.
              //
              fieldRegister.actionNum = fieldRegister.actionNum + 1 // goto next rule
            }
          }
        }
      }
    } // End While
    Assert.invariant(beforeDelimiter !=#= DataInputStream.MarkPos.NoMarkPos)
    input.resetPos(beforeDelimiter)
    val result = {
      if (lmt.longestMatches.isEmpty) {
        //
        // No delimiter found
        // that may or may not be ok
        //
        if (foundBlockEnd && isDelimRequired) Nope
        else if (!foundBlockEnd) Nope
        else {
          //
          // In this case we found a block end, and no delimiter is required
          // so we have enough to be done with the field
          //
          val fieldValue: Maybe[String] = {
            One(fieldRegister.resultString.toString)
          }
          One(new ParseResult(fieldValue, Nope, lmt.longestMatches))
        }
      } else {
        //
        // A delimiter was found
        //
        val fieldValue: Maybe[String] = {
          One(fieldRegister.resultString.toString)
        }
        val delim: Maybe[String] = {
          One(lmt.longestMatchedString)
        }
        One(new ParseResult(fieldValue, delim, lmt.longestMatches))
      }
    }

    state.dfaRegistersPool.returnToPool(fieldRegister)
    result
  }