///|
/// One-based line/column information for a character offset.
pub(all) struct SourceLocation {
offset : Int
line : Int
column : Int
}
///|
pub fn source_location(input : String, offset : Int) -> SourceLocation {
let mut position = 0
let mut line = 1
let mut column = 1
for char in input {
if position >= offset {
break
}
if char == '\n' {
line = line + 1
column = 1
} else {
column = column + 1
}
position = position + 1
}
{ offset, line, column }
}
///|
pub fn ParseError::location(
self : ParseError,
input : String,
) -> SourceLocation {
let offset = match self {
UnexpectedEnd(position) => position
UnexpectedCharacter(position, _) => position
Expected(position, _) => position
InvalidEscape(position, _) => position
InvalidNumber(position, _) => position
DuplicateKey(position, _) => position
TrailingContent(position) => position
}
source_location(input, offset)
}
///|
pub fn SourceLocation::to_string(self : SourceLocation) -> String {
"line " + self.line.to_string() + ", column " + self.column.to_string()
}
///|
pub fn format_parse_error(input : String, error : ParseError) -> String {
let location = error.location(input)
location.to_string() + ": " + error.message()
}