diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-01-15 12:00:13 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-01-15 12:40:27 +0100 |
| commit | 40561e57fbbc68becac07acd54a34f94f591f277 (patch) | |
| tree | 9e3401f987f1b19ef30162ac00395b7bbba871c6 /src/syntax/node.rs | |
| parent | 15f0434d1fdd03bc84cacaf6a39ac294a0c75789 (diff) | |
Remove most fields from `SyntaxKind` enum
Diffstat (limited to 'src/syntax/node.rs')
| -rw-r--r-- | src/syntax/node.rs | 316 |
1 files changed, 199 insertions, 117 deletions
diff --git a/src/syntax/node.rs b/src/syntax/node.rs index 13556ede..283d55b4 100644 --- a/src/syntax/node.rs +++ b/src/syntax/node.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use super::ast::AstNode; use super::{SourceId, Span, SyntaxKind}; use crate::diag::SourceError; +use crate::util::EcoString; /// A node in the untyped syntax tree. #[derive(Clone, PartialEq, Hash)] @@ -15,84 +16,106 @@ pub struct SyntaxNode(Repr); #[derive(Clone, PartialEq, Hash)] enum Repr { /// A leaf node. - Leaf(NodeData), + Leaf(LeafNode), /// A reference-counted inner node. Inner(Arc<InnerNode>), + /// An error. + Error(ErrorNode), } impl SyntaxNode { /// Create a new leaf node. - pub fn leaf(kind: SyntaxKind, len: usize) -> Self { - Self(Repr::Leaf(NodeData::new(kind, len))) + pub fn leaf(kind: SyntaxKind, text: impl Into<EcoString>) -> Self { + Self(Repr::Leaf(LeafNode::new(kind, text))) } /// Create a new inner node with children. pub fn inner(kind: SyntaxKind, children: Vec<SyntaxNode>) -> Self { - Self(Repr::Inner(Arc::new(InnerNode::with_children(kind, children)))) + Self(Repr::Inner(Arc::new(InnerNode::new(kind, children)))) } - /// The type of the node. - pub fn kind(&self) -> &SyntaxKind { - &self.data().kind + /// Create a new error node. + pub fn error(message: impl Into<EcoString>, pos: ErrorPos, len: usize) -> Self { + Self(Repr::Error(ErrorNode::new(message, pos, len))) } - /// Take the kind out of the node. - pub fn take(self) -> SyntaxKind { - match self.0 { + /// The type of the node. + pub fn kind(&self) -> SyntaxKind { + match &self.0 { Repr::Leaf(leaf) => leaf.kind, - Repr::Inner(inner) => inner.data.kind.clone(), + Repr::Inner(inner) => inner.kind, + Repr::Error(_) => SyntaxKind::Error, } } - /// The length of the node. + /// The byte length of the node in the source text. pub fn len(&self) -> usize { - self.data().len + match &self.0 { + Repr::Leaf(leaf) => leaf.len(), + Repr::Inner(inner) => inner.len, + Repr::Error(error) => error.len, + } } /// The span of the node. pub fn span(&self) -> Span { - self.data().span + match &self.0 { + Repr::Leaf(leaf) => leaf.span, + Repr::Inner(inner) => inner.span, + Repr::Error(error) => error.span, + } } - /// The number of descendants, including the node itself. - pub fn descendants(&self) -> usize { + /// The text of the node if it is a leaf node. + /// + /// Returns an empty string if this is an inner or error node. + pub fn text(&self) -> &EcoString { + static EMPTY: EcoString = EcoString::new(); match &self.0 { - Repr::Inner(inner) => inner.descendants, - Repr::Leaf(_) => 1, + Repr::Leaf(leaf) => &leaf.text, + Repr::Inner(_) | Repr::Error(_) => &EMPTY, + } + } + + /// Extract the text from the node. + /// + /// Returns an empty string if this is an inner or error node. + pub fn into_text(self) -> EcoString { + match self.0 { + Repr::Leaf(leaf) => leaf.text, + Repr::Inner(_) | Repr::Error(_) => EcoString::new(), } } /// The node's children. pub fn children(&self) -> std::slice::Iter<'_, SyntaxNode> { match &self.0 { + Repr::Leaf(_) | Repr::Error(_) => [].iter(), Repr::Inner(inner) => inner.children.iter(), - Repr::Leaf(_) => [].iter(), } } - /// Convert the node to a typed AST node. - pub fn cast<T>(&self) -> Option<T> - where - T: AstNode, - { + /// Try to convert the node to a typed AST node. + pub fn cast<T: AstNode>(&self) -> Option<T> { T::from_untyped(self) } - /// Get the first child that can cast to the AST type `T`. - pub fn cast_first_child<T: AstNode>(&self) -> Option<T> { + /// Cast the first child that can cast to the AST type `T`. + pub fn cast_first_match<T: AstNode>(&self) -> Option<T> { self.children().find_map(Self::cast) } - /// Get the last child that can cast to the AST type `T`. - pub fn cast_last_child<T: AstNode>(&self) -> Option<T> { + /// Cast the last child that can cast to the AST type `T`. + pub fn cast_last_match<T: AstNode>(&self) -> Option<T> { self.children().rev().find_map(Self::cast) } /// Whether the node or its children contain an error. pub fn erroneous(&self) -> bool { match &self.0 { + Repr::Leaf(_) => false, Repr::Inner(node) => node.erroneous, - Repr::Leaf(data) => data.kind.is_error(), + Repr::Error(_) => true, } } @@ -102,35 +125,41 @@ impl SyntaxNode { return vec![]; } - match self.kind() { - SyntaxKind::Error(pos, message) => { - vec![SourceError::new(self.span(), message.clone()).with_pos(*pos)] - } - _ => self - .children() + if let Repr::Error(error) = &self.0 { + vec![SourceError::new(error.span, error.message.clone()).with_pos(error.pos)] + } else { + self.children() .filter(|node| node.erroneous()) .flat_map(|node| node.errors()) - .collect(), + .collect() } } /// Change the type of the node. - pub(super) fn convert(&mut self, kind: SyntaxKind) { + pub(super) fn convert_to(&mut self, kind: SyntaxKind) { + debug_assert!(!kind.is_error()); match &mut self.0 { + Repr::Leaf(leaf) => leaf.kind = kind, Repr::Inner(inner) => { let node = Arc::make_mut(inner); - node.erroneous |= kind.is_error(); - node.data.kind = kind; + node.kind = kind; } - Repr::Leaf(leaf) => leaf.kind = kind, + Repr::Error(_) => {} } } + /// Convert the child to an error. + pub(super) fn convert_to_error(&mut self, message: impl Into<EcoString>) { + let len = self.len(); + *self = SyntaxNode::error(message, ErrorPos::Full, len); + } + /// Set a synthetic span for the node and all its descendants. pub(super) fn synthesize(&mut self, span: Span) { match &mut self.0 { + Repr::Leaf(leaf) => leaf.span = span, Repr::Inner(inner) => Arc::make_mut(inner).synthesize(span), - Repr::Leaf(leaf) => leaf.synthesize(span), + Repr::Error(error) => error.span = span, } } @@ -140,17 +169,25 @@ impl SyntaxNode { id: SourceId, within: Range<u64>, ) -> NumberingResult { + if within.start >= within.end { + return Err(Unnumberable); + } + + let mid = Span::new(id, (within.start + within.end) / 2); match &mut self.0 { - Repr::Inner(inner) => Arc::make_mut(inner).numberize(id, None, within), - Repr::Leaf(leaf) => leaf.numberize(id, within), + Repr::Leaf(leaf) => leaf.span = mid, + Repr::Inner(inner) => Arc::make_mut(inner).numberize(id, None, within)?, + Repr::Error(error) => error.span = mid, } + + Ok(()) } /// If the span points into this node, convert it to a byte range. pub(super) fn range(&self, span: Span, offset: usize) -> Option<Range<usize>> { match &self.0 { Repr::Inner(inner) => inner.range(span, offset), - Repr::Leaf(leaf) => leaf.range(span, offset), + _ => (self.span() == span).then(|| offset..offset + self.len()), } } @@ -159,10 +196,18 @@ impl SyntaxNode { matches!(self.0, Repr::Leaf(_)) } + /// The number of descendants, including the node itself. + pub(super) fn descendants(&self) -> usize { + match &self.0 { + Repr::Leaf(_) | Repr::Error(_) => 1, + Repr::Inner(inner) => inner.descendants, + } + } + /// The node's children, mutably. pub(super) fn children_mut(&mut self) -> &mut [SyntaxNode] { match &mut self.0 { - Repr::Leaf(_) => &mut [], + Repr::Leaf(_) | Repr::Error(_) => &mut [], Repr::Inner(inner) => &mut Arc::make_mut(inner).children, } } @@ -199,19 +244,12 @@ impl SyntaxNode { } } - /// The metadata of the node. - fn data(&self) -> &NodeData { - match &self.0 { - Repr::Inner(inner) => &inner.data, - Repr::Leaf(leaf) => leaf, - } - } - /// The upper bound of assigned numbers in this subtree. fn upper(&self) -> u64 { match &self.0 { Repr::Inner(inner) => inner.upper, Repr::Leaf(leaf) => leaf.span.number() + 1, + Repr::Error(error) => error.span.number() + 1, } } } @@ -221,21 +259,64 @@ impl Debug for SyntaxNode { match &self.0 { Repr::Inner(node) => node.fmt(f), Repr::Leaf(node) => node.fmt(f), + Repr::Error(node) => node.fmt(f), } } } impl Default for SyntaxNode { fn default() -> Self { - Self::leaf(SyntaxKind::None, 0) + Self::error("", ErrorPos::Full, 0) + } +} + +/// A leaf node in the untyped syntax tree. +#[derive(Clone, Hash)] +struct LeafNode { + /// What kind of node this is (each kind would have its own struct in a + /// strongly typed AST). + kind: SyntaxKind, + /// The source text of the node. + text: EcoString, + /// The node's span. + span: Span, +} + +impl LeafNode { + /// Create a new leaf node. + fn new(kind: SyntaxKind, text: impl Into<EcoString>) -> Self { + debug_assert!(!kind.is_error()); + Self { kind, text: text.into(), span: Span::detached() } + } + + /// The byte length of the node in the source text. + fn len(&self) -> usize { + self.text.len() + } +} + +impl Debug for LeafNode { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{:?}: {}", self.kind, self.len()) + } +} + +impl PartialEq for LeafNode { + fn eq(&self, other: &Self) -> bool { + self.kind == other.kind && self.text == other.text } } /// An inner node in the untyped syntax tree. #[derive(Clone, Hash)] struct InnerNode { - /// Node metadata. - data: NodeData, + /// What kind of node this is (each kind would have its own struct in a + /// strongly typed AST). + kind: SyntaxKind, + /// The byte length of the node in the source. + len: usize, + /// The node's span. + span: Span, /// The number of nodes in the whole subtree, including this node. descendants: usize, /// Whether this node or any of its children are erroneous. @@ -248,10 +329,12 @@ struct InnerNode { impl InnerNode { /// Create a new inner node with the given kind and children. - fn with_children(kind: SyntaxKind, children: Vec<SyntaxNode>) -> Self { + fn new(kind: SyntaxKind, children: Vec<SyntaxNode>) -> Self { + debug_assert!(!kind.is_error()); + let mut len = 0; let mut descendants = 1; - let mut erroneous = kind.is_error(); + let mut erroneous = false; for child in &children { len += child.len(); @@ -260,7 +343,9 @@ impl InnerNode { } Self { - data: NodeData::new(kind, len), + kind, + len, + span: Span::detached(), descendants, erroneous, upper: 0, @@ -270,7 +355,7 @@ impl InnerNode { /// Set a synthetic span for the node and all its descendants. fn synthesize(&mut self, span: Span) { - self.data.synthesize(span); + self.span = span; for child in &mut self.children { child.synthesize(span); } @@ -310,7 +395,7 @@ impl InnerNode { let mut start = within.start; if range.is_none() { let end = start + stride; - self.data.numberize(id, start..end)?; + self.span = Span::new(id, (start + end) / 2); self.upper = within.end; start = end; } @@ -329,14 +414,14 @@ impl InnerNode { /// If the span points into this node, convert it to a byte range. fn range(&self, span: Span, mut offset: usize) -> Option<Range<usize>> { // Check whether we found it. - if let Some(range) = self.data.range(span, offset) { - return Some(range); + if span == self.span { + return Some(offset..offset + self.len); } // The parent of a subtree has a smaller span number than all of its // descendants. Therefore, we can bail out early if the target span's // number is smaller than our number. - if span.number() < self.data.span.number() { + if span.number() < self.span.number() { return None; } @@ -371,8 +456,7 @@ impl InnerNode { let superseded = &self.children[range.clone()]; // Compute the new byte length. - self.data.len = self.data.len - + replacement.iter().map(SyntaxNode::len).sum::<usize>() + self.len = self.len + replacement.iter().map(SyntaxNode::len).sum::<usize>() - superseded.iter().map(SyntaxNode::len).sum::<usize>(); // Compute the new number of descendants. @@ -412,7 +496,7 @@ impl InnerNode { .start .checked_sub(1) .and_then(|i| self.children.get(i)) - .map_or(self.data.span.number() + 1, |child| child.upper()); + .map_or(self.span.number() + 1, |child| child.upper()); // The upper bound for renumbering is either // - the span number of the first child after the to-be-renumbered @@ -426,7 +510,7 @@ impl InnerNode { // Try to renumber. let within = start_number..end_number; - let id = self.data.span.source(); + let id = self.span.source(); if self.numberize(id, Some(renumber), within).is_ok() { return Ok(()); } @@ -450,7 +534,7 @@ impl InnerNode { prev_descendants: usize, new_descendants: usize, ) { - self.data.len = self.data.len + new_len - prev_len; + self.len = self.len + new_len - prev_len; self.descendants = self.descendants + new_descendants - prev_descendants; self.erroneous = self.children.iter().any(SyntaxNode::erroneous); } @@ -458,7 +542,7 @@ impl InnerNode { impl Debug for InnerNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - self.data.fmt(f)?; + write!(f, "{:?}: {}", self.kind, self.len)?; if !self.children.is_empty() { f.write_str(" ")?; f.debug_list().entries(&self.children).finish()?; @@ -469,64 +553,62 @@ impl Debug for InnerNode { impl PartialEq for InnerNode { fn eq(&self, other: &Self) -> bool { - self.data == other.data + self.kind == other.kind + && self.len == other.len && self.descendants == other.descendants && self.erroneous == other.erroneous && self.children == other.children } } -/// Data shared between leaf and inner nodes. +/// An error node in the untyped syntax tree. #[derive(Clone, Hash)] -struct NodeData { - /// What kind of node this is (each kind would have its own struct in a - /// strongly typed AST). - kind: SyntaxKind, - /// The byte length of the node in the source. +struct ErrorNode { + /// The error message. + message: EcoString, + /// Where in the node an error should be annotated. + pos: ErrorPos, + /// The byte length of the error in the source. len: usize, /// The node's span. span: Span, } -impl NodeData { - /// Create new node metadata. - fn new(kind: SyntaxKind, len: usize) -> Self { - Self { len, kind, span: Span::detached() } - } - - /// Set a synthetic span for the node. - fn synthesize(&mut self, span: Span) { - self.span = span; - } - - /// Assign a span to the node. - fn numberize(&mut self, id: SourceId, within: Range<u64>) -> NumberingResult { - if within.start < within.end { - self.span = Span::new(id, (within.start + within.end) / 2); - Ok(()) - } else { - Err(Unnumberable) +impl ErrorNode { + /// Create new error node. + fn new(message: impl Into<EcoString>, pos: ErrorPos, len: usize) -> Self { + Self { + message: message.into(), + pos, + len, + span: Span::detached(), } } - - /// If the span points into this node, convert it to a byte range. - fn range(&self, span: Span, offset: usize) -> Option<Range<usize>> { - (self.span == span).then(|| offset..offset + self.len) - } } -impl Debug for NodeData { +impl Debug for ErrorNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{:?}: {}", self.kind, self.len) + write!(f, "({}): {}", self.message, self.len) } } -impl PartialEq for NodeData { +impl PartialEq for ErrorNode { fn eq(&self, other: &Self) -> bool { - self.kind == other.kind && self.len == other.len + self.message == other.message && self.pos == other.pos && self.len == other.len } } +/// Where in a node an error should be annotated, +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum ErrorPos { + /// Over the full width of the node. + Full, + /// At the start of the node. + Start, + /// At the end of the node. + End, +} + /// A syntax node in a context. /// /// Knows its exact offset in the file and provides access to its @@ -542,7 +624,7 @@ pub struct LinkedNode<'a> { } impl<'a> LinkedNode<'a> { - /// Start a new traversal at the source's root node. + /// Start a new traversal at a root node. pub fn new(root: &'a SyntaxNode) -> Self { Self { node: root, parent: None, index: 0, offset: 0 } } @@ -557,17 +639,17 @@ impl<'a> LinkedNode<'a> { self.index } - /// The absolute byte offset of the this node in the source file. + /// The absolute byte offset of this node in the source file. pub fn offset(&self) -> usize { self.offset } - /// The byte range of the this node in the source file. + /// The byte range of this node in the source file. pub fn range(&self) -> Range<usize> { self.offset..self.offset + self.node.len() } - /// Get this node's children. + /// An iterator over this node's children. pub fn children(&self) -> LinkedChildren<'a> { LinkedChildren { parent: Rc::new(self.clone()), @@ -586,7 +668,7 @@ impl<'a> LinkedNode<'a> { } /// Get the kind of this node's parent. - pub fn parent_kind(&self) -> Option<&'a SyntaxKind> { + pub fn parent_kind(&self) -> Option<SyntaxKind> { Some(self.parent()?.node.kind()) } @@ -648,7 +730,7 @@ impl<'a> LinkedNode<'a> { None } - /// Get the leaf at the specified cursor position. + /// Get the leaf at the specified byte offset. pub fn leaf_at(&self, cursor: usize) -> Option<Self> { if self.node.children().len() == 0 && cursor <= self.offset + self.len() { return Some(self.clone()); @@ -784,13 +866,13 @@ mod tests { let node = LinkedNode::new(source.root()).leaf_at(7).unwrap(); assert_eq!(node.offset(), 5); assert_eq!(node.len(), 4); - assert_eq!(node.kind(), &SyntaxKind::Ident("text".into())); + assert_eq!(node.kind(), SyntaxKind::Ident); // Go back to "#set". Skips the space. let prev = node.prev_sibling().unwrap(); assert_eq!(prev.offset(), 0); assert_eq!(prev.len(), 4); - assert_eq!(prev.kind(), &SyntaxKind::Set); + assert_eq!(prev.kind(), SyntaxKind::Set); } #[test] @@ -798,15 +880,15 @@ mod tests { let source = Source::detached("#set fun(12pt, red)"); let leaf = LinkedNode::new(source.root()).leaf_at(6).unwrap(); let prev = leaf.prev_leaf().unwrap(); - assert_eq!(leaf.kind(), &SyntaxKind::Ident("fun".into())); - assert_eq!(prev.kind(), &SyntaxKind::Set); + assert_eq!(leaf.kind(), SyntaxKind::Ident); + assert_eq!(prev.kind(), SyntaxKind::Set); let source = Source::detached("#let x = 10"); let leaf = LinkedNode::new(source.root()).leaf_at(9).unwrap(); let prev = leaf.prev_leaf().unwrap(); let next = leaf.next_leaf().unwrap(); - assert_eq!(prev.kind(), &SyntaxKind::Eq); - assert_eq!(leaf.kind(), &SyntaxKind::Space { newlines: 0 }); - assert_eq!(next.kind(), &SyntaxKind::Int(10)); + assert_eq!(prev.kind(), SyntaxKind::Eq); + assert_eq!(leaf.kind(), SyntaxKind::Space { newlines: 0 }); + assert_eq!(next.kind(), SyntaxKind::Int); } } |
