diff --git a/benches/oneshot.rs b/benches/oneshot.rs index 7a5a3dba7..baaf18f08 100644 --- a/benches/oneshot.rs +++ b/benches/oneshot.rs @@ -73,7 +73,7 @@ fn bench_highlight(iai: &mut Iai) { let source = ctx.sources.get(id); iai.run(|| { typst::syntax::highlight_node( - source.red().as_ref(), + source.root(), 0 .. source.len_bytes(), &mut |_, _| {}, ) diff --git a/src/eval/capture.rs b/src/eval/capture.rs index 1192eaa78..252e9b716 100644 --- a/src/eval/capture.rs +++ b/src/eval/capture.rs @@ -1,6 +1,6 @@ use super::{Scope, Scopes, Value}; use crate::syntax::ast::{ClosureParam, Expr, Ident, Imports, TypedNode}; -use crate::syntax::RedRef; +use crate::syntax::SyntaxNode; /// A visitor that captures variable slots. pub struct CapturesVisitor<'a> { @@ -39,7 +39,7 @@ impl<'a> CapturesVisitor<'a> { } /// Visit any node and collect all captured variables. - pub fn visit(&mut self, node: RedRef) { + pub fn visit(&mut self, node: &SyntaxNode) { match node.cast() { // Every identifier is a potential variable that we need to capture. // Identifiers that shouldn't count as captures because they @@ -62,7 +62,7 @@ impl<'a> CapturesVisitor<'a> { Some(Expr::Closure(expr)) => { for param in expr.params() { if let ClosureParam::Named(named) = param { - self.visit(named.expr().as_red()); + self.visit(named.expr().as_untyped()); } } @@ -74,14 +74,14 @@ impl<'a> CapturesVisitor<'a> { } } - self.visit(expr.body().as_red()); + self.visit(expr.body().as_untyped()); } // A let expression contains a binding, but that binding is only // active after the body is evaluated. Some(Expr::Let(expr)) => { if let Some(init) = expr.init() { - self.visit(init.as_red()); + self.visit(init.as_untyped()); } self.bind(expr.binding()); } @@ -89,30 +89,30 @@ impl<'a> CapturesVisitor<'a> { // A show rule contains a binding, but that binding is only active // after the target has been evaluated. Some(Expr::Show(show)) => { - self.visit(show.pattern().as_red()); + self.visit(show.pattern().as_untyped()); if let Some(binding) = show.binding() { self.bind(binding); } - self.visit(show.body().as_red()); + self.visit(show.body().as_untyped()); } // A for loop contains one or two bindings in its pattern. These are // active after the iterable is evaluated but before the body is // evaluated. Some(Expr::For(expr)) => { - self.visit(expr.iter().as_red()); + self.visit(expr.iter().as_untyped()); let pattern = expr.pattern(); if let Some(key) = pattern.key() { self.bind(key); } self.bind(pattern.value()); - self.visit(expr.body().as_red()); + self.visit(expr.body().as_untyped()); } // An import contains items, but these are active only after the // path is evaluated. Some(Expr::Import(expr)) => { - self.visit(expr.path().as_red()); + self.visit(expr.path().as_untyped()); if let Imports::Items(items) = expr.imports() { for item in items { self.bind(item); @@ -134,21 +134,17 @@ impl<'a> CapturesVisitor<'a> { mod tests { use super::*; use crate::parse::parse; - use crate::source::SourceId; - use crate::syntax::RedNode; #[track_caller] fn test(src: &str, result: &[&str]) { - let green = parse(src); - let red = RedNode::from_root(green, SourceId::from_raw(0)); - let mut scopes = Scopes::new(None); scopes.top.define("x", 0); scopes.top.define("y", 0); scopes.top.define("z", 0); let mut visitor = CapturesVisitor::new(&scopes); - visitor.visit(red.as_ref()); + let root = parse(src); + visitor.visit(&root); let captures = visitor.finish(); let mut names: Vec<_> = captures.iter().map(|(k, _)| k).collect(); diff --git a/src/eval/mod.rs b/src/eval/mod.rs index db7595f9c..d39fc3ad3 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -698,7 +698,7 @@ impl Eval for ClosureExpr { // Collect captured variables. let captured = { let mut visitor = CapturesVisitor::new(&vm.scopes); - visitor.visit(self.as_red()); + visitor.visit(self.as_untyped()); visitor.finish() }; @@ -770,7 +770,7 @@ impl Eval for ShowExpr { // Collect captured variables. let captured = { let mut visitor = CapturesVisitor::new(&vm.scopes); - visitor.visit(self.as_red()); + visitor.visit(self.as_untyped()); visitor.finish() }; diff --git a/src/lib.rs b/src/lib.rs index bcbf8478e..f9416463f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,9 @@ //! //! # Steps //! - **Parsing:** The parsing step first transforms a plain string into an -//! [iterator of tokens][tokens]. This token stream is [parsed] into a [green -//! tree]. The green tree itself is untyped, but a typed layer over it is -//! provided in the [AST] module. +//! [iterator of tokens][tokens]. This token stream is [parsed] into a [syntax +//! tree]. The tree itself is untyped, but a typed layer over it is provided +//! in the [AST] module. //! - **Evaluation:** The next step is to [evaluate] the markup. This produces a //! [module], consisting of a scope of values that were exported by the code //! and [content], a hierarchical, styled representation with the contents of @@ -19,7 +19,7 @@ //! //! [tokens]: parse::Tokens //! [parsed]: parse::parse -//! [green tree]: syntax::GreenNode +//! [syntax tree]: syntax::SyntaxNode //! [AST]: syntax::ast //! [evaluate]: eval::evaluate //! [module]: eval::Module diff --git a/src/parse/incremental.rs b/src/parse/incremental.rs index 26f97c521..d81a5a232 100644 --- a/src/parse/incremental.rs +++ b/src/parse/incremental.rs @@ -1,36 +1,39 @@ use std::ops::Range; use std::sync::Arc; -use crate::syntax::{Green, GreenNode, NodeKind}; +use crate::syntax::{InnerNode, NodeKind, SyntaxNode}; use super::{ is_newline, parse, reparse_code_block, reparse_content_block, reparse_markup_elements, }; -/// Refresh the given green node with as little parsing as possible. +/// Refresh the given syntax node with as little parsing as possible. /// /// Takes the new source, the range in the old source that was replaced and the /// length of the replacement. /// /// Returns the range in the new source that was ultimately reparsed. pub fn reparse( - green: &mut Arc, + root: &mut SyntaxNode, src: &str, replaced: Range, replacement_len: usize, ) -> Range { - Reparser { src, replaced, replacement_len } - .reparse_step(Arc::make_mut(green), 0, true) - .unwrap_or_else(|| { - *green = parse(src); - 0 .. src.len() - }) + if let SyntaxNode::Inner(inner) = root { + let reparser = Reparser { src, replaced, replacement_len }; + if let Some(range) = reparser.reparse_step(Arc::make_mut(inner), 0, true) { + return range; + } + } + + *root = parse(src); + 0 .. src.len() } -/// Allows partial refreshs of the [`Green`] node tree. +/// Allows partial refreshs of the syntax tree. /// /// This struct holds a description of a change. Its methods can be used to try -/// and apply the change to a green tree. +/// and apply the change to a syntax tree. struct Reparser<'a> { /// The new source code, with the change applied. src: &'a str, @@ -44,12 +47,12 @@ impl Reparser<'_> { /// Try to reparse inside the given node. fn reparse_step( &self, - green: &mut GreenNode, + node: &mut InnerNode, mut offset: usize, outermost: bool, ) -> Option> { - let is_markup = matches!(green.kind(), NodeKind::Markup(_)); - let original_count = green.children().len(); + let is_markup = matches!(node.kind(), NodeKind::Markup(_)); + let original_count = node.children().len(); let original_offset = offset; let mut search = SearchState::default(); @@ -62,8 +65,8 @@ impl Reparser<'_> { let mut child_outermost = false; // Find the the first child in the range of children to reparse. - for (i, child) in green.children().iter().enumerate() { - let pos = GreenPos { idx: i, offset }; + for (i, child) in node.children().enumerate() { + let pos = NodePos { idx: i, offset }; let child_span = offset .. offset + child.len(); match search { @@ -122,24 +125,24 @@ impl Reparser<'_> { // If we were looking for a non-whitespace element and hit the end of // the file here, we instead use EOF as the end of the span. if let SearchState::RequireNonTrivia(start) = search { - search = SearchState::SpanFound(start, GreenPos { - idx: green.children().len() - 1, - offset: offset - green.children().last().unwrap().len(), + search = SearchState::SpanFound(start, NodePos { + idx: node.children().len() - 1, + offset: offset - node.children().last().unwrap().len(), }) } if let SearchState::Contained(pos) = search { - let child = &mut green.children_mut()[pos.idx]; + let child = &mut node.children_mut()[pos.idx]; let prev_len = child.len(); if let Some(range) = match child { - Green::Node(node) => { + SyntaxNode::Inner(node) => { self.reparse_step(Arc::make_mut(node), pos.offset, child_outermost) } - Green::Token(_) => None, + SyntaxNode::Leaf(_) => None, } { let new_len = child.len(); - green.update_parent(new_len, prev_len); + node.update_parent(new_len, prev_len); return Some(range); } @@ -154,7 +157,7 @@ impl Reparser<'_> { // treat it as a markup element. if let Some(func) = func { if let Some(result) = self.replace( - green, + node, func, pos.idx .. pos.idx + 1, superseded_span, @@ -166,14 +169,14 @@ impl Reparser<'_> { } // Save the current indent if this is a markup node and stop otherwise. - let indent = match green.kind() { + let indent = match node.kind() { NodeKind::Markup(n) => *n, _ => return None, }; let (mut start, end) = search.done()?; if let Some((ahead, ahead_at_start)) = ahead_nontrivia { - let ahead_kind = green.children()[ahead.idx].kind(); + let ahead_kind = node.children().as_slice()[ahead.idx].kind(); if start.offset == self.replaced.start || ahead_kind.only_at_start() @@ -183,14 +186,14 @@ impl Reparser<'_> { at_start = ahead_at_start; } } else { - start = GreenPos { idx: 0, offset: original_offset }; + start = NodePos { idx: 0, offset: original_offset }; } let superseded_span = - start.offset .. end.offset + green.children()[end.idx].len(); + start.offset .. end.offset + node.children().as_slice()[end.idx].len(); self.replace( - green, + node, ReparseMode::MarkupElements(at_start, indent), start.idx .. end.idx + 1, superseded_span, @@ -200,7 +203,7 @@ impl Reparser<'_> { fn replace( &self, - green: &mut GreenNode, + node: &mut InnerNode, mode: ReparseMode, superseded_idx: Range, superseded_span: Range, @@ -237,7 +240,7 @@ impl Reparser<'_> { &self.src[newborn_span.start ..], newborn_span.len(), differential, - &green.children()[superseded_start ..], + &node.children().as_slice()[superseded_start ..], at_start, indent, ), @@ -249,14 +252,14 @@ impl Reparser<'_> { return None; } - green.replace_children(superseded_start .. superseded_start + amount, newborns); + node.replace_children(superseded_start .. superseded_start + amount, newborns); Some(newborn_span) } } -/// The position of a green node. +/// The position of a syntax node. #[derive(Clone, Copy, Debug, PartialEq)] -struct GreenPos { +struct NodePos { /// The index in the parent node. idx: usize, /// The byte offset in the string. @@ -272,15 +275,15 @@ enum SearchState { NoneFound, /// The search has concluded by finding a node that fully contains the /// modifications. - Contained(GreenPos), + Contained(NodePos), /// The search has found the start of the modified nodes. - Inside(GreenPos), + Inside(NodePos), /// The search has found the end of the modified nodes but the change /// touched its boundries so another non-trivia node is needed. - RequireNonTrivia(GreenPos), + RequireNonTrivia(NodePos), /// The search has concluded by finding a start and an end index for nodes /// with a pending reparse. - SpanFound(GreenPos, GreenPos), + SpanFound(NodePos, NodePos), } impl Default for SearchState { @@ -290,7 +293,7 @@ impl Default for SearchState { } impl SearchState { - fn done(self) -> Option<(GreenPos, GreenPos)> { + fn done(self) -> Option<(NodePos, NodePos)> { match self { Self::NoneFound => None, Self::Contained(s) => Some((s, s)), diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 4ef1c96f2..98d6470cd 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -10,24 +10,20 @@ pub use parser::*; pub use tokens::*; use std::collections::HashSet; -use std::sync::Arc; use crate::syntax::ast::{Associativity, BinOp, UnOp}; -use crate::syntax::{ErrorPos, Green, GreenNode, NodeKind}; +use crate::syntax::{ErrorPos, NodeKind, SyntaxNode}; use crate::util::EcoString; /// Parse a source file. -pub fn parse(src: &str) -> Arc { +pub fn parse(src: &str) -> SyntaxNode { let mut p = Parser::new(src, TokenMode::Markup); markup(&mut p, true); - match p.finish().into_iter().next() { - Some(Green::Node(node)) => node, - _ => unreachable!(), - } + p.finish().into_iter().next().unwrap() } /// Parse code directly, only used for syntax highlighting. -pub fn parse_code(src: &str) -> Vec { +pub fn parse_code(src: &str) -> Vec { let mut p = Parser::new(src, TokenMode::Code); code(&mut p); p.finish() @@ -40,7 +36,7 @@ fn reparse_code_block( prefix: &str, src: &str, end_pos: usize, -) -> Option<(Vec, bool, usize)> { +) -> Option<(Vec, bool, usize)> { let mut p = Parser::with_prefix(prefix, src, TokenMode::Code); if !p.at(NodeKind::LeftBrace) { return None; @@ -48,8 +44,8 @@ fn reparse_code_block( code_block(&mut p); - let (mut green, terminated) = p.consume()?; - let first = green.remove(0); + let (mut node, terminated) = p.consume()?; + let first = node.remove(0); if first.len() != end_pos { return None; } @@ -64,7 +60,7 @@ fn reparse_content_block( prefix: &str, src: &str, end_pos: usize, -) -> Option<(Vec, bool, usize)> { +) -> Option<(Vec, bool, usize)> { let mut p = Parser::with_prefix(prefix, src, TokenMode::Code); if !p.at(NodeKind::LeftBracket) { return None; @@ -72,8 +68,8 @@ fn reparse_content_block( content_block(&mut p); - let (mut green, terminated) = p.consume()?; - let first = green.remove(0); + let (mut node, terminated) = p.consume()?; + let first = node.remove(0); if first.len() != end_pos { return None; } @@ -89,13 +85,13 @@ fn reparse_markup_elements( src: &str, end_pos: usize, differential: isize, - reference: &[Green], + reference: &[SyntaxNode], mut at_start: bool, column: usize, -) -> Option<(Vec, bool, usize)> { +) -> Option<(Vec, bool, usize)> { let mut p = Parser::with_prefix(prefix, src, TokenMode::Markup); - let mut node: Option<&Green> = None; + let mut node: Option<&SyntaxNode> = None; let mut iter = reference.iter(); let mut offset = differential; let mut replaced = 0; @@ -683,7 +679,7 @@ fn dict(p: &mut Parser, marker: Marker) { kind if kind.is_paren() => Ok(()), NodeKind::Named | NodeKind::Keyed => { if let Some(NodeKind::Ident(key) | NodeKind::Str(key)) = - x.children().first().map(|child| child.kind()) + x.children().next().map(|child| child.kind()) { if !used.insert(key.clone()) { return Err("pair has duplicate key"); @@ -770,7 +766,7 @@ fn args(p: &mut Parser, direct: bool, brackets: bool) -> ParseResult { marker.filter_children(p, |x| match x.kind() { NodeKind::Named => { if let Some(NodeKind::Ident(ident)) = - x.children().first().map(|child| child.kind()) + x.children().next().map(|child| child.kind()) { if !used.insert(ident.clone()) { return Err("duplicate argument"); diff --git a/src/parse/parser.rs b/src/parse/parser.rs index f3a3ffd1d..3d7cac451 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -3,7 +3,7 @@ use std::mem; use std::ops::Range; use super::{TokenMode, Tokens}; -use crate::syntax::{ErrorPos, Green, GreenData, GreenNode, NodeKind}; +use crate::syntax::{ErrorPos, InnerNode, NodeData, NodeKind, SyntaxNode}; use crate::util::EcoString; /// A convenient token-based parser. @@ -21,7 +21,7 @@ pub struct Parser<'s> { /// The stack of open groups. groups: Vec, /// The children of the currently built node. - children: Vec, + children: Vec, /// Whether the last group was not correctly terminated. unterminated_group: bool, /// Whether a group terminator was found, that did not close a group. @@ -54,14 +54,14 @@ impl<'s> Parser<'s> { } /// End the parsing process and return the parsed children. - pub fn finish(self) -> Vec { + pub fn finish(self) -> Vec { self.children } /// End the parsing process and return the parsed children and whether the /// last token was terminated if all groups were terminated correctly or /// `None` otherwise. - pub fn consume(self) -> Option<(Vec, bool)> { + pub fn consume(self) -> Option<(Vec, bool)> { self.terminated().then(|| (self.children, self.tokens.terminated())) } @@ -94,11 +94,11 @@ impl<'s> Parser<'s> { if self.tokens.mode() == TokenMode::Code { // Trailing trivia should not be wrapped into the new node. let idx = self.children.len(); - self.children.push(Green::default()); + self.children.push(SyntaxNode::default()); self.children.extend(children.drain(until.0 ..)); - self.children[idx] = GreenNode::with_children(kind, children).into(); + self.children[idx] = InnerNode::with_children(kind, children).into(); } else { - self.children.push(GreenNode::with_children(kind, children).into()); + self.children.push(InnerNode::with_children(kind, children).into()); } output @@ -291,7 +291,7 @@ impl<'s> Parser<'s> { if group_mode == TokenMode::Code { let start = self.trivia_start().0; target = self.current_start - - self.children[start ..].iter().map(Green::len).sum::(); + - self.children[start ..].iter().map(SyntaxNode::len).sum::(); self.children.truncate(start); } @@ -314,7 +314,7 @@ impl<'s> Parser<'s> { fn bump(&mut self) { let kind = self.current.take().unwrap(); let len = self.tokens.cursor() - self.current_start; - self.children.push(GreenData::new(kind, len).into()); + self.children.push(NodeData::new(kind, len).into()); self.current_start = self.tokens.cursor(); self.current = self.tokens.next(); } @@ -399,7 +399,7 @@ impl Parser<'_> { pub fn expected_at(&mut self, marker: Marker, what: &str) { let msg = format_eco!("expected {}", what); let error = NodeKind::Error(ErrorPos::Full, msg); - self.children.insert(marker.0, GreenData::new(error, 0).into()); + self.children.insert(marker.0, NodeData::new(error, 0).into()); } /// Eat the current token and add an error that it is not the expected @@ -422,12 +422,12 @@ pub struct Marker(usize); impl Marker { /// Peek at the child directly before the marker. - pub fn before<'a>(self, p: &'a Parser) -> Option<&'a Green> { + pub fn before<'a>(self, p: &'a Parser) -> Option<&'a SyntaxNode> { p.children.get(self.0.checked_sub(1)?) } /// Peek at the child directly after the marker. - pub fn after<'a>(self, p: &'a Parser) -> Option<&'a Green> { + pub fn after<'a>(self, p: &'a Parser) -> Option<&'a SyntaxNode> { p.children.get(self.0) } @@ -455,13 +455,13 @@ impl Marker { let until = p.trivia_start(); let children = p.children.drain(self.0 .. until.0).collect(); p.children - .insert(self.0, GreenNode::with_children(kind, children).into()); + .insert(self.0, InnerNode::with_children(kind, children).into()); } /// Wrap all children that do not fulfill the predicate in error nodes. pub fn filter_children(self, p: &mut Parser, mut f: F) where - F: FnMut(&Green) -> Result<(), &'static str>, + F: FnMut(&SyntaxNode) -> Result<(), &'static str>, { for child in &mut p.children[self.0 ..] { // Don't expose errors. @@ -482,7 +482,7 @@ impl Marker { } let error = NodeKind::Error(ErrorPos::Full, msg); let inner = mem::take(child); - *child = GreenNode::with_child(error, inner).into(); + *child = InnerNode::with_child(error, inner).into(); } } } diff --git a/src/source.rs b/src/source.rs index 77a020cbe..82b545505 100644 --- a/src/source.rs +++ b/src/source.rs @@ -12,7 +12,7 @@ use crate::diag::TypResult; use crate::loading::{FileHash, Loader}; use crate::parse::{is_newline, parse, reparse}; use crate::syntax::ast::Markup; -use crate::syntax::{GreenNode, RedNode, Span}; +use crate::syntax::{Span, SyntaxNode}; use crate::util::{PathExt, StrExt}; #[cfg(feature = "codespan-reporting")] @@ -151,7 +151,7 @@ pub struct SourceFile { path: PathBuf, src: String, lines: Vec, - root: Arc, + root: SyntaxNode, rev: usize, } @@ -178,27 +178,21 @@ impl SourceFile { /// Create a source file with the same synthetic span for all nodes. pub fn synthesized(src: impl Into, span: Span) -> Self { let mut file = Self::detached(src); - Arc::make_mut(&mut file.root).synthesize(Arc::new(span)); + file.root.synthesize(Arc::new(span)); file.id = span.source; file } - /// The root node of the file's untyped green tree. - pub fn root(&self) -> &Arc { + /// The root node of the file's untyped syntax tree. + pub fn root(&self) -> &SyntaxNode { &self.root } - /// The root red node of the file's untyped red tree. - pub fn red(&self) -> RedNode { - RedNode::from_root(self.root.clone(), self.id) - } - /// The root node of the file's typed abstract syntax tree. pub fn ast(&self) -> TypResult { - let red = self.red(); - let errors = red.errors(); + let errors = self.root.errors(); if errors.is_empty() { - Ok(red.cast().unwrap()) + Ok(self.root.cast().unwrap()) } else { Err(Box::new(errors)) } diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs index 0f575f31a..99c6b39f0 100644 --- a/src/syntax/ast.rs +++ b/src/syntax/ast.rs @@ -1,25 +1,25 @@ -//! A typed layer over the red-green tree. +//! A typed layer over the untyped syntax tree. //! //! The AST is rooted in the [`Markup`] node. use std::num::NonZeroUsize; use std::ops::Deref; -use super::{Green, GreenData, NodeKind, RedNode, RedRef, Span, Spanned}; +use super::{NodeData, NodeKind, Span, Spanned, SyntaxNode}; use crate::geom::{AngleUnit, LengthUnit}; use crate::util::EcoString; /// A typed AST node. pub trait TypedNode: Sized { - /// Convert from a red node to a typed node. - fn from_red(value: RedRef) -> Option; + /// Convert a node into its typed variant. + fn from_untyped(node: &SyntaxNode) -> Option; - /// A reference to the underlying red node. - fn as_red(&self) -> RedRef<'_>; + /// A reference to the underlying syntax node. + fn as_untyped(&self) -> &SyntaxNode; /// The source code location. fn span(&self) -> Span { - self.as_red().span() + self.as_untyped().span() } } @@ -34,19 +34,19 @@ macro_rules! node { #[derive(Debug, Clone, PartialEq, Hash)] #[repr(transparent)] $(#[$attr])* - pub struct $name(RedNode); + pub struct $name(SyntaxNode); impl TypedNode for $name { - fn from_red(node: RedRef) -> Option { + fn from_untyped(node: &SyntaxNode) -> Option { if matches!(node.kind(), $variants) { - Some(Self(node.own())) + Some(Self(node.clone())) } else { None } } - fn as_red(&self) -> RedRef<'_> { - self.0.as_ref() + fn as_untyped(&self) -> &SyntaxNode { + &self.0 } } }; @@ -77,7 +77,10 @@ impl Markup { NodeKind::Strong => node.cast().map(MarkupNode::Strong), NodeKind::Emph => node.cast().map(MarkupNode::Emph), NodeKind::Raw(raw) => Some(MarkupNode::Raw(raw.as_ref().clone())), - NodeKind::Math(math) => Some(MarkupNode::Math(Spanned::new(math.as_ref().clone(), node.span()))), + NodeKind::Math(math) => Some(MarkupNode::Math(Spanned::new( + math.as_ref().clone(), + node.span(), + ))), NodeKind::Heading => node.cast().map(MarkupNode::Heading), NodeKind::List => node.cast().map(MarkupNode::List), NodeKind::Enum => node.cast().map(MarkupNode::Enum), @@ -279,7 +282,7 @@ pub enum Expr { } impl TypedNode for Expr { - fn from_red(node: RedRef) -> Option { + fn from_untyped(node: &SyntaxNode) -> Option { match node.kind() { NodeKind::Ident(_) => node.cast().map(Self::Ident), NodeKind::CodeBlock => node.cast().map(Self::Code), @@ -309,33 +312,33 @@ impl TypedNode for Expr { } } - fn as_red(&self) -> RedRef<'_> { + fn as_untyped(&self) -> &SyntaxNode { match self { - Self::Lit(v) => v.as_red(), - Self::Code(v) => v.as_red(), - Self::Content(v) => v.as_red(), - Self::Ident(v) => v.as_red(), - Self::Array(v) => v.as_red(), - Self::Dict(v) => v.as_red(), - Self::Group(v) => v.as_red(), - Self::Unary(v) => v.as_red(), - Self::Binary(v) => v.as_red(), - Self::FieldAccess(v) => v.as_red(), - Self::FuncCall(v) => v.as_red(), - Self::MethodCall(v) => v.as_red(), - Self::Closure(v) => v.as_red(), - Self::Let(v) => v.as_red(), - Self::Set(v) => v.as_red(), - Self::Show(v) => v.as_red(), - Self::Wrap(v) => v.as_red(), - Self::If(v) => v.as_red(), - Self::While(v) => v.as_red(), - Self::For(v) => v.as_red(), - Self::Import(v) => v.as_red(), - Self::Include(v) => v.as_red(), - Self::Break(v) => v.as_red(), - Self::Continue(v) => v.as_red(), - Self::Return(v) => v.as_red(), + Self::Lit(v) => v.as_untyped(), + Self::Code(v) => v.as_untyped(), + Self::Content(v) => v.as_untyped(), + Self::Ident(v) => v.as_untyped(), + Self::Array(v) => v.as_untyped(), + Self::Dict(v) => v.as_untyped(), + Self::Group(v) => v.as_untyped(), + Self::Unary(v) => v.as_untyped(), + Self::Binary(v) => v.as_untyped(), + Self::FieldAccess(v) => v.as_untyped(), + Self::FuncCall(v) => v.as_untyped(), + Self::MethodCall(v) => v.as_untyped(), + Self::Closure(v) => v.as_untyped(), + Self::Let(v) => v.as_untyped(), + Self::Set(v) => v.as_untyped(), + Self::Show(v) => v.as_untyped(), + Self::Wrap(v) => v.as_untyped(), + Self::If(v) => v.as_untyped(), + Self::While(v) => v.as_untyped(), + Self::For(v) => v.as_untyped(), + Self::Import(v) => v.as_untyped(), + Self::Include(v) => v.as_untyped(), + Self::Break(v) => v.as_untyped(), + Self::Continue(v) => v.as_untyped(), + Self::Return(v) => v.as_untyped(), } } } @@ -429,7 +432,7 @@ node! { impl CodeBlock { /// The list of expressions contained in the block. pub fn exprs(&self) -> impl Iterator + '_ { - self.0.children().filter_map(RedRef::cast) + self.0.children().filter_map(SyntaxNode::cast) } } @@ -465,7 +468,7 @@ node! { impl ArrayExpr { /// The array items. pub fn items(&self) -> impl Iterator + '_ { - self.0.children().filter_map(RedRef::cast) + self.0.children().filter_map(SyntaxNode::cast) } } @@ -479,17 +482,17 @@ pub enum ArrayItem { } impl TypedNode for ArrayItem { - fn from_red(node: RedRef) -> Option { + fn from_untyped(node: &SyntaxNode) -> Option { match node.kind() { NodeKind::Spread => node.cast_first_child().map(Self::Spread), _ => node.cast().map(Self::Pos), } } - fn as_red(&self) -> RedRef<'_> { + fn as_untyped(&self) -> &SyntaxNode { match self { - Self::Pos(v) => v.as_red(), - Self::Spread(v) => v.as_red(), + Self::Pos(v) => v.as_untyped(), + Self::Spread(v) => v.as_untyped(), } } } @@ -502,7 +505,7 @@ node! { impl DictExpr { /// The named dictionary items. pub fn items(&self) -> impl Iterator + '_ { - self.0.children().filter_map(RedRef::cast) + self.0.children().filter_map(SyntaxNode::cast) } } @@ -518,7 +521,7 @@ pub enum DictItem { } impl TypedNode for DictItem { - fn from_red(node: RedRef) -> Option { + fn from_untyped(node: &SyntaxNode) -> Option { match node.kind() { NodeKind::Named => node.cast().map(Self::Named), NodeKind::Keyed => node.cast().map(Self::Keyed), @@ -527,11 +530,11 @@ impl TypedNode for DictItem { } } - fn as_red(&self) -> RedRef<'_> { + fn as_untyped(&self) -> &SyntaxNode { match self { - Self::Named(v) => v.as_red(), - Self::Keyed(v) => v.as_red(), - Self::Spread(v) => v.as_red(), + Self::Named(v) => v.as_untyped(), + Self::Keyed(v) => v.as_untyped(), + Self::Spread(v) => v.as_untyped(), } } } @@ -895,7 +898,7 @@ node! { impl CallArgs { /// The positional and named arguments. pub fn items(&self) -> impl Iterator + '_ { - self.0.children().filter_map(RedRef::cast) + self.0.children().filter_map(SyntaxNode::cast) } } @@ -911,7 +914,7 @@ pub enum CallArg { } impl TypedNode for CallArg { - fn from_red(node: RedRef) -> Option { + fn from_untyped(node: &SyntaxNode) -> Option { match node.kind() { NodeKind::Named => node.cast().map(Self::Named), NodeKind::Spread => node.cast_first_child().map(Self::Spread), @@ -919,11 +922,11 @@ impl TypedNode for CallArg { } } - fn as_red(&self) -> RedRef<'_> { + fn as_untyped(&self) -> &SyntaxNode { match self { - Self::Pos(v) => v.as_red(), - Self::Named(v) => v.as_red(), - Self::Spread(v) => v.as_red(), + Self::Pos(v) => v.as_untyped(), + Self::Named(v) => v.as_untyped(), + Self::Spread(v) => v.as_untyped(), } } } @@ -948,7 +951,7 @@ impl ClosureExpr { .find(|x| x.kind() == &NodeKind::ClosureParams) .expect("closure is missing parameter list") .children() - .filter_map(RedRef::cast) + .filter_map(SyntaxNode::cast) } /// The body of the closure. @@ -969,7 +972,7 @@ pub enum ClosureParam { } impl TypedNode for ClosureParam { - fn from_red(node: RedRef) -> Option { + fn from_untyped(node: &SyntaxNode) -> Option { match node.kind() { NodeKind::Ident(_) => node.cast().map(Self::Pos), NodeKind::Named => node.cast().map(Self::Named), @@ -978,11 +981,11 @@ impl TypedNode for ClosureParam { } } - fn as_red(&self) -> RedRef<'_> { + fn as_untyped(&self) -> &SyntaxNode { match self { - Self::Pos(v) => v.as_red(), - Self::Named(v) => v.as_red(), - Self::Sink(v) => v.as_red(), + Self::Pos(v) => v.as_untyped(), + Self::Named(v) => v.as_untyped(), + Self::Sink(v) => v.as_untyped(), } } } @@ -1007,7 +1010,7 @@ impl LetExpr { /// The expression the binding is initialized with. pub fn init(&self) -> Option { if self.0.cast_first_child::().is_some() { - self.0.children().filter_map(RedRef::cast).nth(1) + self.0.children().filter_map(SyntaxNode::cast).nth(1) } else { // This is a let .. with expression. self.0.cast_first_child() @@ -1042,7 +1045,7 @@ impl ShowExpr { pub fn binding(&self) -> Option { let mut children = self.0.children(); children - .find_map(RedRef::cast) + .find_map(SyntaxNode::cast) .filter(|_| children.any(|child| child.kind() == &NodeKind::Colon)) } @@ -1052,7 +1055,7 @@ impl ShowExpr { .children() .rev() .skip_while(|child| child.kind() != &NodeKind::As) - .find_map(RedRef::cast) + .find_map(SyntaxNode::cast) .expect("show rule is missing pattern") } @@ -1094,14 +1097,14 @@ impl IfExpr { pub fn if_body(&self) -> Expr { self.0 .children() - .filter_map(RedRef::cast) + .filter_map(SyntaxNode::cast) .nth(1) .expect("if expression is missing body") } /// The expression to evaluate if the condition is false. pub fn else_body(&self) -> Option { - self.0.children().filter_map(RedRef::cast).nth(2) + self.0.children().filter_map(SyntaxNode::cast).nth(2) } } @@ -1152,7 +1155,7 @@ node! { impl ForPattern { /// The key part of the pattern: index for arrays, name for dictionaries. pub fn key(&self) -> Option { - let mut children = self.0.children().filter_map(RedRef::cast); + let mut children = self.0.children().filter_map(SyntaxNode::cast); let key = children.next(); if children.next().is_some() { key } else { None } } @@ -1176,7 +1179,7 @@ impl ImportExpr { .find_map(|node| match node.kind() { NodeKind::Star => Some(Imports::Wildcard), NodeKind::ImportItems => { - let items = node.children().filter_map(RedRef::cast).collect(); + let items = node.children().filter_map(SyntaxNode::cast).collect(); Some(Imports::Items(items)) } _ => None, @@ -1241,8 +1244,8 @@ node! { impl Ident { /// Take out the contained [`EcoString`]. pub fn take(self) -> EcoString { - match self.0.green { - Green::Token(GreenData { kind: NodeKind::Ident(id), .. }) => id, + match self.0 { + SyntaxNode::Leaf(NodeData { kind: NodeKind::Ident(id), .. }) => id, _ => panic!("identifier is of wrong kind"), } } @@ -1252,8 +1255,8 @@ impl Deref for Ident { type Target = str; fn deref(&self) -> &Self::Target { - match &self.0.green { - Green::Token(GreenData { kind: NodeKind::Ident(id), .. }) => id, + match &self.0 { + SyntaxNode::Leaf(NodeData { kind: NodeKind::Ident(id), .. }) => id, _ => panic!("identifier is of wrong kind"), } } diff --git a/src/syntax/highlight.rs b/src/syntax/highlight.rs index 94abc238b..1b84fdba0 100644 --- a/src/syntax/highlight.rs +++ b/src/syntax/highlight.rs @@ -5,13 +5,12 @@ use std::sync::Arc; use syntect::highlighting::{Color, FontStyle, Highlighter, Style, Theme}; use syntect::parsing::Scope; -use super::{GreenNode, NodeKind, RedNode, RedRef}; +use super::{InnerNode, NodeKind, SyntaxNode}; use crate::parse::TokenMode; -use crate::source::SourceId; /// Provide highlighting categories for the descendants of a node that fall into /// a range. -pub fn highlight_node(node: RedRef, range: Range, f: &mut F) +pub fn highlight_node(node: &SyntaxNode, range: Range, f: &mut F) where F: FnMut(Range, Category), { @@ -36,20 +35,21 @@ where TokenMode::Markup => crate::parse::parse(text), TokenMode::Code => { let children = crate::parse::parse_code(text); - Arc::new(GreenNode::with_children(NodeKind::CodeBlock, children)) + SyntaxNode::Inner(Arc::new(InnerNode::with_children( + NodeKind::CodeBlock, + children, + ))) } }; - let root = RedNode::from_root(root, SourceId::from_raw(0)); let highlighter = Highlighter::new(&theme); - - highlight_themed_impl(text, root.as_ref(), vec![], &highlighter, f); + highlight_themed_impl(text, &root, vec![], &highlighter, f); } /// Recursive implementation for returning syntect styles. fn highlight_themed_impl( text: &str, - node: RedRef, + node: &SyntaxNode, scopes: Vec, highlighter: &Highlighter, f: &mut F, @@ -178,7 +178,11 @@ pub enum Category { impl Category { /// Determine the highlighting category of a node given its parent and its /// index in its siblings. - pub fn determine(child: RedRef, parent: RedRef, i: usize) -> Option { + pub fn determine( + child: &SyntaxNode, + parent: &SyntaxNode, + i: usize, + ) -> Option { match child.kind() { NodeKind::LeftBrace => Some(Category::Bracket), NodeKind::RightBrace => Some(Category::Bracket), @@ -262,7 +266,7 @@ impl Category { if parent .children() .filter(|c| matches!(c.kind(), NodeKind::Ident(_))) - .map(RedRef::span) + .map(SyntaxNode::span) .nth(1) .map_or(false, |span| span == child.span()) => { @@ -359,7 +363,7 @@ mod tests { let mut vec = vec![]; let source = SourceFile::detached(src); let full = 0 .. src.len(); - highlight_node(source.red().as_ref(), full, &mut |range, category| { + highlight_node(source.root(), full, &mut |range, category| { vec.push((range, category)); }); assert_eq!(vec, goal); diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 69bcb0a0d..841c16ff8 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -14,24 +14,23 @@ pub use span::*; use self::ast::{MathNode, RawNode, TypedNode, Unit}; use crate::diag::Error; -use crate::source::SourceId; use crate::util::EcoString; -/// An inner or leaf node in the untyped green tree. +/// An inner or leaf node in the untyped syntax tree. #[derive(Clone, PartialEq, Hash)] -pub enum Green { +pub enum SyntaxNode { /// A reference-counted inner node. - Node(Arc), - /// A terminal, owned token. - Token(GreenData), + Inner(Arc), + /// A leaf token. + Leaf(NodeData), } -impl Green { +impl SyntaxNode { /// Returns the metadata of the node. - fn data(&self) -> &GreenData { + pub fn data(&self) -> &NodeData { match self { - Green::Node(n) => &n.data, - Green::Token(t) => t, + SyntaxNode::Inner(n) => &n.data, + SyntaxNode::Leaf(t) => t, } } @@ -45,106 +44,146 @@ impl Green { self.data().len() } - /// Whether the node or its children contain an error. - pub fn erroneous(&self) -> bool { - match self { - Self::Node(node) => node.erroneous, - Self::Token(data) => data.kind.is_error(), - } + /// The span of the node. + pub fn span(&self) -> Span { + todo!() } /// The node's children. - pub fn children(&self) -> &[Green] { + pub fn children(&self) -> std::slice::Iter<'_, SyntaxNode> { match self { - Green::Node(n) => n.children(), - Green::Token(_) => &[], + SyntaxNode::Inner(n) => n.children(), + SyntaxNode::Leaf(_) => [].iter(), } } - /// Whether the node is a leaf node in the green tree. - pub fn is_leaf(&self) -> bool { - match self { - Green::Node(n) => n.children().is_empty(), - Green::Token(_) => true, + /// Returns all leaf descendants of this node (may include itself). + /// + /// This method is slow and only intended for testing. + pub fn leafs(&self) -> Vec { + if match self { + SyntaxNode::Inner(n) => n.children().len() == 0, + SyntaxNode::Leaf(_) => true, + } { + vec![self.clone()] + } else { + self.children().flat_map(Self::leafs).collect() } } + /// Whether the node or its children contain an error. + pub fn erroneous(&self) -> bool { + match self { + Self::Inner(node) => node.erroneous, + Self::Leaf(data) => data.kind.is_error(), + } + } + + /// The error messages for this node and its descendants. + pub fn errors(&self) -> Vec { + if !self.erroneous() { + return vec![]; + } + + match self.kind() { + NodeKind::Error(..) => todo!(), + _ => self + .children() + .filter(|node| node.erroneous()) + .flat_map(|node| node.errors()) + .collect(), + } + } + + /// Convert the node to a typed AST node. + pub fn cast(&self) -> Option + where + T: TypedNode, + { + T::from_untyped(self) + } + + /// Get the first child that can cast to some AST type. + pub fn cast_first_child(&self) -> Option { + self.children().find_map(Self::cast) + } + + /// Get the last child that can cast to some AST type. + pub fn cast_last_child(&self) -> Option { + self.children().rev().find_map(Self::cast) + } + /// Change the type of the node. pub fn convert(&mut self, kind: NodeKind) { match self { - Self::Node(node) => { + Self::Inner(node) => { let node = Arc::make_mut(node); node.erroneous |= kind.is_error(); node.data.kind = kind; } - Self::Token(data) => data.kind = kind, + Self::Leaf(data) => data.kind = kind, } } /// Set a synthetic span for the node and all its children. pub fn synthesize(&mut self, span: Arc) { match self { - Green::Node(n) => Arc::make_mut(n).synthesize(span), - Green::Token(t) => t.synthesize(span), + SyntaxNode::Inner(n) => Arc::make_mut(n).synthesize(span), + SyntaxNode::Leaf(t) => t.synthesize(span), } } } -impl Default for Green { +impl Default for SyntaxNode { fn default() -> Self { - Self::Token(GreenData::new(NodeKind::None, 0)) + Self::Leaf(NodeData::new(NodeKind::None, 0)) } } -impl Debug for Green { +impl Debug for SyntaxNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Self::Node(node) => node.fmt(f), - Self::Token(token) => token.fmt(f), + Self::Inner(node) => node.fmt(f), + Self::Leaf(token) => token.fmt(f), } } } -/// An inner node in the untyped green tree. +/// An inner node in the untyped syntax tree. #[derive(Clone, PartialEq, Hash)] -pub struct GreenNode { +pub struct InnerNode { /// Node metadata. - data: GreenData, + data: NodeData, /// This node's children, losslessly make up this node. - children: Vec, + children: Vec, /// Whether this node or any of its children are erroneous. erroneous: bool, } -impl GreenNode { +impl InnerNode { /// Creates a new node with the given kind and a single child. - pub fn with_child(kind: NodeKind, child: impl Into) -> Self { + pub fn with_child(kind: NodeKind, child: impl Into) -> Self { Self::with_children(kind, vec![child.into()]) } /// Creates a new node with the given kind and children. - pub fn with_children(kind: NodeKind, children: Vec) -> Self { + pub fn with_children(kind: NodeKind, children: Vec) -> Self { let mut erroneous = kind.is_error(); let len = children .iter() .inspect(|c| erroneous |= c.erroneous()) - .map(Green::len) + .map(SyntaxNode::len) .sum(); Self { - data: GreenData::new(kind, len), + data: NodeData::new(kind, len), children, erroneous, } } - /// The node's children. - pub fn children(&self) -> &[Green] { - &self.children - } - /// The node's metadata. - fn data(&self) -> &GreenData { + pub fn data(&self) -> &NodeData { &self.data } @@ -158,6 +197,11 @@ impl GreenNode { self.data().len() } + /// The node's children. + pub fn children(&self) -> std::slice::Iter<'_, SyntaxNode> { + self.children.iter() + } + /// Set a synthetic span for the node and all its children. pub fn synthesize(&mut self, span: Arc) { self.data.synthesize(span.clone()); @@ -167,7 +211,7 @@ impl GreenNode { } /// The node's children, mutably. - pub(crate) fn children_mut(&mut self) -> &mut [Green] { + pub(crate) fn children_mut(&mut self) -> &mut [SyntaxNode] { &mut self.children } @@ -175,42 +219,44 @@ impl GreenNode { pub(crate) fn replace_children( &mut self, range: Range, - replacement: Vec, + replacement: Vec, ) { let superseded = &self.children[range.clone()]; - let superseded_len: usize = superseded.iter().map(Green::len).sum(); - let replacement_len: usize = replacement.iter().map(Green::len).sum(); + let superseded_len: usize = superseded.iter().map(SyntaxNode::len).sum(); + let replacement_len: usize = replacement.iter().map(SyntaxNode::len).sum(); // If we're erroneous, but not due to the superseded range, then we will // still be erroneous after the replacement. - let still_erroneous = self.erroneous && !superseded.iter().any(Green::erroneous); + let still_erroneous = + self.erroneous && !superseded.iter().any(SyntaxNode::erroneous); self.children.splice(range, replacement); self.data.len = self.data.len + replacement_len - superseded_len; - self.erroneous = still_erroneous || self.children.iter().any(Green::erroneous); + self.erroneous = + still_erroneous || self.children.iter().any(SyntaxNode::erroneous); } /// Update the length of this node given the old and new length of /// replaced children. pub(crate) fn update_parent(&mut self, new_len: usize, old_len: usize) { self.data.len = self.data.len() + new_len - old_len; - self.erroneous = self.children.iter().any(Green::erroneous); + self.erroneous = self.children.iter().any(SyntaxNode::erroneous); } } -impl From for Green { - fn from(node: GreenNode) -> Self { +impl From for SyntaxNode { + fn from(node: InnerNode) -> Self { Arc::new(node).into() } } -impl From> for Green { - fn from(node: Arc) -> Self { - Self::Node(node) +impl From> for SyntaxNode { + fn from(node: Arc) -> Self { + Self::Inner(node) } } -impl Debug for GreenNode { +impl Debug for InnerNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.data.fmt(f)?; if !self.children.is_empty() { @@ -223,20 +269,18 @@ impl Debug for GreenNode { /// Data shared between inner and leaf nodes. #[derive(Clone, PartialEq, Hash)] -pub struct GreenData { +pub struct NodeData { /// What kind of node this is (each kind would have its own struct in a /// strongly typed AST). 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>, } -impl GreenData { +impl NodeData { /// Create new node metadata. pub fn new(kind: NodeKind, len: usize) -> Self { - Self { len, kind, span: None } + Self { len, kind } } /// The type of the node. @@ -250,271 +294,26 @@ impl GreenData { } /// Set a synthetic span for the node. - pub fn synthesize(&mut self, span: Arc) { - self.span = Some(span) + pub fn synthesize(&mut self, _: Arc) { + todo!() } } -impl From for Green { - fn from(token: GreenData) -> Self { - Self::Token(token) +impl From for SyntaxNode { + fn from(token: NodeData) -> Self { + Self::Leaf(token) } } -impl Debug for GreenData { +impl Debug for NodeData { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{:?}: {}", self.kind, self.len) } } -/// A owned wrapper for a green node with span information. -/// -/// Owned variant of [`RedRef`]. Can be [cast](Self::cast) to an AST node. -#[derive(Clone, PartialEq, Hash)] -pub struct RedNode { - id: SourceId, - offset: usize, - green: Green, -} - -impl RedNode { - /// Create a new red node from a root [`GreenNode`]. - pub fn from_root(root: Arc, id: SourceId) -> Self { - Self { id, offset: 0, green: root.into() } - } - - /// Convert to a borrowed representation. - pub fn as_ref(&self) -> RedRef<'_> { - RedRef { - id: self.id, - offset: self.offset, - green: &self.green, - } - } - - /// 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() - } - - /// The length of the node. - pub fn len(&self) -> usize { - self.as_ref().len() - } - - /// The span of the node. - pub fn span(&self) -> Span { - self.as_ref().span() - } - - /// The error messages for this node and its descendants. - pub fn errors(&self) -> Vec { - self.as_ref().errors() - } - - /// Convert the node to a typed AST node. - pub fn cast(self) -> Option - where - T: TypedNode, - { - self.as_ref().cast() - } - - /// The children of the node. - pub fn children(&self) -> Children<'_> { - self.as_ref().children() - } - - /// Get the first child that can cast to some AST type. - pub fn cast_first_child(&self) -> Option { - self.as_ref().cast_first_child() - } - - /// Get the last child that can cast to some AST type. - pub fn cast_last_child(&self) -> Option { - self.as_ref().cast_last_child() - } -} - -impl Debug for RedNode { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - self.as_ref().fmt(f) - } -} - -/// A borrowed wrapper for a [`GreenNode`] with span information. -/// -/// Borrowed variant of [`RedNode`]. Can be [cast](Self::cast) to an AST node. -#[derive(Copy, Clone, PartialEq, Hash)] -pub struct RedRef<'a> { - id: SourceId, - offset: usize, - green: &'a Green, -} - -impl<'a> RedRef<'a> { - /// Convert to an owned representation. - pub fn own(self) -> RedNode { - RedNode { - id: self.id, - offset: self.offset, - green: self.green.clone(), - } - } - - /// 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() - } - - /// The length of the node. - pub fn len(self) -> usize { - self.green.len() - } - - /// The span of the node. - pub fn span(self) -> Span { - 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. - pub fn is_leaf(self) -> bool { - self.green.is_leaf() - } - - /// The error messages for this node and its descendants. - pub fn errors(self) -> Vec { - if !self.green.erroneous() { - return vec![]; - } - - match self.kind() { - NodeKind::Error(pos, msg) => { - 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())] - } - _ => self - .children() - .filter(|red| red.green.erroneous()) - .flat_map(|red| red.errors()) - .collect(), - } - } - - /// Returns all leaf descendants of this node (may include itself). - pub fn leafs(self) -> Vec { - if self.is_leaf() { - vec![self] - } else { - self.children().flat_map(Self::leafs).collect() - } - } - - /// Convert the node to a typed AST node. - pub fn cast(self) -> Option - where - T: TypedNode, - { - T::from_red(self) - } - - /// The node's children. - pub fn children(self) -> Children<'a> { - let children = match &self.green { - Green::Node(node) => node.children(), - Green::Token(_) => &[], - }; - - Children { - id: self.id, - iter: children.iter(), - front: self.offset, - back: self.offset + self.len(), - } - } - - /// Get the first child that can cast to some AST type. - pub fn cast_first_child(self) -> Option { - self.children().find_map(RedRef::cast) - } - - /// Get the last child that can cast to some AST type. - pub fn cast_last_child(self) -> Option { - self.children().rev().find_map(RedRef::cast) - } -} - -impl Debug for RedRef<'_> { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{:?}: {:?}", self.kind(), self.span())?; - let mut children = self.children().peekable(); - if children.peek().is_some() { - f.write_str(" ")?; - f.debug_list().entries(children.map(RedRef::own)).finish()?; - } - Ok(()) - } -} - -/// An iterator over the children of a red node. -pub struct Children<'a> { - id: SourceId, - iter: std::slice::Iter<'a, Green>, - front: usize, - back: usize, -} - -impl<'a> Iterator for Children<'a> { - type Item = RedRef<'a>; - - fn next(&mut self) -> Option { - self.iter.next().map(|green| { - let offset = self.front; - self.front += green.len(); - RedRef { id: self.id, offset, green } - }) - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl DoubleEndedIterator for Children<'_> { - fn next_back(&mut self) -> Option { - self.iter.next_back().map(|green| { - self.back -= green.len(); - RedRef { id: self.id, offset: self.back, green } - }) - } -} - -impl ExactSizeIterator for Children<'_> {} - /// All syntactical building blocks that can be part of a Typst document. /// -/// Can be emitted as a token by the tokenizer or as part of a green node by +/// Can be emitted as a token by the tokenizer or as part of a syntax node by /// the parser. #[derive(Debug, Clone, PartialEq)] pub enum NodeKind { diff --git a/tests/typeset.rs b/tests/typeset.rs index 0d6031259..2eb847ce0 100644 --- a/tests/typeset.rs +++ b/tests/typeset.rs @@ -487,8 +487,7 @@ fn test_reparse(src: &str, i: usize, rng: &mut LinearShift) -> bool { ok &= apply(start .. end, supplement); } - let red = SourceFile::detached(src).red(); - let leafs = red.as_ref().leafs(); + let leafs = typst::parse::parse(src).leafs(); let leaf_start = leafs[pick(0 .. leafs.len())].span().start; let supplement = supplements[pick(0 .. supplements.len())]; ok &= apply(leaf_start .. leaf_start, supplement);