rewrite source reference to use raw offsets
This commit is contained in:
parent
fa736f2dd4
commit
10ea99e95c
@ -30,7 +30,7 @@ peg::parser! {
|
|||||||
stmt:statement() delimiter()+ { stmt }
|
stmt:statement() delimiter()+ { stmt }
|
||||||
|
|
||||||
rule statement() -> Statement =
|
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 =
|
rule statement_kind() -> StatementKind =
|
||||||
__ import:import() { StatementKind::Import(import) } /
|
__ import:import() { StatementKind::Import(import) } /
|
||||||
@ -382,9 +382,9 @@ peg::parser! {
|
|||||||
rule condition_guard() -> Option<Expression> =
|
rule condition_guard() -> Option<Expression> =
|
||||||
("if" _ expr:expression() { expr } )?
|
("if" _ expr:expression() { expr } )?
|
||||||
|
|
||||||
rule expr_or_block() -> Block = block() / ex:expression() {
|
rule expr_or_block() -> Block = block() / pos:position!() ex:expression() {
|
||||||
Statement {
|
Statement {
|
||||||
id: Default::default(), location: Default::default(),
|
id: Default::default(), location: pos.into(),
|
||||||
kind: StatementKind::Expression(ex)
|
kind: StatementKind::Expression(ex)
|
||||||
}.into()
|
}.into()
|
||||||
}
|
}
|
||||||
|
@ -122,24 +122,39 @@ impl<'a> Schala<'a> {
|
|||||||
|
|
||||||
/// Represents lines of source code
|
/// Represents lines of source code
|
||||||
pub(crate) struct SourceReference {
|
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 {
|
impl SourceReference {
|
||||||
fn new() -> SourceReference {
|
fn new() -> SourceReference {
|
||||||
SourceReference { lines: None }
|
SourceReference { last_source: None, newline_offsets: vec![]}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_new_source(&mut self, source: &str) {
|
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 {
|
pub fn get_line(&self, line: usize) -> String {
|
||||||
self.lines
|
//TODO make sure this is utf8-safe
|
||||||
.as_ref()
|
let start_idx = match self.newline_offsets.binary_search(&line) {
|
||||||
.and_then(|x| x.get(line).map(|s| s.to_string()))
|
Ok(index) | Err(index) => index,
|
||||||
.unwrap_or_else(|| "NO LINE FOUND".to_string())
|
};
|
||||||
|
|
||||||
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,12 @@ pub struct Location {
|
|||||||
pub(crate) offset: usize,
|
pub(crate) offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<usize> for Location {
|
||||||
|
fn from(offset: usize) -> Self {
|
||||||
|
Self { offset }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Location {
|
impl fmt::Display for Location {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.offset)
|
write!(f, "{}", self.offset)
|
||||||
|
Loading…
Reference in New Issue
Block a user