mirror of
https://github.com/typst/typst
synced 2025-06-29 08:42:52 +08:00
Consistent block naming
This commit is contained in:
parent
e6b532391d
commit
5ce2a006b6
@ -49,6 +49,15 @@ impl<'a> CapturesVisitor<'a> {
|
|||||||
// through the expressions that contain them).
|
// through the expressions that contain them).
|
||||||
Some(Expr::Ident(ident)) => self.capture(ident),
|
Some(Expr::Ident(ident)) => self.capture(ident),
|
||||||
|
|
||||||
|
// Blocks and templates create a scope.
|
||||||
|
Some(Expr::Code(_) | Expr::Template(_)) => {
|
||||||
|
self.internal.enter();
|
||||||
|
for child in node.children() {
|
||||||
|
self.visit(child);
|
||||||
|
}
|
||||||
|
self.internal.exit();
|
||||||
|
}
|
||||||
|
|
||||||
// A closure contains parameter bindings, which are bound before the
|
// A closure contains parameter bindings, which are bound before the
|
||||||
// body is evaluated. Care must be taken so that the default values
|
// body is evaluated. Care must be taken so that the default values
|
||||||
// of named parameters cannot access previous parameter bindings.
|
// of named parameters cannot access previous parameter bindings.
|
||||||
@ -103,15 +112,6 @@ impl<'a> CapturesVisitor<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blocks and templates create a scope.
|
|
||||||
Some(Expr::Block(_) | Expr::Template(_)) => {
|
|
||||||
self.internal.enter();
|
|
||||||
for child in node.children() {
|
|
||||||
self.visit(child);
|
|
||||||
}
|
|
||||||
self.internal.exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everything else is traversed from left to right.
|
// Everything else is traversed from left to right.
|
||||||
_ => {
|
_ => {
|
||||||
for child in node.children() {
|
for child in node.children() {
|
||||||
|
@ -202,11 +202,11 @@ impl Eval for Expr {
|
|||||||
match self {
|
match self {
|
||||||
Self::Lit(v) => v.eval(ctx, scp),
|
Self::Lit(v) => v.eval(ctx, scp),
|
||||||
Self::Ident(v) => v.eval(ctx, scp),
|
Self::Ident(v) => v.eval(ctx, scp),
|
||||||
|
Self::Code(v) => v.eval(ctx, scp),
|
||||||
|
Self::Template(v) => v.eval(ctx, scp).map(Value::Template),
|
||||||
Self::Array(v) => v.eval(ctx, scp).map(Value::Array),
|
Self::Array(v) => v.eval(ctx, scp).map(Value::Array),
|
||||||
Self::Dict(v) => v.eval(ctx, scp).map(Value::Dict),
|
Self::Dict(v) => v.eval(ctx, scp).map(Value::Dict),
|
||||||
Self::Template(v) => v.eval(ctx, scp).map(Value::Template),
|
|
||||||
Self::Group(v) => v.eval(ctx, scp),
|
Self::Group(v) => v.eval(ctx, scp),
|
||||||
Self::Block(v) => v.eval(ctx, scp),
|
|
||||||
Self::Call(v) => v.eval(ctx, scp),
|
Self::Call(v) => v.eval(ctx, scp),
|
||||||
Self::Closure(v) => v.eval(ctx, scp),
|
Self::Closure(v) => v.eval(ctx, scp),
|
||||||
Self::With(v) => v.eval(ctx, scp),
|
Self::With(v) => v.eval(ctx, scp),
|
||||||
@ -260,25 +260,23 @@ impl Eval for Ident {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for ArrayExpr {
|
impl Eval for CodeBlock {
|
||||||
type Output = Array;
|
type Output = Value;
|
||||||
|
|
||||||
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
|
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
|
||||||
self.items().map(|expr| expr.eval(ctx, scp)).collect()
|
scp.enter();
|
||||||
|
|
||||||
|
let mut output = Value::None;
|
||||||
|
for expr in self.exprs() {
|
||||||
|
output = join_result(output, expr.eval(ctx, scp), expr.span())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
scp.exit();
|
||||||
|
Ok(output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for DictExpr {
|
impl Eval for TemplateBlock {
|
||||||
type Output = Dict;
|
|
||||||
|
|
||||||
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
|
|
||||||
self.items()
|
|
||||||
.map(|x| Ok((x.name().take(), x.expr().eval(ctx, scp)?)))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eval for TemplateExpr {
|
|
||||||
type Output = Template;
|
type Output = Template;
|
||||||
|
|
||||||
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
|
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
|
||||||
@ -297,19 +295,21 @@ impl Eval for GroupExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eval for BlockExpr {
|
impl Eval for ArrayExpr {
|
||||||
type Output = Value;
|
type Output = Array;
|
||||||
|
|
||||||
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
|
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
|
||||||
scp.enter();
|
self.items().map(|expr| expr.eval(ctx, scp)).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut output = Value::None;
|
impl Eval for DictExpr {
|
||||||
for expr in self.exprs() {
|
type Output = Dict;
|
||||||
output = join_result(output, expr.eval(ctx, scp), expr.span())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
scp.exit();
|
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
|
||||||
Ok(output)
|
self.items()
|
||||||
|
.map(|x| Ok((x.name().take(), x.expr().eval(ctx, scp)?)))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use std::hash::{Hash, Hasher};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{ops, Args, Array, Class, Dict, Func, Layout, Template};
|
use super::{ops, Args, Array, Class, Dict, Func, Layout, Template};
|
||||||
use crate::diag::StrResult;
|
use crate::diag::{with_alternative, StrResult};
|
||||||
use crate::geom::{Angle, Color, Fractional, Length, Linear, Relative, RgbaColor};
|
use crate::geom::{Angle, Color, Fractional, Length, Linear, Relative, RgbaColor};
|
||||||
use crate::syntax::Spanned;
|
use crate::syntax::Spanned;
|
||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
@ -533,16 +533,6 @@ impl<T: Cast> Cast for Smart<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transform `expected X, found Y` into `expected X or A, found Y`.
|
|
||||||
pub fn with_alternative(msg: String, alt: &str) -> String {
|
|
||||||
let mut parts = msg.split(", found ");
|
|
||||||
if let (Some(a), Some(b)) = (parts.next(), parts.next()) {
|
|
||||||
format!("{} or {}, found {}", a, alt, b)
|
|
||||||
} else {
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
//! Mathematical formulas.
|
||||||
|
|
||||||
use crate::library::prelude::*;
|
use crate::library::prelude::*;
|
||||||
|
|
||||||
/// A mathematical formula.
|
/// A mathematical formula.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//! Text shaping and paragraph layout.
|
//! Text handling and paragraph layout.
|
||||||
|
|
||||||
mod deco;
|
mod deco;
|
||||||
mod link;
|
mod link;
|
||||||
|
@ -136,8 +136,8 @@ impl Reparser<'_> {
|
|||||||
|
|
||||||
let superseded_span = pos.offset .. pos.offset + prev_len;
|
let superseded_span = pos.offset .. pos.offset + prev_len;
|
||||||
let func: Option<ReparseMode> = match child.kind() {
|
let func: Option<ReparseMode> = match child.kind() {
|
||||||
NodeKind::Template => Some(ReparseMode::Template),
|
NodeKind::CodeBlock => Some(ReparseMode::Code),
|
||||||
NodeKind::Block => Some(ReparseMode::Block),
|
NodeKind::TemplateBlock => Some(ReparseMode::Template),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ impl Reparser<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (newborns, terminated, amount) = match mode {
|
let (newborns, terminated, amount) = match mode {
|
||||||
ReparseMode::Block => reparse_block(
|
ReparseMode::Code => reparse_block(
|
||||||
&prefix,
|
&prefix,
|
||||||
&self.src[newborn_span.start ..],
|
&self.src[newborn_span.start ..],
|
||||||
newborn_span.len(),
|
newborn_span.len(),
|
||||||
@ -292,9 +292,9 @@ impl SearchState {
|
|||||||
/// Which reparse function to choose for a span of elements.
|
/// Which reparse function to choose for a span of elements.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
enum ReparseMode {
|
enum ReparseMode {
|
||||||
/// Reparse a code block with its braces.
|
/// Reparse a code block, including its braces.
|
||||||
Block,
|
Code,
|
||||||
/// Reparse a template, including its square brackets.
|
/// Reparse a template block, including its square brackets.
|
||||||
Template,
|
Template,
|
||||||
/// Reparse elements of the markup. The variant carries whether the node is
|
/// Reparse elements of the markup. The variant carries whether the node is
|
||||||
/// `at_start` and the minimum indent of the containing markup node.
|
/// `at_start` and the minimum indent of the containing markup node.
|
||||||
|
184
src/parse/mod.rs
184
src/parse/mod.rs
@ -28,8 +28,57 @@ pub fn parse(src: &str) -> Arc<GreenNode> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse some markup without the topmost node. Returns `Some` if all of the
|
/// Reparse a code block.
|
||||||
/// input was consumed.
|
///
|
||||||
|
/// Returns `Some` if all of the input was consumed.
|
||||||
|
pub fn reparse_block(
|
||||||
|
prefix: &str,
|
||||||
|
src: &str,
|
||||||
|
end_pos: usize,
|
||||||
|
) -> Option<(Vec<Green>, bool, usize)> {
|
||||||
|
let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
|
||||||
|
if !p.at(&NodeKind::LeftBrace) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
block(&mut p);
|
||||||
|
|
||||||
|
let (mut green, terminated) = p.consume()?;
|
||||||
|
let first = green.remove(0);
|
||||||
|
if first.len() != end_pos {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some((vec![first], terminated, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reparse a template literal.
|
||||||
|
///
|
||||||
|
/// Returns `Some` if all of the input was consumed.
|
||||||
|
pub fn reparse_template(
|
||||||
|
prefix: &str,
|
||||||
|
src: &str,
|
||||||
|
end_pos: usize,
|
||||||
|
) -> Option<(Vec<Green>, bool, usize)> {
|
||||||
|
let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
|
||||||
|
if !p.at(&NodeKind::LeftBracket) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
template(&mut p);
|
||||||
|
|
||||||
|
let (mut green, terminated) = p.consume()?;
|
||||||
|
let first = green.remove(0);
|
||||||
|
if first.len() != end_pos {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some((vec![first], terminated, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reparse some markup elements without the topmost node.
|
||||||
|
///
|
||||||
|
/// Returns `Some` if all of the input was consumed.
|
||||||
pub fn reparse_markup_elements(
|
pub fn reparse_markup_elements(
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
src: &str,
|
src: &str,
|
||||||
@ -100,50 +149,6 @@ pub fn reparse_markup_elements(
|
|||||||
Some((res, terminated, replaced))
|
Some((res, terminated, replaced))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a template literal. Returns `Some` if all of the input was consumed.
|
|
||||||
pub fn reparse_template(
|
|
||||||
prefix: &str,
|
|
||||||
src: &str,
|
|
||||||
end_pos: usize,
|
|
||||||
) -> Option<(Vec<Green>, bool, usize)> {
|
|
||||||
let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
|
|
||||||
if !p.at(&NodeKind::LeftBracket) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
template(&mut p);
|
|
||||||
|
|
||||||
let (mut green, terminated) = p.consume()?;
|
|
||||||
let first = green.remove(0);
|
|
||||||
if first.len() != end_pos {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((vec![first], terminated, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a code block. Returns `Some` if all of the input was consumed.
|
|
||||||
pub fn reparse_block(
|
|
||||||
prefix: &str,
|
|
||||||
src: &str,
|
|
||||||
end_pos: usize,
|
|
||||||
) -> Option<(Vec<Green>, bool, usize)> {
|
|
||||||
let mut p = Parser::with_prefix(prefix, src, TokenMode::Code);
|
|
||||||
if !p.at(&NodeKind::LeftBrace) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
block(&mut p);
|
|
||||||
|
|
||||||
let (mut green, terminated) = p.consume()?;
|
|
||||||
let first = green.remove(0);
|
|
||||||
if first.len() != end_pos {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some((vec![first], terminated, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse markup.
|
/// Parse markup.
|
||||||
///
|
///
|
||||||
/// If `at_start` is true, things like headings that may only appear at the
|
/// If `at_start` is true, things like headings that may only appear at the
|
||||||
@ -201,9 +206,9 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
|
|||||||
|
|
||||||
// Text and markup.
|
// Text and markup.
|
||||||
NodeKind::Text(_)
|
NodeKind::Text(_)
|
||||||
|
| NodeKind::NonBreakingSpace
|
||||||
| NodeKind::EnDash
|
| NodeKind::EnDash
|
||||||
| NodeKind::EmDash
|
| NodeKind::EmDash
|
||||||
| NodeKind::NonBreakingSpace
|
|
||||||
| NodeKind::Linebreak
|
| NodeKind::Linebreak
|
||||||
| NodeKind::Raw(_)
|
| NodeKind::Raw(_)
|
||||||
| NodeKind::Math(_)
|
| NodeKind::Math(_)
|
||||||
@ -350,7 +355,7 @@ fn expr_prec(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
|
|||||||
p.eat();
|
p.eat();
|
||||||
let prec = op.precedence();
|
let prec = op.precedence();
|
||||||
expr_prec(p, atomic, prec)?;
|
expr_prec(p, atomic, prec)?;
|
||||||
marker.end(p, NodeKind::Unary);
|
marker.end(p, NodeKind::UnaryExpr);
|
||||||
}
|
}
|
||||||
_ => primary(p, atomic)?,
|
_ => primary(p, atomic)?,
|
||||||
};
|
};
|
||||||
@ -388,7 +393,7 @@ fn expr_prec(p: &mut Parser, atomic: bool, min_prec: usize) -> ParseResult {
|
|||||||
Associativity::Right => {}
|
Associativity::Right => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
marker.perform(p, NodeKind::Binary, |p| expr_prec(p, atomic, prec))?;
|
marker.perform(p, NodeKind::BinaryExpr, |p| expr_prec(p, atomic, prec))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -410,7 +415,7 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
|
|||||||
if !atomic && p.at(&NodeKind::Arrow) {
|
if !atomic && p.at(&NodeKind::Arrow) {
|
||||||
marker.end(p, NodeKind::ClosureParams);
|
marker.end(p, NodeKind::ClosureParams);
|
||||||
p.eat_assert(&NodeKind::Arrow);
|
p.eat_assert(&NodeKind::Arrow);
|
||||||
marker.perform(p, NodeKind::Closure, expr)
|
marker.perform(p, NodeKind::ClosureExpr, expr)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -418,14 +423,8 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
|
|||||||
|
|
||||||
// Structures.
|
// Structures.
|
||||||
Some(NodeKind::LeftParen) => parenthesized(p, atomic),
|
Some(NodeKind::LeftParen) => parenthesized(p, atomic),
|
||||||
Some(NodeKind::LeftBracket) => {
|
Some(NodeKind::LeftBrace) => Ok(block(p)),
|
||||||
template(p);
|
Some(NodeKind::LeftBracket) => Ok(template(p)),
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Some(NodeKind::LeftBrace) => {
|
|
||||||
block(p);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keywords.
|
// Keywords.
|
||||||
Some(NodeKind::Let) => let_expr(p),
|
Some(NodeKind::Let) => let_expr(p),
|
||||||
@ -478,6 +477,20 @@ fn literal(p: &mut Parser) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse an identifier.
|
||||||
|
fn ident(p: &mut Parser) -> ParseResult {
|
||||||
|
match p.peek() {
|
||||||
|
Some(NodeKind::Ident(_)) => {
|
||||||
|
p.eat();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
p.expected_found("identifier");
|
||||||
|
Err(ParseError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse something that starts with a parenthesis, which can be either of:
|
/// Parse something that starts with a parenthesis, which can be either of:
|
||||||
/// - Array literal
|
/// - Array literal
|
||||||
/// - Dictionary literal
|
/// - Dictionary literal
|
||||||
@ -501,12 +514,12 @@ fn parenthesized(p: &mut Parser, atomic: bool) -> ParseResult {
|
|||||||
if !atomic && p.at(&NodeKind::Arrow) {
|
if !atomic && p.at(&NodeKind::Arrow) {
|
||||||
params(p, marker);
|
params(p, marker);
|
||||||
p.eat_assert(&NodeKind::Arrow);
|
p.eat_assert(&NodeKind::Arrow);
|
||||||
return marker.perform(p, NodeKind::Closure, expr);
|
return marker.perform(p, NodeKind::ClosureExpr, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform into the identified collection.
|
// Transform into the identified collection.
|
||||||
match kind {
|
match kind {
|
||||||
CollectionKind::Group => marker.end(p, NodeKind::Group),
|
CollectionKind::Group => marker.end(p, NodeKind::GroupExpr),
|
||||||
CollectionKind::Positional => array(p, marker),
|
CollectionKind::Positional => array(p, marker),
|
||||||
CollectionKind::Named => dict(p, marker),
|
CollectionKind::Named => dict(p, marker),
|
||||||
}
|
}
|
||||||
@ -614,7 +627,7 @@ fn array(p: &mut Parser, marker: Marker) {
|
|||||||
NodeKind::Spread => Err("spreading is not allowed here"),
|
NodeKind::Spread => Err("spreading is not allowed here"),
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
});
|
});
|
||||||
marker.end(p, NodeKind::Array);
|
marker.end(p, NodeKind::ArrayExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a collection into a dictionary, producing errors for anything other
|
/// Convert a collection into a dictionary, producing errors for anything other
|
||||||
@ -626,7 +639,7 @@ fn dict(p: &mut Parser, marker: Marker) {
|
|||||||
NodeKind::Spread => Err("spreading is not allowed here"),
|
NodeKind::Spread => Err("spreading is not allowed here"),
|
||||||
_ => Err("expected named pair, found expression"),
|
_ => Err("expected named pair, found expression"),
|
||||||
});
|
});
|
||||||
marker.end(p, NodeKind::Dict);
|
marker.end(p, NodeKind::DictExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a collection into a list of parameters, producing errors for
|
/// Convert a collection into a list of parameters, producing errors for
|
||||||
@ -648,18 +661,9 @@ fn params(p: &mut Parser, marker: Marker) {
|
|||||||
marker.end(p, NodeKind::ClosureParams);
|
marker.end(p, NodeKind::ClosureParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a template block: `[...]`.
|
|
||||||
fn template(p: &mut Parser) {
|
|
||||||
p.perform(NodeKind::Template, |p| {
|
|
||||||
p.start_group(Group::Bracket);
|
|
||||||
markup(p, true);
|
|
||||||
p.end_group();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a code block: `{...}`.
|
/// Parse a code block: `{...}`.
|
||||||
fn block(p: &mut Parser) {
|
fn block(p: &mut Parser) {
|
||||||
p.perform(NodeKind::Block, |p| {
|
p.perform(NodeKind::CodeBlock, |p| {
|
||||||
p.start_group(Group::Brace);
|
p.start_group(Group::Brace);
|
||||||
while !p.eof() {
|
while !p.eof() {
|
||||||
p.start_group(Group::Expr);
|
p.start_group(Group::Expr);
|
||||||
@ -675,9 +679,18 @@ fn block(p: &mut Parser) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse a template block: `[...]`.
|
||||||
|
fn template(p: &mut Parser) {
|
||||||
|
p.perform(NodeKind::TemplateBlock, |p| {
|
||||||
|
p.start_group(Group::Bracket);
|
||||||
|
markup(p, true);
|
||||||
|
p.end_group();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a function call.
|
/// Parse a function call.
|
||||||
fn call(p: &mut Parser, callee: Marker) -> ParseResult {
|
fn call(p: &mut Parser, callee: Marker) -> ParseResult {
|
||||||
callee.perform(p, NodeKind::Call, |p| args(p, true, true))
|
callee.perform(p, NodeKind::CallExpr, |p| args(p, true, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the arguments to a function call.
|
/// Parse the arguments to a function call.
|
||||||
@ -744,7 +757,7 @@ fn let_expr(p: &mut Parser) -> ParseResult {
|
|||||||
|
|
||||||
// Rewrite into a closure expression if it's a function definition.
|
// Rewrite into a closure expression if it's a function definition.
|
||||||
if has_params {
|
if has_params {
|
||||||
marker.end(p, NodeKind::Closure);
|
marker.end(p, NodeKind::ClosureExpr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -770,7 +783,7 @@ fn show_expr(p: &mut Parser) -> ParseResult {
|
|||||||
p.expected_found("parameter list");
|
p.expected_found("parameter list");
|
||||||
return Err(ParseError);
|
return Err(ParseError);
|
||||||
}
|
}
|
||||||
p.perform(NodeKind::Closure, |p| {
|
p.perform(NodeKind::ClosureExpr, |p| {
|
||||||
let marker = p.marker();
|
let marker = p.marker();
|
||||||
p.start_group(Group::Paren);
|
p.start_group(Group::Paren);
|
||||||
collection(p);
|
collection(p);
|
||||||
@ -906,31 +919,16 @@ fn return_expr(p: &mut Parser) -> ParseResult {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an identifier.
|
|
||||||
fn ident(p: &mut Parser) -> ParseResult {
|
|
||||||
match p.peek() {
|
|
||||||
Some(NodeKind::Ident(_)) => {
|
|
||||||
p.eat();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
p.expected_found("identifier");
|
|
||||||
Err(ParseError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a control flow body.
|
/// Parse a control flow body.
|
||||||
fn body(p: &mut Parser) -> ParseResult {
|
fn body(p: &mut Parser) -> ParseResult {
|
||||||
match p.peek() {
|
match p.peek() {
|
||||||
Some(NodeKind::LeftBracket) => template(p),
|
Some(NodeKind::LeftBracket) => Ok(template(p)),
|
||||||
Some(NodeKind::LeftBrace) => block(p),
|
Some(NodeKind::LeftBrace) => Ok(block(p)),
|
||||||
_ => {
|
_ => {
|
||||||
p.expected("body");
|
p.expected("body");
|
||||||
return Err(ParseError);
|
Err(ParseError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -229,13 +229,13 @@ impl<'s> Parser<'s> {
|
|||||||
self.groups.push(GroupEntry { kind, prev_mode: self.tokens.mode() });
|
self.groups.push(GroupEntry { kind, prev_mode: self.tokens.mode() });
|
||||||
self.tokens.set_mode(match kind {
|
self.tokens.set_mode(match kind {
|
||||||
Group::Bracket | Group::Strong | Group::Emph => TokenMode::Markup,
|
Group::Bracket | Group::Strong | Group::Emph => TokenMode::Markup,
|
||||||
Group::Paren | Group::Brace | Group::Expr | Group::Imports => TokenMode::Code,
|
Group::Brace | Group::Paren | Group::Expr | Group::Imports => TokenMode::Code,
|
||||||
});
|
});
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
Group::Paren => self.eat_assert(&NodeKind::LeftParen),
|
|
||||||
Group::Bracket => self.eat_assert(&NodeKind::LeftBracket),
|
|
||||||
Group::Brace => self.eat_assert(&NodeKind::LeftBrace),
|
Group::Brace => self.eat_assert(&NodeKind::LeftBrace),
|
||||||
|
Group::Bracket => self.eat_assert(&NodeKind::LeftBracket),
|
||||||
|
Group::Paren => self.eat_assert(&NodeKind::LeftParen),
|
||||||
Group::Strong => self.eat_assert(&NodeKind::Star),
|
Group::Strong => self.eat_assert(&NodeKind::Star),
|
||||||
Group::Emph => self.eat_assert(&NodeKind::Underscore),
|
Group::Emph => self.eat_assert(&NodeKind::Underscore),
|
||||||
Group::Expr => self.repeek(),
|
Group::Expr => self.repeek(),
|
||||||
@ -321,9 +321,9 @@ impl<'s> Parser<'s> {
|
|||||||
/// group.
|
/// group.
|
||||||
fn repeek(&mut self) {
|
fn repeek(&mut self) {
|
||||||
self.eof = match &self.current {
|
self.eof = match &self.current {
|
||||||
Some(NodeKind::RightParen) => self.inside(Group::Paren),
|
|
||||||
Some(NodeKind::RightBracket) => self.inside(Group::Bracket),
|
|
||||||
Some(NodeKind::RightBrace) => self.inside(Group::Brace),
|
Some(NodeKind::RightBrace) => self.inside(Group::Brace),
|
||||||
|
Some(NodeKind::RightBracket) => self.inside(Group::Bracket),
|
||||||
|
Some(NodeKind::RightParen) => self.inside(Group::Paren),
|
||||||
Some(NodeKind::Star) => self.inside(Group::Strong),
|
Some(NodeKind::Star) => self.inside(Group::Strong),
|
||||||
Some(NodeKind::Underscore) => self.inside(Group::Emph),
|
Some(NodeKind::Underscore) => self.inside(Group::Emph),
|
||||||
Some(NodeKind::Semicolon) => self.inside(Group::Expr),
|
Some(NodeKind::Semicolon) => self.inside(Group::Expr),
|
||||||
@ -482,10 +482,10 @@ struct GroupEntry {
|
|||||||
/// A group, confined by optional start and end delimiters.
|
/// A group, confined by optional start and end delimiters.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum Group {
|
pub enum Group {
|
||||||
/// A bracketed group: `[...]`.
|
|
||||||
Bracket,
|
|
||||||
/// A curly-braced group: `{...}`.
|
/// A curly-braced group: `{...}`.
|
||||||
Brace,
|
Brace,
|
||||||
|
/// A bracketed group: `[...]`.
|
||||||
|
Bracket,
|
||||||
/// A parenthesized group: `(...)`.
|
/// A parenthesized group: `(...)`.
|
||||||
Paren,
|
Paren,
|
||||||
/// A group surrounded with stars: `*...*`.
|
/// A group surrounded with stars: `*...*`.
|
||||||
|
@ -26,7 +26,7 @@ pub struct Tokens<'s> {
|
|||||||
pub enum TokenMode {
|
pub enum TokenMode {
|
||||||
/// Text and markup.
|
/// Text and markup.
|
||||||
Markup,
|
Markup,
|
||||||
/// Blocks and expressions.
|
/// Keywords, literals and operators.
|
||||||
Code,
|
Code,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,11 +104,11 @@ impl<'s> Iterator for Tokens<'s> {
|
|||||||
let start = self.s.index();
|
let start = self.s.index();
|
||||||
let c = self.s.eat()?;
|
let c = self.s.eat()?;
|
||||||
Some(match c {
|
Some(match c {
|
||||||
// Blocks and templates.
|
// Blocks.
|
||||||
'[' => NodeKind::LeftBracket,
|
|
||||||
']' => NodeKind::RightBracket,
|
|
||||||
'{' => NodeKind::LeftBrace,
|
'{' => NodeKind::LeftBrace,
|
||||||
'}' => NodeKind::RightBrace,
|
'}' => NodeKind::RightBrace,
|
||||||
|
'[' => NodeKind::LeftBracket,
|
||||||
|
']' => NodeKind::RightBracket,
|
||||||
|
|
||||||
// Whitespace.
|
// Whitespace.
|
||||||
' ' if self.s.check_or(true, |c| !c.is_whitespace()) => NodeKind::Space(0),
|
' ' if self.s.check_or(true, |c| !c.is_whitespace()) => NodeKind::Space(0),
|
||||||
@ -741,18 +741,18 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_tokenize_brackets() {
|
fn test_tokenize_brackets() {
|
||||||
// Test in markup.
|
// Test in markup.
|
||||||
t!(Markup: "[" => LeftBracket);
|
|
||||||
t!(Markup: "]" => RightBracket);
|
|
||||||
t!(Markup: "{" => LeftBrace);
|
t!(Markup: "{" => LeftBrace);
|
||||||
t!(Markup: "}" => RightBrace);
|
t!(Markup: "}" => RightBrace);
|
||||||
|
t!(Markup: "[" => LeftBracket);
|
||||||
|
t!(Markup: "]" => RightBracket);
|
||||||
t!(Markup[" /"]: "(" => Text("("));
|
t!(Markup[" /"]: "(" => Text("("));
|
||||||
t!(Markup[" /"]: ")" => Text(")"));
|
t!(Markup[" /"]: ")" => Text(")"));
|
||||||
|
|
||||||
// Test in code.
|
// Test in code.
|
||||||
t!(Code: "[" => LeftBracket);
|
|
||||||
t!(Code: "]" => RightBracket);
|
|
||||||
t!(Code: "{" => LeftBrace);
|
t!(Code: "{" => LeftBrace);
|
||||||
t!(Code: "}" => RightBrace);
|
t!(Code: "}" => RightBrace);
|
||||||
|
t!(Code: "[" => LeftBracket);
|
||||||
|
t!(Code: "]" => RightBracket);
|
||||||
t!(Code: "(" => LeftParen);
|
t!(Code: "(" => LeftParen);
|
||||||
t!(Code: ")" => RightParen);
|
t!(Code: ")" => RightParen);
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,9 @@ impl Markup {
|
|||||||
Some(MarkupNode::Text(s.clone()))
|
Some(MarkupNode::Text(s.clone()))
|
||||||
}
|
}
|
||||||
NodeKind::Escape(c) => Some(MarkupNode::Text((*c).into())),
|
NodeKind::Escape(c) => Some(MarkupNode::Text((*c).into())),
|
||||||
|
NodeKind::NonBreakingSpace => Some(MarkupNode::Text('\u{00A0}'.into())),
|
||||||
NodeKind::EnDash => Some(MarkupNode::Text('\u{2013}'.into())),
|
NodeKind::EnDash => Some(MarkupNode::Text('\u{2013}'.into())),
|
||||||
NodeKind::EmDash => Some(MarkupNode::Text('\u{2014}'.into())),
|
NodeKind::EmDash => Some(MarkupNode::Text('\u{2014}'.into())),
|
||||||
NodeKind::NonBreakingSpace => Some(MarkupNode::Text('\u{00A0}'.into())),
|
|
||||||
NodeKind::Strong => node.cast().map(MarkupNode::Strong),
|
NodeKind::Strong => node.cast().map(MarkupNode::Strong),
|
||||||
NodeKind::Emph => node.cast().map(MarkupNode::Emph),
|
NodeKind::Emph => node.cast().map(MarkupNode::Emph),
|
||||||
NodeKind::Raw(raw) => Some(MarkupNode::Raw(raw.as_ref().clone())),
|
NodeKind::Raw(raw) => Some(MarkupNode::Raw(raw.as_ref().clone())),
|
||||||
@ -219,16 +219,16 @@ pub enum Expr {
|
|||||||
Lit(Lit),
|
Lit(Lit),
|
||||||
/// An identifier: `left`.
|
/// An identifier: `left`.
|
||||||
Ident(Ident),
|
Ident(Ident),
|
||||||
|
/// A code block: `{ let x = 1; x + 2 }`.
|
||||||
|
Code(CodeBlock),
|
||||||
|
/// A template block: `[*Hi* there!]`.
|
||||||
|
Template(TemplateBlock),
|
||||||
|
/// A grouped expression: `(1 + 2)`.
|
||||||
|
Group(GroupExpr),
|
||||||
/// An array expression: `(1, "hi", 12cm)`.
|
/// An array expression: `(1, "hi", 12cm)`.
|
||||||
Array(ArrayExpr),
|
Array(ArrayExpr),
|
||||||
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
|
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
|
||||||
Dict(DictExpr),
|
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`.
|
/// A unary operation: `-x`.
|
||||||
Unary(UnaryExpr),
|
Unary(UnaryExpr),
|
||||||
/// A binary operation: `a + b`.
|
/// A binary operation: `a + b`.
|
||||||
@ -269,15 +269,15 @@ impl TypedNode for Expr {
|
|||||||
fn from_red(node: RedRef) -> Option<Self> {
|
fn from_red(node: RedRef) -> Option<Self> {
|
||||||
match node.kind() {
|
match node.kind() {
|
||||||
NodeKind::Ident(_) => node.cast().map(Self::Ident),
|
NodeKind::Ident(_) => node.cast().map(Self::Ident),
|
||||||
NodeKind::Array => node.cast().map(Self::Array),
|
NodeKind::CodeBlock => node.cast().map(Self::Code),
|
||||||
NodeKind::Dict => node.cast().map(Self::Dict),
|
NodeKind::TemplateBlock => node.cast().map(Self::Template),
|
||||||
NodeKind::Template => node.cast().map(Self::Template),
|
NodeKind::GroupExpr => node.cast().map(Self::Group),
|
||||||
NodeKind::Group => node.cast().map(Self::Group),
|
NodeKind::ArrayExpr => node.cast().map(Self::Array),
|
||||||
NodeKind::Block => node.cast().map(Self::Block),
|
NodeKind::DictExpr => node.cast().map(Self::Dict),
|
||||||
NodeKind::Unary => node.cast().map(Self::Unary),
|
NodeKind::UnaryExpr => node.cast().map(Self::Unary),
|
||||||
NodeKind::Binary => node.cast().map(Self::Binary),
|
NodeKind::BinaryExpr => node.cast().map(Self::Binary),
|
||||||
NodeKind::Call => node.cast().map(Self::Call),
|
NodeKind::CallExpr => node.cast().map(Self::Call),
|
||||||
NodeKind::Closure => node.cast().map(Self::Closure),
|
NodeKind::ClosureExpr => node.cast().map(Self::Closure),
|
||||||
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),
|
||||||
@ -298,12 +298,12 @@ impl TypedNode for Expr {
|
|||||||
fn as_red(&self) -> RedRef<'_> {
|
fn as_red(&self) -> RedRef<'_> {
|
||||||
match self {
|
match self {
|
||||||
Self::Lit(v) => v.as_red(),
|
Self::Lit(v) => v.as_red(),
|
||||||
|
Self::Code(v) => v.as_red(),
|
||||||
|
Self::Template(v) => v.as_red(),
|
||||||
Self::Ident(v) => v.as_red(),
|
Self::Ident(v) => v.as_red(),
|
||||||
Self::Array(v) => v.as_red(),
|
Self::Array(v) => v.as_red(),
|
||||||
Self::Dict(v) => v.as_red(),
|
Self::Dict(v) => v.as_red(),
|
||||||
Self::Template(v) => v.as_red(),
|
|
||||||
Self::Group(v) => v.as_red(),
|
Self::Group(v) => v.as_red(),
|
||||||
Self::Block(v) => v.as_red(),
|
|
||||||
Self::Unary(v) => v.as_red(),
|
Self::Unary(v) => v.as_red(),
|
||||||
Self::Binary(v) => v.as_red(),
|
Self::Binary(v) => v.as_red(),
|
||||||
Self::Call(v) => v.as_red(),
|
Self::Call(v) => v.as_red(),
|
||||||
@ -406,9 +406,45 @@ pub enum LitKind {
|
|||||||
Str(EcoString),
|
Str(EcoString),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node! {
|
||||||
|
/// A code block: `{ let x = 1; x + 2 }`.
|
||||||
|
CodeBlock: CodeBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CodeBlock {
|
||||||
|
/// The list of expressions contained in the block.
|
||||||
|
pub fn exprs(&self) -> impl Iterator<Item = Expr> + '_ {
|
||||||
|
self.0.children().filter_map(RedRef::cast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node! {
|
||||||
|
/// A template block: `[*Hi* there!]`.
|
||||||
|
TemplateBlock: TemplateBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TemplateBlock {
|
||||||
|
/// The contents of the template.
|
||||||
|
pub fn body(&self) -> Markup {
|
||||||
|
self.0.cast_first_child().expect("template is missing body")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node! {
|
||||||
|
/// A grouped expression: `(1 + 2)`.
|
||||||
|
GroupExpr: GroupExpr
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GroupExpr {
|
||||||
|
/// The wrapped expression.
|
||||||
|
pub fn expr(&self) -> Expr {
|
||||||
|
self.0.cast_first_child().expect("group is missing expression")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// An array expression: `(1, "hi", 12cm)`.
|
/// An array expression: `(1, "hi", 12cm)`.
|
||||||
ArrayExpr: Array
|
ArrayExpr: ArrayExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArrayExpr {
|
impl ArrayExpr {
|
||||||
@ -420,7 +456,7 @@ impl ArrayExpr {
|
|||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
|
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
|
||||||
DictExpr: Dict
|
DictExpr: DictExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DictExpr {
|
impl DictExpr {
|
||||||
@ -447,45 +483,9 @@ impl Named {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node! {
|
|
||||||
/// A template expression: `[*Hi* there!]`.
|
|
||||||
TemplateExpr: Template
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TemplateExpr {
|
|
||||||
/// The contents of the template.
|
|
||||||
pub fn body(&self) -> Markup {
|
|
||||||
self.0.cast_first_child().expect("template is missing body")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node! {
|
|
||||||
/// A grouped expression: `(1 + 2)`.
|
|
||||||
GroupExpr: Group
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GroupExpr {
|
|
||||||
/// The wrapped expression.
|
|
||||||
pub fn expr(&self) -> Expr {
|
|
||||||
self.0.cast_first_child().expect("group is missing expression")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node! {
|
|
||||||
/// A block expression: `{ let x = 1; x + 2 }`.
|
|
||||||
BlockExpr: Block
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BlockExpr {
|
|
||||||
/// The list of expressions contained in the block.
|
|
||||||
pub fn exprs(&self) -> impl Iterator<Item = Expr> + '_ {
|
|
||||||
self.0.children().filter_map(RedRef::cast)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// A unary operation: `-x`.
|
/// A unary operation: `-x`.
|
||||||
UnaryExpr: Unary
|
UnaryExpr: UnaryExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnaryExpr {
|
impl UnaryExpr {
|
||||||
@ -545,7 +545,7 @@ impl UnOp {
|
|||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// A binary operation: `a + b`.
|
/// A binary operation: `a + b`.
|
||||||
BinaryExpr: Binary
|
BinaryExpr: BinaryExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryExpr {
|
impl BinaryExpr {
|
||||||
@ -717,7 +717,7 @@ pub enum Associativity {
|
|||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// An invocation of a function: `foo(...)`.
|
/// An invocation of a function: `foo(...)`.
|
||||||
CallExpr: Call
|
CallExpr: CallExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallExpr {
|
impl CallExpr {
|
||||||
@ -786,7 +786,7 @@ impl CallArg {
|
|||||||
|
|
||||||
node! {
|
node! {
|
||||||
/// A closure expression: `(x, y) => z`.
|
/// A closure expression: `(x, y) => z`.
|
||||||
ClosureExpr: Closure
|
ClosureExpr: ClosureExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClosureExpr {
|
impl ClosureExpr {
|
||||||
|
@ -104,10 +104,10 @@ impl Category {
|
|||||||
/// Determine the highlighting category of a node given its parent.
|
/// Determine the highlighting category of a node given its parent.
|
||||||
pub fn determine(child: RedRef, parent: RedRef) -> Option<Category> {
|
pub fn determine(child: RedRef, parent: RedRef) -> Option<Category> {
|
||||||
match child.kind() {
|
match child.kind() {
|
||||||
NodeKind::LeftBracket => Some(Category::Bracket),
|
|
||||||
NodeKind::RightBracket => Some(Category::Bracket),
|
|
||||||
NodeKind::LeftBrace => Some(Category::Bracket),
|
NodeKind::LeftBrace => Some(Category::Bracket),
|
||||||
NodeKind::RightBrace => Some(Category::Bracket),
|
NodeKind::RightBrace => Some(Category::Bracket),
|
||||||
|
NodeKind::LeftBracket => Some(Category::Bracket),
|
||||||
|
NodeKind::RightBracket => Some(Category::Bracket),
|
||||||
NodeKind::LeftParen => Some(Category::Bracket),
|
NodeKind::LeftParen => Some(Category::Bracket),
|
||||||
NodeKind::RightParen => Some(Category::Bracket),
|
NodeKind::RightParen => Some(Category::Bracket),
|
||||||
NodeKind::Comma => Some(Category::Punctuation),
|
NodeKind::Comma => Some(Category::Punctuation),
|
||||||
@ -176,13 +176,13 @@ impl Category {
|
|||||||
NodeKind::Auto => Some(Category::Auto),
|
NodeKind::Auto => Some(Category::Auto),
|
||||||
NodeKind::Ident(_) => match parent.kind() {
|
NodeKind::Ident(_) => match parent.kind() {
|
||||||
NodeKind::Named => None,
|
NodeKind::Named => None,
|
||||||
NodeKind::Closure if child.span().start == parent.span().start => {
|
NodeKind::ClosureExpr if child.span().start == parent.span().start => {
|
||||||
Some(Category::Function)
|
Some(Category::Function)
|
||||||
}
|
}
|
||||||
NodeKind::WithExpr => Some(Category::Function),
|
NodeKind::WithExpr => Some(Category::Function),
|
||||||
NodeKind::SetExpr => Some(Category::Function),
|
NodeKind::SetExpr => Some(Category::Function),
|
||||||
NodeKind::ShowExpr => Some(Category::Function),
|
NodeKind::ShowExpr => Some(Category::Function),
|
||||||
NodeKind::Call => Some(Category::Function),
|
NodeKind::CallExpr => Some(Category::Function),
|
||||||
_ => Some(Category::Variable),
|
_ => Some(Category::Variable),
|
||||||
},
|
},
|
||||||
NodeKind::Bool(_) => Some(Category::Bool),
|
NodeKind::Bool(_) => Some(Category::Bool),
|
||||||
@ -202,18 +202,18 @@ impl Category {
|
|||||||
NodeKind::TextInLine(_) => None,
|
NodeKind::TextInLine(_) => None,
|
||||||
NodeKind::List => None,
|
NodeKind::List => None,
|
||||||
NodeKind::Enum => None,
|
NodeKind::Enum => None,
|
||||||
NodeKind::Array => None,
|
NodeKind::CodeBlock => None,
|
||||||
NodeKind::Dict => None,
|
NodeKind::TemplateBlock => None,
|
||||||
|
NodeKind::GroupExpr => None,
|
||||||
|
NodeKind::ArrayExpr => None,
|
||||||
|
NodeKind::DictExpr => None,
|
||||||
NodeKind::Named => None,
|
NodeKind::Named => None,
|
||||||
NodeKind::Template => None,
|
NodeKind::UnaryExpr => None,
|
||||||
NodeKind::Group => None,
|
NodeKind::BinaryExpr => None,
|
||||||
NodeKind::Block => None,
|
NodeKind::CallExpr => None,
|
||||||
NodeKind::Unary => None,
|
|
||||||
NodeKind::Binary => None,
|
|
||||||
NodeKind::Call => None,
|
|
||||||
NodeKind::CallArgs => None,
|
NodeKind::CallArgs => None,
|
||||||
NodeKind::Spread => None,
|
NodeKind::Spread => None,
|
||||||
NodeKind::Closure => None,
|
NodeKind::ClosureExpr => None,
|
||||||
NodeKind::ClosureParams => None,
|
NodeKind::ClosureParams => None,
|
||||||
NodeKind::WithExpr => None,
|
NodeKind::WithExpr => None,
|
||||||
NodeKind::LetExpr => None,
|
NodeKind::LetExpr => None,
|
||||||
|
@ -481,14 +481,14 @@ impl ExactSizeIterator for Children<'_> {}
|
|||||||
/// the parser.
|
/// the parser.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum NodeKind {
|
pub enum NodeKind {
|
||||||
/// A left square bracket: `[`.
|
|
||||||
LeftBracket,
|
|
||||||
/// A right square bracket: `]`.
|
|
||||||
RightBracket,
|
|
||||||
/// A left curly brace: `{`.
|
/// A left curly brace: `{`.
|
||||||
LeftBrace,
|
LeftBrace,
|
||||||
/// A right curly brace: `}`.
|
/// A right curly brace: `}`.
|
||||||
RightBrace,
|
RightBrace,
|
||||||
|
/// A left square bracket: `[`.
|
||||||
|
LeftBracket,
|
||||||
|
/// A right square bracket: `]`.
|
||||||
|
RightBracket,
|
||||||
/// A left round parenthesis: `(`.
|
/// A left round parenthesis: `(`.
|
||||||
LeftParen,
|
LeftParen,
|
||||||
/// A right round parenthesis: `)`.
|
/// A right round parenthesis: `)`.
|
||||||
@ -642,30 +642,30 @@ pub enum NodeKind {
|
|||||||
Fraction(f64),
|
Fraction(f64),
|
||||||
/// A quoted string: `"..."`.
|
/// A quoted string: `"..."`.
|
||||||
Str(EcoString),
|
Str(EcoString),
|
||||||
|
/// A code block: `{ let x = 1; x + 2 }`.
|
||||||
|
CodeBlock,
|
||||||
|
/// A template block: `[*Hi* there!]`.
|
||||||
|
TemplateBlock,
|
||||||
|
/// A grouped expression: `(1 + 2)`.
|
||||||
|
GroupExpr,
|
||||||
/// An array expression: `(1, "hi", 12cm)`.
|
/// An array expression: `(1, "hi", 12cm)`.
|
||||||
Array,
|
ArrayExpr,
|
||||||
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
|
/// A dictionary expression: `(thickness: 3pt, pattern: dashed)`.
|
||||||
Dict,
|
DictExpr,
|
||||||
/// A named pair: `thickness: 3pt`.
|
/// A named pair: `thickness: 3pt`.
|
||||||
Named,
|
Named,
|
||||||
/// A template expression: `[*Hi* there!]`.
|
|
||||||
Template,
|
|
||||||
/// A grouped expression: `(1 + 2)`.
|
|
||||||
Group,
|
|
||||||
/// A block expression: `{ let x = 1; x + 2 }`.
|
|
||||||
Block,
|
|
||||||
/// A unary operation: `-x`.
|
/// A unary operation: `-x`.
|
||||||
Unary,
|
UnaryExpr,
|
||||||
/// A binary operation: `a + b`.
|
/// A binary operation: `a + b`.
|
||||||
Binary,
|
BinaryExpr,
|
||||||
/// An invocation of a function: `f(x, y)`.
|
/// An invocation of a function: `f(x, y)`.
|
||||||
Call,
|
CallExpr,
|
||||||
/// A function call's argument list: `(x, y)`.
|
/// A function call's argument list: `(x, y)`.
|
||||||
CallArgs,
|
CallArgs,
|
||||||
/// Spreaded arguments or a parameter sink: `..x`.
|
/// Spreaded arguments or a parameter sink: `..x`.
|
||||||
Spread,
|
Spread,
|
||||||
/// A closure expression: `(x, y) => z`.
|
/// A closure expression: `(x, y) => z`.
|
||||||
Closure,
|
ClosureExpr,
|
||||||
/// A closure's parameters: `(x, y)`.
|
/// A closure's parameters: `(x, y)`.
|
||||||
ClosureParams,
|
ClosureParams,
|
||||||
/// A with expression: `f with (x, y: 1)`.
|
/// A with expression: `f with (x, y: 1)`.
|
||||||
@ -724,16 +724,16 @@ pub enum ErrorPos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NodeKind {
|
impl NodeKind {
|
||||||
/// Whether this is some kind of bracket.
|
|
||||||
pub fn is_bracket(&self) -> bool {
|
|
||||||
matches!(self, Self::LeftBracket | Self::RightBracket)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether this is some kind of brace.
|
/// Whether this is some kind of brace.
|
||||||
pub fn is_brace(&self) -> bool {
|
pub fn is_brace(&self) -> bool {
|
||||||
matches!(self, Self::LeftBrace | Self::RightBrace)
|
matches!(self, Self::LeftBrace | Self::RightBrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this is some kind of bracket.
|
||||||
|
pub fn is_bracket(&self) -> bool {
|
||||||
|
matches!(self, Self::LeftBracket | Self::RightBracket)
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether this is some kind of parenthesis.
|
/// Whether this is some kind of parenthesis.
|
||||||
pub fn is_paren(&self) -> bool {
|
pub fn is_paren(&self) -> bool {
|
||||||
matches!(self, Self::LeftParen | Self::RightParen)
|
matches!(self, Self::LeftParen | Self::RightParen)
|
||||||
@ -782,10 +782,10 @@ impl NodeKind {
|
|||||||
| Self::List
|
| Self::List
|
||||||
| Self::Raw(_)
|
| Self::Raw(_)
|
||||||
| Self::Math(_) => Some(TokenMode::Markup),
|
| Self::Math(_) => Some(TokenMode::Markup),
|
||||||
Self::Template
|
Self::TemplateBlock
|
||||||
| Self::Space(_)
|
| Self::Space(_)
|
||||||
| Self::Block
|
|
||||||
| Self::Ident(_)
|
| Self::Ident(_)
|
||||||
|
| Self::CodeBlock
|
||||||
| Self::LetExpr
|
| Self::LetExpr
|
||||||
| Self::SetExpr
|
| Self::SetExpr
|
||||||
| Self::ShowExpr
|
| Self::ShowExpr
|
||||||
@ -794,7 +794,7 @@ impl NodeKind {
|
|||||||
| Self::WhileExpr
|
| Self::WhileExpr
|
||||||
| Self::ForExpr
|
| Self::ForExpr
|
||||||
| Self::ImportExpr
|
| Self::ImportExpr
|
||||||
| Self::Call
|
| Self::CallExpr
|
||||||
| Self::IncludeExpr
|
| Self::IncludeExpr
|
||||||
| Self::LineComment
|
| Self::LineComment
|
||||||
| Self::BlockComment
|
| Self::BlockComment
|
||||||
@ -808,10 +808,10 @@ impl NodeKind {
|
|||||||
/// A human-readable name for the kind.
|
/// A human-readable name for the kind.
|
||||||
pub fn as_str(&self) -> &'static str {
|
pub fn as_str(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::LeftBracket => "opening bracket",
|
|
||||||
Self::RightBracket => "closing bracket",
|
|
||||||
Self::LeftBrace => "opening brace",
|
Self::LeftBrace => "opening brace",
|
||||||
Self::RightBrace => "closing brace",
|
Self::RightBrace => "closing brace",
|
||||||
|
Self::LeftBracket => "opening bracket",
|
||||||
|
Self::RightBracket => "closing bracket",
|
||||||
Self::LeftParen => "opening paren",
|
Self::LeftParen => "opening paren",
|
||||||
Self::RightParen => "closing paren",
|
Self::RightParen => "closing paren",
|
||||||
Self::Star => "star",
|
Self::Star => "star",
|
||||||
@ -883,18 +883,18 @@ impl NodeKind {
|
|||||||
Self::Percentage(_) => "percentage",
|
Self::Percentage(_) => "percentage",
|
||||||
Self::Fraction(_) => "`fr` value",
|
Self::Fraction(_) => "`fr` value",
|
||||||
Self::Str(_) => "string",
|
Self::Str(_) => "string",
|
||||||
Self::Array => "array",
|
Self::CodeBlock => "code block",
|
||||||
Self::Dict => "dictionary",
|
Self::TemplateBlock => "template block",
|
||||||
|
Self::GroupExpr => "group",
|
||||||
|
Self::ArrayExpr => "array",
|
||||||
|
Self::DictExpr => "dictionary",
|
||||||
Self::Named => "named argument",
|
Self::Named => "named argument",
|
||||||
Self::Template => "template",
|
Self::UnaryExpr => "unary expression",
|
||||||
Self::Group => "group",
|
Self::BinaryExpr => "binary expression",
|
||||||
Self::Block => "block",
|
Self::CallExpr => "call",
|
||||||
Self::Unary => "unary expression",
|
|
||||||
Self::Binary => "binary expression",
|
|
||||||
Self::Call => "call",
|
|
||||||
Self::CallArgs => "call arguments",
|
Self::CallArgs => "call arguments",
|
||||||
Self::Spread => "parameter sink",
|
Self::Spread => "parameter sink",
|
||||||
Self::Closure => "closure",
|
Self::ClosureExpr => "closure",
|
||||||
Self::ClosureParams => "closure parameters",
|
Self::ClosureParams => "closure parameters",
|
||||||
Self::WithExpr => "`with` expression",
|
Self::WithExpr => "`with` expression",
|
||||||
Self::LetExpr => "`let` expression",
|
Self::LetExpr => "`let` expression",
|
||||||
@ -932,10 +932,10 @@ impl Hash for NodeKind {
|
|||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
std::mem::discriminant(self).hash(state);
|
std::mem::discriminant(self).hash(state);
|
||||||
match self {
|
match self {
|
||||||
Self::LeftBracket => {}
|
|
||||||
Self::RightBracket => {}
|
|
||||||
Self::LeftBrace => {}
|
Self::LeftBrace => {}
|
||||||
Self::RightBrace => {}
|
Self::RightBrace => {}
|
||||||
|
Self::LeftBracket => {}
|
||||||
|
Self::RightBracket => {}
|
||||||
Self::LeftParen => {}
|
Self::LeftParen => {}
|
||||||
Self::RightParen => {}
|
Self::RightParen => {}
|
||||||
Self::Star => {}
|
Self::Star => {}
|
||||||
@ -1007,18 +1007,18 @@ impl Hash for NodeKind {
|
|||||||
Self::Percentage(v) => v.to_bits().hash(state),
|
Self::Percentage(v) => v.to_bits().hash(state),
|
||||||
Self::Fraction(v) => v.to_bits().hash(state),
|
Self::Fraction(v) => v.to_bits().hash(state),
|
||||||
Self::Str(v) => v.hash(state),
|
Self::Str(v) => v.hash(state),
|
||||||
Self::Array => {}
|
Self::CodeBlock => {}
|
||||||
Self::Dict => {}
|
Self::TemplateBlock => {}
|
||||||
|
Self::GroupExpr => {}
|
||||||
|
Self::ArrayExpr => {}
|
||||||
|
Self::DictExpr => {}
|
||||||
Self::Named => {}
|
Self::Named => {}
|
||||||
Self::Template => {}
|
Self::UnaryExpr => {}
|
||||||
Self::Group => {}
|
Self::BinaryExpr => {}
|
||||||
Self::Block => {}
|
Self::CallExpr => {}
|
||||||
Self::Unary => {}
|
|
||||||
Self::Binary => {}
|
|
||||||
Self::Call => {}
|
|
||||||
Self::CallArgs => {}
|
Self::CallArgs => {}
|
||||||
Self::Spread => {}
|
Self::Spread => {}
|
||||||
Self::Closure => {}
|
Self::ClosureExpr => {}
|
||||||
Self::ClosureParams => {}
|
Self::ClosureParams => {}
|
||||||
Self::WithExpr => {}
|
Self::WithExpr => {}
|
||||||
Self::LetExpr => {}
|
Self::LetExpr => {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user