///|
/// Small character cursor shared by the line and label parsers.
priv struct TextCursor {
chars : Array[Char]
mut index : Int
}
///|
fn TextCursor::new(source : StringView) -> TextCursor {
{ chars: source.to_array(), index: 0 }
}
///|
fn TextCursor::is_end(self : TextCursor) -> Bool {
self.index >= self.chars.length()
}
///|
fn TextCursor::position(self : TextCursor) -> Int {
self.index
}
///|
fn TextCursor::peek(self : TextCursor) -> Char? {
if self.is_end() {
None
} else {
Some(self.chars[self.index])
}
}
///|
fn TextCursor::next(self : TextCursor) -> Char? {
if self.is_end() {
None
} else {
let value = self.chars[self.index]
self.index += 1
Some(value)
}
}
///|
fn TextCursor::skip_horizontal_space(self : TextCursor) -> Unit {
while !self.is_end() {
match self.peek() {
Some(' ' | '\t') => self.index += 1
_ => return
}
}
}
///|
fn TextCursor::take_horizontal_space(self : TextCursor) -> Bool {
let before = self.index
self.skip_horizontal_space()
self.index > before
}
///|
fn TextCursor::consume(self : TextCursor, expected : Char) -> Bool {
match self.peek() {
Some(actual) =>
if actual == expected {
self.index += 1
true
} else {
false
}
None => false
}
}
///|
fn TextCursor::read_label_name(self : TextCursor) -> String {
let out = StringBuilder()
while !self.is_end() {
let char = self.chars[self.index]
if char.is_ascii_alphabetic() || char.is_ascii_digit() || char == '_' {
out.write_char(char)
self.index += 1
} else {
break
}
}
out.to_string()
}
///|
fn TextCursor::read_metric_name(self : TextCursor) -> String {
let out = StringBuilder()
while !self.is_end() {
let char = self.chars[self.index]
if char.is_ascii_alphabetic() ||
char.is_ascii_digit() ||
char == '_' ||
char == ':' {
out.write_char(char)
self.index += 1
} else {
break
}
}
out.to_string()
}
///|
fn TextCursor::read_token(self : TextCursor) -> String {
let out = StringBuilder()
while !self.is_end() {
let char = self.chars[self.index]
if char == ' ' || char == '\t' || char == '#' {
break
}
out.write_char(char)
self.index += 1
}
out.to_string()
}
///|
fn TextCursor::remaining(self : TextCursor) -> String {
let out = StringBuilder()
for index in self.index..