| /* Copyright (c) 2016 Tresys Technology, LLC. All rights reserved. |
| * |
| * Developed by: Tresys Technology, LLC |
| * http://www.tresys.com |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy of |
| * this software and associated documentation files (the "Software"), to deal with |
| * the Software without restriction, including without limitation the rights to |
| * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
| * of the Software, and to permit persons to whom the Software is furnished to do |
| * so, subject to the following conditions: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimers. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimers in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * 3. Neither the names of Tresys Technology, nor the names of its contributors |
| * may be used to endorse or promote products derived from this Software |
| * without specific prior written permission. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE |
| * SOFTWARE. |
| */ |
| |
| package edu.illinois.ncsa.daffodil.processors |
| |
| import edu.illinois.ncsa.daffodil.dsom._ |
| import edu.illinois.ncsa.daffodil.processors.dfa.DFADelimiter |
| import edu.illinois.ncsa.daffodil.processors.dfa.CreateDelimiterDFA |
| import edu.illinois.ncsa.daffodil.exceptions.Assert |
| import edu.illinois.ncsa.daffodil.processors.unparsers.UState |
| import edu.illinois.ncsa.daffodil.processors.parsers.DelimiterTextType |
| |
| trait DelimiterEvMixin[+T <: AnyRef] |
| extends ExprEvalMixin[String] { self: Evaluatable[T] => |
| |
| final def isKnownNonEmpty = expr.isKnownNonEmpty |
| |
| def expr: CompiledExpression[String] |
| def converter: Converter[String, List[String]] |
| def trd: TermRuntimeData |
| |
| override final def toBriefXML(depth: Int = -1) = if (this.isConstant) this.constValue.toString else expr.toBriefXML(depth) |
| |
| protected def evalAndConvert(state: ParseOrUnparseState): List[String] = { |
| val expressionResult = eval(expr, state) |
| |
| val converterResult = state match { |
| case cs: CompileState => converter.convertConstant(expressionResult, trd, false) |
| case _ => converter.convertRuntime(expressionResult, trd, false) |
| } |
| converterResult |
| } |
| } |
| |
| abstract class DelimiterParseEv(delimType: DelimiterTextType.Type, override val expr: CompiledExpression[String], override val trd: TermRuntimeData) |
| extends Evaluatable[Array[DFADelimiter]](trd) |
| with InfosetCachedEvaluatable[Array[DFADelimiter]] |
| with DelimiterEvMixin[Array[DFADelimiter]] { |
| |
| override lazy val runtimeDependencies = Nil |
| |
| override protected def compute(state: ParseOrUnparseState): Array[DFADelimiter] = { |
| if (state.isInstanceOf[UState]) { |
| Assert.invariantFailed("State was UState in Parser Evaluatable") |
| } |
| |
| val converterResult = evalAndConvert(state) |
| if (converterResult.length == 1 && converterResult(0) == "") { |
| Array() |
| } else { |
| CreateDelimiterDFA(delimType, trd, converterResult) |
| } |
| } |
| } |
| |
| abstract class DelimiterUnparseEv(delimType: DelimiterTextType.Type, override val expr: CompiledExpression[String], outputNewLine: OutputNewLineEv, override val trd: TermRuntimeData) |
| extends Evaluatable[Option[DFADelimiter]](trd) |
| with InfosetCachedEvaluatable[Option[DFADelimiter]] |
| with DelimiterEvMixin[Option[DFADelimiter]] { |
| |
| override lazy val runtimeDependencies = Seq(outputNewLine) |
| |
| override protected def compute(state: ParseOrUnparseState): Option[DFADelimiter] = { |
| if (state.isInstanceOf[PState]) { |
| Assert.invariantFailed("State was PState in Unparser Evaluatable") |
| } |
| |
| val converterResult = evalAndConvert(state) |
| if (converterResult.length == 1 && converterResult(0) == "") { |
| None |
| } else { |
| val onl = outputNewLine.evaluate(state) |
| Some(CreateDelimiterDFA(delimType, trd, converterResult(0), onl)) |
| } |
| } |
| } |
| |
| class InitiatorParseEv(expr: CompiledExpression[String], trd: TermRuntimeData) |
| extends DelimiterParseEv(DelimiterTextType.Initiator, expr, trd) { |
| |
| override val converter = InitiatorCooker |
| } |
| |
| class InitiatorUnparseEv(expr: CompiledExpression[String], outputNewLine: OutputNewLineEv, trd: TermRuntimeData) |
| extends DelimiterUnparseEv(DelimiterTextType.Initiator, expr, outputNewLine, trd) { |
| |
| override val converter = InitiatorCooker |
| } |
| |
| class TerminatorParseEv(expr: CompiledExpression[String], isLengthKindDelimited: Boolean, trd: TermRuntimeData) |
| extends DelimiterParseEv(DelimiterTextType.Terminator, expr, trd) { |
| |
| override val converter = if (isLengthKindDelimited) TerminatorCookerNoES else TerminatorCooker |
| } |
| |
| class TerminatorUnparseEv(expr: CompiledExpression[String], isLengthKindDelimited: Boolean, outputNewLine: OutputNewLineEv, trd: TermRuntimeData) |
| extends DelimiterUnparseEv(DelimiterTextType.Terminator, expr, outputNewLine, trd) { |
| |
| override val converter = if (isLengthKindDelimited) TerminatorCookerNoES else TerminatorCooker |
| } |
| |
| class SeparatorParseEv(expr: CompiledExpression[String], trd: TermRuntimeData) |
| extends DelimiterParseEv(DelimiterTextType.Separator, expr, trd) { |
| |
| override val converter = SeparatorCooker |
| } |
| |
| class SeparatorUnparseEv(expr: CompiledExpression[String], outputNewLine: OutputNewLineEv, trd: TermRuntimeData) |
| extends DelimiterUnparseEv(DelimiterTextType.Separator, expr, outputNewLine, trd) { |
| |
| override val converter = SeparatorCooker |
| } |