mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Parse show
and wrap
expressions
This commit is contained in:
parent
2d97d406ac
commit
76b1d4a93f
@ -76,7 +76,10 @@ pub trait At<T> {
|
|||||||
fn at(self, span: Span) -> TypResult<T>;
|
fn at(self, span: Span) -> TypResult<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> At<T> for StrResult<T> {
|
impl<T, S> At<T> for Result<T, S>
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
fn at(self, span: Span) -> TypResult<T> {
|
fn at(self, span: Span) -> TypResult<T> {
|
||||||
self.map_err(|message| Error::boxed(span, message))
|
self.map_err(|message| Error::boxed(span, message))
|
||||||
}
|
}
|
||||||
|
@ -383,6 +383,8 @@ impl Eval for Expr {
|
|||||||
Self::Binary(v) => v.eval(ctx),
|
Self::Binary(v) => v.eval(ctx),
|
||||||
Self::Let(v) => v.eval(ctx),
|
Self::Let(v) => v.eval(ctx),
|
||||||
Self::Set(v) => v.eval(ctx),
|
Self::Set(v) => v.eval(ctx),
|
||||||
|
Self::Show(v) => v.eval(ctx),
|
||||||
|
Self::Wrap(v) => v.eval(ctx),
|
||||||
Self::If(v) => v.eval(ctx),
|
Self::If(v) => v.eval(ctx),
|
||||||
Self::While(v) => v.eval(ctx),
|
Self::While(v) => v.eval(ctx),
|
||||||
Self::For(v) => v.eval(ctx),
|
Self::For(v) => v.eval(ctx),
|
||||||
@ -759,6 +761,22 @@ impl Eval for SetExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eval for ShowExpr {
|
||||||
|
type Output = Value;
|
||||||
|
|
||||||
|
fn eval(&self, _: &mut EvalContext) -> TypResult<Self::Output> {
|
||||||
|
Err("show rules are not yet implemented").at(self.span())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for WrapExpr {
|
||||||
|
type Output = Value;
|
||||||
|
|
||||||
|
fn eval(&self, _: &mut EvalContext) -> TypResult<Self::Output> {
|
||||||
|
Err("wrap is not yet implemented").at(self.span())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Eval for IfExpr {
|
impl Eval for IfExpr {
|
||||||
type Output = Value;
|
type Output = Value;
|
||||||
|
|
||||||
|
@ -466,10 +466,13 @@ impl NodeKind {
|
|||||||
// how far the expression would go.
|
// how far the expression would go.
|
||||||
Self::Let
|
Self::Let
|
||||||
| Self::Set
|
| Self::Set
|
||||||
|
| Self::Show
|
||||||
|
| Self::Wrap
|
||||||
| Self::If
|
| Self::If
|
||||||
| Self::Else
|
| Self::Else
|
||||||
| Self::For
|
| Self::For
|
||||||
| Self::In
|
| Self::In
|
||||||
|
| Self::As
|
||||||
| Self::While
|
| Self::While
|
||||||
| Self::Break
|
| Self::Break
|
||||||
| Self::Continue
|
| Self::Continue
|
||||||
@ -542,6 +545,8 @@ impl NodeKind {
|
|||||||
| Self::IfExpr
|
| Self::IfExpr
|
||||||
| Self::LetExpr
|
| Self::LetExpr
|
||||||
| Self::SetExpr
|
| Self::SetExpr
|
||||||
|
| Self::ShowExpr
|
||||||
|
| Self::WrapExpr
|
||||||
| Self::ImportExpr
|
| Self::ImportExpr
|
||||||
| Self::IncludeExpr => SuccessionRule::AtomicPrimary,
|
| Self::IncludeExpr => SuccessionRule::AtomicPrimary,
|
||||||
|
|
||||||
|
@ -208,6 +208,8 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
|
|||||||
NodeKind::Ident(_)
|
NodeKind::Ident(_)
|
||||||
| NodeKind::Let
|
| NodeKind::Let
|
||||||
| NodeKind::Set
|
| NodeKind::Set
|
||||||
|
| NodeKind::Show
|
||||||
|
| NodeKind::Wrap
|
||||||
| NodeKind::If
|
| NodeKind::If
|
||||||
| NodeKind::While
|
| NodeKind::While
|
||||||
| NodeKind::For
|
| NodeKind::For
|
||||||
@ -275,7 +277,14 @@ fn enum_node(p: &mut Parser, at_start: bool) {
|
|||||||
/// Parse an expression within markup mode.
|
/// Parse an expression within markup mode.
|
||||||
fn markup_expr(p: &mut Parser) {
|
fn markup_expr(p: &mut Parser) {
|
||||||
if let Some(token) = p.peek() {
|
if let Some(token) = p.peek() {
|
||||||
let stmt = matches!(token, NodeKind::Let | NodeKind::Set | NodeKind::Import);
|
let stmt = matches!(
|
||||||
|
token,
|
||||||
|
NodeKind::Let
|
||||||
|
| NodeKind::Set
|
||||||
|
| NodeKind::Show
|
||||||
|
| NodeKind::Wrap
|
||||||
|
| NodeKind::Import
|
||||||
|
);
|
||||||
let group = if stmt { Group::Stmt } else { Group::Expr };
|
let group = if stmt { Group::Stmt } else { Group::Expr };
|
||||||
|
|
||||||
p.start_group(group);
|
p.start_group(group);
|
||||||
@ -388,6 +397,8 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
|
|||||||
// Keywords.
|
// Keywords.
|
||||||
Some(NodeKind::Let) => let_expr(p),
|
Some(NodeKind::Let) => let_expr(p),
|
||||||
Some(NodeKind::Set) => set_expr(p),
|
Some(NodeKind::Set) => set_expr(p),
|
||||||
|
Some(NodeKind::Show) => show_expr(p),
|
||||||
|
Some(NodeKind::Wrap) => wrap_expr(p),
|
||||||
Some(NodeKind::If) => if_expr(p),
|
Some(NodeKind::If) => if_expr(p),
|
||||||
Some(NodeKind::While) => while_expr(p),
|
Some(NodeKind::While) => while_expr(p),
|
||||||
Some(NodeKind::For) => for_expr(p),
|
Some(NodeKind::For) => for_expr(p),
|
||||||
@ -714,6 +725,26 @@ fn set_expr(p: &mut Parser) -> ParseResult {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a show expression.
|
||||||
|
fn show_expr(p: &mut Parser) -> ParseResult {
|
||||||
|
p.perform(NodeKind::ShowExpr, |p| {
|
||||||
|
p.eat_assert(&NodeKind::Show);
|
||||||
|
expr(p)?;
|
||||||
|
p.eat_expect(&NodeKind::As)?;
|
||||||
|
expr(p)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a wrap expression.
|
||||||
|
fn wrap_expr(p: &mut Parser) -> ParseResult {
|
||||||
|
p.perform(NodeKind::WrapExpr, |p| {
|
||||||
|
p.eat_assert(&NodeKind::Wrap);
|
||||||
|
ident(p)?;
|
||||||
|
p.eat_expect(&NodeKind::In)?;
|
||||||
|
expr(p)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse an if expresion.
|
/// Parse an if expresion.
|
||||||
fn if_expr(p: &mut Parser) -> ParseResult {
|
fn if_expr(p: &mut Parser) -> ParseResult {
|
||||||
p.perform(NodeKind::IfExpr, |p| {
|
p.perform(NodeKind::IfExpr, |p| {
|
||||||
|
@ -540,10 +540,13 @@ fn keyword(ident: &str) -> Option<NodeKind> {
|
|||||||
"with" => NodeKind::With,
|
"with" => NodeKind::With,
|
||||||
"let" => NodeKind::Let,
|
"let" => NodeKind::Let,
|
||||||
"set" => NodeKind::Set,
|
"set" => NodeKind::Set,
|
||||||
|
"show" => NodeKind::Show,
|
||||||
|
"wrap" => NodeKind::Wrap,
|
||||||
"if" => NodeKind::If,
|
"if" => NodeKind::If,
|
||||||
"else" => NodeKind::Else,
|
"else" => NodeKind::Else,
|
||||||
"for" => NodeKind::For,
|
"for" => NodeKind::For,
|
||||||
"in" => NodeKind::In,
|
"in" => NodeKind::In,
|
||||||
|
"as" => NodeKind::As,
|
||||||
"while" => NodeKind::While,
|
"while" => NodeKind::While,
|
||||||
"break" => NodeKind::Break,
|
"break" => NodeKind::Break,
|
||||||
"continue" => NodeKind::Continue,
|
"continue" => NodeKind::Continue,
|
||||||
|
@ -217,6 +217,10 @@ pub enum Expr {
|
|||||||
Let(LetExpr),
|
Let(LetExpr),
|
||||||
/// A set expression: `set text(...)`.
|
/// A set expression: `set text(...)`.
|
||||||
Set(SetExpr),
|
Set(SetExpr),
|
||||||
|
/// A show expression: `show heading(body) as [*{body}*]`.
|
||||||
|
Show(ShowExpr),
|
||||||
|
/// A wrap expression: `wrap body in columns(2, body)`.
|
||||||
|
Wrap(WrapExpr),
|
||||||
/// An if-else expression: `if x { y } else { z }`.
|
/// An if-else expression: `if x { y } else { z }`.
|
||||||
If(IfExpr),
|
If(IfExpr),
|
||||||
/// A while loop expression: `while x { y }`.
|
/// A while loop expression: `while x { y }`.
|
||||||
@ -245,6 +249,8 @@ impl TypedNode for Expr {
|
|||||||
NodeKind::WithExpr => node.cast().map(Self::With),
|
NodeKind::WithExpr => node.cast().map(Self::With),
|
||||||
NodeKind::LetExpr => node.cast().map(Self::Let),
|
NodeKind::LetExpr => node.cast().map(Self::Let),
|
||||||
NodeKind::SetExpr => node.cast().map(Self::Set),
|
NodeKind::SetExpr => node.cast().map(Self::Set),
|
||||||
|
NodeKind::ShowExpr => node.cast().map(Self::Show),
|
||||||
|
NodeKind::WrapExpr => node.cast().map(Self::Wrap),
|
||||||
NodeKind::IfExpr => node.cast().map(Self::If),
|
NodeKind::IfExpr => node.cast().map(Self::If),
|
||||||
NodeKind::WhileExpr => node.cast().map(Self::While),
|
NodeKind::WhileExpr => node.cast().map(Self::While),
|
||||||
NodeKind::ForExpr => node.cast().map(Self::For),
|
NodeKind::ForExpr => node.cast().map(Self::For),
|
||||||
@ -270,6 +276,8 @@ impl TypedNode for Expr {
|
|||||||
Self::With(v) => v.as_red(),
|
Self::With(v) => v.as_red(),
|
||||||
Self::Let(v) => v.as_red(),
|
Self::Let(v) => v.as_red(),
|
||||||
Self::Set(v) => v.as_red(),
|
Self::Set(v) => v.as_red(),
|
||||||
|
Self::Show(v) => v.as_red(),
|
||||||
|
Self::Wrap(v) => v.as_red(),
|
||||||
Self::If(v) => v.as_red(),
|
Self::If(v) => v.as_red(),
|
||||||
Self::While(v) => v.as_red(),
|
Self::While(v) => v.as_red(),
|
||||||
Self::For(v) => v.as_red(),
|
Self::For(v) => v.as_red(),
|
||||||
@ -288,6 +296,8 @@ impl Expr {
|
|||||||
| Self::Call(_)
|
| Self::Call(_)
|
||||||
| Self::Let(_)
|
| Self::Let(_)
|
||||||
| Self::Set(_)
|
| Self::Set(_)
|
||||||
|
| Self::Show(_)
|
||||||
|
| Self::Wrap(_)
|
||||||
| Self::If(_)
|
| Self::If(_)
|
||||||
| Self::While(_)
|
| Self::While(_)
|
||||||
| Self::For(_)
|
| Self::For(_)
|
||||||
@ -913,6 +923,40 @@ impl IncludeExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node! {
|
||||||
|
/// A show expression: `show heading(body) as [*{body}*]`.
|
||||||
|
ShowExpr
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShowExpr {
|
||||||
|
/// The pattern that decides which node's appearence to redefine.
|
||||||
|
pub fn pattern(&self) -> Expr {
|
||||||
|
self.0.cast_first_child().expect("show expression is missing pattern")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The expression that defines the node's appearence.
|
||||||
|
pub fn body(&self) -> Expr {
|
||||||
|
self.0.cast_last_child().expect("show expression is missing body")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node! {
|
||||||
|
/// A wrap expression: wrap body in columns(2, body)`.
|
||||||
|
WrapExpr
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WrapExpr {
|
||||||
|
/// The binding to assign the remaining markup to.
|
||||||
|
pub fn binding(&self) -> Ident {
|
||||||
|
self.0.cast_first_child().expect("wrap expression is missing binding")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The expression to evaluate.
|
||||||
|
pub fn body(&self) -> Expr {
|
||||||
|
self.0.cast_last_child().expect("wrap expression is missing body")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// An if-else expression: `if x { y } else { z }`.
|
/// An if-else expression: `if x { y } else { z }`.
|
||||||
IfExpr
|
IfExpr
|
||||||
|
@ -136,11 +136,14 @@ impl Category {
|
|||||||
NodeKind::With => Some(Category::Keyword),
|
NodeKind::With => Some(Category::Keyword),
|
||||||
NodeKind::Let => Some(Category::Keyword),
|
NodeKind::Let => Some(Category::Keyword),
|
||||||
NodeKind::Set => Some(Category::Keyword),
|
NodeKind::Set => Some(Category::Keyword),
|
||||||
|
NodeKind::Show => Some(Category::Keyword),
|
||||||
|
NodeKind::Wrap => Some(Category::Keyword),
|
||||||
NodeKind::If => Some(Category::Keyword),
|
NodeKind::If => Some(Category::Keyword),
|
||||||
NodeKind::Else => Some(Category::Keyword),
|
NodeKind::Else => Some(Category::Keyword),
|
||||||
NodeKind::While => Some(Category::Keyword),
|
NodeKind::While => Some(Category::Keyword),
|
||||||
NodeKind::For => Some(Category::Keyword),
|
NodeKind::For => Some(Category::Keyword),
|
||||||
NodeKind::In => Some(Category::Keyword),
|
NodeKind::In => Some(Category::Keyword),
|
||||||
|
NodeKind::As => Some(Category::Keyword),
|
||||||
NodeKind::Break => Some(Category::Keyword),
|
NodeKind::Break => Some(Category::Keyword),
|
||||||
NodeKind::Continue => Some(Category::Keyword),
|
NodeKind::Continue => Some(Category::Keyword),
|
||||||
NodeKind::Return => Some(Category::Keyword),
|
NodeKind::Return => Some(Category::Keyword),
|
||||||
@ -211,6 +214,8 @@ impl Category {
|
|||||||
NodeKind::WithExpr => None,
|
NodeKind::WithExpr => None,
|
||||||
NodeKind::LetExpr => None,
|
NodeKind::LetExpr => None,
|
||||||
NodeKind::SetExpr => None,
|
NodeKind::SetExpr => None,
|
||||||
|
NodeKind::ShowExpr => None,
|
||||||
|
NodeKind::WrapExpr => None,
|
||||||
NodeKind::IfExpr => None,
|
NodeKind::IfExpr => None,
|
||||||
NodeKind::WhileExpr => None,
|
NodeKind::WhileExpr => None,
|
||||||
NodeKind::ForExpr => None,
|
NodeKind::ForExpr => None,
|
||||||
|
@ -550,6 +550,10 @@ pub enum NodeKind {
|
|||||||
Let,
|
Let,
|
||||||
/// The `set` keyword.
|
/// The `set` keyword.
|
||||||
Set,
|
Set,
|
||||||
|
/// The `show` keyword.
|
||||||
|
Show,
|
||||||
|
/// The `wrap` keyword.
|
||||||
|
Wrap,
|
||||||
/// The `if` keyword.
|
/// The `if` keyword.
|
||||||
If,
|
If,
|
||||||
/// The `else` keyword.
|
/// The `else` keyword.
|
||||||
@ -572,6 +576,8 @@ pub enum NodeKind {
|
|||||||
Include,
|
Include,
|
||||||
/// The `from` keyword.
|
/// The `from` keyword.
|
||||||
From,
|
From,
|
||||||
|
/// The `as` keyword.
|
||||||
|
As,
|
||||||
/// Template markup of which all lines must start in some column.
|
/// Template markup of which all lines must start in some column.
|
||||||
Markup(usize),
|
Markup(usize),
|
||||||
/// One or more whitespace characters.
|
/// One or more whitespace characters.
|
||||||
@ -665,6 +671,10 @@ pub enum NodeKind {
|
|||||||
LetExpr,
|
LetExpr,
|
||||||
/// A set expression: `set text(...)`.
|
/// A set expression: `set text(...)`.
|
||||||
SetExpr,
|
SetExpr,
|
||||||
|
/// A show expression: `show heading(body) as [*{body}*]`.
|
||||||
|
ShowExpr,
|
||||||
|
/// A wrap expression: `wrap body in columns(2, body)`.
|
||||||
|
WrapExpr,
|
||||||
/// An if-else expression: `if x { y } else { z }`.
|
/// An if-else expression: `if x { y } else { z }`.
|
||||||
IfExpr,
|
IfExpr,
|
||||||
/// A while loop expression: `while x { ... }`.
|
/// A while loop expression: `while x { ... }`.
|
||||||
@ -822,10 +832,13 @@ impl NodeKind {
|
|||||||
Self::Auto => "`auto`",
|
Self::Auto => "`auto`",
|
||||||
Self::Let => "keyword `let`",
|
Self::Let => "keyword `let`",
|
||||||
Self::Set => "keyword `set`",
|
Self::Set => "keyword `set`",
|
||||||
|
Self::Show => "keyword `show`",
|
||||||
|
Self::Wrap => "keyword `wrap`",
|
||||||
Self::If => "keyword `if`",
|
Self::If => "keyword `if`",
|
||||||
Self::Else => "keyword `else`",
|
Self::Else => "keyword `else`",
|
||||||
Self::For => "keyword `for`",
|
Self::For => "keyword `for`",
|
||||||
Self::In => "keyword `in`",
|
Self::In => "keyword `in`",
|
||||||
|
Self::As => "keyword `as`",
|
||||||
Self::While => "keyword `while`",
|
Self::While => "keyword `while`",
|
||||||
Self::Break => "keyword `break`",
|
Self::Break => "keyword `break`",
|
||||||
Self::Continue => "keyword `continue`",
|
Self::Continue => "keyword `continue`",
|
||||||
@ -875,6 +888,8 @@ impl NodeKind {
|
|||||||
Self::WithExpr => "`with` expression",
|
Self::WithExpr => "`with` expression",
|
||||||
Self::LetExpr => "`let` expression",
|
Self::LetExpr => "`let` expression",
|
||||||
Self::SetExpr => "`set` expression",
|
Self::SetExpr => "`set` expression",
|
||||||
|
Self::ShowExpr => "`show` expression",
|
||||||
|
Self::WrapExpr => "`wrap` expression",
|
||||||
Self::IfExpr => "`if` expression",
|
Self::IfExpr => "`if` expression",
|
||||||
Self::WhileExpr => "while-loop expression",
|
Self::WhileExpr => "while-loop expression",
|
||||||
Self::ForExpr => "for-loop expression",
|
Self::ForExpr => "for-loop expression",
|
||||||
|
@ -227,6 +227,8 @@ impl Pretty for Expr {
|
|||||||
Self::With(v) => v.pretty(p),
|
Self::With(v) => v.pretty(p),
|
||||||
Self::Let(v) => v.pretty(p),
|
Self::Let(v) => v.pretty(p),
|
||||||
Self::Set(v) => v.pretty(p),
|
Self::Set(v) => v.pretty(p),
|
||||||
|
Self::Show(v) => v.pretty(p),
|
||||||
|
Self::Wrap(v) => v.pretty(p),
|
||||||
Self::If(v) => v.pretty(p),
|
Self::If(v) => v.pretty(p),
|
||||||
Self::While(v) => v.pretty(p),
|
Self::While(v) => v.pretty(p),
|
||||||
Self::For(v) => v.pretty(p),
|
Self::For(v) => v.pretty(p),
|
||||||
@ -456,6 +458,24 @@ impl Pretty for SetExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Pretty for ShowExpr {
|
||||||
|
fn pretty(&self, p: &mut Printer) {
|
||||||
|
p.push_str("show ");
|
||||||
|
self.pattern().pretty(p);
|
||||||
|
p.push_str(" as ");
|
||||||
|
self.body().pretty(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pretty for WrapExpr {
|
||||||
|
fn pretty(&self, p: &mut Printer) {
|
||||||
|
p.push_str("wrap ");
|
||||||
|
self.binding().pretty(p);
|
||||||
|
p.push_str(" in ");
|
||||||
|
self.body().pretty(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Pretty for IfExpr {
|
impl Pretty for IfExpr {
|
||||||
fn pretty(&self, p: &mut Printer) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
p.push_str("if ");
|
p.push_str("if ");
|
||||||
@ -652,6 +672,8 @@ mod tests {
|
|||||||
roundtrip("#let x = 1 + 2");
|
roundtrip("#let x = 1 + 2");
|
||||||
roundtrip("#let f(x) = y");
|
roundtrip("#let f(x) = y");
|
||||||
roundtrip("#set text(size: 12pt)");
|
roundtrip("#set text(size: 12pt)");
|
||||||
|
roundtrip("#show heading(body) as [*{body}*]");
|
||||||
|
roundtrip("#wrap body in columns(2, body)");
|
||||||
roundtrip("#if x [y] else [z]");
|
roundtrip("#if x [y] else [z]");
|
||||||
roundtrip("#if x {} else if y {} else {}");
|
roundtrip("#if x {} else if y {} else {}");
|
||||||
roundtrip("#while x {y}");
|
roundtrip("#while x {y}");
|
||||||
|
6
tests/typ/style/show.typ
Normal file
6
tests/typ/style/show.typ
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Test show rules.
|
||||||
|
// Ref: false
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 1-34 show rules are not yet implemented
|
||||||
|
#show heading(body) as [*{body}*]
|
6
tests/typ/style/wrap.typ
Normal file
6
tests/typ/style/wrap.typ
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Test wrap.
|
||||||
|
// Ref: false
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 1-31 wrap is not yet implemented
|
||||||
|
#wrap body in columns(2, body)
|
Loading…
x
Reference in New Issue
Block a user