Module String

type String.Builder = iterative choice {
  .add => [String] self,
  .build => String,
}

An incremental string builder. Add strings with .add, then finalize with .build.

String.Builder.add("Hello").add(", ").add("world!").build
// = "Hello, world!"
type String.Parser<e> = recursive iterative@attempt choice {
  .char => either {
    .char (Char) self,
    .end Result<e, !>,
  },
  .close => Result<e, !>,
  .match => [String.Pattern, String.Pattern] either {
    .end Result<e, !>,
    .fail self@attempt,
    .match (String, String) self,
  },
  .matchEnd => [String.Pattern, String.Pattern] either {
    .end Result<e, !>,
    .fail self@attempt,
    .match (String, String)!,
  },
  .remainder => Result<e, String>,
}

A streaming string parser, parameterized by an error type e.

The error type comes from the underlying source: either {} (impossible) when parsing a plain string, or the reader's error type when parsing from a Bytes.Reader.

Operations:

  • .close — close the parser, returning any source error.
  • .remainder — consume the parser and return all remaining unparsed input.
  • .char — read the next character. Returns .end if input is exhausted, or .char(c) with the character.
  • .match(prefix, suffix) — find the leftmost split where prefix matches the left part and suffix matches the longest possible right part. Returns .match(prefix_str, suffix_str) on success, .fail if no match (parser position unchanged), or .end if input is empty.
  • .matchEnd(prefix, suffix) — like .match, but the suffix extends to the end of input. Terminates the parser on success.

Use .begin/.loop (from the recursive wrapper) to iterate over multiple matches.

let r = String.Parser("Hello, world!")
r.match(.str "Hello", .str ", ").case {
  .match(hello, comma) r => ...
  .fail r => ...
  .end _ => ...
}
type String.Pattern = recursive either {
  .and List<self>,
  .concat List<self>,
  .empty !,
  .max Nat,
  .min Nat,
  .non Char.Class,
  .one Char.Class,
  .or List<self>,
  .repeat self,
  .repeat1 self,
  .str String,
}

A pattern for matching within strings.

Atomic patterns:

  • .empty! — matches the empty string.
  • .str s — matches a literal string.
  • .one class — matches a single character of the given Char.Class.
  • .non class — matches a single character NOT in the given Char.Class.
  • .min n — matches at least n characters (any).
  • .max n — matches at most n characters (any).

Combinators:

  • .repeat p — matches zero or more repetitions of pattern p.
  • .repeat1 p — matches one or more repetitions of pattern p.
  • .concat ps — matches a sequence of patterns in order.
  • .and ps — matches only if all patterns match the same input.
  • .or ps — matches if any of the patterns match.

Common idiom: .repeat.one.any! matches any number of any characters.

dec String.Concat : [List<String>] String

Concatenates a list of strings into a single string.

String.Concat(*("Hello", ", ", "world!"))  // = "Hello, world!"
dec String.FromBytes : [Bytes] String

Decodes bytes as UTF-8 into a string, replacing invalid sequences with the Unicode replacement character.

dec String.Join : [List<String>, String] String

Joins a list of strings with a separator between each element.

String.Join(*("a", "b", "c"), ", ")  // = "a, b, c"
dec String.Lines : <e>[String.Parser<e>] List.Fallible<e, String>

Splits a parser's remaining input into lines (separated by \n). Returns a fallible list that may end with a source error.

dec String.Parser : [String] String.Parser<either {}>

Creates a Parser from a string. The error type is either {} (impossible).

dec String.Quote : [String] String

Wraps a string in quotes with escape sequences (e.g. \n, \t, \\).