summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-11-02 12:13:45 +0100
committerMartin Haug <mhaug@live.de>2021-11-05 13:46:41 +0100
commit65fac0e57c9852eb2131aa06c0bac43b70bfbfbc (patch)
tree8ed11d7cefd4e64f523b975f077e4b10f67a7cb9 /src/syntax
parent42afb27cef5540535420fb6d8d9d2fcda7300a47 (diff)
Refactoring
Co-Authored-By: Martin <mhaug@live.de>
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/ast.rs141
-rw-r--r--src/syntax/ident.rs94
-rw-r--r--src/syntax/mod.rs197
-rw-r--r--src/syntax/pretty.rs2
-rw-r--r--src/syntax/span.rs130
5 files changed, 225 insertions, 339 deletions
diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs
index 6ca271a9..9ad04be5 100644
--- a/src/syntax/ast.rs
+++ b/src/syntax/ast.rs
@@ -1,7 +1,18 @@
-use super::{Ident, NodeKind, RedNode, RedRef, Span, TypedNode};
+//! A typed layer over the red-green tree.
+
+use std::ops::Deref;
+
+use super::{NodeKind, RedNode, RedRef, Span};
use crate::geom::{AngularUnit, LengthUnit};
+use crate::parse::is_ident;
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<Self>;
+}
+
macro_rules! node {
($(#[$attr:meta])* $name:ident) => {
node!{$(#[$attr])* $name => $name}
@@ -13,7 +24,7 @@ macro_rules! node {
pub struct $name(RedNode);
impl TypedNode for $name {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
if node.kind() != &NodeKind::$variant {
return None;
}
@@ -23,10 +34,12 @@ macro_rules! node {
}
impl $name {
+ /// The source code location.
pub fn span(&self) -> Span {
self.0.span()
}
+ /// The underlying red node.
pub fn underlying(&self) -> RedRef {
self.0.as_ref()
}
@@ -40,7 +53,8 @@ node! {
}
impl Markup {
- pub fn nodes<'a>(&'a self) -> impl Iterator<Item = MarkupNode> + 'a {
+ /// The markup nodes.
+ pub fn nodes(&self) -> impl Iterator<Item = MarkupNode> + '_ {
self.0.children().filter_map(RedRef::cast)
}
}
@@ -73,7 +87,7 @@ pub enum MarkupNode {
}
impl TypedNode for MarkupNode {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
match node.kind() {
NodeKind::Space(_) => Some(MarkupNode::Space),
NodeKind::Linebreak => Some(MarkupNode::Linebreak),
@@ -81,17 +95,14 @@ impl TypedNode for MarkupNode {
NodeKind::Strong => Some(MarkupNode::Strong),
NodeKind::Emph => Some(MarkupNode::Emph),
NodeKind::Text(s) => Some(MarkupNode::Text(s.clone())),
- NodeKind::UnicodeEscape(u) => Some(MarkupNode::Text(u.character.into())),
- NodeKind::EnDash => Some(MarkupNode::Text(EcoString::from("\u{2013}"))),
- NodeKind::EmDash => Some(MarkupNode::Text(EcoString::from("\u{2014}"))),
- NodeKind::NonBreakingSpace => {
- Some(MarkupNode::Text(EcoString::from("\u{00A0}")))
- }
+ NodeKind::UnicodeEscape(c) => Some(MarkupNode::Text((*c).into())),
+ NodeKind::EnDash => Some(MarkupNode::Text("\u{2013}".into())),
+ NodeKind::EmDash => Some(MarkupNode::Text("\u{2014}".into())),
+ NodeKind::NonBreakingSpace => Some(MarkupNode::Text("\u{00A0}".into())),
NodeKind::Raw(_) => node.cast().map(MarkupNode::Raw),
NodeKind::Heading => node.cast().map(MarkupNode::Heading),
NodeKind::List => node.cast().map(MarkupNode::List),
NodeKind::Enum => node.cast().map(MarkupNode::Enum),
- NodeKind::Error(_, _) => None,
_ => node.cast().map(MarkupNode::Expr),
}
}
@@ -111,16 +122,16 @@ pub struct RawNode {
}
impl TypedNode for RawNode {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
match node.kind() {
NodeKind::Raw(raw) => {
- let span = node.span();
- let start = span.start + raw.backticks as usize;
+ let full = node.span();
+ let start = full.start + raw.backticks as usize;
Some(Self {
block: raw.block,
- lang: raw.lang.as_ref().and_then(|x| {
- let span = Span::new(span.source, start, start + x.len());
- Ident::new(x, span)
+ lang: raw.lang.as_ref().and_then(|lang| {
+ let span = Span::new(full.source, start, start + lang.len());
+ Ident::new(lang, span)
}),
text: raw.text.clone(),
})
@@ -272,7 +283,7 @@ impl Expr {
}
impl TypedNode for Expr {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
match node.kind() {
NodeKind::Ident(_) => node.cast().map(Self::Ident),
NodeKind::Array => node.cast().map(Self::Array),
@@ -325,7 +336,7 @@ pub enum Lit {
}
impl TypedNode for Lit {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
match node.kind() {
NodeKind::None => Some(Self::None(node.span())),
NodeKind::Auto => Some(Self::Auto(node.span())),
@@ -336,13 +347,14 @@ impl TypedNode for Lit {
NodeKind::Angle(f, unit) => Some(Self::Angle(node.span(), *f, *unit)),
NodeKind::Percentage(f) => Some(Self::Percent(node.span(), *f)),
NodeKind::Fraction(f) => Some(Self::Fractional(node.span(), *f)),
- NodeKind::Str(s) => Some(Self::Str(node.span(), s.string.clone())),
+ NodeKind::Str(s) => Some(Self::Str(node.span(), s.clone())),
_ => None,
}
}
}
impl Lit {
+ /// The source code location.
pub fn span(&self) -> Span {
match self {
Self::None(span) => *span,
@@ -366,7 +378,7 @@ node! {
impl ArrayExpr {
/// The array items.
- pub fn items<'a>(&'a self) -> impl Iterator<Item = Expr> + 'a {
+ pub fn items(&self) -> impl Iterator<Item = Expr> + '_ {
self.0.children().filter_map(RedRef::cast)
}
}
@@ -378,7 +390,7 @@ node! {
impl DictExpr {
/// The named dictionary items.
- pub fn items<'a>(&'a self) -> impl Iterator<Item = Named> + 'a {
+ pub fn items(&self) -> impl Iterator<Item = Named> + '_ {
self.0.children().filter_map(RedRef::cast)
}
}
@@ -439,7 +451,7 @@ node! {
impl BlockExpr {
/// The list of expressions contained in the block.
- pub fn exprs<'a>(&'a self) -> impl Iterator<Item = Expr> + 'a {
+ pub fn exprs(&self) -> impl Iterator<Item = Expr> + '_ {
self.0.children().filter_map(RedRef::cast)
}
}
@@ -477,7 +489,7 @@ pub enum UnOp {
}
impl TypedNode for UnOp {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
Self::from_token(node.kind())
}
}
@@ -581,7 +593,7 @@ pub enum BinOp {
}
impl TypedNode for BinOp {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
Self::from_token(node.kind())
}
}
@@ -709,7 +721,7 @@ node! {
impl CallArgs {
/// The positional and named arguments.
- pub fn items<'a>(&'a self) -> impl Iterator<Item = CallArg> + 'a {
+ pub fn items(&self) -> impl Iterator<Item = CallArg> + '_ {
self.0.children().filter_map(RedRef::cast)
}
}
@@ -726,7 +738,7 @@ pub enum CallArg {
}
impl TypedNode for CallArg {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
match node.kind() {
NodeKind::Named => Some(CallArg::Named(
node.cast().expect("named call argument is missing name"),
@@ -767,7 +779,7 @@ impl ClosureExpr {
}
/// The parameter bindings.
- pub fn params<'a>(&'a self) -> impl Iterator<Item = ClosureParam> + 'a {
+ pub fn params(&self) -> impl Iterator<Item = ClosureParam> + '_ {
self.0
.children()
.find(|x| x.kind() == &NodeKind::ClosureParams)
@@ -805,10 +817,10 @@ pub enum ClosureParam {
}
impl TypedNode for ClosureParam {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
match node.kind() {
- NodeKind::Ident(i) => {
- Some(ClosureParam::Pos(Ident::new(i, node.span()).unwrap()))
+ NodeKind::Ident(id) => {
+ Some(ClosureParam::Pos(Ident::new_unchecked(id, node.span())))
}
NodeKind::Named => Some(ClosureParam::Named(
node.cast().expect("named closure parameter is missing name"),
@@ -921,7 +933,7 @@ pub enum Imports {
}
impl TypedNode for Imports {
- fn cast_from(node: RedRef) -> Option<Self> {
+ fn from_red(node: RedRef) -> Option<Self> {
match node.kind() {
NodeKind::Star => Some(Imports::Wildcard),
NodeKind::ImportItems => {
@@ -1043,14 +1055,75 @@ node! {
}
impl ForPattern {
+ /// The key part of the pattern: index for arrays, name for dictionaries.
pub fn key(&self) -> Option<Ident> {
- let mut items: Vec<_> = self.0.children().filter_map(RedRef::cast).collect();
- if items.len() > 1 { Some(items.remove(0)) } else { None }
+ let mut children = self.0.children().filter_map(RedRef::cast);
+ let key = children.next();
+ if children.next().is_some() { key } else { None }
}
+ /// The value part of the pattern.
pub fn value(&self) -> Ident {
self.0
.cast_last_child()
.expect("for-in loop pattern is missing value")
}
}
+
+/// An unicode identifier with a few extra permissible characters.
+///
+/// In addition to what is specified in the [Unicode Standard][uax31], we allow:
+/// - `_` as a starting character,
+/// - `_` and `-` as continuing characters.
+///
+/// [uax31]: http://www.unicode.org/reports/tr31/
+#[derive(Debug, Clone, PartialEq)]
+pub struct Ident {
+ /// The source code location.
+ pub span: Span,
+ /// The identifier string.
+ pub string: EcoString,
+}
+
+impl Ident {
+ /// Create a new identifier from a string checking that it is a valid.
+ pub fn new(
+ string: impl AsRef<str> + Into<EcoString>,
+ span: impl Into<Span>,
+ ) -> Option<Self> {
+ is_ident(string.as_ref())
+ .then(|| Self { span: span.into(), string: string.into() })
+ }
+
+ /// Create a new identifier from a string and a span.
+ ///
+ /// The `string` must be a valid identifier.
+ #[track_caller]
+ pub fn new_unchecked(string: impl Into<EcoString>, span: Span) -> Self {
+ let string = string.into();
+ debug_assert!(is_ident(&string), "`{}` is not a valid identifier", string);
+ Self { span, string }
+ }
+
+ /// Return a reference to the underlying string.
+ pub fn as_str(&self) -> &str {
+ &self.string
+ }
+}
+
+impl Deref for Ident {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ self.as_str()
+ }
+}
+
+impl TypedNode for Ident {
+ fn from_red(node: RedRef) -> Option<Self> {
+ match node.kind() {
+ NodeKind::Ident(string) => Some(Ident::new_unchecked(string, node.span())),
+ _ => None,
+ }
+ }
+}
diff --git a/src/syntax/ident.rs b/src/syntax/ident.rs
deleted file mode 100644
index f5cc6330..00000000
--- a/src/syntax/ident.rs
+++ /dev/null
@@ -1,94 +0,0 @@
-use std::borrow::Borrow;
-use std::ops::Deref;
-
-use unicode_xid::UnicodeXID;
-
-use super::{NodeKind, RedRef, Span, TypedNode};
-use crate::util::EcoString;
-
-/// An unicode identifier with a few extra permissible characters.
-///
-/// In addition to what is specified in the [Unicode Standard][uax31], we allow:
-/// - `_` as a starting character,
-/// - `_` and `-` as continuing characters.
-///
-/// [uax31]: http://www.unicode.org/reports/tr31/
-#[derive(Debug, Clone, PartialEq)]
-pub struct Ident {
- /// The source code location.
- pub span: Span,
- /// The identifier string.
- pub string: EcoString,
-}
-
-impl Ident {
- /// Create a new identifier from a string checking that it is a valid.
- pub fn new(
- string: impl AsRef<str> + Into<EcoString>,
- span: impl Into<Span>,
- ) -> Option<Self> {
- if is_ident(string.as_ref()) {
- Some(Self { span: span.into(), string: string.into() })
- } else {
- None
- }
- }
-
- /// Return a reference to the underlying string.
- pub fn as_str(&self) -> &str {
- self
- }
-}
-
-impl Deref for Ident {
- type Target = str;
-
- fn deref(&self) -> &Self::Target {
- self.string.as_str()
- }
-}
-
-impl AsRef<str> for Ident {
- fn as_ref(&self) -> &str {
- self
- }
-}
-
-impl Borrow<str> for Ident {
- fn borrow(&self) -> &str {
- self
- }
-}
-
-impl From<&Ident> for EcoString {
- fn from(ident: &Ident) -> Self {
- ident.string.clone()
- }
-}
-
-impl TypedNode for Ident {
- fn cast_from(node: RedRef) -> Option<Self> {
- match node.kind() {
- NodeKind::Ident(i) => Some(Ident::new(i, node.span()).unwrap()),
- _ => None,
- }
- }
-}
-
-/// Whether a string is a valid identifier.
-pub fn is_ident(string: &str) -> bool {
- let mut chars = string.chars();
- chars
- .next()
- .map_or(false, |c| is_id_start(c) && chars.all(is_id_continue))
-}
-
-/// Whether a character can start an identifier.
-pub fn is_id_start(c: char) -> bool {
- c.is_xid_start() || c == '_'
-}
-
-/// Whether a character can continue an identifier.
-pub fn is_id_continue(c: char) -> bool {
- c.is_xid_continue() || c == '_' || c == '-'
-}
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<GreenNode>),
- /// 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<Rc<GreenNode>> 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<GreenData> 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<T>(self) -> Option<T>
- 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<Item = RedRef<'a>> + 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<Error> {
+ pub fn errors(self) -> Vec<Error> {
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<T>(self) -> Option<T>
+ where
+ T: TypedNode,
+ {
+ T::from_red(self)
+ }
+
+ /// The node's children.
+ pub fn children(self) -> impl Iterator<Item = RedRef<'a>> {
+ 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<RedRef> {
+ pub(crate) fn typed_child(self, kind: &NodeKind) -> Option<RedRef<'a>> {
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<T: TypedNode>(&self) -> Option<T> {
+ pub(crate) fn cast_first_child<T: TypedNode>(self) -> Option<T> {
self.children().find_map(RedRef::cast)
}
/// Get the last child that can cast to some AST type.
- pub(crate) fn cast_last_child<T: TypedNode>(&self) -> Option<T> {
+ pub(crate) fn cast_last_child<T: TypedNode>(self) -> Option<T> {
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<Error> {
+ self.as_ref().errors()
+ }
+
/// Convert the node to a typed AST node.
pub fn cast<T>(self) -> Option<T>
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<Item = RedRef<'a>> + Clone {
+ pub fn children(&self) -> impl Iterator<Item = RedRef<'_>> {
self.as_ref().children()
}
- /// The error messages for this node and its descendants.
- pub fn errors<'a>(&'a self) -> Vec<Error> {
- self.as_ref().errors()
- }
-
/// Get the first child of some type.
pub(crate) fn typed_child(&self, kind: &NodeKind) -> Option<RedNode> {
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<Self>;
-}
-
+/// 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())
+ }
+}
diff --git a/src/syntax/pretty.rs b/src/syntax/pretty.rs
index da0bdd44..b396a39c 100644
--- a/src/syntax/pretty.rs
+++ b/src/syntax/pretty.rs
@@ -2,7 +2,7 @@
use std::fmt::{self, Arguments, Write};
-use super::*;
+use super::ast::*;
/// Pretty print an item and return the resulting string.
pub fn pretty<T>(item: &T) -> String
diff --git a/src/syntax/span.rs b/src/syntax/span.rs
index ee7cba4c..c26011bd 100644
--- a/src/syntax/span.rs
+++ b/src/syntax/span.rs
@@ -1,6 +1,6 @@
use std::cmp::Ordering;
use std::fmt::{self, Debug, Formatter};
-use std::ops::{Add, Range};
+use std::ops::Range;
use serde::{Deserialize, Serialize};
@@ -53,23 +53,19 @@ pub struct Span {
/// The id of the source file.
pub source: SourceId,
/// The inclusive start position.
- pub start: Pos,
+ pub start: usize,
/// The inclusive end position.
- pub end: Pos,
+ pub end: usize,
}
impl Span {
/// Create a new span from start and end positions.
- pub fn new(source: SourceId, start: impl Into<Pos>, end: impl Into<Pos>) -> Self {
- Self {
- source,
- start: start.into(),
- end: end.into(),
- }
+ pub fn new(source: SourceId, start: usize, end: usize) -> Self {
+ Self { source, start, end }
}
/// Create a span including just a single position.
- pub fn at(source: SourceId, pos: impl Into<Pos> + Copy) -> Self {
+ pub fn at(source: SourceId, pos: usize) -> Self {
Self::new(source, pos, pos)
}
@@ -77,19 +73,29 @@ impl Span {
pub fn detached() -> Self {
Self {
source: SourceId::from_raw(0),
- start: Pos::ZERO,
- end: Pos::ZERO,
+ start: 0,
+ end: 0,
}
}
/// Create a span with a different start position.
- pub fn with_start(self, start: impl Into<Pos>) -> Self {
- Self { start: start.into(), ..self }
+ pub fn with_start(self, start: usize) -> Self {
+ Self { start, ..self }
}
/// Create a span with a different end position.
- pub fn with_end(self, end: impl Into<Pos>) -> Self {
- Self { end: end.into(), ..self }
+ pub fn with_end(self, end: usize) -> Self {
+ Self { end, ..self }
+ }
+
+ /// A new span at the position of this span's start.
+ pub fn at_start(&self) -> Span {
+ Self::at(self.source, self.start)
+ }
+
+ /// A new span at the position of this span's end.
+ pub fn at_end(&self) -> Span {
+ Self::at(self.source, self.end)
}
/// Create a new span with the earlier start and later end position.
@@ -110,28 +116,18 @@ impl Span {
}
/// Test whether a position is within the span.
- pub fn contains_pos(&self, pos: Pos) -> bool {
+ pub fn contains(&self, pos: usize) -> bool {
self.start <= pos && self.end >= pos
}
/// Test whether one span complete contains the other span.
- pub fn contains(self, other: Self) -> bool {
+ pub fn surrounds(self, other: Self) -> bool {
self.source == other.source && self.start <= other.start && self.end >= other.end
}
- /// Convert to a `Range<Pos>` for indexing.
+ /// Convert to a `Range<usize>` for indexing.
pub fn to_range(self) -> Range<usize> {
- self.start.to_usize() .. self.end.to_usize()
- }
-
- /// A new span at the position of this span's start.
- pub fn at_start(&self) -> Span {
- Self::at(self.source, self.start)
- }
-
- /// A new span at the position of this span's end.
- pub fn at_end(&self) -> Span {
- Self::at(self.source, self.end)
+ self.start .. self.end
}
}
@@ -150,77 +146,3 @@ impl PartialOrd for Span {
}
}
}
-
-/// A byte position in source code.
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
-pub struct Pos(pub u32);
-
-impl Pos {
- /// The zero position.
- pub const ZERO: Self = Self(0);
-
- /// Convert to a usize for indexing.
- pub fn to_usize(self) -> usize {
- self.0 as usize
- }
-}
-
-impl Debug for Pos {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- Debug::fmt(&self.0, f)
- }
-}
-
-impl From<u32> for Pos {
- fn from(index: u32) -> Self {
- Self(index)
- }
-}
-
-impl From<usize> for Pos {
- fn from(index: usize) -> Self {
- Self(index as u32)
- }
-}
-
-impl<T> Add<T> for Pos
-where
- T: Into<Pos>,
-{
- type Output = Self;
-
- fn add(self, rhs: T) -> Self {
- Pos(self.0 + rhs.into().0)
- }
-}
-
-/// Convert a position or range into a span.
-pub trait IntoSpan {
- /// Convert into a span by providing the source id.
- fn into_span(self, source: SourceId) -> Span;
-}
-
-impl IntoSpan for Span {
- fn into_span(self, source: SourceId) -> Span {
- debug_assert_eq!(self.source, source);
- self
- }
-}
-
-impl IntoSpan for Pos {
- fn into_span(self, source: SourceId) -> Span {
- Span::new(source, self, self)
- }
-}
-
-impl IntoSpan for usize {
- fn into_span(self, source: SourceId) -> Span {
- Span::new(source, self, self)
- }
-}
-
-impl IntoSpan for Range<usize> {
- fn into_span(self, source: SourceId) -> Span {
- Span::new(source, self.start, self.end)
- }
-}