76 lines
2.2 KiB
Swift
76 lines
2.2 KiB
Swift
extension PureYAML.Parsing {
|
|
struct Reader {
|
|
private let source: String
|
|
private var position: String.Index
|
|
private var line: Int
|
|
private var column: Int
|
|
private var utf8Index: Int
|
|
|
|
init(_ source: String) {
|
|
self.source = source
|
|
position = source.startIndex
|
|
line = 1
|
|
column = 1
|
|
utf8Index = 0
|
|
}
|
|
|
|
var isAtEnd: Bool {
|
|
position >= source.endIndex
|
|
}
|
|
|
|
var mark: Mark {
|
|
Mark(line: line, column: column, index: utf8Index)
|
|
}
|
|
|
|
func peek(offset: Int = 0) -> Character? {
|
|
var cursor = position
|
|
for _ in 0 ..< offset {
|
|
guard cursor < source.endIndex else {
|
|
return nil
|
|
}
|
|
cursor = source.index(after: cursor)
|
|
}
|
|
guard cursor < source.endIndex else {
|
|
return nil
|
|
}
|
|
return source[cursor]
|
|
}
|
|
|
|
@discardableResult
|
|
mutating func advance() -> Character? {
|
|
guard position < source.endIndex else {
|
|
return nil
|
|
}
|
|
let character = source[position]
|
|
position = source.index(after: position)
|
|
utf8Index += String(character).utf8.count
|
|
if character == "\r\n" {
|
|
line += 1
|
|
column = 1
|
|
} else if character == "\r" {
|
|
if position < source.endIndex, source[position] == "\n" {
|
|
position = source.index(after: position)
|
|
utf8Index += 1
|
|
}
|
|
line += 1
|
|
column = 1
|
|
} else if character == "\n" {
|
|
line += 1
|
|
column = 1
|
|
} else {
|
|
column += 1
|
|
}
|
|
return character
|
|
}
|
|
|
|
mutating func consume(while predicate: (Character) -> Bool) -> String {
|
|
var output = ""
|
|
while let character = peek(), predicate(character) {
|
|
output.append(character)
|
|
advance()
|
|
}
|
|
return output
|
|
}
|
|
}
|
|
}
|