summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/expr.rs397
-rw-r--r--src/syntax/ident.rs35
-rw-r--r--src/syntax/mod.rs7
-rw-r--r--src/syntax/node.rs8
-rw-r--r--src/syntax/span.rs17
-rw-r--r--src/syntax/token.rs2
-rw-r--r--src/syntax/visit.rs108
7 files changed, 353 insertions, 221 deletions
diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs
index 3160e0e4..f431ba8d 100644
--- a/src/syntax/expr.rs
+++ b/src/syntax/expr.rs
@@ -1,3 +1,5 @@
+use std::rc::Rc;
+
use super::*;
use crate::color::RgbaColor;
use crate::geom::{AngularUnit, LengthUnit};
@@ -5,29 +7,10 @@ use crate::geom::{AngularUnit, LengthUnit};
/// An expression.
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
- /// The none literal: `none`.
- None,
- /// A identifier literal: `left`.
+ /// A literal.
+ Lit(Lit),
+ /// An identifier: `left`.
Ident(Ident),
- /// A boolean literal: `true`, `false`.
- Bool(bool),
- /// An integer literal: `120`.
- Int(i64),
- /// A floating-point literal: `1.2`, `10e-4`.
- Float(f64),
- /// A length literal: `12pt`, `3cm`.
- Length(f64, LengthUnit),
- /// An angle literal: `1.5rad`, `90deg`.
- Angle(f64, AngularUnit),
- /// A percent literal: `50%`.
- ///
- /// _Note_: `50%` is stored as `50.0` here, but as `0.5` in the
- /// corresponding [value](crate::geom::Relative).
- Percent(f64),
- /// A color literal: `#ffccee`.
- Color(RgbaColor),
- /// A string literal: `"hello!"`.
- Str(String),
/// An array expression: `(1, "hi", 12cm)`.
Array(ExprArray),
/// A dictionary expression: `(color: #f79143, pattern: dashed)`.
@@ -52,11 +35,92 @@ pub enum Expr {
For(ExprFor),
}
+impl Expr {
+ /// The source code location.
+ pub fn span(&self) -> Span {
+ match self {
+ Self::Lit(v) => v.span,
+ Self::Ident(v) => v.span,
+ Self::Array(v) => v.span,
+ Self::Dict(v) => v.span,
+ Self::Template(v) => v.span,
+ Self::Group(v) => v.span,
+ Self::Block(v) => v.span,
+ Self::Unary(v) => v.span,
+ Self::Binary(v) => v.span,
+ Self::Call(v) => v.span,
+ Self::Let(v) => v.span,
+ Self::If(v) => v.span,
+ Self::For(v) => v.span,
+ }
+ }
+}
+
impl Pretty for Expr {
fn pretty(&self, p: &mut Printer) {
match self {
- Self::None => p.push_str("none"),
+ Self::Lit(v) => v.pretty(p),
Self::Ident(v) => v.pretty(p),
+ Self::Array(v) => v.pretty(p),
+ Self::Dict(v) => v.pretty(p),
+ Self::Template(v) => v.pretty(p),
+ Self::Group(v) => v.pretty(p),
+ Self::Block(v) => v.pretty(p),
+ Self::Unary(v) => v.pretty(p),
+ Self::Binary(v) => v.pretty(p),
+ Self::Call(v) => v.pretty(p),
+ Self::Let(v) => v.pretty(p),
+ Self::If(v) => v.pretty(p),
+ Self::For(v) => v.pretty(p),
+ }
+ }
+}
+
+/// A literal.
+#[derive(Debug, Clone, PartialEq)]
+pub struct Lit {
+ /// The source code location.
+ pub span: Span,
+ /// The kind of literal.
+ pub kind: LitKind,
+}
+
+impl Pretty for Lit {
+ fn pretty(&self, p: &mut Printer) {
+ self.kind.pretty(p);
+ }
+}
+
+/// A kind of literal.
+#[derive(Debug, Clone, PartialEq)]
+pub enum LitKind {
+ /// The none literal: `none`.
+ None,
+ /// A boolean literal: `true`, `false`.
+ Bool(bool),
+ /// An integer literal: `120`.
+ Int(i64),
+ /// A floating-point literal: `1.2`, `10e-4`.
+ Float(f64),
+ /// A length literal: `12pt`, `3cm`.
+ Length(f64, LengthUnit),
+ /// An angle literal: `1.5rad`, `90deg`.
+ Angle(f64, AngularUnit),
+ /// A percent literal: `50%`.
+ ///
+ /// _Note_: `50%` is stored as `50.0` here, but as `0.5` in the
+ /// corresponding [value](crate::geom::Relative).
+ Percent(f64),
+ /// A color literal: `#ffccee`.
+ Color(RgbaColor),
+ /// A string literal: `"hello!"`.
+ Str(String),
+}
+
+impl Pretty for LitKind {
+ fn pretty(&self, p: &mut Printer) {
+ match self {
+ Self::None => p.push_str("none"),
Self::Bool(v) => v.pretty(p),
Self::Int(v) => v.pretty(p),
Self::Float(v) => v.pretty(p),
@@ -71,33 +135,24 @@ impl Pretty for Expr {
}
Self::Color(v) => v.pretty(p),
Self::Str(v) => v.pretty(p),
- Self::Array(v) => v.pretty(p),
- Self::Dict(v) => v.pretty(p),
- Self::Template(v) => pretty_template(v, p),
- Self::Group(v) => {
- p.push('(');
- v.v.pretty(p);
- p.push(')');
- }
- Self::Block(v) => v.pretty(p),
- Self::Unary(v) => v.pretty(p),
- Self::Binary(v) => v.pretty(p),
- Self::Call(v) => v.pretty(p),
- Self::Let(v) => v.pretty(p),
- Self::If(v) => v.pretty(p),
- Self::For(v) => v.pretty(p),
}
}
}
/// An array expression: `(1, "hi", 12cm)`.
-pub type ExprArray = SpanVec<Expr>;
+#[derive(Debug, Clone, PartialEq)]
+pub struct ExprArray {
+ /// The source code location.
+ pub span: Span,
+ /// The entries of the array.
+ pub items: Vec<Expr>,
+}
impl Pretty for ExprArray {
fn pretty(&self, p: &mut Printer) {
p.push('(');
- p.join(self, ", ", |item, p| item.v.pretty(p));
- if self.len() == 1 {
+ p.join(&self.items, ", ", |item, p| item.pretty(p));
+ if self.items.len() == 1 {
p.push(',');
}
p.push(')');
@@ -105,15 +160,21 @@ impl Pretty for ExprArray {
}
/// A dictionary expression: `(color: #f79143, pattern: dashed)`.
-pub type ExprDict = Vec<Named>;
+#[derive(Debug, Clone, PartialEq)]
+pub struct ExprDict {
+ /// The source code location.
+ pub span: Span,
+ /// The named dictionary entries.
+ pub items: Vec<Named>,
+}
impl Pretty for ExprDict {
fn pretty(&self, p: &mut Printer) {
p.push('(');
- if self.is_empty() {
+ if self.items.is_empty() {
p.push(':');
} else {
- p.join(self, ", ", |named, p| named.pretty(p));
+ p.join(&self.items, ", ", |named, p| named.pretty(p));
}
p.push(')');
}
@@ -123,43 +184,73 @@ impl Pretty for ExprDict {
#[derive(Debug, Clone, PartialEq)]
pub struct Named {
/// The name: `pattern`.
- pub name: Spanned<Ident>,
+ pub name: Ident,
/// The right-hand side of the pair: `dashed`.
- pub expr: Spanned<Expr>,
+ pub expr: Expr,
+}
+
+impl Named {
+ /// The source code location.
+ pub fn span(&self) -> Span {
+ self.name.span.join(self.expr.span())
+ }
}
impl Pretty for Named {
fn pretty(&self, p: &mut Printer) {
- self.name.v.pretty(p);
+ self.name.pretty(p);
p.push_str(": ");
- self.expr.v.pretty(p);
+ self.expr.pretty(p);
}
}
/// A template expression: `[*Hi* there!]`.
-pub type ExprTemplate = Tree;
+#[derive(Debug, Clone, PartialEq)]
+pub struct ExprTemplate {
+ /// The source code location.
+ pub span: Span,
+ /// The contents of the template.
+ pub tree: Rc<Tree>,
+}
-/// Pretty print a template.
-pub fn pretty_template(template: &ExprTemplate, p: &mut Printer) {
- if let [Spanned { v: Node::Expr(Expr::Call(call)), .. }] = template.as_slice() {
- pretty_func_template(call, p, false)
- } else {
- p.push('[');
- template.pretty(p);
- p.push(']');
+impl Pretty for ExprTemplate {
+ fn pretty(&self, p: &mut Printer) {
+ if let [Node::Expr(Expr::Call(call))] = self.tree.as_slice() {
+ call.pretty_bracketed(p, false);
+ } else {
+ p.push('[');
+ self.tree.pretty(p);
+ p.push(']');
+ }
}
}
/// A grouped expression: `(1 + 2)`.
-pub type ExprGroup = SpanBox<Expr>;
+#[derive(Debug, Clone, PartialEq)]
+pub struct ExprGroup {
+ /// The source code location.
+ pub span: Span,
+ /// The wrapped expression.
+ pub expr: Box<Expr>,
+}
+
+impl Pretty for ExprGroup {
+ fn pretty(&self, p: &mut Printer) {
+ p.push('(');
+ self.expr.pretty(p);
+ p.push(')');
+ }
+}
/// A block expression: `{ #let x = 1; x + 2 }`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprBlock {
+ /// The source code location.
+ pub span: Span,
/// The list of expressions contained in the block.
- pub exprs: SpanVec<Expr>,
+ pub exprs: Vec<Expr>,
/// Whether the block should create a scope.
- pub scopes: bool,
+ pub scoping: bool,
}
impl Pretty for ExprBlock {
@@ -168,7 +259,7 @@ impl Pretty for ExprBlock {
if self.exprs.len() > 1 {
p.push(' ');
}
- p.join(&self.exprs, "; ", |expr, p| expr.v.pretty(p));
+ p.join(&self.exprs, "; ", |expr, p| expr.pretty(p));
if self.exprs.len() > 1 {
p.push(' ');
}
@@ -179,19 +270,21 @@ impl Pretty for ExprBlock {
/// A unary operation: `-x`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprUnary {
+ /// The source code location.
+ pub span: Span,
/// The operator: `-`.
- pub op: Spanned<UnOp>,
+ pub op: UnOp,
/// The expression to operator on: `x`.
- pub expr: SpanBox<Expr>,
+ pub expr: Box<Expr>,
}
impl Pretty for ExprUnary {
fn pretty(&self, p: &mut Printer) {
- self.op.v.pretty(p);
- if self.op.v == UnOp::Not {
+ self.op.pretty(p);
+ if self.op == UnOp::Not {
p.push(' ');
}
- self.expr.v.pretty(p);
+ self.expr.pretty(p);
}
}
@@ -244,21 +337,23 @@ impl Pretty for UnOp {
/// A binary operation: `a + b`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprBinary {
+ /// The source code location.
+ pub span: Span,
/// The left-hand side of the operation: `a`.
- pub lhs: SpanBox<Expr>,
+ pub lhs: Box<Expr>,
/// The operator: `+`.
- pub op: Spanned<BinOp>,
+ pub op: BinOp,
/// The right-hand side of the operation: `b`.
- pub rhs: SpanBox<Expr>,
+ pub rhs: Box<Expr>,
}
impl Pretty for ExprBinary {
fn pretty(&self, p: &mut Printer) {
- self.lhs.v.pretty(p);
+ self.lhs.pretty(p);
p.push(' ');
- self.op.v.pretty(p);
+ self.op.pretty(p);
p.push(' ');
- self.rhs.v.pretty(p);
+ self.rhs.pretty(p);
}
}
@@ -407,71 +502,83 @@ pub enum Associativity {
/// An invocation of a function: `foo(...)`, `#[foo ...]`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprCall {
+ /// The source code location.
+ pub span: Span,
/// The callee of the function.
- pub callee: SpanBox<Expr>,
+ pub callee: Box<Expr>,
/// The arguments to the function.
- pub args: Spanned<ExprArgs>,
+ pub args: ExprArgs,
}
impl Pretty for ExprCall {
fn pretty(&self, p: &mut Printer) {
- self.callee.v.pretty(p);
+ self.callee.pretty(p);
p.push('(');
- self.args.v.pretty(p);
+ self.args.pretty(p);
p.push(')');
}
}
-/// Pretty print a function template, with body or chaining when possible.
-pub fn pretty_func_template(call: &ExprCall, p: &mut Printer, chained: bool) {
- if chained {
- p.push_str(" | ");
- } else {
- p.push_str("#[");
- }
+impl ExprCall {
+ /// Pretty print a function template, with body or chaining when possible.
+ pub fn pretty_bracketed(&self, p: &mut Printer, chained: bool) {
+ if chained {
+ p.push_str(" | ");
+ } else {
+ p.push_str("#[");
+ }
- // Function name.
- call.callee.v.pretty(p);
+ // Function name.
+ self.callee.pretty(p);
- // Find out whether this can be written with a body or as a chain.
- //
- // Example: Transforms "#[v [Hi]]" => "#[v][Hi]".
- if let [head @ .., Argument::Pos(Spanned { v: Expr::Template(template), .. })] =
- call.args.v.as_slice()
- {
- // Previous arguments.
- if !head.is_empty() {
- p.push(' ');
- p.join(head, ", ", |item, p| item.pretty(p));
- }
+ let mut write_args = |items: &[Argument]| {
+ if !items.is_empty() {
+ p.push(' ');
+ p.join(items, ", ", |item, p| item.pretty(p));
+ }
+ };
+
+ match self.args.items.as_slice() {
+ // This can written as a chain.
+ //
+ // Example: Transforms "#[v][[f]]" => "#[v | f]".
+ [head @ .., Argument::Pos(Expr::Call(call))] => {
+ write_args(head);
+ call.pretty_bracketed(p, true);
+ }
- // Find out whether this can written as a chain.
- //
- // Example: Transforms "#[v][[f]]" => "#[v | f]".
- if let [Spanned { v: Node::Expr(Expr::Call(call)), .. }] = template.as_slice() {
- return pretty_func_template(call, p, true);
- } else {
- p.push_str("][");
- template.pretty(p);
+ // This can be written with a body.
+ //
+ // Example: Transforms "#[v [Hi]]" => "#[v][Hi]".
+ [head @ .., Argument::Pos(Expr::Template(template))] => {
+ write_args(head);
+ p.push(']');
+ template.pretty(p);
+ }
+
+ items => {
+ write_args(items);
+ p.push(']');
+ }
}
- } else if !call.args.v.is_empty() {
- p.push(' ');
- call.args.v.pretty(p);
}
-
- // Either end of header or end of body.
- p.push(']');
}
/// The arguments to a function: `12, draw: false`.
///
/// In case of a bracketed invocation with a body, the body is _not_
/// included in the span for the sake of clearer error messages.
-pub type ExprArgs = Vec<Argument>;
+#[derive(Debug, Clone, PartialEq)]
+pub struct ExprArgs {
+ /// The source code location.
+ pub span: Span,
+ /// The positional and named arguments.
+ pub items: Vec<Argument>,
+}
-impl Pretty for Vec<Argument> {
+impl Pretty for ExprArgs {
fn pretty(&self, p: &mut Printer) {
- p.join(self, ", ", |item, p| item.pretty(p));
+ p.join(&self.items, ", ", |item, p| item.pretty(p));
}
}
@@ -479,15 +586,25 @@ impl Pretty for Vec<Argument> {
#[derive(Debug, Clone, PartialEq)]
pub enum Argument {
/// A positional arguments.
- Pos(Spanned<Expr>),
+ Pos(Expr),
/// A named argument.
Named(Named),
}
+impl Argument {
+ /// The source code location.
+ pub fn span(&self) -> Span {
+ match self {
+ Self::Pos(expr) => expr.span(),
+ Self::Named(named) => named.span(),
+ }
+ }
+}
+
impl Pretty for Argument {
fn pretty(&self, p: &mut Printer) {
match self {
- Self::Pos(expr) => expr.v.pretty(p),
+ Self::Pos(expr) => expr.pretty(p),
Self::Named(named) => named.pretty(p),
}
}
@@ -496,19 +613,21 @@ impl Pretty for Argument {
/// A let expression: `#let x = 1`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprLet {
- /// The pattern to assign to.
- pub pat: Spanned<Ident>,
+ /// The source code location.
+ pub span: Span,
+ /// The binding to assign to.
+ pub binding: Ident,
/// The expression the pattern is initialized with.
- pub init: Option<SpanBox<Expr>>,
+ pub init: Option<Box<Expr>>,
}
impl Pretty for ExprLet {
fn pretty(&self, p: &mut Printer) {
p.push_str("#let ");
- self.pat.v.pretty(p);
+ self.binding.pretty(p);
if let Some(init) = &self.init {
p.push_str(" = ");
- init.v.pretty(p);
+ init.pretty(p);
}
}
}
@@ -516,23 +635,25 @@ impl Pretty for ExprLet {
/// An if expression: `#if x { y } #else { z }`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprIf {
+ /// The source code location.
+ pub span: Span,
/// The condition which selects the body to evaluate.
- pub condition: SpanBox<Expr>,
+ pub condition: Box<Expr>,
/// The expression to evaluate if the condition is true.
- pub if_body: SpanBox<Expr>,
+ pub if_body: Box<Expr>,
/// The expression to evaluate if the condition is false.
- pub else_body: Option<SpanBox<Expr>>,
+ pub else_body: Option<Box<Expr>>,
}
impl Pretty for ExprIf {
fn pretty(&self, p: &mut Printer) {
p.push_str("#if ");
- self.condition.v.pretty(p);
+ self.condition.pretty(p);
p.push(' ');
- self.if_body.v.pretty(p);
+ self.if_body.pretty(p);
if let Some(expr) = &self.else_body {
p.push_str(" #else ");
- expr.v.pretty(p);
+ expr.pretty(p);
}
}
}
@@ -540,22 +661,24 @@ impl Pretty for ExprIf {
/// A for expression: `#for x #in y { z }`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprFor {
+ /// The source code location.
+ pub span: Span,
/// The pattern to assign to.
- pub pat: Spanned<ForPattern>,
+ pub pattern: ForPattern,
/// The expression to iterate over.
- pub iter: SpanBox<Expr>,
+ pub iter: Box<Expr>,
/// The expression to evaluate for each iteration.
- pub body: SpanBox<Expr>,
+ pub body: Box<Expr>,
}
impl Pretty for ExprFor {
fn pretty(&self, p: &mut Printer) {
p.push_str("#for ");
- self.pat.v.pretty(p);
+ self.pattern.pretty(p);
p.push_str(" #in ");
- self.iter.v.pretty(p);
+ self.iter.pretty(p);
p.push(' ');
- self.body.v.pretty(p);
+ self.body.pretty(p);
}
}
@@ -568,6 +691,16 @@ pub enum ForPattern {
KeyValue(Ident, Ident),
}
+impl ForPattern {
+ /// The source code location.
+ pub fn span(&self) -> Span {
+ match self {
+ Self::Value(v) => v.span,
+ Self::KeyValue(k, v) => k.span.join(v.span),
+ }
+ }
+}
+
impl Pretty for ForPattern {
fn pretty(&self, p: &mut Printer) {
match self {
diff --git a/src/syntax/ident.rs b/src/syntax/ident.rs
index c4cc19bc..731a2789 100644
--- a/src/syntax/ident.rs
+++ b/src/syntax/ident.rs
@@ -2,6 +2,7 @@ use std::ops::Deref;
use unicode_xid::UnicodeXID;
+use super::Span;
use crate::pretty::{Pretty, Printer};
/// An Unicode identifier with a few extra permissible characters.
@@ -12,13 +13,21 @@ use crate::pretty::{Pretty, Printer};
///
/// [uax31]: http://www.unicode.org/reports/tr31/
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
-pub struct Ident(pub String);
+pub struct Ident {
+ /// The source code location.
+ pub span: Span,
+ /// The identifier string.
+ pub string: String,
+}
impl Ident {
/// Create a new identifier from a string checking that it is a valid.
- pub fn new(ident: impl AsRef<str> + Into<String>) -> Option<Self> {
- if is_ident(ident.as_ref()) {
- Some(Self(ident.into()))
+ pub fn new(
+ string: impl AsRef<str> + Into<String>,
+ span: impl Into<Span>,
+ ) -> Option<Self> {
+ if is_ident(string.as_ref()) {
+ Some(Self { span: span.into(), string: string.into() })
} else {
None
}
@@ -26,19 +35,13 @@ impl Ident {
/// Return a reference to the underlying string.
pub fn as_str(&self) -> &str {
- self
- }
-}
-
-impl Pretty for Ident {
- fn pretty(&self, p: &mut Printer) {
- p.push_str(self.as_str());
+ self.string.as_str()
}
}
impl AsRef<str> for Ident {
fn as_ref(&self) -> &str {
- self
+ self.as_str()
}
}
@@ -46,7 +49,13 @@ impl Deref for Ident {
type Target = str;
fn deref(&self) -> &Self::Target {
- self.0.as_str()
+ self.as_str()
+ }
+}
+
+impl Pretty for Ident {
+ fn pretty(&self, p: &mut Printer) {
+ p.push_str(self.as_str());
}
}
diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs
index 8bb6931a..a8ed2457 100644
--- a/src/syntax/mod.rs
+++ b/src/syntax/mod.rs
@@ -16,12 +16,12 @@ pub use token::*;
use crate::pretty::{Pretty, Printer};
/// The abstract syntax tree.
-pub type Tree = SpanVec<Node>;
+pub type Tree = Vec<Node>;
impl Pretty for Tree {
fn pretty(&self, p: &mut Printer) {
for node in self {
- node.v.pretty(p);
+ node.pretty(p);
}
}
}
@@ -133,9 +133,8 @@ mod tests {
roundtrip("#[v 1]");
roundtrip("#[v 1, 2][*Ok*]");
roundtrip("#[v 1 | f 2]");
- roundtrip("{#[v]}");
+ test("{#[v]}", "{v()}");
test("#[v 1, #[f 2]]", "#[v 1 | f 2]");
- test("#[v 1, 2][#[f 3]]", "#[v 1, 2 | f 3]");
// Keywords.
roundtrip("#let x = 1 + 2");
diff --git a/src/syntax/node.rs b/src/syntax/node.rs
index b4866068..fe9767a1 100644
--- a/src/syntax/node.rs
+++ b/src/syntax/node.rs
@@ -37,7 +37,7 @@ impl Pretty for Node {
Self::Expr(expr) => {
if let Expr::Call(call) = expr {
// Format function templates appropriately.
- pretty_func_template(call, p, false)
+ call.pretty_bracketed(p, false)
} else {
expr.pretty(p);
}
@@ -49,15 +49,15 @@ impl Pretty for Node {
/// A section heading: `= Introduction`.
#[derive(Debug, Clone, PartialEq)]
pub struct NodeHeading {
- /// The section depth (numer of equals signs minus 1, capped at 5).
- pub level: Spanned<u8>,
+ /// The section depth (numer of equals signs minus 1).
+ pub level: usize,
/// The contents of the heading.
pub contents: Tree,
}
impl Pretty for NodeHeading {
fn pretty(&self, p: &mut Printer) {
- for _ in 0 ..= self.level.v {
+ for _ in 0 ..= self.level {
p.push('=');
}
self.contents.pretty(p);
diff --git a/src/syntax/span.rs b/src/syntax/span.rs
index 5087dffa..65b1d637 100644
--- a/src/syntax/span.rs
+++ b/src/syntax/span.rs
@@ -19,14 +19,15 @@ impl<T> WithSpan for T {}
/// Span offsetting.
pub trait Offset {
/// Offset all spans contained in `Self` by the given position.
- fn offset(self, by: Pos) -> Self;
+ fn offset(self, by: impl Into<Pos>) -> Self;
}
/// A vector of spanned values of type `T`.
pub type SpanVec<T> = Vec<Spanned<T>>;
impl<T> Offset for SpanVec<T> {
- fn offset(mut self, by: Pos) -> Self {
+ fn offset(mut self, by: impl Into<Pos>) -> Self {
+ let by = by.into();
for spanned in &mut self {
spanned.span = spanned.span.offset(by);
}
@@ -34,9 +35,6 @@ impl<T> Offset for SpanVec<T> {
}
}
-/// A box of a spanned value of type `T`.
-pub type SpanBox<T> = Box<Spanned<T>>;
-
/// A value with the span it corresponds to in the source code.
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
@@ -90,7 +88,7 @@ impl<T> Spanned<Option<T>> {
}
impl<T> Offset for Spanned<T> {
- fn offset(self, by: Pos) -> Self {
+ fn offset(self, by: impl Into<Pos>) -> Self {
self.map_span(|span| span.offset(by))
}
}
@@ -174,7 +172,8 @@ impl Span {
}
impl Offset for Span {
- fn offset(self, by: Pos) -> Self {
+ fn offset(self, by: impl Into<Pos>) -> Self {
+ let by = by.into();
Self {
start: self.start.offset(by),
end: self.end.offset(by),
@@ -236,8 +235,8 @@ impl Pos {
}
impl Offset for Pos {
- fn offset(self, by: Self) -> Self {
- Pos(self.0 + by.0)
+ fn offset(self, by: impl Into<Pos>) -> Self {
+ Pos(self.0 + by.into().0)
}
}
diff --git a/src/syntax/token.rs b/src/syntax/token.rs
index 5e69a350..411e835f 100644
--- a/src/syntax/token.rs
+++ b/src/syntax/token.rs
@@ -123,7 +123,7 @@ pub enum Token<'s> {
/// A percentage: `50%`.
///
/// _Note_: `50%` is stored as `50.0` here, as in the corresponding
- /// [literal](super::Expr::Percent).
+ /// [literal](super::LitKind::Percent).
Percent(f64),
/// A color value: `#20d82a`.
Color(RgbaColor),
diff --git a/src/syntax/visit.rs b/src/syntax/visit.rs
index 3a289eb1..70159d2d 100644
--- a/src/syntax/visit.rs
+++ b/src/syntax/visit.rs
@@ -3,17 +3,17 @@
use super::*;
macro_rules! visit {
- ($(fn $name:ident($v:ident, $item:ident: &$ty:ty) $body:block)*) => {
+ ($(fn $name:ident($v:ident, $node:ident: &$ty:ty) $body:block)*) => {
/// Traverses the syntax tree.
pub trait Visit<'ast> {
- $(fn $name(&mut self, $item: &'ast $ty) {
- $name(self, $item);
+ $(fn $name(&mut self, $node: &'ast $ty) {
+ $name(self, $node);
})*
}
$(visit! {
@concat!("Walk a node of type [`", stringify!($ty), "`]."),
- pub fn $name<'ast, V>($v: &mut V, $item: &'ast $ty)
+ pub fn $name<'ast, V>($v: &mut V, $node: &'ast $ty)
where
V: Visit<'ast> + ?Sized
$body
@@ -27,14 +27,14 @@ macro_rules! visit {
}
visit! {
- fn visit_tree(v, item: &Tree) {
- for node in item {
- v.visit_node(&node.v);
+ fn visit_tree(v, node: &Tree) {
+ for node in node {
+ v.visit_node(&node);
}
}
- fn visit_node(v, item: &Node) {
- match item {
+ fn visit_node(v, node: &Node) {
+ match node {
Node::Strong => {}
Node::Emph => {}
Node::Space => {}
@@ -47,18 +47,10 @@ visit! {
}
}
- fn visit_expr(v, item: &Expr) {
- match item {
- Expr::None => {}
+ fn visit_expr(v, node: &Expr) {
+ match node {
+ Expr::Lit(_) => {}
Expr::Ident(_) => {}
- Expr::Bool(_) => {}
- Expr::Int(_) => {}
- Expr::Float(_) => {}
- Expr::Length(_, _) => {}
- Expr::Angle(_, _) => {}
- Expr::Percent(_) => {}
- Expr::Color(_) => {}
- Expr::Str(_) => {}
Expr::Array(e) => v.visit_array(e),
Expr::Dict(e) => v.visit_dict(e),
Expr::Template(e) => v.visit_template(e),
@@ -73,75 +65,75 @@ visit! {
}
}
- fn visit_array(v, item: &ExprArray) {
- for expr in item {
- v.visit_expr(&expr.v);
+ fn visit_array(v, node: &ExprArray) {
+ for expr in &node.items {
+ v.visit_expr(&expr);
}
}
- fn visit_dict(v, item: &ExprDict) {
- for named in item {
- v.visit_expr(&named.expr.v);
+ fn visit_dict(v, node: &ExprDict) {
+ for named in &node.items {
+ v.visit_expr(&named.expr);
}
}
- fn visit_template(v, item: &ExprTemplate) {
- v.visit_tree(item);
+ fn visit_template(v, node: &ExprTemplate) {
+ v.visit_tree(&node.tree);
}
- fn visit_group(v, item: &ExprGroup) {
- v.visit_expr(&item.v);
+ fn visit_group(v, node: &ExprGroup) {
+ v.visit_expr(&node.expr);
}
- fn visit_block(v, item: &ExprBlock) {
- for expr in &item.exprs {
- v.visit_expr(&expr.v);
+ fn visit_block(v, node: &ExprBlock) {
+ for expr in &node.exprs {
+ v.visit_expr(&expr);
}
}
- fn visit_binary(v, item: &ExprBinary) {
- v.visit_expr(&item.lhs.v);
- v.visit_expr(&item.rhs.v);
+ fn visit_binary(v, node: &ExprBinary) {
+ v.visit_expr(&node.lhs);
+ v.visit_expr(&node.rhs);
}
- fn visit_unary(v, item: &ExprUnary) {
- v.visit_expr(&item.expr.v);
+ fn visit_unary(v, node: &ExprUnary) {
+ v.visit_expr(&node.expr);
}
- fn visit_call(v, item: &ExprCall) {
- v.visit_expr(&item.callee.v);
- v.visit_args(&item.args.v);
+ fn visit_call(v, node: &ExprCall) {
+ v.visit_expr(&node.callee);
+ v.visit_args(&node.args);
}
- fn visit_args(v, item: &ExprArgs) {
- for arg in item {
+ fn visit_args(v, node: &ExprArgs) {
+ for arg in &node.items {
v.visit_arg(arg);
}
}
- fn visit_arg(v, item: &Argument) {
- match item {
- Argument::Pos(expr) => v.visit_expr(&expr.v),
- Argument::Named(named) => v.visit_expr(&named.expr.v),
+ fn visit_arg(v, node: &Argument) {
+ match node {
+ Argument::Pos(expr) => v.visit_expr(&expr),
+ Argument::Named(named) => v.visit_expr(&named.expr),
}
}
- fn visit_let(v, item: &ExprLet) {
- if let Some(init) = &item.init {
- v.visit_expr(&init.v);
+ fn visit_let(v, node: &ExprLet) {
+ if let Some(init) = &node.init {
+ v.visit_expr(&init);
}
}
- fn visit_if(v, item: &ExprIf) {
- v.visit_expr(&item.condition.v);
- v.visit_expr(&item.if_body.v);
- if let Some(body) = &item.else_body {
- v.visit_expr(&body.v);
+ fn visit_if(v, node: &ExprIf) {
+ v.visit_expr(&node.condition);
+ v.visit_expr(&node.if_body);
+ if let Some(body) = &node.else_body {
+ v.visit_expr(&body);
}
}
- fn visit_for(v, item: &ExprFor) {
- v.visit_expr(&item.iter.v);
- v.visit_expr(&item.body.v);
+ fn visit_for(v, node: &ExprFor) {
+ v.visit_expr(&node.iter);
+ v.visit_expr(&node.body);
}
}