summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-01-17 16:18:36 +0100
committerLaurenz <laurmaedje@gmail.com>2021-01-17 16:18:36 +0100
commitdd246e5bc944f90be7ba2981c2b73520a4bfbf45 (patch)
tree0fee09e170431ba88501ee165743a4d7010e6a84
parent29be90bf95f2ea10c435e7b02f8c26626b956417 (diff)
Spans for group and block contents 📐
-rw-r--r--src/eval/mod.rs48
-rw-r--r--src/parse/collection.rs2
-rw-r--r--src/parse/mod.rs2
-rw-r--r--src/syntax/expr.rs92
-rw-r--r--tests/lang/typ/bracket-call.typ2
-rw-r--r--tests/lang/typ/expressions.typ7
-rw-r--r--tests/lang/typ/let.typ2
-rw-r--r--tests/lang/typ/values.typ8
8 files changed, 86 insertions, 77 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index efc77f69..c7b87aef 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -172,14 +172,14 @@ impl Eval for Spanned<&Expr> {
Expr::Percent(v) => Value::Relative(Relative::new(v / 100.0)),
Expr::Color(v) => Value::Color(Color::Rgba(*v)),
Expr::Str(v) => Value::Str(v.clone()),
- Expr::Call(v) => v.with_span(self.span).eval(ctx),
- Expr::Unary(v) => v.with_span(self.span).eval(ctx),
- Expr::Binary(v) => v.with_span(self.span).eval(ctx),
Expr::Array(v) => Value::Array(v.with_span(self.span).eval(ctx)),
Expr::Dict(v) => Value::Dict(v.with_span(self.span).eval(ctx)),
Expr::Template(v) => Value::Template(v.clone()),
- Expr::Group(v) => v.as_ref().with_span(self.span).eval(ctx),
- Expr::Block(v) => v.as_ref().with_span(self.span).eval(ctx),
+ Expr::Call(v) => v.with_span(self.span).eval(ctx),
+ Expr::Unary(v) => v.with_span(self.span).eval(ctx),
+ Expr::Binary(v) => v.with_span(self.span).eval(ctx),
+ Expr::Group(v) => v.as_ref().eval(ctx),
+ Expr::Block(v) => v.as_ref().eval(ctx),
Expr::Let(v) => {
let value = match &v.expr {
Some(expr) => expr.as_ref().eval(ctx),
@@ -192,6 +192,25 @@ impl Eval for Spanned<&Expr> {
}
}
+impl Eval for Spanned<&ExprArray> {
+ type Output = ValueArray;
+
+ fn eval(self, ctx: &mut EvalContext) -> Self::Output {
+ self.v.iter().map(|expr| expr.as_ref().eval(ctx)).collect()
+ }
+}
+
+impl Eval for Spanned<&ExprDict> {
+ type Output = ValueDict;
+
+ fn eval(self, ctx: &mut EvalContext) -> Self::Output {
+ self.v
+ .iter()
+ .map(|Named { name, expr }| (name.v.0.clone(), expr.as_ref().eval(ctx)))
+ .collect()
+ }
+}
+
impl Eval for Spanned<&ExprUnary> {
type Output = Value;
@@ -230,22 +249,3 @@ impl Eval for Spanned<&ExprBinary> {
}
}
}
-
-impl Eval for Spanned<&ExprArray> {
- type Output = ValueArray;
-
- fn eval(self, ctx: &mut EvalContext) -> Self::Output {
- self.v.iter().map(|expr| expr.as_ref().eval(ctx)).collect()
- }
-}
-
-impl Eval for Spanned<&ExprDict> {
- type Output = ValueDict;
-
- fn eval(self, ctx: &mut EvalContext) -> Self::Output {
- self.v
- .iter()
- .map(|Named { name, expr }| (name.v.0.clone(), expr.as_ref().eval(ctx)))
- .collect()
- }
-}
diff --git a/src/parse/collection.rs b/src/parse/collection.rs
index ca05b998..9addcef0 100644
--- a/src/parse/collection.rs
+++ b/src/parse/collection.rs
@@ -93,7 +93,7 @@ impl State {
fn into_expr(self) -> Expr {
match self {
Self::Unknown => Expr::Array(vec![]),
- Self::Expr(expr) => Expr::Group(Box::new(expr.v)),
+ Self::Expr(expr) => Expr::Group(Box::new(expr)),
Self::Array(array) => Expr::Array(array),
Self::Dict(dict) => Expr::Dict(dict),
}
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 7c92185d..0a656366 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -222,7 +222,7 @@ fn bracket_body(p: &mut Parser) -> Tree {
fn block(p: &mut Parser) -> Option<Expr> {
p.push_mode(TokenMode::Code);
p.start_group(Group::Brace);
- let expr = expr(p);
+ let expr = p.span_if(expr);
while !p.eof() {
p.diag_unexpected();
}
diff --git a/src/syntax/expr.rs b/src/syntax/expr.rs
index 79533918..79713cf1 100644
--- a/src/syntax/expr.rs
+++ b/src/syntax/expr.rs
@@ -28,22 +28,22 @@ pub enum Expr {
Color(RgbaColor),
/// A string literal: `"hello!"`.
Str(String),
- /// An invocation of a function: `[foo ...]`, `foo(...)`.
- Call(ExprCall),
- /// A unary operation: `-x`.
- Unary(ExprUnary),
- /// A binary operation: `a + b`, `a / b`.
- Binary(ExprBinary),
/// An array expression: `(1, "hi", 12cm)`.
Array(ExprArray),
/// A dictionary expression: `(color: #f79143, pattern: dashed)`.
Dict(ExprDict),
/// A template expression: `[*Hi* there!]`.
Template(ExprTemplate),
+ /// A unary operation: `-x`.
+ Unary(ExprUnary),
+ /// A binary operation: `a + b`, `a / b`.
+ Binary(ExprBinary),
+ /// An invocation of a function: `[foo ...]`, `foo(...)`.
+ Call(ExprCall),
/// A grouped expression: `(1 + 2)`.
- Group(Box<Expr>),
+ Group(ExprGroup),
/// A block expression: `{1 + 2}`.
- Block(Box<Expr>),
+ Block(ExprBlock),
/// A let expression: `let x = 1`.
Let(ExprLet),
}
@@ -61,9 +61,6 @@ impl Pretty for Expr {
Self::Percent(v) => write!(p, "{}%", v).unwrap(),
Self::Color(v) => write!(p, "{}", v).unwrap(),
Self::Str(v) => write!(p, "{:?}", &v).unwrap(),
- Self::Call(v) => v.pretty(p),
- Self::Unary(v) => v.pretty(p),
- Self::Binary(v) => v.pretty(p),
Self::Array(v) => v.pretty(p),
Self::Dict(v) => v.pretty(p),
Self::Template(v) => {
@@ -71,14 +68,17 @@ impl Pretty for Expr {
v.pretty(p);
p.push_str("]");
}
+ Self::Unary(v) => v.pretty(p),
+ Self::Binary(v) => v.pretty(p),
+ Self::Call(v) => v.pretty(p),
Self::Group(v) => {
p.push_str("(");
- v.pretty(p);
+ v.v.pretty(p);
p.push_str(")");
}
Self::Block(v) => {
p.push_str("{");
- v.pretty(p);
+ v.v.pretty(p);
p.push_str("}");
}
Self::Let(v) => v.pretty(p),
@@ -86,6 +86,38 @@ impl Pretty for Expr {
}
}
+/// An array expression: `(1, "hi", 12cm)`.
+pub type ExprArray = SpanVec<Expr>;
+
+impl Pretty for ExprArray {
+ fn pretty(&self, p: &mut Printer) {
+ p.push_str("(");
+ p.join(self, ", ", |item, p| item.v.pretty(p));
+ if self.len() == 1 {
+ p.push_str(",");
+ }
+ p.push_str(")");
+ }
+}
+
+/// A dictionary expression: `(color: #f79143, pattern: dashed)`.
+pub type ExprDict = Vec<Named>;
+
+impl Pretty for ExprDict {
+ fn pretty(&self, p: &mut Printer) {
+ p.push_str("(");
+ if self.is_empty() {
+ p.push_str(":");
+ } else {
+ p.join(self, ", ", |named, p| named.pretty(p));
+ }
+ p.push_str(")");
+ }
+}
+
+/// A template expression: `[*Hi* there!]`.
+pub type ExprTemplate = Tree;
+
/// An invocation of a function: `[foo ...]`, `foo(...)`.
#[derive(Debug, Clone, PartialEq)]
pub struct ExprCall {
@@ -271,37 +303,11 @@ impl Pretty for BinOp {
}
}
-/// An array expression: `(1, "hi", 12cm)`.
-pub type ExprArray = SpanVec<Expr>;
+/// A grouped expression: `(1 + 2)`.
+pub type ExprGroup = Box<Spanned<Expr>>;
-impl Pretty for ExprArray {
- fn pretty(&self, p: &mut Printer) {
- p.push_str("(");
- p.join(self, ", ", |item, p| item.v.pretty(p));
- if self.len() == 1 {
- p.push_str(",");
- }
- p.push_str(")");
- }
-}
-
-/// A dictionary expression: `(color: #f79143, pattern: dashed)`.
-pub type ExprDict = Vec<Named>;
-
-impl Pretty for ExprDict {
- fn pretty(&self, p: &mut Printer) {
- p.push_str("(");
- if self.is_empty() {
- p.push_str(":");
- } else {
- p.join(self, ", ", |named, p| named.pretty(p));
- }
- p.push_str(")");
- }
-}
-
-/// A template expression: `[*Hi* there!]`.
-pub type ExprTemplate = Tree;
+/// A block expression: `{1 + 2}`.
+pub type ExprBlock = Box<Spanned<Expr>>;
/// A let expression: `let x = 1`.
#[derive(Debug, Clone, PartialEq)]
diff --git a/tests/lang/typ/bracket-call.typ b/tests/lang/typ/bracket-call.typ
index 79667e61..7bbaeac1 100644
--- a/tests/lang/typ/bracket-call.typ
+++ b/tests/lang/typ/bracket-call.typ
@@ -71,7 +71,7 @@
---
// Ref: false
// Error: 2:2-2:3 a value of type string is not callable
-#let x = "string";
+#let x = "string"
[x]
// Error: 1:2-1:3 expected function name, found hex value
diff --git a/tests/lang/typ/expressions.typ b/tests/lang/typ/expressions.typ
index 74150c4b..97aa8d81 100644
--- a/tests/lang/typ/expressions.typ
+++ b/tests/lang/typ/expressions.typ
@@ -1,7 +1,7 @@
// Ref: false
-#let a = 2;
-#let b = 4;
+#let a = 2
+#let b = 4
// Paren call.
[eq f(1), "f(1)"]
@@ -30,6 +30,9 @@
[eq (2), 2]
[eq (1+2)*3, 9]
+// Error: 1:3-1:10 cannot add integer and string
+{(1 + "2")}
+
// Confusion with floating-point literal.
[eq 1e+2-1e-2, 99.99]
diff --git a/tests/lang/typ/let.typ b/tests/lang/typ/let.typ
index a966f243..28fc6649 100644
--- a/tests/lang/typ/let.typ
+++ b/tests/lang/typ/let.typ
@@ -5,7 +5,7 @@
[eq x, none]
// Initialized with `1`.
-#let y = 1;
+#let y = 1
[eq y, 1]
// Multiple bindings in one line.
diff --git a/tests/lang/typ/values.typ b/tests/lang/typ/values.typ
index 51d0bd17..cab63044 100644
--- a/tests/lang/typ/values.typ
+++ b/tests/lang/typ/values.typ
@@ -1,15 +1,15 @@
// Test representation of values in the document.
-#let name = "Typst";
-#let ke-bab = "Kebab!";
-#let α = "Alpha";
+#let name = "Typst"
+#let ke-bab = "Kebab!"
+#let α = "Alpha"
// Variables.
{name} \
{ke-bab} \
{α} \
-// Error: 1:1-1:4 unknown variable
+// Error: 1:2-1:3 unknown variable
{_}
// Literal values.