The result of a parser function is a discriminated union that
represents either success or failure. In both cases need the
position field to indicate where in the input stream we are.
This is field is defined in the base interface.
interface Position {
position: number
}
When parsing succeeds we return the the Ok<T> object. It contains
the result returned by the parser. Type parameter T indicates
its type.
interface Ok<T> extends Position {
kind: "ok"
result: T
}
When parsing fails we return the Fail object. It does not have a
result, but information about the input found and input expected.
interface Fail extends Position {
kind: "fail"
found: string
expected: string[]
}
The actual result type is a discriminated union of the Ok<T> and
Fail objects.
export type ParseResult<T> = Ok<T> | Fail
The joinExpected function concatenates the list of expected
inputs from the other failed parse result into the expected
array of the first one.
export function joinExpected(result: Fail, other: Fail) {
if (other.expected.length > 0)
result.expected = result.expected.concat(other.expected)
}
This function formats the array of expected inputs as a string for printing.
export function expectedAsCsv(result: Fail): string {
return result.expected.map(s => `"${s}"`).join(", ")
}
The following function is used to construct an Ok<T> result.
export function succeeded<T>(pos: number, res: T): ParseResult<T> {
return {
kind: "ok",
position: pos,
result: res
}
}
The next one constructs a Fail result.
export function failed<T>(pos: number, fnd: string, exp: string[] = []): ParseResult<T> {
return {
kind: "fail",
position: pos,
found: fnd,
expected: exp
}
}