You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
1.7 KiB
66 lines
1.7 KiB
4 years ago
|
use std::{fmt, cmp};
|
||
|
use std::fmt::{Formatter, Debug};
|
||
|
|
||
|
/// Position in the input string
|
||
|
#[derive(PartialEq, Clone, Default)]
|
||
|
pub struct SourcePosition {
|
||
|
/// The line number on which the error occurred.
|
||
|
pub line: u32,
|
||
|
/// The column number on which the error occurred.
|
||
|
pub column: u32,
|
||
|
/// The index in the given string which caused the error.
|
||
|
pub index: u32,
|
||
|
/// File index if there are multiple files
|
||
|
pub file: u32,
|
||
|
}
|
||
|
|
||
|
impl fmt::Display for SourcePosition {
|
||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||
|
write!(f, "{}:{}", self.line, self.column)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Debug for SourcePosition {
|
||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||
|
if f.alternate() {
|
||
|
f.debug_struct("SourcePosition")
|
||
|
.field("line", &self.line)
|
||
|
.field("column", &self.column)
|
||
|
.field("index", &self.index)
|
||
|
.field("file", &self.file)
|
||
|
.finish()
|
||
|
} else {
|
||
|
// shorter version
|
||
|
write!(f, "Pos({}:{})", self.line, self.column)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub(crate) fn get_line_and_column(s: &str, pos: usize) -> SourcePosition {
|
||
|
let mut line: usize = 1;
|
||
|
let mut col: isize = -1;
|
||
|
for c in s.chars().take(pos + 1) {
|
||
|
if c == '\n' {
|
||
|
line += 1;
|
||
|
col = -1;
|
||
|
} else {
|
||
|
col += 1;
|
||
|
}
|
||
|
}
|
||
|
SourcePosition {
|
||
|
line: line as u32,
|
||
|
column: cmp::max(col, 0) as u32,
|
||
|
index: pos as u32,
|
||
|
file: 0
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Build a span
|
||
|
pub(crate) fn spos(s: &str, pos: usize) -> SourcePosition {
|
||
|
if pos >= s.len() {
|
||
|
Default::default()
|
||
|
} else {
|
||
|
get_line_and_column(s, pos)
|
||
|
}
|
||
|
}
|