1
1
mirror of https://github.com/github/semantic.git synced 2024-12-22 14:21:31 +03:00
semantic/prototype/Doubt/Parse.swift

92 lines
3.1 KiB
Swift
Raw Normal View History

2015-09-11 16:59:40 +03:00
public struct State<T> {
2015-09-11 17:03:52 +03:00
public let rest: String
public let value: T
2015-07-18 22:43:49 +03:00
}
2015-09-11 16:59:40 +03:00
public prefix func ^(string: String)(_ input: String) -> State<String>? {
2015-07-18 22:43:49 +03:00
return input.characters.startsWith(string.characters)
? State(rest: input.from(string.characters.count), value: string)
: nil
}
2015-09-11 16:59:40 +03:00
public prefix func ^(strings: [String])(_ input: String) -> State<String>? {
2015-07-18 22:43:49 +03:00
return strings.indexOf { input.characters.startsWith($0.characters) }
.flatMap { index in
let string = strings[index]
return (^string)(input)
}
}
public prefix func ^<S where S: SequenceType, S.Generator.Element == Character>(strings: S) -> String -> State<String>? {
return ^strings.map { String($0) }
}
2015-09-18 22:03:50 +03:00
/// Parse the full string with parser or fail.
public func full<A>(parser: String -> State<A>?)(_ input: String) -> A? {
return parser(input).flatMap { $0.rest.isEmpty ? $0.value : nil }
}
/// A convenience for use while developing parsers.
public func never<T>(_: String) -> State<T>? {
return nil
}
//// Matches a single character that is not matched by `parser`.
public func not<T>(parser: String -> State<T>?)(_ input: String) -> State<String>? {
2015-09-18 22:08:24 +03:00
if input.isEmpty { return nil }
return parser(input).map(const(nil)) ?? State(rest: input.from(1), value: input.to(1))
}
2015-09-11 16:59:40 +03:00
public func parseWhile(predicate: Character -> Bool)(_ input: String) -> State<String>? {
2015-07-18 22:43:49 +03:00
return input.characters.count > 0 && predicate(input.characters[input.startIndex])
? parseWhile(predicate)(input.from(1)).map { State(rest: $0.rest, value: input.to(1) + $0.value) } ?? State(rest: input.from(1), value: input.to(1))
: nil
}
2015-09-11 16:59:40 +03:00
public postfix func * <T>(parser: String -> State<T>?) -> String -> State<[T]>? {
2015-07-18 22:43:49 +03:00
return (Array.cons <^> (parser <*> { (parser*)($0) })) <|> pure([])
}
2015-09-11 16:59:40 +03:00
public postfix func + <T> (parser: String -> State<T>?) -> String -> State<[T]>? {
2015-07-18 22:43:49 +03:00
return (Array.cons <^> (parser <*> parser*))
}
2015-09-11 16:59:40 +03:00
public func interpolate<Separator, Element>(element: String -> State<Element>?, _ separator: String -> State<Separator>?) -> String -> State<[Element]>? {
2015-07-18 22:43:49 +03:00
return Array.cons <^> (element <*> (separator *> element)*) <|> pure([])
}
2015-09-11 16:59:40 +03:00
public func <*> <T, U> (left: String -> State<T>?, right: String -> State<U>?)(_ input: String) -> State<(T, U)>? {
2015-07-18 22:43:49 +03:00
return left(input).flatMap { l in
right(l.rest).map { r in
State(rest: r.rest, value: (l.value, r.value))
}
}
}
2015-09-11 16:59:40 +03:00
public func <* <T, U> (left: String -> State<T>?, right: String -> State<U>?) -> String -> State<T>? {
2015-07-18 22:43:49 +03:00
return left >>- { const($0) <^> right }
}
2015-09-11 16:59:40 +03:00
public func *> <T, U> (left: String -> State<T>?, right: String -> State<U>?) -> String -> State<U>? {
2015-07-18 22:43:49 +03:00
return left >>- const(right)
}
2015-09-11 16:59:40 +03:00
public func <|> <T> (left: String -> State<T>?, right: String -> State<T>?)(_ input: String) -> State<T>? {
2015-07-18 22:43:49 +03:00
return left(input) ?? right(input)
}
2015-09-11 16:59:40 +03:00
public func <^> <T, U> (left: T -> U, right: String -> State<T>?) -> String -> State<U>? {
2015-07-18 22:43:49 +03:00
return right >>- { pure(left($0)) }
}
2015-09-11 16:59:40 +03:00
public func >>- <T, U> (left: String -> State<T>?, right: T -> String -> State<U>?)(_ input: String) -> State<U>? {
2015-07-18 22:43:49 +03:00
return left(input).flatMap { state in right(state.value)(state.rest) }
}
2015-09-11 16:59:40 +03:00
public func pure<A>(value: A)(_ input: String) -> State<A>? {
2015-07-18 22:43:49 +03:00
return State(rest: input, value: value)
}