String Parser Construction Kit
ParserCombinators
provides a set of elementary building blocks for deriving structured information from unstructured string data.
Overview
Parsers are represented by a function of the form (Substring) throws -> (Value, Substring)?
. A substring is taken as input and a parsed result as well as the unparsed remainder of the input are returned. An error may be thrown if some kind of invalid state is encountered during parsing and nil
is returned if the parser isn’t able to parse the desired result from the given input.
The package defines a number of primitive parsers capable of matching user-defined sequences of characters (e.g. character
and substring
) as well as various modifiers which can either change a parser’s behavior (e.g. map
and filter
) or combine multiple parsers into a single, more sophisticated parser (e.g. join
, fallback
, and chain
).
Example
Constructing a parser to match a bracketed comma-separated list of words might look something like this:
extension Parser {
static var listExpression: Parser<Array<String>> {
.character("[").trailingPadding()
.joinRight(to:
.substring(\.isLetter)
.chain(with: .whitespace)
.map(String.init)
.collection(separatedBy: .character(",").padding(), allowingTrailingSeparator: true)
)
.joinLeft(to: .character("]").leadingPadding())
}
}
Applying the parser is straightforward and produces the desired result:
let cities = " [ London, New York , San Francisco ,] "
let parser: Parser<Array<String>> = .listExpression.padding().terminate()
if let (cities, _) = try? parser.parse(cities) {
print(cities) // ["London", "New York", "San Francisco"]
}
More examples can be found here.