hwtest.parsers

Type members

Types

type Parser[T] = Src => T

The type of a Parser that, when given a Src (essentially an iterator through text), consumes characters to produce a value of type T.

The type of a Parser that, when given a Src (essentially an iterator through text), consumes characters to produce a value of type T.

Every Parser should begin by discarding any leading whitespace.

Value members

Concrete methods

def chain[A, T](pa: => () => A, f: A => T): () => T

Returns a new parser built from the given parser and function.

Returns a new parser built from the given parser and function.

When run, the new parser runs the given parser and transforms its result using the function. The transformed result is then returned as the result of the new parser.

chain also comes in versions that are given up to six parsers instead of one, together with a function that transforms the combined results of the given parsers.

Notice that the given parser (pa) is a delayed (by-name) parameter, which allows chain to be used in recursive definitions. For example, consider

 def pNat: Int =
   choose(
     'S' -> chain(pNat, _+1),
     'Z' -> const(0)
   )

Without the by-name parameter in chain, pNat would always fall into infinite recursion.

def chain[A, B, T](pa: => () => A, pb: => () => B, f: (A, B) => T): () => T

Like chain[A,T] but takes two parsers and a function.

Like chain[A,T] but takes two parsers and a function.

def chain[A, B, C, T](pa: => () => A, pb: => () => B, pc: => () => C, f: (A, B, C) => T): () => T

Like chain[A,T] but takes three parsers and a function.

Like chain[A,T] but takes three parsers and a function.

def chain[A, B, C, D, T](pa: => () => A, pb: => () => B, pc: => () => C, pd: => () => D, f: (A, B, C, D) => T): () => T

Like chain[A,T] but takes four parsers and a function.

Like chain[A,T] but takes four parsers and a function.

def chain[A, B, C, D, E, T](pa: => () => A, pb: => () => B, pc: => () => C, pd: => () => D, pe: => () => E, f: (A, B, C, D, E) => T): () => T

Like chain[A,T] but takes five parsers and a function.

Like chain[A,T] but takes five parsers and a function.

def chain[A, B, C, D, E, F, T](pa: => () => A, pb: => () => B, pc: => () => C, pd: => () => D, pe: => () => E, pf: => () => F, f: (A, B, C, D, E, F) => T): () => T

Like chain[A,T] but takes six parsers and a function.

Like chain[A,T] but takes six parsers and a function.

def choose[A](pairs: (Char, () => A)*): () => A

Returns a Parser that, when run, uses the next non-whitespace character (the "tag") to decide which of several parsers to run next.

Returns a Parser that, when run, uses the next non-whitespace character (the "tag") to decide which of several parsers to run next.

Example: Parse an Either[Int, Int].

 def pEitherIntInt: Parser[Either[Int, Int]] =
   choose(
     'L' -> chain(rInt, Left(_)),
     'R' -> chain(rInt, Right(_))
   )

This would parse L 5 as Left(5) and R -99 as Right(-99). Whitespace can be omitted between the tag and the subsequent value, so R-99 would also be parsed Right(-99). (This is one of the very few places where whitespace can be omitted.)

WARNINGS:

  • Tags are case sensitive.
  • All tags within a single choose should be distinct.
  • Tags should not be whitespace characters.
  • Do NOT use $ as a tag, because it has special meaning in the tester as marking the end of a test.
def const[T](v: T): () => T

Returns a Parser that produces v without consuming any characters from src.

Returns a Parser that produces v without consuming any characters from src.

def conversion[A](f: String => A, desiredType: String): String => A

Wraps a function (like _.toInt) that converts a String to another type, but that might throw an exception, into one that will do the same conversion but will call call parseError instead.

Wraps a function (like _.toInt) that converts a String to another type, but that might throw an exception, into one that will do the same conversion but will call call parseError instead.

def pArray[A : ClassTag](pa: () => A): () => Array[A]

Returns a Parser for a Array of As.

Returns a Parser for a Array of As.

The test data is formatted as

 (<element1> <element2> ... <elementN>)
Value parameters:
pa

the parser to be used for each individual element

def pBigInt: () => BigInt

A parser for BigInts.

A parser for BigInts.

Throws an exception if the next token cannot be converted to a BigInt, or if there is no next token.

def pBoolean: () => Boolean

Returns the next Boolean from the source.

Returns the next Boolean from the source.

In the test data, the Boolean should be formatted as F or T.

def pChar: () => Char
def pColl[A, B](pa: () => A, convert: List[A] => B): () => B

Reads a collection of As.

Reads a collection of As.

Many built-in collections, such as list, arrays, sets, and maps, will be formatted in the test data as

 (element1 element2 ... elementN)

instead of using Polish notation.

An empty collection is written as

 ()

pColl will use pa to read each element, save them all in a list, and then call convert on the list of all the just-read elements to produce the final result. Usually, that result will be some kind of collection, such as a list or array or set, but convert has the flexibility to return other types as well.

Value parameters:
convert

function to convert a list of all the individual As to the desired type (B)

pa

the parser to be used for each individual A

Returns:

a parser for B

def pDouble: () => Double

A parser for Doubles.

A parser for Doubles.

Throws an exception if the next token cannot be converted to a Double, or if there is no next token.

def pInt: () => Int

A parser for Ints.

A parser for Ints.

Throws an exception if the next token cannot be converted to an Int, or if there is no next token.

def pList[A](pa: () => A): () => List[A]

Returns a Parser for a List of As.

Returns a Parser for a List of As.

The test data is formatted as

 (<element1> <element2> ... <elementN>)
Value parameters:
pa

the parser to be used for each individual element

def pLong: () => Long

A parser for Longs.

A parser for Longs.

Throws an exception if the next token cannot be converted to a Long, or if there is no next token.

def pMap[K, V](pk: () => K, pv: () => V): () => Map[K, V]

Returns a Parser for an immutable Map of keys (K) and values (V).

Returns a Parser for an immutable Map of keys (K) and values (V).

The test data is formatted as

 (<key1> <value1> <key2> <value2> ... <keyN> <valueN>)

Note that there are NOT extra parentheses around each individual key-value pair.

Warning: The parser makes no effort to check for equivalent keys. The creator of the test data should avoid including two keys in the same set if they might be considered equivalent.

Value parameters:
pk

the parser to be used for each individual key

pv

the parser to be used for each individual value

def pOption[A](pa: () => A): () => Option[A]

Returns the next Option[A] from the source.

Returns the next Option[A] from the source.

In the test data, the Option[A] should be formatted as 'N' or S <data>. The latter can also be written as S<data> (without the space).

def pSet[A](pa: () => A): () => Set[A]

Returns a Parser for an immutable Set of As.

Returns a Parser for an immutable Set of As.

The test data is formatted as

 (<element1> <element2> ... <elementN>)

Warning: The parser makes no effort to check for equivalent elements. The creator of the test data should avoid including two elements in the same set if they might be considered equivalent.

Value parameters:
pa

the parser to be used for each individual element

def pString: () => String
def pTree[A, T](pa: () => A, e: T, mkNode: (A, T, T) => T): () => T

Generic parser for binary trees with data at internal nodes but no data at external nodes.

Generic parser for binary trees with data at internal nodes but no data at external nodes.

When called, the parser reads trees formatted as

  • E for the empty tree
  • T <data> <left-subtree> <right-subtree> for a node with data
  • L <data> for a node with data and two empty subtrees Note that L <data> is merely shorthand for T <data> E E. It is mainly useful when generating test data by hand. If you are generating test data programmatically, just use E and T.

Whitespace is optional after the tag so T <data> E E could also be written as T<data> E E.

Example:

 enum SizedBST:
   case Empty
   case Node(left: SizedBST, item: Int, right: SizedBST, size: Int)

 def pSizedBST: SizedBST =
   pTree(pTuple(pInt,pInt),
         Empty,
         (tup,left,right) => Node(left, tup._1, right, tup._2))

Then the tree Node(Empty, 10, Node(Empty, 20, Empty, 1), 2) could be formatted in a test as

 T10 2 E T20 1 E E

or

 T 10 2 E L 20 1

Although T is normally some type of tree, it is also possible to use pTree on tree-like input data, even if the final result is not itself a tree.

Value parameters:
e

the empty tree

node

a function to combine data from pA and two subtrees into a new tree

pa

a Parser for the data at each internal node (other than the two subtrees)

Returns:

a Parser for type T

def pTuple[A, B](pa: () => A, pb: () => B): () => (A, B)

Returns a parser for a 2-tuple of values.

Returns a parser for a 2-tuple of values.

The test data is formatted as

 <element1> <element2>

Note that the test data does NOT include parentheses around the elements.

Value parameters:
pa

a parser for values of type A

pb

a parser for values of type B

Returns:

a Parser[(A,B)] that uses the input parsers to read space-separated values of types A and B, and returns those values in a tuple.

def pTuple[A, B, C](pa: () => A, pb: () => B, pc: () => C): () => (A, B, C)

Returns a parser for a 3-tuple of values.

Returns a parser for a 3-tuple of values.

The test data is formatted as

 <element1> <element2> <element3>

Note that the test data does NOT include parentheses around the elements.

Value parameters:
pa

a parser for values of type A

pb

a parser for values of type B

pc

a parser for values of type C

Returns:

a Parser[(A,B,C)] that uses the input parsers to read space-separated values of types A, B, and C, and returns those values in a tuple.

def pTuple[A, B, C, D](pa: () => A, pb: () => B, pc: () => C, pd: () => D): () => (A, B, C, D)

Returns a parser for a 4-tuple of values.

Returns a parser for a 4-tuple of values.

The test data is formatted as

 <element1> <element2> <element3> <element4>

Note that the test data does NOT include parentheses around the elements.

Value parameters:
pa

a parser for values of type A

pb

a parser for values of type B

pc

a parser for values of type C

pd

a parser for values of type D

Returns:

a Parser[(A,B,C,D)] that uses the input parsers to read space-separated values of types A, B, C, and D, and returns those values in a tuple.

def pTuple[A, B, C, D, E](pa: () => A, pb: () => B, pc: () => C, pd: () => D, pe: () => E): () => (A, B, C, D, E)

Returns a parser for a 5-tuple of values.

Returns a parser for a 5-tuple of values.

The test data is formatted as

 <element1> <element2> <element3> <element4> <element5>

Note that the test data does NOT include parentheses around the elements.

Value parameters:
pa

a parser for values of type A

pb

a parser for values of type B

pc

a parser for values of type C

pd

a parser for values of type D

pe

a parser for values of type E

Returns:

a Parser[(A,B,C,D,E)] that uses the input parsers to read space-separated values of types A, B, C, D, and E, and returns those values in a tuple.

def pTuple[A, B, C, D, E, F](pa: () => A, pb: () => B, pc: () => C, pd: () => D, pe: () => E, pf: () => F): () => (A, B, C, D, E, F)

Returns a parser for a 6-tuple of values.

Returns a parser for a 6-tuple of values.

The test data is formatted as

 <element1> <element2> <element3> <element4> <element5> <element6>

Note that the test data does NOT include parentheses around the elements.

Value parameters:
pa

a parser for values of type A

pb

a parser for values of type B

pc

a parser for values of type C

pd

a parser for values of type D

pe

a parser for values of type E

pf

a parser for values of type F

Returns:

a Parser[(A,B,C,D,E,F)] that uses the input parsers to read space-separated values of types A, B, C, D, E, and F, and returns those values in a tuple.

def parseError(msg: String): Nothing

Prints an error message (extended with some hints), and halts the program.

Prints an error message (extended with some hints), and halts the program.

def token(): () => String

Reads the next chunk of simple text from the source, where "simple" means letters, digits, -, +, and ..

Reads the next chunk of simple text from the source, where "simple" means letters, digits, -, +, and ..

Stops at the first non-simple character, which might or might not be whitespace, or at the end of the source. For example, if the source was

 __-123.4) ...

where the __ represents whitespace, token would skip the whitespace, and return the -123.4, leaving the ) still in the source.

Throws a ParseError if the chunk is empty.