All Downloads are FREE. Search and download functionalities are using the official Maven repository.

laika.parse.markup.DefaultRecursiveSpanParsers.scala Maven / Gradle / Ivy

/*
 * Copyright 2013-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package laika.parse.markup

import laika.ast.{InvalidElement, Span}
import laika.parse.text.DelimitedText
import laika.parse.{Failure, Parser, Success}

/** Default implementation for parsing inline markup recursively.
  *
  * @author Jens Halm
  */
trait DefaultRecursiveSpanParsers extends RecursiveSpanParsers with DefaultEscapedTextParsers {


  /** The mapping of markup start characters to their corresponding
    *  span parsers.
    *
    *  A parser mapped to a start character is not required
    *  to successfully parse the subsequent input. If it fails the
    *  character that triggered the parser invocation will be treated
    *  as normal text. The mapping is merely used as a performance
    *  optimization. The parser will be invoked with the input
    *  offset pointing to the character after the one
    *  specified as the key for the mapping.
    */
  protected def spanParsers: Map[Char,Parser[Span]]


  private lazy val defaultSpanParser: Parser[List[Span]] = InlineParsers.spans(DelimitedText.Undelimited, spanParsers)

  private def createRecursiveSpanParser (textParser: Parser[String], spanParser: => Parser[List[Span]]): Parser[List[Span]] = {
    lazy val spanParser0 = spanParser
    Parser { ctx =>
      textParser.parse(ctx) match {
        case Success(str, next) =>
          spanParser0.parse(str) match {
            case Success(spans, _) => Success(spans, next)
            case f: Failure => f
          }
        case f: Failure => f
      }
    }
  }


  def recursiveSpans (p: Parser[String]): Parser[List[Span]] =
    createRecursiveSpanParser(p, defaultSpanParser)

  def recursiveSpans (p: Parser[String],
                      additionalParsers: => Map[Char, Parser[Span]] = Map.empty): Parser[List[Span]] =
    createRecursiveSpanParser(p, InlineParsers.spans(DelimitedText.Undelimited, spanParsers ++ additionalParsers))

  def recursiveSpans: Parser[List[Span]] = defaultSpanParser

  def delimitedRecursiveSpans (textParser: DelimitedText[String],
                               additionalSpanParsers: => Map[Char, Parser[Span]]): Parser[List[Span]] =
    InlineParsers.spans(textParser, spanParsers ++ additionalSpanParsers)

  def delimitedRecursiveSpans (textParser: DelimitedText[String]): Parser[List[Span]] =
    InlineParsers.spans(textParser, spanParsers)

  def withRecursiveSpanParser [T] (p: Parser[T]): Parser[(String => List[Span], T)] = Parser { ctx =>
    p.parse(ctx) match {
      case Success(res, next) =>
        val recParser: String => List[Span] = { source: String =>
          defaultSpanParser.parse(source) match {
            case Success(spans, _)  => spans
            case Failure(msg, next) => List(InvalidElement(msg.message(next), source).asSpan)
          }
        }
        Success((recParser, res), next)
      case f: Failure => f
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy