Store syntax errors

This commit is contained in:
Aleksey Kladov 2018-01-07 10:10:35 +03:00
parent 31a07da88d
commit 50132db4c6
2 changed files with 77 additions and 6 deletions

View file

@ -1,5 +1,5 @@
use {SyntaxKind, TextUnit, TextRange}; use {SyntaxKind, TextUnit, TextRange};
use super::{NodeData, NodeIdx, File}; use super::{NodeData, SyntaxErrorData, NodeIdx, File};
pub trait Sink { pub trait Sink {
fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
@ -11,6 +11,7 @@ pub trait Sink {
pub struct FileBuilder { pub struct FileBuilder {
text: String, text: String,
nodes: Vec<NodeData>, nodes: Vec<NodeData>,
errors: Vec<SyntaxErrorData>,
in_progress: Vec<(NodeIdx, Option<NodeIdx>)>, // (parent, last_child) in_progress: Vec<(NodeIdx, Option<NodeIdx>)>, // (parent, last_child)
pos: TextUnit, pos: TextUnit,
} }
@ -58,6 +59,7 @@ impl FileBuilder {
FileBuilder { FileBuilder {
text, text,
nodes: Vec::new(), nodes: Vec::new(),
errors: Vec::new(),
in_progress: Vec::new(), in_progress: Vec::new(),
pos: TextUnit::new(0), pos: TextUnit::new(0),
} }
@ -75,6 +77,7 @@ impl FileBuilder {
File { File {
text: self.text, text: self.text,
nodes: self.nodes, nodes: self.nodes,
errors: self.errors,
} }
} }

View file

@ -36,6 +36,7 @@ pub struct Token {
pub struct File { pub struct File {
text: String, text: String,
nodes: Vec<NodeData>, nodes: Vec<NodeData>,
errors: Vec<SyntaxErrorData>,
} }
impl File { impl File {
@ -72,6 +73,14 @@ impl<'f> Node<'f> {
Children { next: self.as_node(self.data().first_child) } Children { next: self.as_node(self.data().first_child) }
} }
pub fn SyntaxErrors(&self) -> SyntaxErrors<'f> {
let pos = self.file.errors.iter().position(|e| e.node == self.idx);
let next = pos
.map(|i| ErrorIdx(i as u32))
.map(|idx| SyntaxError { file: self.file, idx });
SyntaxErrors { next }
}
fn data(&self) -> &'f NodeData { fn data(&self) -> &'f NodeData {
&self.file.nodes[self.idx] &self.file.nodes[self.idx]
} }
@ -81,7 +90,41 @@ impl<'f> Node<'f> {
} }
} }
impl<'f> fmt::Debug for Node<'f> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{:?}@{:?}", self.kind(), self.range())
}
}
#[derive(Clone, Copy)]
pub struct SyntaxError<'f> {
file: &'f File,
idx: ErrorIdx,
}
impl<'f> SyntaxError<'f> {
pub fn message(&self) -> &'f str {
self.data().message.as_str()
}
fn data(&self) -> &'f SyntaxErrorData {
&self.file.errors[self.idx]
}
fn next(&self) -> Option<SyntaxError<'f>> {
if self.file.errors.len() == self.idx.0 as usize {
return None;
}
let result = SyntaxError {
file: self.file,
idx: ErrorIdx(self.idx.0 + 1)
};
if result.data().node != self.data().node {
return None;
}
Some(result)
}
}
pub struct Children<'f> { pub struct Children<'f> {
next: Option<Node<'f>>, next: Option<Node<'f>>,
@ -97,7 +140,22 @@ impl<'f> Iterator for Children<'f> {
} }
} }
#[derive(Clone, Copy)] pub struct SyntaxErrors<'f> {
next: Option<SyntaxError<'f>>,
}
impl<'f> Iterator for SyntaxErrors<'f> {
type Item = SyntaxError<'f>;
fn next(&mut self) -> Option<SyntaxError<'f>> {
let next = self.next;
self.next = next.as_ref().and_then(SyntaxError::next);
next
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
struct NodeIdx(u32); struct NodeIdx(u32);
struct NodeData { struct NodeData {
@ -122,8 +180,18 @@ impl ::std::ops::IndexMut<NodeIdx> for Vec<NodeData> {
} }
} }
impl<'f> fmt::Debug for Node<'f> { #[derive(Clone, Copy)]
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { struct ErrorIdx(u32);
write!(fmt, "{:?}@{:?}", self.kind(), self.range())
struct SyntaxErrorData {
node: NodeIdx,
message: String,
}
impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> {
type Output = SyntaxErrorData;
fn index(&self, ErrorIdx(idx): ErrorIdx) -> &SyntaxErrorData {
&self[idx as usize]
} }
} }