summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-05-16 19:13:39 +0200
committerLaurenz <laurmaedje@gmail.com>2022-05-16 20:22:48 +0200
commit242b01549a472d4eeca1404b8f63427e23224253 (patch)
tree7d44ef801ce857469912a75233a1e7a1603e405e /src/syntax
parenta741bd6b83d1e374c8218b5439e26522499cc4ae (diff)
Safe `eval` function
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/mod.rs53
1 files changed, 46 insertions, 7 deletions
diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs
index abe541b8..29e2718b 100644
--- a/src/syntax/mod.rs
+++ b/src/syntax/mod.rs
@@ -81,6 +81,14 @@ impl Green {
Self::Token(data) => data.kind = kind,
}
}
+
+ /// Set a synthetic span for the node and all its children.
+ pub fn synthesize(&mut self, span: Arc<Span>) {
+ match self {
+ Green::Node(n) => Arc::make_mut(n).synthesize(span),
+ Green::Token(t) => t.synthesize(span),
+ }
+ }
}
impl Default for Green {
@@ -151,6 +159,14 @@ impl GreenNode {
self.data().len()
}
+ /// Set a synthetic span for the node and all its children.
+ pub fn synthesize(&mut self, span: Arc<Span>) {
+ self.data.synthesize(span.clone());
+ for child in &mut self.children {
+ child.synthesize(span.clone());
+ }
+ }
+
/// The node's children, mutably.
pub(crate) fn children_mut(&mut self) -> &mut [Green] {
&mut self.children
@@ -214,12 +230,14 @@ pub struct GreenData {
kind: NodeKind,
/// The byte length of the node in the source.
len: usize,
+ /// A synthetic span for the node, usually this is `None`.
+ span: Option<Arc<Span>>,
}
impl GreenData {
/// Create new node metadata.
pub fn new(kind: NodeKind, len: usize) -> Self {
- Self { len, kind }
+ Self { len, kind, span: None }
}
/// The type of the node.
@@ -231,6 +249,11 @@ impl GreenData {
pub fn len(&self) -> usize {
self.len
}
+
+ /// Set a synthetic span for the node.
+ pub fn synthesize(&mut self, span: Arc<Span>) {
+ self.span = Some(span)
+ }
}
impl From<GreenData> for Green {
@@ -270,6 +293,11 @@ impl RedNode {
}
}
+ /// The node's metadata.
+ pub fn data(&self) -> &GreenData {
+ self.as_ref().data()
+ }
+
/// The type of the node.
pub fn kind(&self) -> &NodeKind {
self.as_ref().kind()
@@ -340,6 +368,11 @@ impl<'a> RedRef<'a> {
}
}
+ /// The node's metadata.
+ pub fn data(self) -> &'a GreenData {
+ self.green.data()
+ }
+
/// The type of the node.
pub fn kind(self) -> &'a NodeKind {
self.green.kind()
@@ -352,7 +385,10 @@ impl<'a> RedRef<'a> {
/// The span of the node.
pub fn span(self) -> Span {
- Span::new(self.id, self.offset, self.offset + self.green.len())
+ match self.data().span.as_deref() {
+ Some(&span) => span,
+ None => Span::new(self.id, self.offset, self.offset + self.len()),
+ }
}
/// Whether the node is a leaf node.
@@ -368,11 +404,14 @@ impl<'a> RedRef<'a> {
match self.kind() {
NodeKind::Error(pos, msg) => {
- let span = match pos {
- ErrorPos::Start => self.span().at_start(),
- ErrorPos::Full => self.span(),
- ErrorPos::End => self.span().at_end(),
- };
+ let mut span = self.span();
+ if self.data().span.is_none() {
+ span = match pos {
+ ErrorPos::Start => span.at_start(),
+ ErrorPos::Full => span,
+ ErrorPos::End => span.at_end(),
+ };
+ }
vec![Error::new(span, msg.to_string())]
}