rewrite source reference to use raw offsets

This commit is contained in:
Greg Shuflin 2021-11-12 02:02:31 -08:00
parent fa736f2dd4
commit 10ea99e95c
3 changed files with 32 additions and 11 deletions

View File

@ -30,7 +30,7 @@ peg::parser! {
stmt:statement() delimiter()+ { stmt }
rule statement() -> Statement =
kind:statement_kind() { Statement { id: Default::default(), location: Default::default(), kind } }
pos:position!() kind:statement_kind() { Statement { id: Default::default(), location: pos.into(), kind } }
rule statement_kind() -> StatementKind =
__ import:import() { StatementKind::Import(import) } /
@ -382,9 +382,9 @@ peg::parser! {
rule condition_guard() -> Option<Expression> =
("if" _ expr:expression() { expr } )?
rule expr_or_block() -> Block = block() / ex:expression() {
rule expr_or_block() -> Block = block() / pos:position!() ex:expression() {
Statement {
id: Default::default(), location: Default::default(),
id: Default::default(), location: pos.into(),
kind: StatementKind::Expression(ex)
}.into()
}

View File

@ -122,24 +122,39 @@ impl<'a> Schala<'a> {
/// Represents lines of source code
pub(crate) struct SourceReference {
lines: Option<Vec<String>>,
last_source: Option<String>,
/// Offsets in *bytes* (not chars) representing a newline character
newline_offsets: Vec<usize>,
}
impl SourceReference {
fn new() -> SourceReference {
SourceReference { lines: None }
SourceReference { last_source: None, newline_offsets: vec![]}
}
fn load_new_source(&mut self, source: &str) {
//TODO this is a lot of heap allocations - maybe there's a way to make it more efficient?
self.lines = Some(source.lines().map(|s| s.to_string()).collect());
for (offset, ch) in source.as_bytes().iter().enumerate() {
if *ch == ('\n' as u8) {
self.newline_offsets.push(offset);
}
}
self.last_source = Some(source.to_string());
}
pub fn get_line(&self, line: usize) -> String {
self.lines
.as_ref()
.and_then(|x| x.get(line).map(|s| s.to_string()))
.unwrap_or_else(|| "NO LINE FOUND".to_string())
//TODO make sure this is utf8-safe
let start_idx = match self.newline_offsets.binary_search(&line) {
Ok(index) | Err(index) => index,
};
let last_source = self.last_source.as_ref().unwrap();
let start = self.newline_offsets[start_idx];
let end = self.newline_offsets.get(start_idx + 1).cloned().unwrap_or_else(|| last_source.len());
let slice = &last_source.as_bytes()[start..end];
std::str::from_utf8(slice).unwrap().to_string()
}
}

View File

@ -18,6 +18,12 @@ pub struct Location {
pub(crate) offset: usize,
}
impl From<usize> for Location {
fn from(offset: usize) -> Self {
Self { offset }
}
}
impl fmt::Display for Location {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.offset)