summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
authorMartin Haug <mhaug@live.de>2021-11-01 13:03:18 +0100
committerMartin Haug <mhaug@live.de>2021-11-05 13:44:50 +0100
commit49fb3cd4e2a5d6997ad4046d3514f154d8c866dd (patch)
tree4fb2a245a4cb84a6ef238ac1bc71786a0996913d /src/syntax
parent7d34a548ccd14debe0668e23454e1ced70e485ec (diff)
Code Review: Life is Like a Box of Iterators
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/ast.rs33
-rw-r--r--src/syntax/mod.rs156
2 files changed, 102 insertions, 87 deletions
diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs
index bdd0767d..6ca271a9 100644
--- a/src/syntax/ast.rs
+++ b/src/syntax/ast.rs
@@ -1,8 +1,39 @@
use super::{Ident, NodeKind, RedNode, RedRef, Span, TypedNode};
use crate::geom::{AngularUnit, LengthUnit};
-use crate::node;
use crate::util::EcoString;
+macro_rules! node {
+ ($(#[$attr:meta])* $name:ident) => {
+ node!{$(#[$attr])* $name => $name}
+ };
+ ($(#[$attr:meta])* $variant:ident => $name:ident) => {
+ #[derive(Debug, Clone, PartialEq)]
+ #[repr(transparent)]
+ $(#[$attr])*
+ pub struct $name(RedNode);
+
+ impl TypedNode for $name {
+ fn cast_from(node: RedRef) -> Option<Self> {
+ if node.kind() != &NodeKind::$variant {
+ return None;
+ }
+
+ Some(Self(node.own()))
+ }
+ }
+
+ impl $name {
+ pub fn span(&self) -> Span {
+ self.0.span()
+ }
+
+ pub fn underlying(&self) -> RedRef {
+ self.0.as_ref()
+ }
+ }
+ };
+}
+
node! {
/// The syntactical root capable of representing a full parsed document.
Markup
diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs
index 9fd2b21d..ca41d33f 100644
--- a/src/syntax/mod.rs
+++ b/src/syntax/mod.rs
@@ -15,6 +15,7 @@ pub use ident::*;
pub use pretty::*;
pub use span::*;
+use crate::diag::Error;
use crate::geom::{AngularUnit, LengthUnit};
use crate::source::SourceId;
use crate::util::EcoString;
@@ -94,9 +95,9 @@ impl GreenNode {
}
pub fn with_children(kind: NodeKind, len: usize, children: Vec<Green>) -> Self {
- let mut meta = GreenData::new(kind, len);
- meta.erroneous |= children.iter().any(|c| c.erroneous());
- Self { data: meta, children }
+ let mut data = GreenData::new(kind, len);
+ data.erroneous |= children.iter().any(|c| c.erroneous());
+ Self { data, children }
}
pub fn with_child(kind: NodeKind, len: usize, child: impl Into<Green>) -> Self {
@@ -180,6 +181,10 @@ impl<'a> RedRef<'a> {
Span::new(self.id, self.offset, self.offset + self.green.len())
}
+ pub fn len(&self) -> usize {
+ self.green.len()
+ }
+
pub fn cast<T>(self) -> Option<T>
where
T: TypedNode,
@@ -205,6 +210,29 @@ impl<'a> RedRef<'a> {
})
}
+ pub fn errors(&self) -> Vec<Error> {
+ if !self.green.erroneous() {
+ return vec![];
+ }
+
+ match self.kind() {
+ NodeKind::Error(pos, msg) => {
+ let span = match pos {
+ ErrorPosition::Start => self.span().at_start(),
+ ErrorPosition::Full => self.span(),
+ ErrorPosition::End => self.span().at_end(),
+ };
+
+ vec![Error::new(span, msg.to_string())]
+ }
+ _ => self
+ .children()
+ .filter(|red| red.green.erroneous())
+ .flat_map(|red| red.errors())
+ .collect(),
+ }
+ }
+
pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option<RedRef> {
self.children()
.find(|x| mem::discriminant(x.kind()) == mem::discriminant(kind))
@@ -219,6 +247,18 @@ impl<'a> RedRef<'a> {
}
}
+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(())
+ }
+}
+
#[derive(Clone, PartialEq)]
pub struct RedNode {
id: SourceId,
@@ -231,12 +271,27 @@ impl RedNode {
Self { id, offset: 0, green: root.into() }
}
+ pub fn as_ref<'a>(&'a self) -> RedRef<'a> {
+ RedRef {
+ id: self.id,
+ offset: self.offset,
+ green: &self.green,
+ }
+ }
+
pub fn span(&self) -> Span {
self.as_ref().span()
}
pub fn len(&self) -> usize {
- self.green.len()
+ self.as_ref().len()
+ }
+
+ pub fn cast<T>(self) -> Option<T>
+ where
+ T: TypedNode,
+ {
+ T::cast_from(self.as_ref())
}
pub fn kind(&self) -> &NodeKind {
@@ -247,36 +302,8 @@ impl RedNode {
self.as_ref().children()
}
- pub fn errors(&self) -> Vec<(Span, EcoString)> {
- if !self.green.erroneous() {
- return vec![];
- }
-
- match self.kind() {
- NodeKind::Error(pos, msg) => {
- let span = match pos {
- ErrorPosition::Start => self.span().at_start(),
- ErrorPosition::Full => self.span(),
- ErrorPosition::End => self.span().at_end(),
- };
-
- vec![(span, msg.clone())]
- }
- _ => self
- .as_ref()
- .children()
- .filter(|red| red.green.erroneous())
- .flat_map(|red| red.own().errors())
- .collect(),
- }
- }
-
- pub fn as_ref<'a>(&'a self) -> RedRef<'a> {
- RedRef {
- id: self.id,
- offset: self.offset,
- green: &self.green,
- }
+ pub fn errors<'a>(&'a self) -> Vec<Error> {
+ self.as_ref().errors()
}
pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option<RedNode> {
@@ -294,15 +321,7 @@ impl RedNode {
impl Debug for RedNode {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- write!(f, "{:?}: {:?}", self.kind(), self.span())?;
- let children = self.as_ref().children().collect::<Vec<_>>();
- if !children.is_empty() {
- f.write_str(" ")?;
- f.debug_list()
- .entries(children.into_iter().map(RedRef::own))
- .finish()?;
- }
- Ok(())
+ self.as_ref().fmt(f)
}
}
@@ -419,7 +438,7 @@ pub enum NodeKind {
EmDash,
/// A slash and the letter "u" followed by a hexadecimal unicode entity
/// enclosed in curly braces: `\u{1F5FA}`.
- UnicodeEscape(UnicodeEscapeToken),
+ UnicodeEscape(UnicodeEscapeData),
/// Strong text was enabled / disabled: `*`.
Strong,
/// Emphasized text was enabled / disabled: `_`.
@@ -440,9 +459,9 @@ pub enum NodeKind {
ListBullet,
/// An arbitrary number of backticks followed by inner contents, terminated
/// with the same number of backticks: `` `...` ``.
- Raw(Rc<RawToken>),
+ Raw(Rc<RawData>),
/// Dollar signs surrounding inner contents.
- Math(Rc<MathToken>),
+ Math(Rc<MathData>),
/// An identifier: `center`.
Ident(EcoString),
/// A boolean: `true`, `false`.
@@ -463,7 +482,7 @@ pub enum NodeKind {
/// A fraction unit: `3fr`.
Fraction(f64),
/// A quoted string: `"..."`.
- Str(StrToken),
+ Str(StrData),
/// An array expression: `(1, "hi", 12cm)`.
Array,
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
@@ -534,15 +553,14 @@ pub enum ErrorPosition {
/// A quoted string token: `"..."`.
#[derive(Debug, Clone, PartialEq)]
-#[repr(transparent)]
-pub struct StrToken {
+pub struct StrData {
/// The string inside the quotes.
pub string: EcoString,
}
/// A raw block token: `` `...` ``.
#[derive(Debug, Clone, PartialEq)]
-pub struct RawToken {
+pub struct RawData {
/// The raw text in the block.
pub text: EcoString,
/// The programming language of the raw text.
@@ -555,7 +573,7 @@ pub struct RawToken {
/// A math formula token: `$2pi + x$` or `$[f'(x) = x^2]$`.
#[derive(Debug, Clone, PartialEq)]
-pub struct MathToken {
+pub struct MathData {
/// The formula between the dollars.
pub formula: EcoString,
/// Whether the formula is display-level, that is, it is surrounded by
@@ -565,8 +583,7 @@ pub struct MathToken {
/// A unicode escape sequence token: `\u{1F5FA}`.
#[derive(Debug, Clone, PartialEq)]
-#[repr(transparent)]
-pub struct UnicodeEscapeToken {
+pub struct UnicodeEscapeData {
/// The resulting unicode character.
pub character: char,
}
@@ -712,36 +729,3 @@ impl NodeKind {
}
}
}
-
-#[macro_export]
-macro_rules! node {
- ($(#[$attr:meta])* $name:ident) => {
- node!{$(#[$attr])* $name => $name}
- };
- ($(#[$attr:meta])* $variant:ident => $name:ident) => {
- #[derive(Debug, Clone, PartialEq)]
- #[repr(transparent)]
- $(#[$attr])*
- pub struct $name(RedNode);
-
- impl TypedNode for $name {
- fn cast_from(node: RedRef) -> Option<Self> {
- if node.kind() != &NodeKind::$variant {
- return None;
- }
-
- Some(Self(node.own()))
- }
- }
-
- impl $name {
- pub fn span(&self) -> Span {
- self.0.span()
- }
-
- pub fn underlying(&self) -> RedRef {
- self.0.as_ref()
- }
- }
- };
-}