///|
priv struct ParserState {
text : String
cursor : Array[Int]
line : Array[Int]
column : Array[Int]
diagnostics : Array[Diagnostic]
max_depth : Int
}
///|
fn ParserState::new(text : String, max_depth : Int) -> ParserState {
{ text, cursor: [0], line: [1], column: [1], diagnostics: [], max_depth }
}
///|
fn ParserState::location(self : ParserState) -> SourceLocation {
SourceLocation::new(self.line[0], self.column[0], self.cursor[0])
}
///|
fn ParserState::peek(self : ParserState) -> UInt16? {
if self.cursor[0] >= self.text.length() {
None
} else {
Some(self.text[self.cursor[0]])
}
}
///|
fn ParserState::advance(self : ParserState) -> UInt16? {
match self.peek() {
None => None
Some(ch) => {
self.cursor[0] += 1
if ch == '\n' {
self.line[0] += 1
self.column[0] = 1
} else {
self.column[0] += 1
}
Some(ch)
}
}
}
///|
fn ParserState::error(
self : ParserState,
path : String,
message : String,
) -> Unit {
self.diagnostics.push(Diagnostic::error(path, message, Some(self.location())))
}
///|
fn ParserState::skip_space(self : ParserState) -> Unit {
while self.cursor[0] < self.text.length() {
let ch = self.text[self.cursor[0]]
if ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' {
ignore(self.advance())
} else {
break
}
}
}
///|
fn append_code_unit(builder : StringBuilder, unit : UInt16) -> Bool {
match unit.to_char() {
Some(ch) => {
builder.write_char(ch)
true
}
None => false
}
}