// Parser combinators — compose simple parsers into complex ones
///|
pub fn[T] many0(
parser : (ParseInput) -> (ParseInput, T)?,
input : ParseInput,
) -> (ParseInput, Array[T]) {
many0_acc(parser, input, [])
}
///|
fn[T] many0_acc(
parser : (ParseInput) -> (ParseInput, T)?,
input : ParseInput,
acc : Array[T],
) -> (ParseInput, Array[T]) {
match parser(input) {
Some((rest, val)) => {
let new_acc = acc
new_acc.push(val)
many0_acc(parser, rest, new_acc)
}
None => (input, acc)
}
}
///|
pub fn[T] many1(
parser : (ParseInput) -> (ParseInput, T)?,
input : ParseInput,
) -> (ParseInput, Array[T])? {
match parser(input) {
Some((rest, first)) => {
let new_acc : Array[T] = [first]
let (final_rest, result) = many0_acc(parser, rest, new_acc)
Some((final_rest, result))
}
None => None
}
}
///|
pub fn[T] many_n(
parser : (ParseInput) -> (ParseInput, T)?,
n : Int,
input : ParseInput,
) -> (ParseInput, Array[T])? {
let (rest, result) = count(parser, n, input, [])
if result.length() == n {
Some((rest, result))
} else {
None
}
}
///|
fn[T] count(
parser : (ParseInput) -> (ParseInput, T)?,
n : Int,
input : ParseInput,
acc : Array[T],
) -> (ParseInput, Array[T]) {
if n <= 0 {
(input, acc)
} else {
match parser(input) {
Some((rest, val)) => {
acc.push(val)
count(parser, n - 1, rest, acc)
}
None => (input, acc)
}
}
}
///|
pub fn[T, U] many_till(
parser : (ParseInput) -> (ParseInput, T)?,
end : (ParseInput) -> (ParseInput, U)?,
input : ParseInput,
) -> (ParseInput, (Array[T], U))? {
match end(input) {
Some((rest, e)) => Some((rest, ([], e)))
None =>
match parser(input) {
Some((r1, val)) =>
match many_till(parser, end, r1) {
Some((r2, (vals, e))) => {
let new_vals = vals
new_vals.push(val)
Some((r2, (new_vals, e)))
}
None => None
}
None => None
}
}
}
///|
pub fn[T, S] separated_list(
parser : (ParseInput) -> (ParseInput, T)?,
sep : (ParseInput) -> (ParseInput, S)?,
input : ParseInput,
) -> (ParseInput, Array[T]) {
match parser(input) {
Some((r1, first)) => {
let acc : Array[T] = [first]
separated_more(parser, sep, r1, acc)
}
None => (input, [])
}
}
///|
fn[T, S] separated_more(
parser : (ParseInput) -> (ParseInput, T)?,
sep : (ParseInput) -> (ParseInput, S)?,
input : ParseInput,
acc : Array[T],
) -> (ParseInput, Array[T]) {
match sep(input) {
Some((r1, _)) =>
match parser(r1) {
Some((r2, val)) => {
acc.push(val)
separated_more(parser, sep, r2, acc)
}
None => (input, acc)
}
None => (input, acc)
}
}
///|
pub fn[T, S] separated_list1(
parser : (ParseInput) -> (ParseInput, T)?,
sep : (ParseInput) -> (ParseInput, S)?,
input : ParseInput,
) -> (ParseInput, Array[T])? {
match parser(input) {
Some((r1, first)) => {
let acc : Array[T] = [first]
let (rest, result) = separated_more(parser, sep, r1, acc)
Some((rest, result))
}
None => None
}
}
///|
pub fn[T, U] tuple2(
p1 : (ParseInput) -> (ParseInput, T)?,
p2 : (ParseInput) -> (ParseInput, U)?,
input : ParseInput,
) -> (ParseInput, (T, U))? {
match p1(input) {
Some((r1, v1)) =>
match p2(r1) {
Some((r2, v2)) => Some((r2, (v1, v2)))
None => None
}
None => None
}
}
///|
pub fn[T, U, V] tuple3(
p1 : (ParseInput) -> (ParseInput, T)?,
p2 : (ParseInput) -> (ParseInput, U)?,
p3 : (ParseInput) -> (ParseInput, V)?,
input : ParseInput,
) -> (ParseInput, (T, U, V))? {
match p1(input) {
Some((r1, v1)) =>
match p2(r1) {
Some((r2, v2)) =>
match p3(r2) {
Some((r3, v3)) => Some((r3, (v1, v2, v3)))
None => None
}
None => None
}
None => None
}
}
///|
pub fn[T, U] preceded(
prefix : (ParseInput) -> (ParseInput, T)?,
parser : (ParseInput) -> (ParseInput, U)?,
input : ParseInput,
) -> (ParseInput, U)? {
match prefix(input) {
Some((r1, _)) => parser(r1)
None => None
}
}
///|
pub fn[T, U] terminated(
parser : (ParseInput) -> (ParseInput, T)?,
suffix : (ParseInput) -> (ParseInput, U)?,
input : ParseInput,
) -> (ParseInput, T)? {
match parser(input) {
Some((r1, val)) =>
match suffix(r1) {
Some((r2, _)) => Some((r2, val))
None => None
}
None => None
}
}
///|
pub fn[T, U, V] delimited(
left : (ParseInput) -> (ParseInput, T)?,
parser : (ParseInput) -> (ParseInput, U)?,
right : (ParseInput) -> (ParseInput, V)?,
input : ParseInput,
) -> (ParseInput, U)? {
match left(input) {
Some((r1, _)) =>
match parser(r1) {
Some((r2, val)) =>
match right(r2) {
Some((r3, _)) => Some((r3, val))
None => None
}
None => None
}
None => None
}
}
///|
pub fn[T, U] map(
parser : (ParseInput) -> (ParseInput, T)?,
f : (T) -> U,
input : ParseInput,
) -> (ParseInput, U)? {
match parser(input) {
Some((rest, val)) => Some((rest, f(val)))
None => None
}
}
///|
pub fn[T] recognize(
parser : (ParseInput) -> (ParseInput, T)?,
input : ParseInput,
) -> (ParseInput, String)? {
let start = input.pos
match parser(input) {
Some((rest, _)) => {
let end = rest.pos
Some((rest, input.source.substring(start~, end~)))
}
None => None
}
}
///|
pub fn[T] not_parser(
parser : (ParseInput) -> (ParseInput, T)?,
input : ParseInput,
) -> (ParseInput, String)? {
match parser(input) {
Some(_) => None
None => Some((input, ""))
}
}
///|
pub fn[T] success(val : T, input : ParseInput) -> (ParseInput, T)? {
Some((input, val))
}
///|
pub fn[T] fail(input : ParseInput) -> (ParseInput, T)? {
None
}
///|
pub fn[T] cond(
b : Bool,
parser : (ParseInput) -> (ParseInput, T)?,
input : ParseInput,
) -> (ParseInput, T)? {
if b {
parser(input)
} else {
None
}
}