Croissant Runtime
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.
 
 
crsn/crsn/crsn-sexp/src/position.rs

72 lines
1.8 KiB

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 SourcePosition {
pub fn with_file(mut self, file: u32) -> Self {
self.file = file;
self
}
}
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.file, 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)
}
}