Packages

  • package root
    Definition Classes
    root
  • package io
    Definition Classes
    root
  • package dylemma
    Definition Classes
    io
  • package spac

    SPaC (short for "Streaming Parser Combinators") is a library for building stream consumers in a declarative style, specialized for tree-like data types like XML and JSON.

    SPaC (short for "Streaming Parser Combinators") is a library for building stream consumers in a declarative style, specialized for tree-like data types like XML and JSON.

    Many utilities for handling XML and JSON data involve parsing the entire "document" to some DOM model, then inspecting and transforming that model to extract information. The downside to these utilities is that when the document is very large, the DOM may not fit in memory. The workaround for this type of problem is to treat the document as a stream of "events", e.g. "StartElement" and "EndElement" for XML, or "StartObject" and "EndObject" for JSON. The downside to this workaround is that writing code to handle these streams can be complicated and error-prone, especially when the DOM is complicated.

    SPaC's goal is to drastically simplify the process of creating code to handle these streams.

    This package contains the "core" SPaC traits; Parser, Transformer, Splitter, and ContextMatcher.

    See the xml and json subpackages (provided by the xml-spac and json-spac libraries respectively) for specific utilities related to handling XML and JSON event streams.

    Definition Classes
    dylemma
  • package interop
    Definition Classes
    spac
  • package json

    This package provides extensions to the core "spac" library which allow for the handling of JSON data.

    This package provides extensions to the core "spac" library which allow for the handling of JSON data.

    Rather than creating explicit classes that extend Parser, Transformer, and Splitter, this package provides type aliases and implicit extensions. For example, JsonParser[A] is just a type alias for Parser[JsonEvent, A], and JsonParser is just a call to Parser[JsonEvent].

    Implicit JsonParsers are available for each of the JSON primitive types:

    • string
    • number (expressed as Int, Long, Float, or Double)
    • boolean
    • null (expressed as None.type)

    Helpers are available for parsing JSON arrays and objects:

    • JsonParser.listOf[A] to parse an array where each value is an A
    • JsonParser.objectOf[A] to parse an object where the value for each field an A
    • JsonParser.objectOfNullable[A] to parse an object where the value for each field is either null or an A, filtering out the nulls
    • JsonParser.fieldOf[A](fieldName) to parse a specific field from an object

    A DSL for creating json-specific ContextMatchers is provided to make it more convenient to call Splitter.json. For example:

    Splitter.json("foo" \ "bar").as[String].parseFirst

    Can be used to capture rootJson.foo.bar as a String in

    {
      "foo": {
        "bar": "hello"
      }
    }

    To "split" values inside arrays, index-related context matchers are available, e.g.

    Splitter.json("foo" \ anyIndex).as[Int].parseToList

    Can be used to capture each of the numbers in the "foo" array in

    {
      "foo": [1, 2, 3]
    }

    A note about JsonEvents in spac: JSON doesn't have any explicit markers for when a field ends, or when an array index starts or ends; those context changes are essentially inferred by the presence of some other event. For example, instead of a "field end" event, typically there will be either a new "field start" or a token representing the end of the current object. With spac, splitters and context matchers generally operate under the assumption that a "stack push" event (like a field start) will eventually be followed by a corresponding "stack pop" event (i.e. field end).

    To allow for this, these "inferred" events (FieldEnd, IndexStart, IndexEnd) are explicitly represented as JsonEvents in the stream being parsed. Keep this in mind when creating JSON ContextMatchers:

    • field-related matchers will match a stack like case ObjectStart :: FieldStart(_) :: _
    • index-related matchers will match a stack like case ArrayStart :: IndexStart(_) :: _
    Definition Classes
    spac
  • package xml

    This package provides extensions to the core "spac" library which allow for the handling of XML data.

    This package provides extensions to the core "spac" library which allow for the handling of XML data.

    Rather than creating explicit classes that extend Parser, Transformer, and Splitter, this package provides type aliases and implicit extensions. For example, XmlParser[A] is just a type alias for Parser[XmlEvent, A], and XmlParser is just a call to Parser[XmlEvent].

    Three main Parser methods are added to Parser[XmlEvent] via the XmlParserApplyOps implicit class:

    • XmlParser.forText - for capturing raw text
    • XmlParser.attr - for capturing mandatory attributes from elements
    • XmlParser.attrOpt - for capturing optional attributes from elements

    One main Splitter constructor method is added to Splitter via the XmlSplitterApplyOps implicit class:

    • Splitter.xml - for creating splitters based on an inspection of an "element stack"

    Three main Splitter member methods are added to Splitter[XmlEvent, C] via the XmlSplitterOps implicit class:

    • .attr - alias for .joinBy(XmlParser.attr(...))
    • .attrOpt - alias for .joinBy(XmlParser.attrOpt(...))
    • .text - alias for .joinBy(XmlParser.forText)

    A DSL for creating xml-specific ContextMatchers is provided to make it more convenient to call Splitter.xml. For example:

    Splitter.xml("things" \ "thing").attr("foo").parseToList

    Can be used to capture a list of the "foo" attributes in the <thing> elements in

    <things>
       <thing foo="hello" />
       <thing foo="Goodbye">
          <extra>junk</extra>
       </thing>
    </thing>
    Definition Classes
    spac
  • CallerPos
  • ContextChange
  • ContextLocation
  • ContextMatcher
  • ContextPop
  • ContextPush
  • ContextTrace
  • HasLocation
  • LowPriorityTypeReduceImplicits
  • Parser
  • ParserApplyWithBoundInput
  • Signal
  • SingleItemContextMatcher
  • Source
  • SpacException
  • SpacTraceElement
  • Splitter
  • SplitterApplyWithBoundInput
  • StackInterpretation
  • StackLike
  • Transformer
  • TransformerApplyWithBoundInput
  • TypeReduce
  • Unconsable

trait Parser[-In, +Out] extends AnyRef

Primary "spac" abstraction which represents a sink for data events.

Parsers are responsible for interpreting a stream of In events as a single result of type Out. The actual interpretation is performed by a Parser.Handler which the Parser is responsible for constructing. Handlers may be internally-mutable, and so they are generally only constructed by the parse helper methods or by other handlers. Parsers themselves are immutable, acting as "handler factories", and so they may be freely reused.

A parser differs from typical "fold" operations in that it may choose to abort early with a result, leaving the remainder of the data stream untouched.

In

event/input type

Out

result type

Self Type
Parser[In, Out]
Source
Parser.scala
Linear Supertypes
AnyRef, Any
Known Subclasses
Ordering
  1. Grouped
  2. Alphabetic
  3. By Inheritance
Inherited
  1. Parser
  2. AnyRef
  3. Any
Implicitly
  1. by ParserFollowedByOps
  2. by any2stringadd
  3. by StringFormat
  4. by Ensuring
  5. by ArrowAssoc
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Abstract Value Members

  1. abstract def newHandler: Handler[In, Out]

    Parser's main abstract method; constructs a new Handler representing this parser's logic.

    Parser's main abstract method; constructs a new Handler representing this parser's logic. Parsers are expected to be immutable, but Handlers may be internally-mutable.

Concrete Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int
    Definition Classes
    AnyRef → Any
  3. def +(other: String): String
    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toany2stringadd[Parser[In, Out]] performed by method any2stringadd in scala.Predef.
    Definition Classes
    any2stringadd
  4. def ->[B](y: B): (Parser[In, Out], B)
    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toArrowAssoc[Parser[In, Out]] performed by method ArrowAssoc in scala.Predef.
    Definition Classes
    ArrowAssoc
    Annotations
    @inline()
  5. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  6. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  7. def asTransformer: Transformer[In, Out]

    Represent this parser as a Transformer which emits this parser's result

  8. def attempt: Parser[In, Either[Throwable, Out]]

    Like wrapSafe, but represents exceptions as Left and successful results as Right

  9. def beforeContext[I2 <: In, StackElem](matcher: ContextMatcher[StackElem, Any])(implicit stackable: StackLike[I2, StackElem], pos: CallerPos): Parser[I2, Out]

    Specialization of interruptedBy for stack-like input types, such that an interruption will occur upon entering a stack context that can be matched by the given matcher.

    Specialization of interruptedBy for stack-like input types, such that an interruption will occur upon entering a stack context that can be matched by the given matcher.

    Example:

    val preludeContext = * \ "prelude"
    val dataContext = * \ "data"
    for {
      prelude <- Splitter(preludeContext).firstOption[Prelude].beforeContext(dataContext).followedByStream
      data <- Splitter(dataContext).as[Data]
    } yield data
    I2

    Subtype of In, or just In (to satisfy contravariance of Parser's In type)

    StackElem

    Specialization of the In type for when it represents a stack push or pop

    matcher

    A matching function that operates on a context stack

    stackable

    Interprets the inputs as stack push/pop events to accumulate a context stack

    returns

    A parser which will perform an early finish() when a matching context is encountered

  10. def clone(): AnyRef
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.CloneNotSupportedException]) @native()
  11. def ensuring(cond: (Parser[In, Out]) => Boolean, msg: => Any): Parser[In, Out]
    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toEnsuring[Parser[In, Out]] performed by method Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  12. def ensuring(cond: (Parser[In, Out]) => Boolean): Parser[In, Out]
    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toEnsuring[Parser[In, Out]] performed by method Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  13. def ensuring(cond: Boolean, msg: => Any): Parser[In, Out]
    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toEnsuring[Parser[In, Out]] performed by method Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  14. def ensuring(cond: Boolean): Parser[In, Out]
    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toEnsuring[Parser[In, Out]] performed by method Ensuring in scala.Predef.
    Definition Classes
    Ensuring
  15. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  16. def equals(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef → Any
  17. def expectInputs[I2 <: In](expectations: List[(String, (I2) => Boolean)]): Parser[I2, Out]

    Impose expectations on the sequence of inputs to be received by handlers created by this parser.

    Impose expectations on the sequence of inputs to be received by handlers created by this parser. As this parser's handler receives an input, the input will be tested against the head of the expectations list. If the test returns false, the expectation is failed and the handler will throw an exception. If the test returns true, the expectation is satisfied, and the handler will advance to the next expectation. If there are no more expectations left in the list (i.e. N inputs have satisfied the corresponding N expectations), then all expectations have been met and inputs will be treated as normal by the handler. If the handler receives an EOF before all expectations are met, it will throw an exception.

    expectations

    A sequence of label -> test expectations imposed on inputs to this parser

    returns

    A copy of this parser with expectations imposed on its inputs

  18. def finalize(): Unit
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.Throwable])
  19. def followedBy: FollowedBy[In, Out, Parser]

    Intermediate object for creating a sequenced parser in which the result of this parser will be used to initialize a second parser as soon as it is available.

    Intermediate object for creating a sequenced parser in which the result of this parser will be used to initialize a second parser as soon as it is available.

    In other words, the source (series of In values) will be fed into this Parser until this parser's handler returns a result of type Out. At that point, the second parser (as specified by using the apply or flatMap methods on the FollowedBy returned by this method) will be instantiated. Any relevant "stack events" (see Stackable) will be replayed so the second parser has the right context, and from that point on, all In values will be sent to the second parser. When that second parser returns a result, that result becomes the output of the combined parser created by this.followedBy(out => makeSecondParser(out))

    Examples:

    val p1: Parser[A] = /* ... */
    def getP2(p1Result: A): Parser[B] = /* ... */
    val combined: Parser[B] = p1.followedBy(getP2)
    
    // alternative `flatMap` syntax
    val combined: Parser[B] = for {
      p1Result <- p1.followedBy
      p2Result <- getP2(p1Result)
    } yield p2Result

    See Parser's interruptedBy, which is useful when a transformer.parseFirstOption must be followedBy some other parser.

    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toParserFollowedByOps[In, Out] performed by method ParserFollowedByOps in io.dylemma.spac.Parser.
    Definition Classes
    ParserFollowedByOps
  20. def followedByParser: FollowedBy[In, Out, Parser]

    Alias for followedBy, for use when Cat's ApplyOps gets in the way with its own useless followedBy method.

    Alias for followedBy, for use when Cat's ApplyOps gets in the way with its own useless followedBy method.

    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toParserFollowedByOps[In, Out] performed by method ParserFollowedByOps in io.dylemma.spac.Parser.
    Definition Classes
    ParserFollowedByOps
  21. def followedByStream: FollowedBy[In, Out, Transformer]

    Intermediate object creating a transformer that depends on this parser.

    Intermediate object creating a transformer that depends on this parser. Particularly useful in cases where one or more specific "info" elements precede a stream of other elements which require that "info" to be parsed.

    Examples:

    val p1: Parser[In, A] = /* ... */
    def getP2Stream(p1Result: A): Transformer[In, B] = /* ... */
    val combined: Transformer[In, B] = p1.andThenStream(getP2Stream)
    
    // alternative `flatMap` syntax
    val combined: Transformer[In, B] = for {
      p1Result <- p1.andThenStream
      p2Result <- getP2Stream(p1Result)
    } yield p2Result

    See followedBy for a general explanation of how the combination works.

    See also, interruptedBy, which is useful when a transformer.parseFirstOption must be followedBy some other transformer.

    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toParserFollowedByOps[In, Out] performed by method ParserFollowedByOps in io.dylemma.spac.Parser.
    Definition Classes
    ParserFollowedByOps
  22. def formatted(fmtstr: String): String
    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toStringFormat[Parser[In, Out]] performed by method StringFormat in scala.Predef.
    Definition Classes
    StringFormat
    Annotations
    @inline()
  23. final def getClass(): Class[_ <: AnyRef]
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  24. def hashCode(): Int
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  25. def interruptedBy[I2 <: In](interrupter: Parser[I2, Any]): Parser[I2, Out]

    Create a copy of this parser that will treat a result from the interrupter as an early EOF.

    Create a copy of this parser that will treat a result from the interrupter as an early EOF. This is especially useful for creating followedBy chains involving optional elements.

    Normally, a parser for an optional item in some context will not finish until that context ends, or until the item is encountered. So if the item is not present, followedBy logic won't work since the followUp parser/transformer will not see any events.

    To make sure the leading parser can "fail fast", you can "interrupt" it, typically by creating a parser that immediately returns a result upon entering a particular context, i.e. the context in which the "following" parser will start. Parser#beforeContext provides a convenience for doing so.

    Note that if the interrupter throws an exception, that exception will not be caught. If your interrupter might throw, pass interrupter.wrapSafe instead to swallow the exception.

    I2

    Subtype of In, or just In (to satisfy contravariance of Parser's In type)

    interrupter

    A parser which will be run in parallel with this parser, and whose result will be treated as an early EOF for this parser, forcing an early call to finish().

    returns

    A parser which will perform an early finish() call when the interrupter produces a result.

  26. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  27. def map[Out2](f: (Out) => Out2): Parser[In, Out2]

    Create a copy of this Parser whose result is transformed by the given function f.

    Create a copy of this Parser whose result is transformed by the given function f.

    Out2

    The new parser's result type

    f

    Result transformation function

  28. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  29. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  30. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  31. def orElse[In2 <: In, Out2 >: Out](fallback: Parser[In2, Out2]): Parser[In2, Out2]

    Combine this parser with the fallback such that failures from the underlying parsers will be ignored as long as at least one succeeds.

    Combine this parser with the fallback such that failures from the underlying parsers will be ignored as long as at least one succeeds. The result will be the result of whichever underlying parser succeeds first. If all of the underlying parsers fail, a SpacException.FallbackChainFailure will be thrown by the returned parser's handler.

    In2

    Subtype of In, or just In (to satisfy Parser's contravariance on the In type)

    Out2

    Supertype of Out, or just Out (to satisfy Parser's covariance on the Out type)

    fallback

    another parser of the same(ish) type as this one

    returns

    A new parser that will succeed if either this parser or the fallback succeed

  32. def parse(source: Source[In])(implicit pos: CallerPos): Out

    Consume the given source to produce an output or possibly throw a SpacException.

    Consume the given source to produce an output or possibly throw a SpacException.

    The Source[A] type is like Iterable[A] but uses the "lender" pattern to acquire the iterator and close any resources associated with the iterator after the iterator is consumed.

    XML and JSON-specific Source constructors are provided by the "parser backend" libraries i.e. xml-spac-javax and json-spac-jackson.

    source

    An object that can provide a series of In values, e.g. XmlEvent or JsonEvent

    pos

    Captures the caller filename and line number, used to fill in the 'spac trace' if the parser throws an exception

    returns

    The parser result based on the given source

  33. def parse(inputs: Iterator[In])(implicit pos: CallerPos): Out

    Consume the given inputs iterator to produce an output or possibly throw a SpacException.

    Consume the given inputs iterator to produce an output or possibly throw a SpacException.

    After calling this method, the inputs should be discarded, since consuming an Iterator is a destructive operation.

    inputs

    A series of In values, e.g. XmlEvent or JsonEvent

    pos

    Captures the caller filename and line number, used to fill in the 'spac trace' if the parser throws an exception

    returns

    The parser result based on the given inputs

    Annotations
    @throws(scala.this.throws.<init>$default$1[io.dylemma.spac.SpacException[_]])
  34. def rethrow[T](implicit ev: <:<[Out, Either[Throwable, T]]): Parser[In, T]

    Like unwrapSafe, but rethrows exceptions from Left or returns results from Right.

    Like unwrapSafe, but rethrows exceptions from Left or returns results from Right. This operation is the opposite of attempt.

  35. def start(methodName: String = "start")(implicit pos: CallerPos): Handler[In, Out]

    Low-level consumer method: creates a new handler and binds the caller position for its SpacTraceElement.

    Low-level consumer method: creates a new handler and binds the caller position for its SpacTraceElement.

    Used internally by the parse methods. Start with this method if you have some sequence-like datatype that doesn't provide an Iterator.

    This is just a convenience for newHandler.asTopLevelhandler which helps construct a useful SpacTraceElement.

    methodName

    The method name used to construct the SpacTraceElement for the handler. Defaults to "start"

    pos

    Captures the caller filename and line number, used to fill in the 'spac trace' if the parser throws an exception

    returns

    A parser handler that can be used to eventually produce a result by calling its step and/or finish methods

  36. final def synchronized[T0](arg0: => T0): T0
    Definition Classes
    AnyRef
  37. def toString(): String
    Definition Classes
    AnyRef → Any
  38. def unwrapSafe[T](implicit ev: <:<[Out, Try[T]]): Parser[In, T]

    Creates a copy of this parser which unwraps the resulting Try, throwing an exception if the result was a Failure.

    Creates a copy of this parser which unwraps the resulting Try, throwing an exception if the result was a Failure. This operation is the opposite of wrapSafe.

  39. def upcast[Out2](implicit ev: <:<[Out, Out2]): Parser[In, Out2]

    Returns this parser, with the output type widened to Out2, which is some supertype of Out.

    Returns this parser, with the output type widened to Out2, which is some supertype of Out. Uses asInstanceOf rather than creating a new parser.

  40. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])
  41. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])
  42. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException]) @native()
  43. def withName(name: String): Parser[In, Out]

    Creates a copy of this parser, but with a different toString

    Creates a copy of this parser, but with a different toString

    name

    The new "name" (i.e. toString) for this parser

    returns

    A copy of this parser whose toString returns the given name

  44. def wrapSafe: Parser[In, Try[Out]]

    Create a copy of this Parser whose handler will catch NonFatal exceptions thrown by the underlying logic.

    Create a copy of this Parser whose handler will catch NonFatal exceptions thrown by the underlying logic. Caught exceptions will be yielded as a Failure output. Normal results will be wrapped in Success.

    returns

    A copy of this parser that will return a Failure instead of throwing exceptions

Deprecated Value Members

  1. def [B](y: B): (Parser[In, Out], B)
    Implicit
    This member is added by an implicit conversion from Parser[In, Out] toArrowAssoc[Parser[In, Out]] performed by method ArrowAssoc in scala.Predef.
    Definition Classes
    ArrowAssoc
    Annotations
    @deprecated
    Deprecated

    (Since version 2.13.0) Use -> instead. If you still wish to display it as one character, consider using a font with programming ligatures such as Fira Code.

Inherited from AnyRef

Inherited from Any

Inherited by implicit conversion ParserFollowedByOps fromParser[In, Out] to ParserFollowedByOps[In, Out]

Inherited by implicit conversion any2stringadd fromParser[In, Out] to any2stringadd[Parser[In, Out]]

Inherited by implicit conversion StringFormat fromParser[In, Out] to StringFormat[Parser[In, Out]]

Inherited by implicit conversion Ensuring fromParser[In, Out] to Ensuring[Parser[In, Out]]

Inherited by implicit conversion ArrowAssoc fromParser[In, Out] to ArrowAssoc[Parser[In, Out]]

Abstract Members

Consumer Methods

Transformation / Combinator Methods

Ungrouped