diff options
Diffstat (limited to 'src/syntax')
| -rw-r--r-- | src/syntax/ast/expr.rs (renamed from src/syntax/expr.rs) | 7 | ||||
| -rw-r--r-- | src/syntax/ast/lit.rs (renamed from src/syntax/lit.rs) | 10 | ||||
| -rw-r--r-- | src/syntax/ast/mod.rs | 9 | ||||
| -rw-r--r-- | src/syntax/ast/tree.rs (renamed from src/syntax/tree.rs) | 34 | ||||
| -rw-r--r-- | src/syntax/mod.rs | 15 | ||||
| -rw-r--r-- | src/syntax/span.rs | 44 | ||||
| -rw-r--r-- | src/syntax/token.rs | 147 |
7 files changed, 149 insertions, 117 deletions
diff --git a/src/syntax/expr.rs b/src/syntax/ast/expr.rs index 7f4d03d5..c07c6216 100644 --- a/src/syntax/expr.rs +++ b/src/syntax/ast/expr.rs @@ -1,9 +1,8 @@ //! Expressions. -use super::span::{SpanWith, Spanned}; -use super::{Decoration, Ident, Lit, LitDict}; use crate::eval::Value; use crate::layout::LayoutContext; +use crate::syntax::{Decoration, Ident, Lit, LitDict, SpanWith, Spanned}; use crate::Feedback; /// An expression. @@ -50,7 +49,7 @@ impl ExprUnary { } /// A unary operator. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum UnOp { /// The negation operator: `-`. Neg, @@ -80,7 +79,7 @@ impl ExprBinary { } /// A binary operator. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum BinOp { /// The addition operator: `+`. Add, diff --git a/src/syntax/lit.rs b/src/syntax/ast/lit.rs index 3cd94583..bbdd0c81 100644 --- a/src/syntax/lit.rs +++ b/src/syntax/ast/lit.rs @@ -1,10 +1,10 @@ //! Literals. -use super::{Expr, Ident, SpanWith, Spanned, SynTree}; use crate::color::RgbaColor; use crate::eval::{DictKey, DictValue, SpannedEntry, Value}; use crate::layout::LayoutContext; use crate::length::Length; +use crate::syntax::{Expr, Ident, SpanWith, Spanned, SynTree}; use crate::{DynFuture, Feedback}; /// A literal. @@ -55,7 +55,7 @@ impl Lit { } /// A dictionary literal: `(false, 12cm, greeting = "hi")`. -#[derive(Debug, Default, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub struct LitDict(pub Vec<LitDictEntry>); impl LitDict { @@ -74,8 +74,8 @@ impl LitDict { let mut dict = DictValue::new(); for entry in &self.0 { - let val = entry.value.v.eval(ctx, f).await; - let spanned = val.span_with(entry.value.span); + let val = entry.expr.v.eval(ctx, f).await; + let spanned = val.span_with(entry.expr.span); if let Some(key) = &entry.key { dict.insert(&key.v, SpannedEntry::new(key.span, spanned)); } else { @@ -94,5 +94,5 @@ pub struct LitDictEntry { /// The key of the entry if there was one: `greeting`. pub key: Option<Spanned<DictKey>>, /// The value of the entry: `"hi"`. - pub value: Spanned<Expr>, + pub expr: Spanned<Expr>, } diff --git a/src/syntax/ast/mod.rs b/src/syntax/ast/mod.rs new file mode 100644 index 00000000..56ae4134 --- /dev/null +++ b/src/syntax/ast/mod.rs @@ -0,0 +1,9 @@ +//! Abstract syntax tree definition. + +mod expr; +mod lit; +mod tree; + +pub use expr::*; +pub use lit::*; +pub use tree::*; diff --git a/src/syntax/tree.rs b/src/syntax/ast/tree.rs index 80bca399..03aa3439 100644 --- a/src/syntax/tree.rs +++ b/src/syntax/ast/tree.rs @@ -1,7 +1,6 @@ //! The syntax tree. -use super::span::{SpanVec, Spanned}; -use super::{Expr, Ident}; +use crate::syntax::{Expr, Ident, SpanVec, Spanned}; /// A collection of nodes which form a tree together with the nodes' children. pub type SynTree = SpanVec<SynNode>; @@ -11,7 +10,10 @@ pub type SynTree = SpanVec<SynNode>; #[derive(Debug, Clone, PartialEq)] pub enum SynNode { /// Whitespace containing less than two newlines. - Spacing, + Space, + /// Plain text. + Text(String), + /// A forced line break. Linebreak, /// A paragraph break. @@ -20,16 +22,25 @@ pub enum SynNode { ToggleItalic, /// Bolder was enabled / disabled. ToggleBolder, - /// Plain text. - Text(String), - /// An optionally syntax-highlighted raw block. - Raw(NodeRaw), + /// A section heading. Heading(NodeHeading), + /// An optionally syntax-highlighted raw block. + Raw(NodeRaw), + /// An expression. Expr(Expr), } +/// A section heading. +#[derive(Debug, Clone, PartialEq)] +pub struct NodeHeading { + /// The section depth (how many hashtags minus 1). + pub level: Spanned<u8>, + /// The contents of the heading. + pub contents: SynTree, +} + /// A raw block, rendered in monospace with optional syntax highlighting. /// /// Raw blocks start with an arbitrary number of backticks and end with the same @@ -108,12 +119,3 @@ pub struct NodeRaw { /// are inline-level when they contain no newlines. pub inline: bool, } - -/// A section heading. -#[derive(Debug, Clone, PartialEq)] -pub struct NodeHeading { - /// The section depth (how many hashtags minus 1). - pub level: Spanned<u8>, - /// The contents of the heading. - pub contents: SynTree, -} diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index f4472df5..98e1b4d7 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -1,19 +1,10 @@ //! Syntax types. -mod expr; +pub mod ast; +pub mod token; + mod ident; -mod lit; mod span; -mod token; -mod tree; - -/// Abstract syntax tree definition. -pub mod ast { - use super::*; - pub use expr::*; - pub use lit::*; - pub use tree::*; -} pub use ast::*; pub use ident::*; diff --git a/src/syntax/span.rs b/src/syntax/span.rs index 62929706..179c46de 100644 --- a/src/syntax/span.rs +++ b/src/syntax/span.rs @@ -13,7 +13,7 @@ thread_local! { /// Annotate a value with a span. pub trait SpanWith: Sized { /// Wraps `self` in a `Spanned` with the given span. - fn span_with(self, span: Span) -> Spanned<Self> { + fn span_with(self, span: impl Into<Span>) -> Spanned<Self> { Spanned::new(self, span) } } @@ -50,8 +50,8 @@ pub struct Spanned<T> { impl<T> Spanned<T> { /// Create a new instance from a value and its span. - pub fn new(v: T, span: Span) -> Self { - Self { v, span } + pub fn new(v: T, span: impl Into<Span>) -> Self { + Self { v, span: span.into() } } /// Create a new instance from a value with the zero span. @@ -123,16 +123,16 @@ impl Span { } /// Create a new span with the earlier start and later end position. - pub fn merge(a: Self, b: Self) -> Self { + pub fn join(self, other: Self) -> Self { Self { - start: a.start.min(b.start), - end: a.end.max(b.end), + start: self.start.min(other.start), + end: self.end.max(other.end), } } /// Expand a span by merging it with another span. pub fn expand(&mut self, other: Self) { - *self = Self::merge(*self, other) + *self = self.join(other) } /// When set to `false` comparisons with `PartialEq` ignore spans. @@ -164,6 +164,24 @@ impl PartialEq for Span { } } +impl<T> From<T> for Span +where + T: Into<Pos> + Copy, +{ + fn from(pos: T) -> Self { + Self::at(pos) + } +} + +impl<T> From<(T, T)> for Span +where + T: Into<Pos>, +{ + fn from((start, end): (T, T)) -> Self { + Self::new(start, end) + } +} + impl Debug for Span { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "<{:?}-{:?}>", self.start, self.end) @@ -185,6 +203,12 @@ impl Pos { } } +impl Offset for Pos { + fn offset(self, by: Self) -> Self { + Pos(self.0 + by.0) + } +} + impl From<u32> for Pos { fn from(index: u32) -> Self { Self(index) @@ -197,12 +221,6 @@ impl From<usize> for Pos { } } -impl Offset for Pos { - fn offset(self, by: Self) -> Self { - Pos(self.0 + by.0) - } -} - impl Debug for Pos { fn fmt(&self, f: &mut Formatter) -> fmt::Result { Debug::fmt(&self.0, f) diff --git a/src/syntax/token.rs b/src/syntax/token.rs index 4cb8501f..5c159bbd 100644 --- a/src/syntax/token.rs +++ b/src/syntax/token.rs @@ -1,4 +1,4 @@ -//! Tokenization. +//! Token definition. use crate::length::Length; @@ -8,6 +8,8 @@ pub enum Token<'s> { /// One or more whitespace characters. The contained `usize` denotes the /// number of newlines that were contained in the whitespace. Space(usize), + /// A consecutive non-markup string. + Text(&'s str), /// A line comment with inner string contents `//<str>\n`. LineComment(&'s str), @@ -15,6 +17,20 @@ pub enum Token<'s> { /// can contain nested block comments. BlockComment(&'s str), + /// A star. It can appear in a function header where it signifies the + /// multiplication of expressions or the body where it modifies the styling. + Star, + /// An underscore in body-text. + Underscore, + /// A backslash followed by whitespace in text. + Backslash, + /// A hashtag indicating a section heading. + Hashtag, + /// A raw block. + Raw(TokenRaw<'s>), + /// A unicode escape sequence. + UnicodeEscape(TokenUnicodeEscape<'s>), + /// A left bracket starting a function invocation or body: `[`. LeftBracket, /// A right bracket ending a function invocation or body: `]`. @@ -28,29 +44,24 @@ pub enum Token<'s> { /// A right parenthesis in a function header: `)`. RightParen, - /// A double forward chevron in a function header: `>>`. - Chain, - /// A colon in a function header: `:`. Colon, /// A comma in a function header: `,`. Comma, /// An equals sign in a function header: `=`. Equals, + /// A double forward chevron in a function header: `>>`. + Chain, + /// A plus in a function header, signifying the addition of expressions. + Plus, + /// A hyphen in a function header, signifying the subtraction of + /// expressions. + Hyphen, + /// A slash in a function header, signifying the division of expressions. + Slash, /// An identifier in a function header: `center`. Ident(&'s str), - /// A quoted string in a function header: `"..."`. - Str { - /// The string inside the quotes. - /// - /// _Note_: If the string contains escape sequences these are not yet - /// applied to be able to just store a string slice here instead of - /// a String. The escaping is done later in the parser. - string: &'s str, - /// Whether the closing quote was present. - terminated: bool, - }, /// A boolean in a function header: `true | false`. Bool(bool), /// A number in a function header: `3.14`. @@ -59,48 +70,44 @@ pub enum Token<'s> { Length(Length), /// A hex value in a function header: `#20d82a`. Hex(&'s str), - /// A plus in a function header, signifying the addition of expressions. - Plus, - /// A hyphen in a function header, signifying the subtraction of - /// expressions. - Hyphen, - /// A slash in a function header, signifying the division of expressions. - Slash, + /// A quoted string in a function header: `"..."`. + Str(TokenStr<'s>), - /// A star. It can appear in a function header where it signifies the - /// multiplication of expressions or the body where it modifies the styling. - Star, - /// An underscore in body-text. - Underscore, - /// A backslash followed by whitespace in text. - Backslash, + /// Things that are not valid in the context they appeared in. + Invalid(&'s str), +} - /// A hashtag token in the body can indicate compute mode or headings. - Hashtag, +/// A quoted string in a function header: `"..."`. +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct TokenStr<'s> { + /// The string inside the quotes. + /// + /// _Note_: If the string contains escape sequences these are not yet + /// applied to be able to just store a string slice here instead of + /// a `String`. The resolving is done later in the parser. + pub string: &'s str, + /// Whether the closing quote was present. + pub terminated: bool, +} - /// A unicode escape sequence. - UnicodeEscape { - /// The escape sequence between two braces. - sequence: &'s str, - /// Whether the closing brace was present. - terminated: bool, - }, - - /// Raw block. - Raw { - /// The raw text between the backticks. - raw: &'s str, - /// The number of opening backticks. - backticks: usize, - /// Whether all closing backticks were present. - terminated: bool, - }, - - /// Any other consecutive string. - Text(&'s str), +/// A unicode escape sequence. +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct TokenUnicodeEscape<'s> { + /// The escape sequence between two braces. + pub sequence: &'s str, + /// Whether the closing brace was present. + pub terminated: bool, +} - /// Things that are not valid in the context they appeared in. - Invalid(&'s str), +/// A raw block. +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct TokenRaw<'s> { + /// The raw text between the backticks. + pub text: &'s str, + /// The number of opening backticks. + pub backticks: usize, + /// Whether all closing backticks were present. + pub terminated: bool, } impl<'s> Token<'s> { @@ -108,34 +115,40 @@ impl<'s> Token<'s> { pub fn name(self) -> &'static str { match self { Self::Space(_) => "space", + Self::Text(_) => "text", + Self::LineComment(_) => "line comment", Self::BlockComment(_) => "block comment", + + Self::Star => "star", + Self::Underscore => "underscore", + Self::Backslash => "backslash", + Self::Hashtag => "hashtag", + Self::Raw { .. } => "raw block", + Self::UnicodeEscape { .. } => "unicode escape sequence", + Self::LeftBracket => "opening bracket", Self::RightBracket => "closing bracket", - Self::LeftParen => "opening paren", - Self::RightParen => "closing paren", Self::LeftBrace => "opening brace", Self::RightBrace => "closing brace", - Self::Chain => "function chain operator", + Self::LeftParen => "opening paren", + Self::RightParen => "closing paren", + Self::Colon => "colon", Self::Comma => "comma", Self::Equals => "equals sign", + Self::Chain => "function chaining operator", + Self::Plus => "plus sign", + Self::Hyphen => "minus sign", + Self::Slash => "slash", + Self::Ident(_) => "identifier", - Self::Str { .. } => "string", Self::Bool(_) => "bool", Self::Number(_) => "number", Self::Length(_) => "length", Self::Hex(_) => "hex value", - Self::Plus => "plus", - Self::Hyphen => "minus", - Self::Slash => "slash", - Self::Star => "star", - Self::Underscore => "underscore", - Self::Backslash => "backslash", - Self::Hashtag => "hashtag", - Self::UnicodeEscape { .. } => "unicode escape sequence", - Self::Raw { .. } => "raw block", - Self::Text(_) => "text", + Self::Str { .. } => "string", + Self::Invalid("*/") => "end of block comment", Self::Invalid(_) => "invalid token", } |
