summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
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.rs9
-rw-r--r--src/syntax/ast/tree.rs (renamed from src/syntax/tree.rs)34
-rw-r--r--src/syntax/mod.rs15
-rw-r--r--src/syntax/span.rs44
-rw-r--r--src/syntax/token.rs147
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",
}