mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Optimize memory sizes
This commit is contained in:
parent
6a3385e4e7
commit
f6814b7732
@ -177,6 +177,33 @@ impl Eval for Expr {
|
|||||||
type Output = Value;
|
type Output = Value;
|
||||||
|
|
||||||
fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> {
|
fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> {
|
||||||
|
match self {
|
||||||
|
Self::Ident(v) => v.eval(ctx),
|
||||||
|
Self::Lit(v) => v.eval(ctx),
|
||||||
|
Self::Array(v) => v.eval(ctx).map(Value::Array),
|
||||||
|
Self::Dict(v) => v.eval(ctx).map(Value::Dict),
|
||||||
|
Self::Template(v) => v.eval(ctx).map(Value::Template),
|
||||||
|
Self::Group(v) => v.eval(ctx),
|
||||||
|
Self::Block(v) => v.eval(ctx),
|
||||||
|
Self::Call(v) => v.eval(ctx),
|
||||||
|
Self::Closure(v) => v.eval(ctx),
|
||||||
|
Self::With(v) => v.eval(ctx),
|
||||||
|
Self::Unary(v) => v.eval(ctx),
|
||||||
|
Self::Binary(v) => v.eval(ctx),
|
||||||
|
Self::Let(v) => v.eval(ctx),
|
||||||
|
Self::If(v) => v.eval(ctx),
|
||||||
|
Self::While(v) => v.eval(ctx),
|
||||||
|
Self::For(v) => v.eval(ctx),
|
||||||
|
Self::Import(v) => v.eval(ctx),
|
||||||
|
Self::Include(v) => v.eval(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for Lit {
|
||||||
|
type Output = Value;
|
||||||
|
|
||||||
|
fn eval(&self, _: &mut EvalContext) -> TypResult<Self::Output> {
|
||||||
Ok(match *self {
|
Ok(match *self {
|
||||||
Self::None(_) => Value::None,
|
Self::None(_) => Value::None,
|
||||||
Self::Auto(_) => Value::Auto,
|
Self::Auto(_) => Value::Auto,
|
||||||
@ -188,23 +215,6 @@ impl Eval for Expr {
|
|||||||
Self::Percent(_, v) => Value::Relative(Relative::new(v / 100.0)),
|
Self::Percent(_, v) => Value::Relative(Relative::new(v / 100.0)),
|
||||||
Self::Fractional(_, v) => Value::Fractional(Fractional::new(v)),
|
Self::Fractional(_, v) => Value::Fractional(Fractional::new(v)),
|
||||||
Self::Str(_, ref v) => Value::Str(v.clone()),
|
Self::Str(_, ref v) => Value::Str(v.clone()),
|
||||||
Self::Ident(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Array(ref v) => Value::Array(v.eval(ctx)?),
|
|
||||||
Self::Dict(ref v) => Value::Dict(v.eval(ctx)?),
|
|
||||||
Self::Template(ref v) => Value::Template(v.eval(ctx)?),
|
|
||||||
Self::Group(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Block(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Call(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Closure(ref v) => v.eval(ctx)?,
|
|
||||||
Self::With(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Unary(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Binary(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Let(ref v) => v.eval(ctx)?,
|
|
||||||
Self::If(ref v) => v.eval(ctx)?,
|
|
||||||
Self::While(ref v) => v.eval(ctx)?,
|
|
||||||
Self::For(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Import(ref v) => v.eval(ctx)?,
|
|
||||||
Self::Include(ref v) => v.eval(ctx)?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -674,8 +684,8 @@ impl Walk for SyntaxTree {
|
|||||||
impl Walk for SyntaxNode {
|
impl Walk for SyntaxNode {
|
||||||
fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
|
fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
|
||||||
match self {
|
match self {
|
||||||
Self::Text(_) => {}
|
|
||||||
Self::Space => {}
|
Self::Space => {}
|
||||||
|
Self::Text(_) => {}
|
||||||
Self::Linebreak(_) => {}
|
Self::Linebreak(_) => {}
|
||||||
Self::Parbreak(_) => {}
|
Self::Parbreak(_) => {}
|
||||||
Self::Strong(_) => {}
|
Self::Strong(_) => {}
|
||||||
|
@ -52,8 +52,8 @@ impl ExecWithMap for SyntaxTree {
|
|||||||
impl ExecWithMap for SyntaxNode {
|
impl ExecWithMap for SyntaxNode {
|
||||||
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
|
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
|
||||||
match self {
|
match self {
|
||||||
Self::Text(text) => ctx.push_text(text),
|
|
||||||
Self::Space => ctx.push_word_space(),
|
Self::Space => ctx.push_word_space(),
|
||||||
|
Self::Text(text) => ctx.push_text(text),
|
||||||
Self::Linebreak(_) => ctx.linebreak(),
|
Self::Linebreak(_) => ctx.linebreak(),
|
||||||
Self::Parbreak(_) => ctx.parbreak(),
|
Self::Parbreak(_) => ctx.parbreak(),
|
||||||
Self::Strong(_) => ctx.state.font_mut().strong ^= true,
|
Self::Strong(_) => ctx.state.font_mut().strong ^= true,
|
||||||
|
@ -5,7 +5,7 @@ use super::*;
|
|||||||
/// A relative length.
|
/// A relative length.
|
||||||
///
|
///
|
||||||
/// _Note_: `50%` is represented as `0.5` here, but stored as `50.0` in the
|
/// _Note_: `50%` is represented as `0.5` here, but stored as `50.0` in the
|
||||||
/// corresponding [literal](crate::syntax::Expr::Percent).
|
/// corresponding [literal](crate::syntax::Lit::Percent).
|
||||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
pub struct Relative(N64);
|
pub struct Relative(N64);
|
||||||
|
|
||||||
|
149
src/parse/mod.rs
149
src/parse/mod.rs
@ -65,10 +65,12 @@ where
|
|||||||
if call.wide {
|
if call.wide {
|
||||||
let start = p.next_start();
|
let start = p.next_start();
|
||||||
let tree = tree_while(p, true, f);
|
let tree = tree_while(p, true, f);
|
||||||
call.args.items.push(CallArg::Pos(Expr::Template(TemplateExpr {
|
call.args.items.push(CallArg::Pos(Expr::Template(Box::new(
|
||||||
span: p.span_from(start),
|
TemplateExpr {
|
||||||
tree: Rc::new(tree),
|
span: p.span_from(start),
|
||||||
})));
|
tree: Rc::new(tree),
|
||||||
|
},
|
||||||
|
))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +183,7 @@ fn raw(p: &mut Parser, token: RawToken) -> SyntaxNode {
|
|||||||
if !token.terminated {
|
if !token.terminated {
|
||||||
p.error(span.end, "expected backtick(s)");
|
p.error(span.end, "expected backtick(s)");
|
||||||
}
|
}
|
||||||
SyntaxNode::Raw(raw)
|
SyntaxNode::Raw(Box::new(raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a heading.
|
/// Parse a heading.
|
||||||
@ -201,7 +203,11 @@ fn heading(p: &mut Parser) -> SyntaxNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let body = tree_indented(p, column);
|
let body = tree_indented(p, column);
|
||||||
SyntaxNode::Heading(HeadingNode { span: p.span_from(start), level, body })
|
SyntaxNode::Heading(Box::new(HeadingNode {
|
||||||
|
span: p.span_from(start),
|
||||||
|
level,
|
||||||
|
body,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a single list item.
|
/// Parse a single list item.
|
||||||
@ -210,7 +216,7 @@ fn list_item(p: &mut Parser) -> SyntaxNode {
|
|||||||
let column = p.column(start);
|
let column = p.column(start);
|
||||||
p.eat_assert(Token::Hyph);
|
p.eat_assert(Token::Hyph);
|
||||||
let body = tree_indented(p, column);
|
let body = tree_indented(p, column);
|
||||||
SyntaxNode::List(ListItem { span: p.span_from(start), body })
|
SyntaxNode::List(Box::new(ListItem { span: p.span_from(start), body }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a single enum item.
|
/// Parse a single enum item.
|
||||||
@ -219,7 +225,11 @@ fn enum_item(p: &mut Parser, number: Option<usize>) -> SyntaxNode {
|
|||||||
let column = p.column(start);
|
let column = p.column(start);
|
||||||
p.eat_assert(Token::Numbering(number));
|
p.eat_assert(Token::Numbering(number));
|
||||||
let body = tree_indented(p, column);
|
let body = tree_indented(p, column);
|
||||||
SyntaxNode::Enum(EnumItem { span: p.span_from(start), number, body })
|
SyntaxNode::Enum(Box::new(EnumItem {
|
||||||
|
span: p.span_from(start),
|
||||||
|
number,
|
||||||
|
body,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an expression.
|
/// Parse an expression.
|
||||||
@ -239,8 +249,8 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> Option<Expr> {
|
|||||||
let mut lhs = match p.eat_map(UnOp::from_token) {
|
let mut lhs = match p.eat_map(UnOp::from_token) {
|
||||||
Some(op) => {
|
Some(op) => {
|
||||||
let prec = op.precedence();
|
let prec = op.precedence();
|
||||||
let expr = Box::new(expr_with(p, atomic, prec)?);
|
let expr = expr_with(p, atomic, prec)?;
|
||||||
Expr::Unary(UnaryExpr { span: p.span_from(start), op, expr })
|
Expr::Unary(Box::new(UnaryExpr { span: p.span_from(start), op, expr }))
|
||||||
}
|
}
|
||||||
None => primary(p, atomic)?,
|
None => primary(p, atomic)?,
|
||||||
};
|
};
|
||||||
@ -281,12 +291,12 @@ fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> Option<Expr> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let rhs = match expr_with(p, atomic, prec) {
|
let rhs = match expr_with(p, atomic, prec) {
|
||||||
Some(rhs) => Box::new(rhs),
|
Some(rhs) => rhs,
|
||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = lhs.span().join(rhs.span());
|
let span = lhs.span().join(rhs.span());
|
||||||
lhs = Expr::Binary(BinaryExpr { span, lhs: Box::new(lhs), op, rhs });
|
lhs = Expr::Binary(Box::new(BinaryExpr { span, lhs, op, rhs }));
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(lhs)
|
Some(lhs)
|
||||||
@ -309,14 +319,14 @@ fn primary(p: &mut Parser, atomic: bool) -> Option<Expr> {
|
|||||||
// Arrow means this is a closure's lone parameter.
|
// Arrow means this is a closure's lone parameter.
|
||||||
Some(if !atomic && p.eat_if(Token::Arrow) {
|
Some(if !atomic && p.eat_if(Token::Arrow) {
|
||||||
let body = expr(p)?;
|
let body = expr(p)?;
|
||||||
Expr::Closure(ClosureExpr {
|
Expr::Closure(Box::new(ClosureExpr {
|
||||||
span: ident.span.join(body.span()),
|
span: ident.span.join(body.span()),
|
||||||
name: None,
|
name: None,
|
||||||
params: vec![ClosureParam::Pos(ident)],
|
params: vec![ClosureParam::Pos(ident)],
|
||||||
body: Rc::new(body),
|
body: Rc::new(body),
|
||||||
})
|
}))
|
||||||
} else {
|
} else {
|
||||||
Expr::Ident(ident)
|
Expr::Ident(Box::new(ident))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,18 +354,18 @@ fn primary(p: &mut Parser, atomic: bool) -> Option<Expr> {
|
|||||||
/// Parse a literal.
|
/// Parse a literal.
|
||||||
fn literal(p: &mut Parser) -> Option<Expr> {
|
fn literal(p: &mut Parser) -> Option<Expr> {
|
||||||
let span = p.peek_span();
|
let span = p.peek_span();
|
||||||
let expr = match p.peek()? {
|
let lit = match p.peek()? {
|
||||||
// Basic values.
|
// Basic values.
|
||||||
Token::None => Expr::None(span),
|
Token::None => Lit::None(span),
|
||||||
Token::Auto => Expr::Auto(span),
|
Token::Auto => Lit::Auto(span),
|
||||||
Token::Bool(b) => Expr::Bool(span, b),
|
Token::Bool(b) => Lit::Bool(span, b),
|
||||||
Token::Int(i) => Expr::Int(span, i),
|
Token::Int(i) => Lit::Int(span, i),
|
||||||
Token::Float(f) => Expr::Float(span, f),
|
Token::Float(f) => Lit::Float(span, f),
|
||||||
Token::Length(val, unit) => Expr::Length(span, val, unit),
|
Token::Length(val, unit) => Lit::Length(span, val, unit),
|
||||||
Token::Angle(val, unit) => Expr::Angle(span, val, unit),
|
Token::Angle(val, unit) => Lit::Angle(span, val, unit),
|
||||||
Token::Percent(p) => Expr::Percent(span, p),
|
Token::Percent(p) => Lit::Percent(span, p),
|
||||||
Token::Fraction(p) => Expr::Fractional(span, p),
|
Token::Fraction(p) => Lit::Fractional(span, p),
|
||||||
Token::Str(token) => Expr::Str(span, {
|
Token::Str(token) => Lit::Str(span, {
|
||||||
if !token.terminated {
|
if !token.terminated {
|
||||||
p.expected_at(span.end, "quote");
|
p.expected_at(span.end, "quote");
|
||||||
}
|
}
|
||||||
@ -364,7 +374,7 @@ fn literal(p: &mut Parser) -> Option<Expr> {
|
|||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
p.eat();
|
p.eat();
|
||||||
Some(expr)
|
Some(Expr::Lit(Box::new(lit)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse something that starts with a parenthesis, which can be either of:
|
/// Parse something that starts with a parenthesis, which can be either of:
|
||||||
@ -387,21 +397,19 @@ fn parenthesized(p: &mut Parser) -> Option<Expr> {
|
|||||||
if p.eat_if(Token::Arrow) {
|
if p.eat_if(Token::Arrow) {
|
||||||
let params = params(p, items);
|
let params = params(p, items);
|
||||||
let body = expr(p)?;
|
let body = expr(p)?;
|
||||||
return Some(Expr::Closure(ClosureExpr {
|
return Some(Expr::Closure(Box::new(ClosureExpr {
|
||||||
span: span.join(body.span()),
|
span: span.join(body.span()),
|
||||||
name: None,
|
name: None,
|
||||||
params,
|
params,
|
||||||
body: Rc::new(body),
|
body: Rc::new(body),
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find out which kind of collection this is.
|
// Find out which kind of collection this is.
|
||||||
Some(match items.as_slice() {
|
Some(match items.as_slice() {
|
||||||
[] => array(p, items, span),
|
[] => array(p, items, span),
|
||||||
[CallArg::Pos(_)] if !has_comma => match items.into_iter().next() {
|
[CallArg::Pos(_)] if !has_comma => match items.into_iter().next() {
|
||||||
Some(CallArg::Pos(expr)) => {
|
Some(CallArg::Pos(expr)) => Expr::Group(Box::new(GroupExpr { span, expr })),
|
||||||
Expr::Group(GroupExpr { span, expr: Box::new(expr) })
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
[CallArg::Pos(_), ..] => array(p, items, span),
|
[CallArg::Pos(_), ..] => array(p, items, span),
|
||||||
@ -454,7 +462,7 @@ fn item(p: &mut Parser) -> Option<CallArg> {
|
|||||||
let first = expr(p)?;
|
let first = expr(p)?;
|
||||||
if p.eat_if(Token::Colon) {
|
if p.eat_if(Token::Colon) {
|
||||||
if let Expr::Ident(name) = first {
|
if let Expr::Ident(name) = first {
|
||||||
Some(CallArg::Named(Named { name, expr: expr(p)? }))
|
Some(CallArg::Named(Named { name: *name, expr: expr(p)? }))
|
||||||
} else {
|
} else {
|
||||||
p.error(first.span(), "expected identifier");
|
p.error(first.span(), "expected identifier");
|
||||||
expr(p);
|
expr(p);
|
||||||
@ -479,7 +487,7 @@ fn array(p: &mut Parser, items: Vec<CallArg>, span: Span) -> Expr {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Expr::Array(ArrayExpr { span, items: iter.collect() })
|
Expr::Array(Box::new(ArrayExpr { span, items: iter.collect() }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a collection into a dictionary, producing errors for anything other
|
/// Convert a collection into a dictionary, producing errors for anything other
|
||||||
@ -496,16 +504,16 @@ fn dict(p: &mut Parser, items: Vec<CallArg>, span: Span) -> Expr {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Expr::Dict(DictExpr { span, items: iter.collect() })
|
Expr::Dict(Box::new(DictExpr { span, items: iter.collect() }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a collection into a list of parameters, producing errors for
|
/// Convert a collection into a list of parameters, producing errors for
|
||||||
/// anything other than identifiers, spread operations and named pairs.
|
/// anything other than identifiers, spread operations and named pairs.
|
||||||
fn params(p: &mut Parser, items: Vec<CallArg>) -> Vec<ClosureParam> {
|
fn params(p: &mut Parser, items: Vec<CallArg>) -> Vec<ClosureParam> {
|
||||||
let iter = items.into_iter().filter_map(|item| match item {
|
let iter = items.into_iter().filter_map(|item| match item {
|
||||||
CallArg::Pos(Expr::Ident(ident)) => Some(ClosureParam::Pos(ident)),
|
CallArg::Pos(Expr::Ident(ident)) => Some(ClosureParam::Pos(*ident)),
|
||||||
CallArg::Named(named) => Some(ClosureParam::Named(named)),
|
CallArg::Named(named) => Some(ClosureParam::Named(named)),
|
||||||
CallArg::Spread(Expr::Ident(ident)) => Some(ClosureParam::Sink(ident)),
|
CallArg::Spread(Expr::Ident(ident)) => Some(ClosureParam::Sink(*ident)),
|
||||||
_ => {
|
_ => {
|
||||||
p.error(item.span(), "expected identifier");
|
p.error(item.span(), "expected identifier");
|
||||||
None
|
None
|
||||||
@ -518,7 +526,7 @@ fn params(p: &mut Parser, items: Vec<CallArg>) -> Vec<ClosureParam> {
|
|||||||
/// anything other than identifiers.
|
/// anything other than identifiers.
|
||||||
fn idents(p: &mut Parser, items: Vec<CallArg>) -> Vec<Ident> {
|
fn idents(p: &mut Parser, items: Vec<CallArg>) -> Vec<Ident> {
|
||||||
let iter = items.into_iter().filter_map(|item| match item {
|
let iter = items.into_iter().filter_map(|item| match item {
|
||||||
CallArg::Pos(Expr::Ident(id)) => Some(id),
|
CallArg::Pos(Expr::Ident(ident)) => Some(*ident),
|
||||||
_ => {
|
_ => {
|
||||||
p.error(item.span(), "expected identifier");
|
p.error(item.span(), "expected identifier");
|
||||||
None
|
None
|
||||||
@ -532,7 +540,7 @@ fn template(p: &mut Parser) -> Expr {
|
|||||||
p.start_group(Group::Bracket, TokenMode::Markup);
|
p.start_group(Group::Bracket, TokenMode::Markup);
|
||||||
let tree = Rc::new(tree(p));
|
let tree = Rc::new(tree(p));
|
||||||
let span = p.end_group();
|
let span = p.end_group();
|
||||||
Expr::Template(TemplateExpr { span, tree })
|
Expr::Template(Box::new(TemplateExpr { span, tree }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a block expression: `{...}`.
|
/// Parse a block expression: `{...}`.
|
||||||
@ -553,7 +561,7 @@ fn block(p: &mut Parser, scoping: bool) -> Expr {
|
|||||||
p.eat_while(|t| matches!(t, Token::Space(_)));
|
p.eat_while(|t| matches!(t, Token::Space(_)));
|
||||||
}
|
}
|
||||||
let span = p.end_group();
|
let span = p.end_group();
|
||||||
Expr::Block(BlockExpr { span, exprs, scoping })
|
Expr::Block(Box::new(BlockExpr { span, exprs, scoping }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a function call.
|
/// Parse a function call.
|
||||||
@ -582,12 +590,12 @@ fn call(p: &mut Parser, callee: Expr) -> Option<Expr> {
|
|||||||
args.items.push(CallArg::Pos(body));
|
args.items.push(CallArg::Pos(body));
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Expr::Call(CallExpr {
|
Some(Expr::Call(Box::new(CallExpr {
|
||||||
span: p.span_from(callee.span().start),
|
span: p.span_from(callee.span().start),
|
||||||
callee: Box::new(callee),
|
callee,
|
||||||
wide,
|
wide,
|
||||||
args,
|
args,
|
||||||
}))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the arguments to a function call.
|
/// Parse the arguments to a function call.
|
||||||
@ -601,11 +609,11 @@ fn args(p: &mut Parser) -> CallArgs {
|
|||||||
/// Parse a with expression.
|
/// Parse a with expression.
|
||||||
fn with_expr(p: &mut Parser, callee: Expr) -> Option<Expr> {
|
fn with_expr(p: &mut Parser, callee: Expr) -> Option<Expr> {
|
||||||
if p.peek() == Some(Token::LeftParen) {
|
if p.peek() == Some(Token::LeftParen) {
|
||||||
Some(Expr::With(WithExpr {
|
Some(Expr::With(Box::new(WithExpr {
|
||||||
span: p.span_from(callee.span().start),
|
span: p.span_from(callee.span().start),
|
||||||
callee: Box::new(callee),
|
callee,
|
||||||
args: args(p),
|
args: args(p),
|
||||||
}))
|
})))
|
||||||
} else {
|
} else {
|
||||||
p.expected("argument list");
|
p.expected("argument list");
|
||||||
None
|
None
|
||||||
@ -622,7 +630,7 @@ fn let_expr(p: &mut Parser) -> Option<Expr> {
|
|||||||
let mut init = None;
|
let mut init = None;
|
||||||
|
|
||||||
if p.eat_if(Token::With) {
|
if p.eat_if(Token::With) {
|
||||||
init = with_expr(p, Expr::Ident(binding.clone()));
|
init = with_expr(p, Expr::Ident(Box::new(binding.clone())));
|
||||||
} else {
|
} else {
|
||||||
// If a parenthesis follows, this is a function definition.
|
// If a parenthesis follows, this is a function definition.
|
||||||
let mut maybe_params = None;
|
let mut maybe_params = None;
|
||||||
@ -643,20 +651,20 @@ fn let_expr(p: &mut Parser) -> Option<Expr> {
|
|||||||
// Rewrite into a closure expression if it's a function definition.
|
// Rewrite into a closure expression if it's a function definition.
|
||||||
if let Some(params) = maybe_params {
|
if let Some(params) = maybe_params {
|
||||||
let body = init?;
|
let body = init?;
|
||||||
init = Some(Expr::Closure(ClosureExpr {
|
init = Some(Expr::Closure(Box::new(ClosureExpr {
|
||||||
span: binding.span.join(body.span()),
|
span: binding.span.join(body.span()),
|
||||||
name: Some(binding.clone()),
|
name: Some(binding.clone()),
|
||||||
params,
|
params,
|
||||||
body: Rc::new(body),
|
body: Rc::new(body),
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let_expr = Some(Expr::Let(LetExpr {
|
let_expr = Some(Expr::Let(Box::new(LetExpr {
|
||||||
span: p.span_from(start),
|
span: p.span_from(start),
|
||||||
binding,
|
binding,
|
||||||
init: init.map(Box::new),
|
init,
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
let_expr
|
let_expr
|
||||||
@ -680,12 +688,12 @@ fn if_expr(p: &mut Parser) -> Option<Expr> {
|
|||||||
else_body = body(p);
|
else_body = body(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if_expr = Some(Expr::If(IfExpr {
|
if_expr = Some(Expr::If(Box::new(IfExpr {
|
||||||
span: p.span_from(start),
|
span: p.span_from(start),
|
||||||
condition: Box::new(condition),
|
condition,
|
||||||
if_body: Box::new(if_body),
|
if_body,
|
||||||
else_body: else_body.map(Box::new),
|
else_body,
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,11 +708,11 @@ fn while_expr(p: &mut Parser) -> Option<Expr> {
|
|||||||
let mut while_expr = None;
|
let mut while_expr = None;
|
||||||
if let Some(condition) = expr(p) {
|
if let Some(condition) = expr(p) {
|
||||||
if let Some(body) = body(p) {
|
if let Some(body) = body(p) {
|
||||||
while_expr = Some(Expr::While(WhileExpr {
|
while_expr = Some(Expr::While(Box::new(WhileExpr {
|
||||||
span: p.span_from(start),
|
span: p.span_from(start),
|
||||||
condition: Box::new(condition),
|
condition,
|
||||||
body: Box::new(body),
|
body,
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,12 +729,12 @@ fn for_expr(p: &mut Parser) -> Option<Expr> {
|
|||||||
if p.eat_expect(Token::In) {
|
if p.eat_expect(Token::In) {
|
||||||
if let Some(iter) = expr(p) {
|
if let Some(iter) = expr(p) {
|
||||||
if let Some(body) = body(p) {
|
if let Some(body) = body(p) {
|
||||||
for_expr = Some(Expr::For(ForExpr {
|
for_expr = Some(Expr::For(Box::new(ForExpr {
|
||||||
span: p.span_from(start),
|
span: p.span_from(start),
|
||||||
pattern,
|
pattern,
|
||||||
iter: Box::new(iter),
|
iter,
|
||||||
body: Box::new(body),
|
body,
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -768,11 +776,11 @@ fn import_expr(p: &mut Parser) -> Option<Expr> {
|
|||||||
let mut import_expr = None;
|
let mut import_expr = None;
|
||||||
if p.eat_expect(Token::From) {
|
if p.eat_expect(Token::From) {
|
||||||
if let Some(path) = expr(p) {
|
if let Some(path) = expr(p) {
|
||||||
import_expr = Some(Expr::Import(ImportExpr {
|
import_expr = Some(Expr::Import(Box::new(ImportExpr {
|
||||||
span: p.span_from(start),
|
span: p.span_from(start),
|
||||||
imports,
|
imports,
|
||||||
path: Box::new(path),
|
path,
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,10 +793,7 @@ fn include_expr(p: &mut Parser) -> Option<Expr> {
|
|||||||
p.eat_assert(Token::Include);
|
p.eat_assert(Token::Include);
|
||||||
|
|
||||||
expr(p).map(|path| {
|
expr(p).map(|path| {
|
||||||
Expr::Include(IncludeExpr {
|
Expr::Include(Box::new(IncludeExpr { span: p.span_from(start), path }))
|
||||||
span: p.span_from(start),
|
|
||||||
path: Box::new(path),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ impl Pretty for SyntaxNode {
|
|||||||
fn pretty(&self, p: &mut Printer) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
match self {
|
match self {
|
||||||
// TODO: Handle escaping.
|
// TODO: Handle escaping.
|
||||||
Self::Text(text) => p.push_str(text),
|
|
||||||
Self::Space => p.push(' '),
|
Self::Space => p.push(' '),
|
||||||
|
Self::Text(text) => p.push_str(text),
|
||||||
Self::Linebreak(_) => p.push_str(r"\"),
|
Self::Linebreak(_) => p.push_str(r"\"),
|
||||||
Self::Parbreak(_) => p.push_str("\n\n"),
|
Self::Parbreak(_) => p.push_str("\n\n"),
|
||||||
Self::Strong(_) => p.push('*'),
|
Self::Strong(_) => p.push('*'),
|
||||||
@ -196,17 +196,8 @@ impl Pretty for EnumItem {
|
|||||||
impl Pretty for Expr {
|
impl Pretty for Expr {
|
||||||
fn pretty(&self, p: &mut Printer) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
match self {
|
match self {
|
||||||
Self::None(_) => p.push_str("none"),
|
|
||||||
Self::Auto(_) => p.push_str("auto"),
|
|
||||||
Self::Bool(_, v) => v.pretty(p),
|
|
||||||
Self::Int(_, v) => v.pretty(p),
|
|
||||||
Self::Float(_, v) => v.pretty(p),
|
|
||||||
Self::Length(_, v, u) => write!(p, "{}{}", v, u).unwrap(),
|
|
||||||
Self::Angle(_, v, u) => write!(p, "{}{}", v, u).unwrap(),
|
|
||||||
Self::Percent(_, v) => write!(p, "{}%", v).unwrap(),
|
|
||||||
Self::Fractional(_, v) => write!(p, "{}fr", v).unwrap(),
|
|
||||||
Self::Str(_, v) => v.pretty(p),
|
|
||||||
Self::Ident(v) => v.pretty(p),
|
Self::Ident(v) => v.pretty(p),
|
||||||
|
Self::Lit(v) => v.pretty(p),
|
||||||
Self::Array(v) => v.pretty(p),
|
Self::Array(v) => v.pretty(p),
|
||||||
Self::Dict(v) => v.pretty(p),
|
Self::Dict(v) => v.pretty(p),
|
||||||
Self::Template(v) => v.pretty(p),
|
Self::Template(v) => v.pretty(p),
|
||||||
@ -227,6 +218,23 @@ impl Pretty for Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Pretty for Lit {
|
||||||
|
fn pretty(&self, p: &mut Printer) {
|
||||||
|
match self {
|
||||||
|
Self::None(_) => p.push_str("none"),
|
||||||
|
Self::Auto(_) => p.push_str("auto"),
|
||||||
|
Self::Bool(_, v) => v.pretty(p),
|
||||||
|
Self::Int(_, v) => v.pretty(p),
|
||||||
|
Self::Float(_, v) => v.pretty(p),
|
||||||
|
Self::Length(_, v, u) => write!(p, "{}{}", v, u).unwrap(),
|
||||||
|
Self::Angle(_, v, u) => write!(p, "{}{}", v, u).unwrap(),
|
||||||
|
Self::Percent(_, v) => write!(p, "{}%", v).unwrap(),
|
||||||
|
Self::Fractional(_, v) => write!(p, "{}fr", v).unwrap(),
|
||||||
|
Self::Str(_, v) => v.pretty(p),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Pretty for ArrayExpr {
|
impl Pretty for ArrayExpr {
|
||||||
fn pretty(&self, p: &mut Printer) {
|
fn pretty(&self, p: &mut Printer) {
|
||||||
p.push('(');
|
p.push('(');
|
||||||
|
@ -6,6 +6,87 @@ use crate::geom::{AngularUnit, LengthUnit};
|
|||||||
/// An expression.
|
/// An expression.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
|
/// An identifier: `left`.
|
||||||
|
Ident(Box<Ident>),
|
||||||
|
/// A literal: `1`, `true`, ...
|
||||||
|
Lit(Box<Lit>),
|
||||||
|
/// An array expression: `(1, "hi", 12cm)`.
|
||||||
|
Array(Box<ArrayExpr>),
|
||||||
|
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
|
||||||
|
Dict(Box<DictExpr>),
|
||||||
|
/// A template expression: `[*Hi* there!]`.
|
||||||
|
Template(Box<TemplateExpr>),
|
||||||
|
/// A grouped expression: `(1 + 2)`.
|
||||||
|
Group(Box<GroupExpr>),
|
||||||
|
/// A block expression: `{ let x = 1; x + 2 }`.
|
||||||
|
Block(Box<BlockExpr>),
|
||||||
|
/// A unary operation: `-x`.
|
||||||
|
Unary(Box<UnaryExpr>),
|
||||||
|
/// A binary operation: `a + b`.
|
||||||
|
Binary(Box<BinaryExpr>),
|
||||||
|
/// An invocation of a function: `f(x, y)`.
|
||||||
|
Call(Box<CallExpr>),
|
||||||
|
/// A closure expression: `(x, y) => z`.
|
||||||
|
Closure(Box<ClosureExpr>),
|
||||||
|
/// A with expression: `f with (x, y: 1)`.
|
||||||
|
With(Box<WithExpr>),
|
||||||
|
/// A let expression: `let x = 1`.
|
||||||
|
Let(Box<LetExpr>),
|
||||||
|
/// An if-else expression: `if x { y } else { z }`.
|
||||||
|
If(Box<IfExpr>),
|
||||||
|
/// A while loop expression: `while x { y }`.
|
||||||
|
While(Box<WhileExpr>),
|
||||||
|
/// A for loop expression: `for x in y { z }`.
|
||||||
|
For(Box<ForExpr>),
|
||||||
|
/// An import expression: `import a, b, c from "utils.typ"`.
|
||||||
|
Import(Box<ImportExpr>),
|
||||||
|
/// An include expression: `include "chapter1.typ"`.
|
||||||
|
Include(Box<IncludeExpr>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Expr {
|
||||||
|
/// The source code location.
|
||||||
|
pub fn span(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
Self::Ident(v) => v.span,
|
||||||
|
Self::Lit(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::Closure(v) => v.span,
|
||||||
|
Self::With(v) => v.span,
|
||||||
|
Self::Let(v) => v.span,
|
||||||
|
Self::If(v) => v.span,
|
||||||
|
Self::While(v) => v.span,
|
||||||
|
Self::For(v) => v.span,
|
||||||
|
Self::Import(v) => v.span,
|
||||||
|
Self::Include(v) => v.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the expression can be shortened in markup with a hashtag.
|
||||||
|
pub fn has_short_form(&self) -> bool {
|
||||||
|
matches!(self,
|
||||||
|
Self::Ident(_)
|
||||||
|
| Self::Call(_)
|
||||||
|
| Self::Let(_)
|
||||||
|
| Self::If(_)
|
||||||
|
| Self::While(_)
|
||||||
|
| Self::For(_)
|
||||||
|
| Self::Import(_)
|
||||||
|
| Self::Include(_)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A literal: `1`, `true`, ...
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Lit {
|
||||||
/// The none literal: `none`.
|
/// The none literal: `none`.
|
||||||
None(Span),
|
None(Span),
|
||||||
/// The auto literal: `auto`.
|
/// The auto literal: `auto`.
|
||||||
@ -29,43 +110,9 @@ pub enum Expr {
|
|||||||
Fractional(Span, f64),
|
Fractional(Span, f64),
|
||||||
/// A string literal: `"hello!"`.
|
/// A string literal: `"hello!"`.
|
||||||
Str(Span, EcoString),
|
Str(Span, EcoString),
|
||||||
/// An identifier: `left`.
|
|
||||||
Ident(Ident),
|
|
||||||
/// An array expression: `(1, "hi", 12cm)`.
|
|
||||||
Array(ArrayExpr),
|
|
||||||
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
|
|
||||||
Dict(DictExpr),
|
|
||||||
/// A template expression: `[*Hi* there!]`.
|
|
||||||
Template(TemplateExpr),
|
|
||||||
/// A grouped expression: `(1 + 2)`.
|
|
||||||
Group(GroupExpr),
|
|
||||||
/// A block expression: `{ let x = 1; x + 2 }`.
|
|
||||||
Block(BlockExpr),
|
|
||||||
/// A unary operation: `-x`.
|
|
||||||
Unary(UnaryExpr),
|
|
||||||
/// A binary operation: `a + b`.
|
|
||||||
Binary(BinaryExpr),
|
|
||||||
/// An invocation of a function: `f(x, y)`.
|
|
||||||
Call(CallExpr),
|
|
||||||
/// A closure expression: `(x, y) => z`.
|
|
||||||
Closure(ClosureExpr),
|
|
||||||
/// A with expression: `f with (x, y: 1)`.
|
|
||||||
With(WithExpr),
|
|
||||||
/// A let expression: `let x = 1`.
|
|
||||||
Let(LetExpr),
|
|
||||||
/// An if-else expression: `if x { y } else { z }`.
|
|
||||||
If(IfExpr),
|
|
||||||
/// A while loop expression: `while x { y }`.
|
|
||||||
While(WhileExpr),
|
|
||||||
/// A for loop expression: `for x in y { z }`.
|
|
||||||
For(ForExpr),
|
|
||||||
/// An import expression: `import a, b, c from "utils.typ"`.
|
|
||||||
Import(ImportExpr),
|
|
||||||
/// An include expression: `include "chapter1.typ"`.
|
|
||||||
Include(IncludeExpr),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expr {
|
impl Lit {
|
||||||
/// The source code location.
|
/// The source code location.
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
match *self {
|
match *self {
|
||||||
@ -79,39 +126,8 @@ impl Expr {
|
|||||||
Self::Percent(span, _) => span,
|
Self::Percent(span, _) => span,
|
||||||
Self::Fractional(span, _) => span,
|
Self::Fractional(span, _) => span,
|
||||||
Self::Str(span, _) => span,
|
Self::Str(span, _) => span,
|
||||||
Self::Ident(ref v) => v.span,
|
|
||||||
Self::Array(ref v) => v.span,
|
|
||||||
Self::Dict(ref v) => v.span,
|
|
||||||
Self::Template(ref v) => v.span,
|
|
||||||
Self::Group(ref v) => v.span,
|
|
||||||
Self::Block(ref v) => v.span,
|
|
||||||
Self::Unary(ref v) => v.span,
|
|
||||||
Self::Binary(ref v) => v.span,
|
|
||||||
Self::Call(ref v) => v.span,
|
|
||||||
Self::Closure(ref v) => v.span,
|
|
||||||
Self::With(ref v) => v.span,
|
|
||||||
Self::Let(ref v) => v.span,
|
|
||||||
Self::If(ref v) => v.span,
|
|
||||||
Self::While(ref v) => v.span,
|
|
||||||
Self::For(ref v) => v.span,
|
|
||||||
Self::Import(ref v) => v.span,
|
|
||||||
Self::Include(ref v) => v.span,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the expression can be shortened in markup with a hashtag.
|
|
||||||
pub fn has_short_form(&self) -> bool {
|
|
||||||
matches!(self,
|
|
||||||
Self::Ident(_)
|
|
||||||
| Self::Call(_)
|
|
||||||
| Self::Let(_)
|
|
||||||
| Self::If(_)
|
|
||||||
| Self::While(_)
|
|
||||||
| Self::For(_)
|
|
||||||
| Self::Import(_)
|
|
||||||
| Self::Include(_)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An array expression: `(1, "hi", 12cm)`.
|
/// An array expression: `(1, "hi", 12cm)`.
|
||||||
@ -163,7 +179,7 @@ pub struct GroupExpr {
|
|||||||
/// The source code location.
|
/// The source code location.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// The wrapped expression.
|
/// The wrapped expression.
|
||||||
pub expr: Box<Expr>,
|
pub expr: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A block expression: `{ let x = 1; x + 2 }`.
|
/// A block expression: `{ let x = 1; x + 2 }`.
|
||||||
@ -185,7 +201,7 @@ pub struct UnaryExpr {
|
|||||||
/// The operator: `-`.
|
/// The operator: `-`.
|
||||||
pub op: UnOp,
|
pub op: UnOp,
|
||||||
/// The expression to operator on: `x`.
|
/// The expression to operator on: `x`.
|
||||||
pub expr: Box<Expr>,
|
pub expr: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A unary operator.
|
/// A unary operator.
|
||||||
@ -234,11 +250,11 @@ pub struct BinaryExpr {
|
|||||||
/// The source code location.
|
/// The source code location.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// The left-hand side of the operation: `a`.
|
/// The left-hand side of the operation: `a`.
|
||||||
pub lhs: Box<Expr>,
|
pub lhs: Expr,
|
||||||
/// The operator: `+`.
|
/// The operator: `+`.
|
||||||
pub op: BinOp,
|
pub op: BinOp,
|
||||||
/// The right-hand side of the operation: `b`.
|
/// The right-hand side of the operation: `b`.
|
||||||
pub rhs: Box<Expr>,
|
pub rhs: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A binary operator.
|
/// A binary operator.
|
||||||
@ -389,7 +405,7 @@ pub struct CallExpr {
|
|||||||
/// The source code location.
|
/// The source code location.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// The function to call.
|
/// The function to call.
|
||||||
pub callee: Box<Expr>,
|
pub callee: Expr,
|
||||||
/// Whether the call is wide, that is, capturing the template behind it.
|
/// Whether the call is wide, that is, capturing the template behind it.
|
||||||
pub wide: bool,
|
pub wide: bool,
|
||||||
/// The arguments to the function.
|
/// The arguments to the function.
|
||||||
@ -475,7 +491,7 @@ pub struct WithExpr {
|
|||||||
/// The source code location.
|
/// The source code location.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// The function to apply the arguments to.
|
/// The function to apply the arguments to.
|
||||||
pub callee: Box<Expr>,
|
pub callee: Expr,
|
||||||
/// The arguments to apply to the function.
|
/// The arguments to apply to the function.
|
||||||
pub args: CallArgs,
|
pub args: CallArgs,
|
||||||
}
|
}
|
||||||
@ -488,7 +504,7 @@ pub struct LetExpr {
|
|||||||
/// The binding to assign to.
|
/// The binding to assign to.
|
||||||
pub binding: Ident,
|
pub binding: Ident,
|
||||||
/// The expression the binding is initialized with.
|
/// The expression the binding is initialized with.
|
||||||
pub init: Option<Box<Expr>>,
|
pub init: Option<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An import expression: `import a, b, c from "utils.typ"`.
|
/// An import expression: `import a, b, c from "utils.typ"`.
|
||||||
@ -499,7 +515,7 @@ pub struct ImportExpr {
|
|||||||
/// The items to be imported.
|
/// The items to be imported.
|
||||||
pub imports: Imports,
|
pub imports: Imports,
|
||||||
/// The location of the importable file.
|
/// The location of the importable file.
|
||||||
pub path: Box<Expr>,
|
pub path: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The items that ought to be imported from a file.
|
/// The items that ought to be imported from a file.
|
||||||
@ -517,7 +533,7 @@ pub struct IncludeExpr {
|
|||||||
/// The source code location.
|
/// The source code location.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// The location of the file to be included.
|
/// The location of the file to be included.
|
||||||
pub path: Box<Expr>,
|
pub path: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An if-else expression: `if x { y } else { z }`.
|
/// An if-else expression: `if x { y } else { z }`.
|
||||||
@ -526,11 +542,11 @@ pub struct IfExpr {
|
|||||||
/// The source code location.
|
/// The source code location.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// The condition which selects the body to evaluate.
|
/// The condition which selects the body to evaluate.
|
||||||
pub condition: Box<Expr>,
|
pub condition: Expr,
|
||||||
/// The expression to evaluate if the condition is true.
|
/// The expression to evaluate if the condition is true.
|
||||||
pub if_body: Box<Expr>,
|
pub if_body: Expr,
|
||||||
/// The expression to evaluate if the condition is false.
|
/// The expression to evaluate if the condition is false.
|
||||||
pub else_body: Option<Box<Expr>>,
|
pub else_body: Option<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A while loop expression: `while x { y }`.
|
/// A while loop expression: `while x { y }`.
|
||||||
@ -539,9 +555,9 @@ pub struct WhileExpr {
|
|||||||
/// The source code location.
|
/// The source code location.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
/// The condition which selects whether to evaluate the body.
|
/// The condition which selects whether to evaluate the body.
|
||||||
pub condition: Box<Expr>,
|
pub condition: Expr,
|
||||||
/// The expression to evaluate while the condition is true.
|
/// The expression to evaluate while the condition is true.
|
||||||
pub body: Box<Expr>,
|
pub body: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A for loop expression: `for x in y { z }`.
|
/// A for loop expression: `for x in y { z }`.
|
||||||
@ -552,9 +568,9 @@ pub struct ForExpr {
|
|||||||
/// The pattern to assign to.
|
/// The pattern to assign to.
|
||||||
pub pattern: ForPattern,
|
pub pattern: ForPattern,
|
||||||
/// The expression to iterate over.
|
/// The expression to iterate over.
|
||||||
pub iter: Box<Expr>,
|
pub iter: Expr,
|
||||||
/// The expression to evaluate for each iteration.
|
/// The expression to evaluate for each iteration.
|
||||||
pub body: Box<Expr>,
|
pub body: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A pattern in a for loop.
|
/// A pattern in a for loop.
|
||||||
|
@ -3,10 +3,10 @@ use super::*;
|
|||||||
/// A syntax node, encompassing a single logical entity of parsed source code.
|
/// A syntax node, encompassing a single logical entity of parsed source code.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum SyntaxNode {
|
pub enum SyntaxNode {
|
||||||
/// Plain text.
|
|
||||||
Text(EcoString),
|
|
||||||
/// Whitespace containing less than two newlines.
|
/// Whitespace containing less than two newlines.
|
||||||
Space,
|
Space,
|
||||||
|
/// Plain text.
|
||||||
|
Text(EcoString),
|
||||||
/// A forced line break: `\`.
|
/// A forced line break: `\`.
|
||||||
Linebreak(Span),
|
Linebreak(Span),
|
||||||
/// A paragraph break: Two or more newlines.
|
/// A paragraph break: Two or more newlines.
|
||||||
@ -16,13 +16,13 @@ pub enum SyntaxNode {
|
|||||||
/// Emphasized text was enabled / disabled: `_`.
|
/// Emphasized text was enabled / disabled: `_`.
|
||||||
Emph(Span),
|
Emph(Span),
|
||||||
/// A raw block with optional syntax highlighting: `` `...` ``.
|
/// A raw block with optional syntax highlighting: `` `...` ``.
|
||||||
Raw(RawNode),
|
Raw(Box<RawNode>),
|
||||||
/// A section heading: `= Introduction`.
|
/// A section heading: `= Introduction`.
|
||||||
Heading(HeadingNode),
|
Heading(Box<HeadingNode>),
|
||||||
/// An item in an unordered list: `- ...`.
|
/// An item in an unordered list: `- ...`.
|
||||||
List(ListItem),
|
List(Box<ListItem>),
|
||||||
/// An item in an enumeration (ordered list): `1. ...`.
|
/// An item in an enumeration (ordered list): `1. ...`.
|
||||||
Enum(EnumItem),
|
Enum(Box<EnumItem>),
|
||||||
/// An expression.
|
/// An expression.
|
||||||
Expr(Expr),
|
Expr(Expr),
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ pub enum Token<'s> {
|
|||||||
/// A percentage: `50%`.
|
/// A percentage: `50%`.
|
||||||
///
|
///
|
||||||
/// _Note_: `50%` is stored as `50.0` here, as in the corresponding
|
/// _Note_: `50%` is stored as `50.0` here, as in the corresponding
|
||||||
/// [literal](super::Expr::Percent).
|
/// [literal](super::Lit::Percent).
|
||||||
Percent(f64),
|
Percent(f64),
|
||||||
/// A fraction unit: `3fr`.
|
/// A fraction unit: `3fr`.
|
||||||
Fraction(f64),
|
Fraction(f64),
|
||||||
|
@ -86,8 +86,8 @@ impl_visitors! {
|
|||||||
|
|
||||||
visit_node(v, node: SyntaxNode) {
|
visit_node(v, node: SyntaxNode) {
|
||||||
match node {
|
match node {
|
||||||
SyntaxNode::Text(_) => {}
|
|
||||||
SyntaxNode::Space => {}
|
SyntaxNode::Space => {}
|
||||||
|
SyntaxNode::Text(_) => {}
|
||||||
SyntaxNode::Linebreak(_) => {}
|
SyntaxNode::Linebreak(_) => {}
|
||||||
SyntaxNode::Parbreak(_) => {}
|
SyntaxNode::Parbreak(_) => {}
|
||||||
SyntaxNode::Strong(_) => {}
|
SyntaxNode::Strong(_) => {}
|
||||||
@ -114,17 +114,8 @@ impl_visitors! {
|
|||||||
|
|
||||||
visit_expr(v, expr: Expr) {
|
visit_expr(v, expr: Expr) {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::None(_) => {}
|
|
||||||
Expr::Auto(_) => {}
|
|
||||||
Expr::Bool(_, _) => {}
|
|
||||||
Expr::Int(_, _) => {}
|
|
||||||
Expr::Float(_, _) => {}
|
|
||||||
Expr::Length(_, _, _) => {}
|
|
||||||
Expr::Angle(_, _, _) => {}
|
|
||||||
Expr::Percent(_, _) => {}
|
|
||||||
Expr::Fractional(_, _) => {}
|
|
||||||
Expr::Str(_, _) => {}
|
|
||||||
Expr::Ident(_) => {}
|
Expr::Ident(_) => {}
|
||||||
|
Expr::Lit(_) => {},
|
||||||
Expr::Array(e) => v.visit_array(e),
|
Expr::Array(e) => v.visit_array(e),
|
||||||
Expr::Dict(e) => v.visit_dict(e),
|
Expr::Dict(e) => v.visit_dict(e),
|
||||||
Expr::Template(e) => v.visit_template(e),
|
Expr::Template(e) => v.visit_template(e),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user