package combinator
public struct Combinator<I, O> {
public Combinator(public let parse:
(List<I>) -> Option<(O, List<I>)>) {}
}
extend<I, O> Combinator<I, O> {
public func map<T>(f: (O) -> T): Combinator<I, T> {
Combinator { input =>
if (let Some((output, rest)) <- parse(input)) {
Some((f(output), rest))
} else {
None
}
}
}
public func and<T>(other: Combinator<I, T>): Combinator<I, (O, T)> {
Combinator { input =>
if (let Some((output1, rest1)) <- parse(input)) {
if (let Some((output2, rest2)) <- other.parse(rest1)) {
return Some(((output1, output2), rest2))
}
}
return None
}
}
public func or(other: Combinator<I, O>): Combinator<I, O> {
Combinator { input =>
let result = parse(input)
if (let None <- result) {
other.parse(input)
} else {
result
}
}
}
public operator func |(other: Combinator<I, O>): Combinator<I, O> {
this.or(other)
}
public func least(min: Int64): Combinator<I, List<O>> {
Combinator { input =>
var list = List<O>.empty()
var rest = input
while (let Some((result, tail)) <- parse(rest)) {
list = list.add(result)
rest = tail
}
if (list.lenth() >= min) {
Some((list.reverse(), rest))
} else {
None
}
}
}
public static func next(assert: (I) -> Bool): Combinator<I, I> {
Combinator { input =>
if (let Cons(head, tail) <- input) {
if (assert(head)) {
return Some((head, tail))
}
}
return None
}
}
}
extend<I, O> Combinator<I, O> where I <: Equatable<I> {
public static func next(item: I, output: O): Combinator<I, O> {
Combinator { input =>
if (let Cons(head, tail) <- input) {
if (head == item) {
return Some((output, tail))
}
}
return None
}
}
public static func next(item: I): Combinator<I, I> {
// next(item, item) // 这样写报错,确认是否为 Sema 问题
Combinator { input =>
if (let Cons(head, tail) <- input) {
if (head == item) {
return Some((head, tail))
}
}
return None
}
}
}