From 65fac0e57c9852eb2131aa06c0bac43b70bfbfbc Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 2 Nov 2021 12:13:45 +0100 Subject: Refactoring Co-Authored-By: Martin --- src/syntax/mod.rs | 197 +++++++++++++++++++++++++----------------------------- 1 file changed, 91 insertions(+), 106 deletions(-) (limited to 'src/syntax/mod.rs') diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 61e0bb7e..d26c6484 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -1,31 +1,28 @@ //! Syntax types. -mod ast; -mod ident; +pub mod ast; mod pretty; mod span; -use std::fmt; -use std::fmt::{Debug, Display, Formatter}; +use std::fmt::{self, Debug, Display, Formatter}; use std::mem; use std::rc::Rc; -pub use ast::*; -pub use ident::*; pub use pretty::*; pub use span::*; +use self::ast::TypedNode; use crate::diag::Error; use crate::geom::{AngularUnit, LengthUnit}; use crate::source::SourceId; use crate::util::EcoString; -/// Children of a [`GreenNode`]. +/// An inner of leaf node in the untyped green tree. #[derive(Clone, PartialEq)] pub enum Green { - /// A non-terminal node in an Rc. + /// A reference-counted inner node. Node(Rc), - /// A terminal owned token. + /// A terminal, owned token. Token(GreenData), } @@ -77,13 +74,12 @@ impl Debug for Green { f.debug_list().entries(&n.children).finish()?; } } - Ok(()) } } -/// A syntactical node. -#[derive(Clone, PartialEq)] +/// An inner node in the untyped green tree. +#[derive(Debug, Clone, PartialEq)] pub struct GreenNode { /// Node metadata. data: GreenData, @@ -122,15 +118,15 @@ impl From> for Green { } } -/// Data shared between [`GreenNode`]s and leaf nodes. -#[derive(Clone, PartialEq)] +/// Data shared between inner and leaf nodes. +#[derive(Debug, Clone, PartialEq)] pub struct GreenData { /// 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, - /// Whether this node or any of its children are erroneous. + /// Whether this node or any of its children contain an error. erroneous: bool, } @@ -162,8 +158,9 @@ impl From for Green { } } -/// A borrowed wrapper for the [`GreenNode`] type that allows to access spans, -/// error lists and cast to an AST. +/// 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)] pub struct RedRef<'a> { id: SourceId, @@ -182,50 +179,27 @@ impl<'a> RedRef<'a> { } /// The type of the node. - pub fn kind(&self) -> &NodeKind { + pub fn kind(self) -> &'a NodeKind { self.green.kind() } - /// The span of the node. - pub fn span(&self) -> Span { - Span::new(self.id, self.offset, self.offset + self.green.len()) - } - /// The length of the node. - pub fn len(&self) -> usize { + pub fn len(self) -> usize { self.green.len() } - /// Convert the node to a typed AST node. - pub fn cast(self) -> Option - where - T: TypedNode, - { - T::cast_from(self) + /// The span of the node. + pub fn span(self) -> Span { + Span::new(self.id, self.offset, self.offset + self.green.len()) } /// Whether the node or its children contain an error. - pub fn erroneous(&self) -> bool { + pub fn erroneous(self) -> bool { self.green.erroneous() } - /// The node's children. - pub fn children(self) -> impl Iterator> + Clone { - let children = match &self.green { - Green::Node(node) => node.children(), - Green::Token(_) => &[], - }; - - let mut offset = self.offset; - children.iter().map(move |green| { - let child_offset = offset; - offset += green.len(); - RedRef { id: self.id, offset: child_offset, green } - }) - } - /// The error messages for this node and its descendants. - pub fn errors(&self) -> Vec { + pub fn errors(self) -> Vec { if !self.green.erroneous() { return vec![]; } @@ -248,19 +222,42 @@ impl<'a> RedRef<'a> { } } + /// 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) -> impl Iterator> { + let children = match &self.green { + Green::Node(node) => node.children(), + Green::Token(_) => &[], + }; + + let mut offset = self.offset; + children.iter().map(move |green| { + let child_offset = offset; + offset += green.len(); + RedRef { id: self.id, offset: child_offset, green } + }) + } + /// Get the first child of some type. - pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option { + pub(crate) fn typed_child(self, kind: &NodeKind) -> Option> { self.children() .find(|x| mem::discriminant(x.kind()) == mem::discriminant(kind)) } /// Get the first child that can cast to some AST type. - pub(crate) fn cast_first_child(&self) -> Option { + pub(crate) fn cast_first_child(self) -> Option { self.children().find_map(RedRef::cast) } /// Get the last child that can cast to some AST type. - pub(crate) fn cast_last_child(&self) -> Option { + pub(crate) fn cast_last_child(self) -> Option { self.children().filter_map(RedRef::cast).last() } } @@ -277,8 +274,9 @@ impl Debug for RedRef<'_> { } } -/// An owned wrapper for the [`GreenNode`] type that allows to access spans, -/// error lists and cast to an AST. +/// A owned wrapper for a [`GreenNode`] with span information. +/// +/// Owned variant of [`RedRef`]. Can be [cast](Self::cast) to an AST nodes. #[derive(Clone, PartialEq)] pub struct RedNode { id: SourceId, @@ -293,7 +291,7 @@ impl RedNode { } /// Convert to a borrowed representation. - pub fn as_ref<'a>(&'a self) -> RedRef<'a> { + pub fn as_ref(&self) -> RedRef<'_> { RedRef { id: self.id, offset: self.offset, @@ -301,9 +299,9 @@ impl RedNode { } } - /// The span of the node. - pub fn span(&self) -> Span { - self.as_ref().span() + /// The type of the node. + pub fn kind(&self) -> &NodeKind { + self.as_ref().kind() } /// The length of the node. @@ -311,29 +309,29 @@ impl RedNode { 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, { - T::cast_from(self.as_ref()) - } - - /// The type of the node. - pub fn kind(&self) -> &NodeKind { - self.green.kind() + self.as_ref().cast() } /// The children of the node. - pub fn children<'a>(&'a self) -> impl Iterator> + Clone { + pub fn children(&self) -> impl Iterator> { self.as_ref().children() } - /// The error messages for this node and its descendants. - pub fn errors<'a>(&'a self) -> Vec { - self.as_ref().errors() - } - /// Get the first child of some type. pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option { self.as_ref().typed_child(kind).map(RedRef::own) @@ -356,11 +354,10 @@ impl Debug for RedNode { } } -pub trait TypedNode: Sized { - /// Performs the conversion. - fn cast_from(value: RedRef) -> Option; -} - +/// 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 +/// the parser. #[derive(Debug, Clone, PartialEq)] pub enum NodeKind { /// A left square bracket: `[`. @@ -469,7 +466,7 @@ pub enum NodeKind { EmDash, /// A slash and the letter "u" followed by a hexadecimal unicode entity /// enclosed in curly braces: `\u{1F5FA}`. - UnicodeEscape(UnicodeEscapeData), + UnicodeEscape(char), /// Strong text was enabled / disabled: `*`. Strong, /// Emphasized text was enabled / disabled: `_`. @@ -508,12 +505,12 @@ pub enum NodeKind { /// A percentage: `50%`. /// /// _Note_: `50%` is stored as `50.0` here, as in the corresponding - /// [literal](Lit::Percent). + /// [literal](ast::Lit::Percent). Percentage(f64), /// A fraction unit: `3fr`. Fraction(f64), /// A quoted string: `"..."`. - Str(StrData), + Str(EcoString), /// An array expression: `(1, "hi", 12cm)`. Array, /// A dictionary expression: `(thickness: 3pt, pattern: dashed)`. @@ -572,24 +569,7 @@ pub enum NodeKind { Unknown(EcoString), } -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ErrorPosition { - /// At the start of the node. - Start, - /// Over the full width of the node. - Full, - /// At the end of the node. - End, -} - -/// A quoted string token: `"..."`. -#[derive(Debug, Clone, PartialEq)] -pub struct StrData { - /// The string inside the quotes. - pub string: EcoString, -} - -/// A raw block token: `` `...` ``. +/// Payload of a raw block: `` `...` ``. #[derive(Debug, Clone, PartialEq)] pub struct RawData { /// The raw text in the block. @@ -602,7 +582,7 @@ pub struct RawData { pub block: bool, } -/// A math formula token: `$2pi + x$` or `$[f'(x) = x^2]$`. +/// Payload of a math formula: `$2pi + x$` or `$[f'(x) = x^2]$`. #[derive(Debug, Clone, PartialEq)] pub struct MathData { /// The formula between the dollars. @@ -612,17 +592,15 @@ pub struct MathData { pub display: bool, } -/// A unicode escape sequence token: `\u{1F5FA}`. -#[derive(Debug, Clone, PartialEq)] -pub struct UnicodeEscapeData { - /// The resulting unicode character. - pub character: char, -} - -impl Display for NodeKind { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.pad(self.as_str()) - } +/// Where in a node an error should be annotated. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum ErrorPosition { + /// At the start of the node. + Start, + /// Over the full width of the node. + Full, + /// At the end of the node. + End, } impl NodeKind { @@ -658,6 +636,7 @@ impl NodeKind { matches!(self, NodeKind::Error(_, _) | NodeKind::Unknown(_)) } + /// A human-readable name for the kind. pub fn as_str(&self) -> &'static str { match self { Self::LeftBracket => "opening bracket", @@ -764,3 +743,9 @@ impl NodeKind { } } } + +impl Display for NodeKind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.pad(self.as_str()) + } +} -- cgit v1.2.3