From 5afb42ad89abb518a01a09051f0f9b6f75bd383e Mon Sep 17 00:00:00 2001 From: Laurenz Date: Wed, 9 Jun 2021 00:37:13 +0200 Subject: [PATCH] Lists with indent-based parsing - Unordered lists with indent-based parsing and basic layout using stacks - Headings are now also indent based - Removes syntax functions since they will be superseded by select & transform --- src/eval/capture.rs | 39 +-- src/eval/mod.rs | 27 +- src/eval/scope.rs | 3 +- src/eval/value.rs | 16 +- src/exec/context.rs | 20 +- src/exec/mod.rs | 91 ++++++- src/exec/state.rs | 2 +- src/library/markup.rs | 170 ------------ src/library/mod.rs | 12 +- src/library/pad.rs | 2 +- src/library/shapes.rs | 4 +- src/library/stack.rs | 2 +- src/parse/lines.rs | 28 +- src/parse/mod.rs | 153 ++++++----- src/parse/parser.rs | 126 ++++----- src/parse/scanner.rs | 2 +- src/parse/tokens.rs | 502 ++++++++++++++++++----------------- src/pretty.rs | 50 ++-- src/syntax/node.rs | 110 ++------ src/syntax/token.rs | 14 +- src/syntax/visit.rs | 15 +- tests/ref/code/include.png | Bin 31098 -> 31078 bytes tests/ref/markup/basic.png | Bin 3788 -> 3464 bytes tests/ref/markup/emph.png | Bin 3390 -> 2544 bytes tests/ref/markup/heading.png | Bin 5301 -> 7446 bytes tests/ref/markup/lists.png | Bin 0 -> 14750 bytes tests/ref/markup/raw.png | Bin 8225 -> 7281 bytes tests/ref/markup/strong.png | Bin 3365 -> 2401 bytes tests/typ/code/include.typ | 2 +- tests/typ/markup/basic.typ | 12 +- tests/typ/markup/emph.typ | 12 - tests/typ/markup/heading.typ | 48 ++-- tests/typ/markup/lists.typ | 45 ++++ tests/typ/markup/raw.typ | 8 - tests/typ/markup/strong.typ | 12 - 35 files changed, 710 insertions(+), 817 deletions(-) delete mode 100644 src/library/markup.rs create mode 100644 tests/ref/markup/lists.png create mode 100644 tests/typ/markup/lists.typ diff --git a/src/eval/capture.rs b/src/eval/capture.rs index 74da4747..64275e93 100644 --- a/src/eval/capture.rs +++ b/src/eval/capture.rs @@ -2,7 +2,7 @@ use std::rc::Rc; use super::{Scope, Scopes, Value}; use crate::syntax::visit::{visit_expr, Visit}; -use crate::syntax::{Expr, Ident, Node}; +use crate::syntax::{Expr, Ident}; /// A visitor that captures variable slots. #[derive(Debug)] @@ -26,37 +26,20 @@ impl<'a> CapturesVisitor<'a> { pub fn finish(self) -> Scope { self.captures } - - /// Find out whether the name is not locally defined and if so if it can be - /// captured. - fn process(&mut self, name: &str) { - if self.internal.get(name).is_none() { - if let Some(slot) = self.external.get(name) { - self.captures.def_slot(name, Rc::clone(slot)); - } - } - } } impl<'ast> Visit<'ast> for CapturesVisitor<'_> { - fn visit_node(&mut self, node: &'ast Node) { - match node { - Node::Text(_) => {} - Node::Space => {} - Node::Linebreak(_) => self.process(Node::LINEBREAK), - Node::Parbreak(_) => self.process(Node::PARBREAK), - Node::Strong(_) => self.process(Node::STRONG), - Node::Emph(_) => self.process(Node::EMPH), - Node::Heading(_) => self.process(Node::HEADING), - Node::Raw(_) => self.process(Node::RAW), - Node::Expr(expr) => self.visit_expr(expr), - } - } - fn visit_expr(&mut self, node: &'ast Expr) { - match node { - Expr::Ident(ident) => self.process(ident), - expr => visit_expr(self, expr), + if let Expr::Ident(ident) = node { + // Find out whether the name is not locally defined and if so if it + // can be captured. + if self.internal.get(ident).is_none() { + if let Some(slot) = self.external.get(ident) { + self.captures.def_slot(ident.as_str(), Rc::clone(slot)); + } + } + } else { + visit_expr(self, node); } } diff --git a/src/eval/mod.rs b/src/eval/mod.rs index c480ddfe..d1307b6d 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -218,24 +218,23 @@ pub trait Eval { } impl Eval for Tree { - type Output = NodeMap; + type Output = ExprMap; fn eval(&self, ctx: &mut EvalContext) -> Self::Output { - let mut map = NodeMap::new(); - - for node in self { - let value = if let Some(call) = node.desugar() { - call.eval(ctx) - } else if let Node::Expr(expr) = node { - expr.eval(ctx) - } else { - continue; - }; - - map.insert(node as *const _, value); + struct ExprVisitor<'a, 'b> { + ctx: &'a mut EvalContext<'b>, + map: ExprMap, } - map + impl<'ast> Visit<'ast> for ExprVisitor<'_, '_> { + fn visit_expr(&mut self, node: &'ast Expr) { + self.map.insert(node as *const _, node.eval(self.ctx)); + } + } + + let mut visitor = ExprVisitor { ctx, map: ExprMap::new() }; + visitor.visit_tree(self); + visitor.map } } diff --git a/src/eval/scope.rs b/src/eval/scope.rs index e5afb6b0..3f7c4c62 100644 --- a/src/eval/scope.rs +++ b/src/eval/scope.rs @@ -33,8 +33,7 @@ impl<'a> Scopes<'a> { /// Exit the topmost scope. /// - /// # Panics - /// Panics if no scope was entered. + /// This panics if no scope was entered. pub fn exit(&mut self) { self.top = self.scopes.pop().expect("no pushed scope"); } diff --git a/src/eval/value.rs b/src/eval/value.rs index e2ff5383..94f7f569 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -9,7 +9,7 @@ use super::EvalContext; use crate::color::{Color, RgbaColor}; use crate::exec::ExecContext; use crate::geom::{Angle, Length, Linear, Relative}; -use crate::syntax::{Node, Span, Spanned, Tree}; +use crate::syntax::{Expr, Span, Spanned, Tree}; /// A computational value. #[derive(Debug, Clone, PartialEq)] @@ -148,7 +148,7 @@ pub enum TemplateNode { /// The syntax tree of the corresponding template expression. tree: Rc, /// The evaluated expressions for the `tree`. - map: NodeMap, + map: ExprMap, }, /// A template that was converted from a string. Str(String), @@ -163,13 +163,13 @@ impl PartialEq for TemplateNode { } } -/// A map from nodes to the values they evaluated to. +/// A map from expressions to the values they evaluated to. /// -/// The raw pointers point into the nodes contained in some [`Tree`]. Since the -/// lifetime is erased, the tree could go out of scope while the hash map still -/// lives. Although this could lead to lookup panics, it is not unsafe since the -/// pointers are never dereferenced. -pub type NodeMap = HashMap<*const Node, Value>; +/// The raw pointers point into the expressions contained in some [`Tree`]. +/// Since the lifetime is erased, the tree could go out of scope while the hash +/// map still lives. Although this could lead to lookup panics, it is not unsafe +/// since the pointers are never dereferenced. +pub type ExprMap = HashMap<*const Expr, Value>; /// A reference-counted dynamic template node that can implement custom /// behaviour. diff --git a/src/exec/context.rs b/src/exec/context.rs index 016b092a..63008260 100644 --- a/src/exec/context.rs +++ b/src/exec/context.rs @@ -1,13 +1,13 @@ use std::mem; -use super::{Exec, FontFamily, State}; +use super::{Exec, ExecWithMap, FontFamily, State}; use crate::diag::{Diag, DiagSet, Pass}; -use crate::eval::TemplateValue; +use crate::eval::{ExprMap, TemplateValue}; use crate::geom::{Align, Dir, Gen, GenAxis, Length, Linear, Sides, Size}; use crate::layout::{ AnyNode, PadNode, PageRun, ParChild, ParNode, StackChild, StackNode, Tree, }; -use crate::syntax::Span; +use crate::syntax::{self, Span}; /// The context for execution. pub struct ExecContext { @@ -48,12 +48,22 @@ impl ExecContext { } /// Execute a template and return the result as a stack node. - pub fn exec_template(&mut self, template: &TemplateValue) -> StackNode { + pub fn exec_template_stack(&mut self, template: &TemplateValue) -> StackNode { + self.exec_stack(|ctx| template.exec(ctx)) + } + + /// Execute a tree with a map and return the result as a stack node. + pub fn exec_tree_stack(&mut self, tree: &syntax::Tree, map: &ExprMap) -> StackNode { + self.exec_stack(|ctx| tree.exec_with_map(ctx, map)) + } + + /// Execute something and return the result as a stack node. + pub fn exec_stack(&mut self, f: impl FnOnce(&mut Self)) -> StackNode { let snapshot = self.state.clone(); let page = self.page.take(); let stack = mem::replace(&mut self.stack, StackBuilder::new(&self.state)); - template.exec(self); + f(self); self.state = snapshot; self.page = page; diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 35e6b55c..a13d8c5e 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -9,10 +9,11 @@ pub use state::*; use std::rc::Rc; use crate::diag::Pass; -use crate::eval::{NodeMap, TemplateFunc, TemplateNode, TemplateValue, Value}; -use crate::layout; +use crate::eval::{ExprMap, TemplateFunc, TemplateNode, TemplateValue, Value}; +use crate::geom::{Dir, Gen}; +use crate::layout::{self, FixedNode, StackChild, StackNode}; use crate::pretty::pretty; -use crate::syntax::*; +use crate::syntax; /// Execute a template to produce a layout tree. pub fn exec(template: &TemplateValue, state: State) -> Pass { @@ -33,30 +34,96 @@ pub trait Exec { fn exec(&self, ctx: &mut ExecContext); } -/// Execute a node with a node map that applies to it. +/// Execute a node with an expression map that applies to it. pub trait ExecWithMap { /// Execute the node. - fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap); + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap); } -impl ExecWithMap for Tree { - fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap) { +impl ExecWithMap for syntax::Tree { + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { for node in self { node.exec_with_map(ctx, map); } } } -impl ExecWithMap for Node { - fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap) { +impl ExecWithMap for syntax::Node { + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { match self { - Node::Text(text) => ctx.push_text(text), - Node::Space => ctx.push_word_space(), - _ => map[&(self as *const _)].exec(ctx), + Self::Text(text) => ctx.push_text(text), + Self::Space => ctx.push_word_space(), + Self::Linebreak(_) => ctx.linebreak(), + Self::Parbreak(_) => ctx.parbreak(), + Self::Strong(_) => ctx.state.font.strong ^= true, + Self::Emph(_) => ctx.state.font.emph ^= true, + Self::Raw(raw) => raw.exec(ctx), + Self::Heading(heading) => heading.exec_with_map(ctx, map), + Self::List(list) => list.exec_with_map(ctx, map), + Self::Expr(expr) => map[&(expr as *const _)].exec(ctx), } } } +impl Exec for syntax::RawNode { + fn exec(&self, ctx: &mut ExecContext) { + if self.block { + ctx.parbreak(); + } + + let snapshot = ctx.state.clone(); + ctx.set_monospace(); + ctx.push_text(&self.text); + ctx.state = snapshot; + + if self.block { + ctx.parbreak(); + } + } +} + +impl ExecWithMap for syntax::HeadingNode { + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { + let snapshot = ctx.state.clone(); + + let upscale = 1.6 - 0.1 * self.level as f64; + ctx.state.font.scale *= upscale; + ctx.state.font.strong = true; + + self.body.exec_with_map(ctx, map); + + ctx.state = snapshot; + ctx.parbreak(); + } +} + +impl ExecWithMap for syntax::ListNode { + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { + ctx.parbreak(); + + let bullet = ctx.exec_stack(|ctx| ctx.push_text("•")); + let body = ctx.exec_tree_stack(&self.body, map); + + let stack = StackNode { + dirs: Gen::new(Dir::TTB, ctx.state.lang.dir), + aspect: None, + children: vec![ + StackChild::Any(bullet.into(), Gen::default()), + StackChild::Spacing(ctx.state.font.resolve_size() / 2.0), + StackChild::Any(body.into(), Gen::default()), + ], + }; + + ctx.push(FixedNode { + width: None, + height: None, + child: stack.into(), + }); + + ctx.parbreak(); + } +} + impl Exec for Value { fn exec(&self, ctx: &mut ExecContext) { match self { diff --git a/src/exec/state.rs b/src/exec/state.rs index 9a8971cc..aeeeaed5 100644 --- a/src/exec/state.rs +++ b/src/exec/state.rs @@ -7,7 +7,7 @@ use crate::geom::*; use crate::layout::Fill; use crate::paper::{Paper, PaperClass, PAPER_A4}; -/// The evaluation state. +/// The execution state. #[derive(Debug, Clone, PartialEq)] pub struct State { /// The current language-related settings. diff --git a/src/library/markup.rs b/src/library/markup.rs deleted file mode 100644 index 0a80fe74..00000000 --- a/src/library/markup.rs +++ /dev/null @@ -1,170 +0,0 @@ -use super::*; -use crate::syntax::{HeadingNode, RawNode}; - -/// `linebreak`: Start a new line. -/// -/// # Syntax -/// This function has dedicated syntax: -/// ```typst -/// This line ends here, \ -/// And a new one begins. -/// ``` -/// -/// # Return value -/// A template that inserts a line break. -pub fn linebreak(_: &mut EvalContext, _: &mut FuncArgs) -> Value { - Value::template(Node::LINEBREAK, move |ctx| { - ctx.linebreak(); - }) -} - -/// `parbreak`: Start a new paragraph. -/// -/// # Return value -/// A template that inserts a paragraph break. -pub fn parbreak(_: &mut EvalContext, _: &mut FuncArgs) -> Value { - Value::template(Node::PARBREAK, move |ctx| { - ctx.parbreak(); - }) -} - -/// `strong`: Strong text. -/// -/// # Syntax -/// This function has dedicated syntax. -/// ```typst -/// This is *important*! -/// ``` -/// -/// # Positional parameters -/// - Body: optional, of type `template`. -/// -/// # Return value -/// A template that flips the boldness of text. The effect is scoped to the -/// body if present. -pub fn strong(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let body = args.eat::(ctx); - Value::template(Node::STRONG, move |ctx| { - let snapshot = ctx.state.clone(); - ctx.state.font.strong ^= true; - - if let Some(body) = &body { - body.exec(ctx); - ctx.state = snapshot; - } - }) -} - -/// `emph`: Emphasized text. -/// -/// # Syntax -/// This function has dedicated syntax. -/// ```typst -/// I would have _never_ thought so! -/// ``` -/// -/// # Positional parameters -/// - Body: optional, of type `template`. -/// -/// # Return value -/// A template that flips whether text is set in italics. The effect is scoped -/// to the body if present. -pub fn emph(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let body = args.eat::(ctx); - Value::template(Node::EMPH, move |ctx| { - let snapshot = ctx.state.clone(); - ctx.state.font.emph ^= true; - - if let Some(body) = &body { - body.exec(ctx); - ctx.state = snapshot; - } - }) -} - -/// `heading`: A section heading. -/// -/// # Syntax -/// This function has dedicated syntax. -/// ```typst -/// = Section -/// ... -/// -/// == Subsection -/// ... -/// ``` -/// -/// # Positional parameters -/// - Body, of type `template`. -/// -/// # Named parameters -/// - Section depth: `level`, of type `integer` between 1 and 6. -/// -/// # Return value -/// A template that sets the body as a section heading, that is, large and in -/// bold. -pub fn heading(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let level = args.eat_named(ctx, HeadingNode::LEVEL).unwrap_or(1); - let body = args - .eat_expect::(ctx, HeadingNode::BODY) - .unwrap_or_default(); - - Value::template(Node::HEADING, move |ctx| { - let snapshot = ctx.state.clone(); - let upscale = 1.6 - 0.1 * level as f64; - ctx.state.font.scale *= upscale; - ctx.state.font.strong = true; - - body.exec(ctx); - ctx.state = snapshot; - - ctx.parbreak(); - }) -} - -/// `raw`: Raw text. -/// -/// # Syntax -/// This function has dedicated syntax: -/// - For inline-level raw text: -/// ```typst -/// `...` -/// ``` -/// - For block-level raw text: -/// ````typst -/// ```rust -/// println!("Hello World!"); -/// ``` -/// ```` -/// -/// # Positional parameters -/// - Text, of type `string`. -/// -/// # Named parameters -/// - Language for syntax highlighting: `lang`, of type `string`. -/// - Whether the item is block level (split in its own paragraph): `block`, of -/// type `boolean`. -/// -/// # Return value -/// A template that sets the text raw, that is, in monospace and optionally with -/// syntax highlighting. -pub fn raw(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let text = args.eat_expect::(ctx, RawNode::TEXT).unwrap_or_default(); - let _lang = args.eat_named::(ctx, RawNode::LANG); - let block = args.eat_named(ctx, RawNode::BLOCK).unwrap_or(false); - - Value::template(Node::RAW, move |ctx| { - if block { - ctx.parbreak(); - } - - let snapshot = ctx.state.clone(); - ctx.set_monospace(); - ctx.push_text(&text); - ctx.state = snapshot; - - if block { - ctx.parbreak(); - } - }) -} diff --git a/src/library/mod.rs b/src/library/mod.rs index 6a46314c..f9e4f68a 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -8,7 +8,6 @@ mod basic; mod font; mod image; mod lang; -mod markup; mod math; mod pad; mod page; @@ -22,7 +21,6 @@ pub use align::*; pub use basic::*; pub use font::*; pub use lang::*; -pub use markup::*; pub use math::*; pub use pad::*; pub use page::*; @@ -38,20 +36,12 @@ use crate::eval::{EvalContext, FuncArgs, Scope, TemplateValue, Value}; use crate::exec::{Exec, FontFamily}; use crate::font::{FontStyle, FontWeight, VerticalFontMetric}; use crate::geom::*; -use crate::syntax::{Node, Spanned}; +use crate::syntax::Spanned; /// Construct a scope containing all standard library definitions. pub fn new() -> Scope { let mut std = Scope::new(); - // Syntax functions. - std.def_func(Node::LINEBREAK, linebreak); - std.def_func(Node::PARBREAK, parbreak); - std.def_func(Node::STRONG, strong); - std.def_func(Node::EMPH, emph); - std.def_func(Node::HEADING, heading); - std.def_func(Node::RAW, raw); - // Library functions. std.def_func("align", align); std.def_func("circle", circle); diff --git a/src/library/pad.rs b/src/library/pad.rs index 4b6236d0..6b944c9c 100644 --- a/src/library/pad.rs +++ b/src/library/pad.rs @@ -31,7 +31,7 @@ pub fn pad(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { ); Value::template("pad", move |ctx| { - let child = ctx.exec_template(&body).into(); + let child = ctx.exec_template_stack(&body).into(); ctx.push(PadNode { padding, child }); }) } diff --git a/src/library/shapes.rs b/src/library/shapes.rs index a47203c4..287b1c10 100644 --- a/src/library/shapes.rs +++ b/src/library/shapes.rs @@ -61,7 +61,7 @@ fn rect_impl( body: TemplateValue, ) -> Value { Value::template(name, move |ctx| { - let mut stack = ctx.exec_template(&body); + let mut stack = ctx.exec_template_stack(&body); stack.aspect = aspect; let fixed = FixedNode { width, height, child: stack.into() }; @@ -137,7 +137,7 @@ fn ellipse_impl( // perfectly into the ellipse. const PAD: f64 = 0.5 - SQRT_2 / 4.0; - let mut stack = ctx.exec_template(&body); + let mut stack = ctx.exec_template_stack(&body); stack.aspect = aspect; let fixed = FixedNode { diff --git a/src/library/stack.rs b/src/library/stack.rs index b6f92e16..03bdc6a1 100644 --- a/src/library/stack.rs +++ b/src/library/stack.rs @@ -26,7 +26,7 @@ pub fn stack(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let children = children .iter() .map(|child| { - let child = ctx.exec_template(child).into(); + let child = ctx.exec_template_stack(child).into(); StackChild::Any(child, ctx.state.aligns) }) .collect(); diff --git a/src/parse/lines.rs b/src/parse/lines.rs index 8693af44..bbdedaa5 100644 --- a/src/parse/lines.rs +++ b/src/parse/lines.rs @@ -32,6 +32,8 @@ impl<'s> LineMap<'s> { let start = self.line_starts.get(line_index)?; let head = self.src.get(start.to_usize() .. pos.to_usize())?; + + // TODO: What about tabs? let column_index = head.chars().count(); Some(Location { @@ -52,12 +54,14 @@ impl<'s> LineMap<'s> { let line = self.src.get(line_start.to_usize() .. line_end)?; - // Find the index in the line. For the first column, the index is always zero. For - // other columns, we have to look at which byte the char directly before the - // column in question ends. We can't do `nth(column_idx)` directly since the - // column may be behind the last char. + // Find the index in the line. For the first column, the index is always + // zero. For other columns, we have to look at which byte the char + // directly before the column in question ends. We can't do + // `nth(column_idx)` directly since the column may be behind the last + // char. let column_idx = location.column.checked_sub(1)? as usize; let line_offset = if let Some(prev_idx) = column_idx.checked_sub(1) { + // TODO: What about tabs? let (idx, prev) = line.char_indices().nth(prev_idx)?; idx + prev.len_utf8() } else { @@ -68,6 +72,22 @@ impl<'s> LineMap<'s> { } } +/// Determine the column at the end of the string. +pub fn search_column(src: &str) -> usize { + let mut column = 0; + for c in src.chars().rev() { + if is_newline(c) { + break; + } else if c == '\t' { + // TODO: How many columns per tab? + column += 2; + } else { + column += 1; + } + } + column +} + /// Whether this character denotes a newline. pub fn is_newline(character: char) -> bool { matches!( diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 1b32b31e..048bcb1c 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -25,14 +25,32 @@ pub fn parse(src: &str) -> Pass { /// Parse a syntax tree. fn tree(p: &mut Parser) -> Tree { + tree_while(p, |_| true) +} + +/// Parse a syntax tree that stays right of the column at the start of the next +/// non-whitespace token. +fn tree_indented(p: &mut Parser) -> Tree { + p.skip_white(); + let column = p.column(p.next_start()); + tree_while(p, |p| match p.peek() { + Some(Token::Space(n)) if n >= 1 => p.column(p.next_end()) >= column, + _ => true, + }) +} + +/// Parse a syntax tree. +fn tree_while(p: &mut Parser, mut f: impl FnMut(&mut Parser) -> bool) -> Tree { // We keep track of whether we are at the start of a block or paragraph - // to know whether headings are allowed. + // to know whether things like headings are allowed. let mut at_start = true; let mut tree = vec![]; - while !p.eof() { + while !p.eof() && f(p) { if let Some(node) = node(p, &mut at_start) { - if !matches!(node, Node::Parbreak(_) | Node::Space) { - at_start = false; + match node { + Node::Space => {} + Node::Parbreak(_) => {} + _ => at_start = false, } tree.push(node); } @@ -57,10 +75,16 @@ fn node(p: &mut Parser, at_start: &mut bool) -> Option { // Text. Token::Text(text) => Node::Text(text.into()), + Token::Tilde => Node::Text("\u{00A0}".into()), + Token::HyphHyph => Node::Text("\u{2013}".into()), + Token::HyphHyphHyph => Node::Text("\u{2014}".into()), + Token::UnicodeEscape(t) => Node::Text(unicode_escape(p, t)), // Markup. + Token::Backslash => Node::Linebreak(span), Token::Star => Node::Strong(span), Token::Underscore => Node::Emph(span), + Token::Raw(t) => raw(p, t), Token::Hashtag => { if *at_start { return Some(heading(p)); @@ -68,10 +92,13 @@ fn node(p: &mut Parser, at_start: &mut bool) -> Option { Node::Text(p.peek_src().into()) } } - Token::Tilde => Node::Text("\u{00A0}".into()), - Token::Backslash => Node::Linebreak(span), - Token::Raw(t) => raw(p, t), - Token::UnicodeEscape(t) => Node::Text(unicode_escape(p, t)), + Token::Hyph => { + if *at_start { + return Some(list(p)); + } else { + Node::Text(p.peek_src().into()) + } + } // Hashtag + keyword / identifier. Token::Ident(_) @@ -81,31 +108,27 @@ fn node(p: &mut Parser, at_start: &mut bool) -> Option { | Token::For | Token::Import | Token::Include => { - *at_start = false; let stmt = matches!(token, Token::Let | Token::Import); let group = if stmt { Group::Stmt } else { Group::Expr }; p.start_group(group, TokenMode::Code); let expr = expr_with(p, true, 0); if stmt && expr.is_some() && !p.eof() { - p.expected_at("semicolon or line break", p.end()); + p.expected_at("semicolon or line break", p.prev_end()); } p.end_group(); // Uneat spaces we might have eaten eagerly. - p.jump(p.end()); return expr.map(Node::Expr); } // Block. Token::LeftBrace => { - *at_start = false; return Some(Node::Expr(block(p, false))); } // Template. Token::LeftBracket => { - *at_start = false; return Some(Node::Expr(template(p))); } @@ -125,33 +148,22 @@ fn node(p: &mut Parser, at_start: &mut bool) -> Option { Some(node) } -/// Parse a heading. -fn heading(p: &mut Parser) -> Node { - let start = p.start(); - p.assert(Token::Hashtag); +/// Handle a unicode escape sequence. +fn unicode_escape(p: &mut Parser, token: UnicodeEscapeToken) -> String { + let span = p.peek_span(); + let text = if let Some(c) = resolve::resolve_hex(token.sequence) { + c.to_string() + } else { + // Print out the escape sequence verbatim if it is invalid. + p.diag(error!(span, "invalid unicode escape sequence")); + p.peek_src().into() + }; - // Count depth. - let mut level: usize = 1; - while p.eat_if(Token::Hashtag) { - level += 1; + if !token.terminated { + p.diag(error!(span.end, "expected closing brace")); } - if level > 6 { - p.diag(warning!(start .. p.end(), "should not exceed depth 6")); - level = 6; - } - - // Parse the heading contents. - let mut tree = vec![]; - while p.check(|t| !matches!(t, Token::Space(n) if n >= 1)) { - tree.extend(node(p, &mut false)); - } - - Node::Heading(HeadingNode { - span: p.span(start), - level, - contents: Rc::new(tree), - }) + text } /// Handle a raw block. @@ -164,22 +176,37 @@ fn raw(p: &mut Parser, token: RawToken) -> Node { Node::Raw(raw) } -/// Handle a unicode escape sequence. -fn unicode_escape(p: &mut Parser, token: UnicodeEscapeToken) -> String { - let span = p.peek_span(); - let text = if let Some(c) = resolve::resolve_hex(token.sequence) { - c.to_string() - } else { - // Print out the escape sequence verbatim if it is invalid. - p.diag(error!(span, "invalid unicode escape sequence")); - p.get(span).into() - }; +/// Parse a heading. +fn heading(p: &mut Parser) -> Node { + let start = p.next_start(); + p.assert(Token::Hashtag); - if !token.terminated { - p.diag(error!(span.end, "expected closing brace")); + // Count depth. + let mut level: usize = 1; + while p.eat_if(Token::Hashtag) { + level += 1; } - text + if level > 6 { + p.diag(warning!(start .. p.prev_end(), "should not exceed depth 6")); + level = 6; + } + + let body = tree_indented(p); + + Node::Heading(HeadingNode { + span: p.span(start), + level, + body: Rc::new(body), + }) +} + +/// Parse a single list item. +fn list(p: &mut Parser) -> Node { + let start = p.next_start(); + p.assert(Token::Hyph); + let body = tree_indented(p); + Node::List(ListNode { span: p.span(start), body }) } /// Parse an expression. @@ -195,7 +222,7 @@ fn expr(p: &mut Parser) -> Option { /// /// Stops parsing at operations with lower precedence than `min_prec`, fn expr_with(p: &mut Parser, atomic: bool, min_prec: usize) -> Option { - let start = p.start(); + let start = p.next_start(); let mut lhs = match p.eat_map(UnOp::from_token) { Some(op) => { let prec = op.precedence(); @@ -383,7 +410,7 @@ fn collection(p: &mut Parser) -> (Vec, bool) { break; } - let behind = p.end(); + let behind = p.prev_end(); if p.eat_if(Token::Comma) { has_comma = true; } else { @@ -467,7 +494,7 @@ fn block(p: &mut Parser, scoping: bool) -> Expr { if let Some(expr) = expr(p) { exprs.push(expr); if !p.eof() { - p.expected_at("semicolon or line break", p.end()); + p.expected_at("semicolon or line break", p.prev_end()); } } p.end_group(); @@ -506,14 +533,14 @@ fn call(p: &mut Parser, callee: Expr) -> Expr { /// Parse the arguments to a function call. fn args(p: &mut Parser) -> CallArgs { - let start = p.start(); + let start = p.next_start(); let items = collection(p).0; CallArgs { span: p.span(start), items } } /// Parse a let expression. fn expr_let(p: &mut Parser) -> Option { - let start = p.start(); + let start = p.next_start(); p.assert(Token::Let); let mut expr_let = None; @@ -532,7 +559,7 @@ fn expr_let(p: &mut Parser) -> Option { init = expr(p); } else if params.is_some() { // Function definitions must have a body. - p.expected_at("body", p.end()); + p.expected_at("body", p.prev_end()); } // Rewrite into a closure expression if it's a function definition. @@ -558,7 +585,7 @@ fn expr_let(p: &mut Parser) -> Option { /// Parse an if expresion. fn expr_if(p: &mut Parser) -> Option { - let start = p.start(); + let start = p.next_start(); p.assert(Token::If); let mut expr_if = None; @@ -589,7 +616,7 @@ fn expr_if(p: &mut Parser) -> Option { /// Parse a while expresion. fn expr_while(p: &mut Parser) -> Option { - let start = p.start(); + let start = p.next_start(); p.assert(Token::While); let mut expr_while = None; @@ -608,7 +635,7 @@ fn expr_while(p: &mut Parser) -> Option { /// Parse a for expression. fn expr_for(p: &mut Parser) -> Option { - let start = p.start(); + let start = p.next_start(); p.assert(Token::For); let mut expr_for = None; @@ -643,7 +670,7 @@ fn for_pattern(p: &mut Parser) -> Option { /// Parse an import expression. fn expr_import(p: &mut Parser) -> Option { - let start = p.start(); + let start = p.next_start(); p.assert(Token::Import); let mut expr_import = None; @@ -657,7 +684,7 @@ fn expr_import(p: &mut Parser) -> Option { p.start_group(Group::Expr, TokenMode::Code); let items = collection(p).0; if items.is_empty() { - p.expected_at("import items", p.end()); + p.expected_at("import items", p.prev_end()); } let idents = idents(p, items); @@ -680,7 +707,7 @@ fn expr_import(p: &mut Parser) -> Option { /// Parse an include expression. fn expr_include(p: &mut Parser) -> Option { - let start = p.start(); + let start = p.next_start(); p.assert(Token::Include); expr(p).map(|path| { @@ -710,7 +737,7 @@ fn body(p: &mut Parser) -> Option { Some(Token::LeftBracket) => Some(template(p)), Some(Token::LeftBrace) => Some(block(p, true)), _ => { - p.expected_at("body", p.end()); + p.expected_at("body", p.prev_end()); None } } diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 6269ad73..27346587 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,6 +1,7 @@ use std::fmt::{self, Debug, Formatter}; +use std::ops::Range; -use super::{Scanner, TokenMode, Tokens}; +use super::{search_column, TokenMode, Tokens}; use crate::diag::{Diag, DiagSet}; use crate::syntax::{Pos, Span, Token}; @@ -17,10 +18,10 @@ pub struct Parser<'s> { /// The peeked token. /// (Same as `next` except if we are at the end of group, then `None`). peeked: Option>, - /// The start position of the peeked token. - next_start: Pos, /// The end position of the last (non-whitespace if in code mode) token. - last_end: Pos, + prev_end: usize, + /// The start position of the peeked token. + next_start: usize, } /// A logical group of tokens, e.g. `[...]`. @@ -28,7 +29,7 @@ pub struct Parser<'s> { struct GroupEntry { /// The start position of the group. Used by `Parser::end_group` to return /// The group's full span. - pub start: Pos, + pub start: usize, /// The kind of group this is. This decides which tokens will end the group. /// For example, a [`Group::Paren`] will be ended by /// [`Token::RightParen`]. @@ -59,12 +60,12 @@ impl<'s> Parser<'s> { let next = tokens.next(); Self { diags: DiagSet::new(), - next, tokens, - last_end: Pos::ZERO, - peeked: next, - next_start: Pos::ZERO, groups: vec![], + next, + peeked: next, + prev_end: 0, + next_start: 0, } } @@ -76,9 +77,9 @@ impl<'s> Parser<'s> { /// Eat the next token and add a diagnostic that it is not the expected /// `thing`. pub fn expected(&mut self, what: &str) { - let before = self.next_start; + let before = self.next_start(); if let Some(found) = self.eat() { - let after = self.last_end; + let after = self.prev_end(); self.diag(error!( before .. after, "expected {}, found {}", @@ -86,20 +87,20 @@ impl<'s> Parser<'s> { found.name(), )); } else { - self.expected_at(what, self.next_start); + self.expected_at(what, self.next_start()); } } /// Add a diagnostic that `what` was expected at the given position. - pub fn expected_at(&mut self, what: &str, pos: Pos) { - self.diag(error!(pos, "expected {}", what)); + pub fn expected_at(&mut self, what: &str, pos: impl Into) { + self.diag(error!(pos.into(), "expected {}", what)); } /// Eat the next token and add a diagnostic that it is unexpected. pub fn unexpected(&mut self) { - let before = self.next_start; + let before = self.next_start(); if let Some(found) = self.eat() { - let after = self.last_end; + let after = self.prev_end(); self.diag(error!(before .. after, "unexpected {}", found.name())); } } @@ -110,11 +111,10 @@ impl<'s> Parser<'s> { /// `eat()` and `peek()` return `None`. Parsing can only continue with /// a matching call to `end_group`. /// - /// # Panics /// This panics if the next token does not start the given group. pub fn start_group(&mut self, kind: Group, mode: TokenMode) { self.groups.push(GroupEntry { - start: self.next_start, + start: self.next_start(), kind, outer_mode: self.tokens.mode(), }); @@ -133,7 +133,6 @@ impl<'s> Parser<'s> { /// End the parsing of a group. /// - /// # Panics /// This panics if no group was started. pub fn end_group(&mut self) -> Span { let prev_mode = self.tokens.mode(); @@ -156,17 +155,16 @@ impl<'s> Parser<'s> { self.bump(); rescan = false; } else if required { - self.diag(error!(self.next_start, "expected {}", end.name())); + self.diag(error!(self.next_start(), "expected {}", end.name())); } } // Rescan the peeked token if the mode changed. if rescan { - self.tokens.jump(self.last_end); - self.bump(); + self.jump(self.prev_end()); } - Span::new(group.start, self.last_end) + Span::new(group.start, self.prev_end()) } /// The tokenization mode outside of the current group. @@ -193,7 +191,7 @@ impl<'s> Parser<'s> { /// Peek at the next token if it follows immediately after the last one /// without any whitespace in between. pub fn peek_direct(&self) -> Option> { - if self.next_start == self.last_end { + if self.next_start() == self.prev_end() { self.peeked } else { None @@ -204,15 +202,17 @@ impl<'s> Parser<'s> { /// /// Has length zero if `peek()` returns `None`. pub fn peek_span(&self) -> Span { - Span::new( - self.next_start, - if self.eof() { self.next_start } else { self.tokens.pos() }, - ) + self.peek_range().into() } /// Peek at the source of the next token. pub fn peek_src(&self) -> &'s str { - self.get(self.peek_span()) + self.tokens.scanner().get(self.peek_range()) + } + + /// Peek at the source range (start and end index) of the next token. + pub fn peek_range(&self) -> Range { + self.next_start() .. self.next_end() } /// Checks whether the next token fulfills a condition. @@ -255,11 +255,11 @@ impl<'s> Parser<'s> { mapped } - /// Eat the next token and return its span. + /// Eat the next token and return its source range. pub fn eat_span(&mut self) -> Span { - let start = self.next_start; + let start = self.next_start(); self.eat(); - Span::new(start, self.last_end) + Span::new(start, self.prev_end()) } /// Consume the next token if it is the given one and produce a diagnostic @@ -267,7 +267,7 @@ impl<'s> Parser<'s> { pub fn expect(&mut self, t: Token) -> bool { let eaten = self.eat_if(t); if !eaten { - self.expected_at(t.name(), self.last_end); + self.expected_at(t.name(), self.prev_end()); } eaten } @@ -290,45 +290,48 @@ impl<'s> Parser<'s> { } } - /// The position at which the next token starts. - pub fn start(&self) -> Pos { + /// The index at which the last token ended. + /// + /// Refers to the end of the last _non-whitespace_ token in code mode. + pub fn prev_end(&self) -> usize { + self.prev_end + } + + /// The index at which the next token starts. + pub fn next_start(&self) -> usize { self.next_start } - /// The position at which the last token ended. + /// The index at which the next token will end. /// - /// Refers to the end of the last _non-whitespace_ token in code mode. - pub fn end(&self) -> Pos { - self.last_end + /// Is the same as [`next_start()`][Self::next_start] if `peek()` returns + /// `None`. + pub fn next_end(&self) -> usize { + self.tokens.index() } - /// The span from `start` to the end of the last token. - pub fn span(&self, start: Pos) -> Span { - Span::new(start, self.last_end) + /// Determine the column for the given index in the source. + pub fn column(&self, index: usize) -> usize { + search_column(self.tokens.scanner().get(.. index)) } - /// Jump to a position in the source string. - pub fn jump(&mut self, pos: Pos) { - self.tokens.jump(pos); + /// The span from `start` to [`self.prev_end()`](Self::prev_end). + pub fn span(&self, start: impl Into) -> Span { + Span::new(start, self.prev_end()) + } + + /// Jump to an index in the string. + /// + /// You need to know the correct column. + fn jump(&mut self, index: usize) { + self.tokens.jump(index); self.bump(); } - /// Slice a part out of the source string. - pub fn get(&self, span: impl Into) -> &'s str { - self.tokens.scanner().get(span.into().to_range()) - } - - /// The underlying scanner. - pub fn scanner(&self) -> Scanner<'s> { - let mut scanner = self.tokens.scanner().clone(); - scanner.jump(self.next_start.to_usize()); - scanner - } - /// Move to the next token. fn bump(&mut self) { - self.last_end = self.tokens.pos(); - self.next_start = self.tokens.pos(); + self.prev_end = self.tokens.index(); + self.next_start = self.tokens.index(); self.next = self.tokens.next(); if self.tokens.mode() == TokenMode::Code { @@ -339,7 +342,7 @@ impl<'s> Parser<'s> { Some(Token::BlockComment(_)) => true, _ => false, } { - self.next_start = self.tokens.pos(); + self.next_start = self.tokens.index(); self.next = self.tokens.next(); } } @@ -381,7 +384,8 @@ impl<'s> Parser<'s> { impl Debug for Parser<'_> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let s = self.scanner(); + let mut s = self.tokens.scanner(); + s.jump(self.next_start()); write!(f, "Parser({}|{})", s.eaten(), s.rest()) } } diff --git a/src/parse/scanner.rs b/src/parse/scanner.rs index cc23a612..1f262e63 100644 --- a/src/parse/scanner.rs +++ b/src/parse/scanner.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Debug, Formatter}; use std::slice::SliceIndex; /// A featureful char-based scanner. -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Scanner<'s> { src: &'s str, index: usize, diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs index fa86d2f1..74051801 100644 --- a/src/parse/tokens.rs +++ b/src/parse/tokens.rs @@ -38,20 +38,22 @@ impl<'s> Tokens<'s> { self.mode = mode; } - /// The position in the string at which the last token ends and next token + /// The index in the string at which the last token ends and next token /// will start. - pub fn pos(&self) -> Pos { - self.s.index().into() + pub fn index(&self) -> usize { + self.s.index() } - /// Jump to the given position. - pub fn jump(&mut self, pos: Pos) { - self.s.jump(pos.to_usize()); + /// Jump to the given index in the string. + /// + /// You need to know the correct column. + pub fn jump(&mut self, index: usize) { + self.s.jump(index); } /// The underlying scanner. - pub fn scanner(&self) -> &Scanner<'s> { - &self.s + pub fn scanner(&self) -> Scanner<'s> { + self.s } } @@ -62,126 +64,100 @@ impl<'s> Iterator for Tokens<'s> { fn next(&mut self) -> Option { let start = self.s.index(); let c = self.s.eat()?; + Some(match c { + // Blocks and templates. + '[' => Token::LeftBracket, + ']' => Token::RightBracket, + '{' => Token::LeftBrace, + '}' => Token::RightBrace, - // This never loops. It just exists to allow breaking out of it. - loop { - // Common elements. - return Some(match c { - // Blocks and templates. - '[' => Token::LeftBracket, - ']' => Token::RightBracket, - '{' => Token::LeftBrace, - '}' => Token::RightBrace, + // Headings, keywords, identifiers, colors. + '#' => self.hash(start), - // Headings, keywords, identifiers, colors. - '#' => self.hash(start), + // Whitespace. + c if c.is_whitespace() => self.whitespace(c), - // Whitespace. - c if c.is_whitespace() => self.whitespace(c), + // Comments. + '/' if self.s.eat_if('/') => self.line_comment(), + '/' if self.s.eat_if('*') => self.block_comment(), + '*' if self.s.eat_if('/') => Token::Invalid(self.s.eaten_from(start)), - // Comments. - '/' if self.s.eat_if('/') => self.line_comment(), - '/' if self.s.eat_if('*') => self.block_comment(), - '*' if self.s.eat_if('/') => Token::Invalid(self.s.eaten_from(start)), - - _ => break, - }); - } - - Some(match self.mode { - TokenMode::Markup => match c { - // Markup. - '*' => Token::Star, - '_' => Token::Underscore, - '~' => Token::Tilde, - '`' => self.raw(), - '$' => self.math(), - '\\' => self.backslash(), - - // Plain text. - _ => self.text(start), - }, - - TokenMode::Code => match c { - // Parens. - '(' => Token::LeftParen, - ')' => Token::RightParen, - - // Length two. - '=' if self.s.eat_if('=') => Token::EqEq, - '!' if self.s.eat_if('=') => Token::BangEq, - '<' if self.s.eat_if('=') => Token::LtEq, - '>' if self.s.eat_if('=') => Token::GtEq, - '+' if self.s.eat_if('=') => Token::PlusEq, - '-' if self.s.eat_if('=') => Token::HyphEq, - '*' if self.s.eat_if('=') => Token::StarEq, - '/' if self.s.eat_if('=') => Token::SlashEq, - '.' if self.s.eat_if('.') => Token::Dots, - '=' if self.s.eat_if('>') => Token::Arrow, - - // Length one. - ',' => Token::Comma, - ';' => Token::Semicolon, - ':' => Token::Colon, - '+' => Token::Plus, - '-' => Token::Hyph, - '*' => Token::Star, - '/' => Token::Slash, - '=' => Token::Eq, - '<' => Token::Lt, - '>' => Token::Gt, - - // Identifiers. - c if is_id_start(c) => self.ident(start), - - // Numbers. - c if c.is_ascii_digit() - || (c == '.' && self.s.check(|n| n.is_ascii_digit())) => - { - self.number(start, c) - } - - // Strings. - '"' => self.string(), - - _ => Token::Invalid(self.s.eaten_from(start)), + // Other things. + _ => match self.mode { + TokenMode::Markup => self.markup(start, c), + TokenMode::Code => self.code(start, c), }, }) } } impl<'s> Tokens<'s> { - fn hash(&mut self, start: usize) -> Token<'s> { - let read = self.s.eat_while(is_id_continue); + fn markup(&mut self, start: usize, c: char) -> Token<'s> { + match c { + // Markup. + '~' => Token::Tilde, + '*' => Token::Star, + '_' => Token::Underscore, + '\\' => self.backslash(), + '`' => self.raw(), + '$' => self.math(), + '-' => self.hyph(start), - match self.mode { - TokenMode::Markup => { - if read.is_empty() { - return Token::Hashtag; - } - - if let Some(token) = keyword(read) { - return token; - } - - if read.chars().next().map_or(false, is_id_start) { - return Token::Ident(read); - } - } - - TokenMode::Code => { - if let Ok(color) = RgbaColor::from_str(read) { - return Token::Color(color); - } - } + // Plain text. + _ => self.text(start), } + } - Token::Invalid(self.s.eaten_from(start)) + fn code(&mut self, start: usize, c: char) -> Token<'s> { + match c { + // Parens. + '(' => Token::LeftParen, + ')' => Token::RightParen, + + // Length two. + '=' if self.s.eat_if('=') => Token::EqEq, + '!' if self.s.eat_if('=') => Token::BangEq, + '<' if self.s.eat_if('=') => Token::LtEq, + '>' if self.s.eat_if('=') => Token::GtEq, + '+' if self.s.eat_if('=') => Token::PlusEq, + '-' if self.s.eat_if('=') => Token::HyphEq, + '*' if self.s.eat_if('=') => Token::StarEq, + '/' if self.s.eat_if('=') => Token::SlashEq, + '.' if self.s.eat_if('.') => Token::Dots, + '=' if self.s.eat_if('>') => Token::Arrow, + + // Length one. + ',' => Token::Comma, + ';' => Token::Semicolon, + ':' => Token::Colon, + '+' => Token::Plus, + '-' => Token::Hyph, + '*' => Token::Star, + '/' => Token::Slash, + '=' => Token::Eq, + '<' => Token::Lt, + '>' => Token::Gt, + + // Identifiers. + c if is_id_start(c) => self.ident(start), + + // Numbers. + c if c.is_ascii_digit() + || (c == '.' && self.s.check(|n| n.is_ascii_digit())) => + { + self.number(start, c) + } + + // Strings. + '"' => self.string(), + + _ => Token::Invalid(self.s.eaten_from(start)), + } } fn whitespace(&mut self, first: char) -> Token<'s> { // Fast path for just a single space - if first == ' ' && !self.s.check(|c| c.is_whitespace()) { + if first == ' ' && !self.s.check(char::is_whitespace) { Token::Space(0) } else { self.s.uneat(); @@ -210,12 +186,13 @@ impl<'s> Tokens<'s> { c if c.is_whitespace() => true, // Comments. '/' if self.s.check(|c| c == '/' || c == '*') => true, - // Parenthesis and hashtag. - '[' | ']' | '{' | '}' | '#' => true, + // Parentheses. + '[' | ']' | '{' | '}' => true, // Markup. - '*' | '_' | '=' | '~' | '`' | '$' => true, + '#' | '~' | '*' | '_' | '-' | '`' | '$' => true, // Escaping. '\\' => true, + // Just text. _ => false, } { self.s.uneat(); @@ -226,6 +203,77 @@ impl<'s> Tokens<'s> { Token::Text(self.s.eaten_from(start)) } + fn backslash(&mut self) -> Token<'s> { + if let Some(c) = self.s.peek() { + match c { + // Backslash and comments. + '\\' | '/' | + // Parenthesis and hashtag. + '[' | ']' | '{' | '}' | '#' | + // Markup. + '*' | '_' | '=' | '~' | '`' | '$' => { + let start = self.s.index(); + self.s.eat_assert(c); + Token::Text(&self.s.eaten_from(start)) + } + 'u' if self.s.peek_nth(1) == Some('{') => { + self.s.eat_assert('u'); + self.s.eat_assert('{'); + Token::UnicodeEscape(UnicodeEscapeToken { + // Allow more than `ascii_hexdigit` for better error recovery. + sequence: self.s.eat_while(|c| c.is_ascii_alphanumeric()), + terminated: self.s.eat_if('}'), + }) + } + c if c.is_whitespace() => Token::Backslash, + _ => Token::Text("\\"), + } + } else { + Token::Backslash + } + } + + fn hash(&mut self, start: usize) -> Token<'s> { + match self.mode { + TokenMode::Markup => { + if self.s.check(is_id_start) { + let read = self.s.eat_while(is_id_continue); + if let Some(keyword) = keyword(read) { + keyword + } else { + Token::Ident(read) + } + } else if self.s.check(|c| c != '#' && !c.is_whitespace()) { + Token::Text(self.s.eaten_from(start)) + } else { + Token::Hashtag + } + } + TokenMode::Code => { + let read = self.s.eat_while(is_id_continue); + if let Ok(color) = RgbaColor::from_str(read) { + Token::Color(color) + } else { + Token::Invalid(self.s.eaten_from(start)) + } + } + } + } + + fn hyph(&mut self, start: usize) -> Token<'s> { + if self.s.eat_if('-') { + if self.s.eat_if('-') { + Token::HyphHyphHyph + } else { + Token::HyphHyph + } + } else if self.s.check(|c| !c.is_whitespace()) { + Token::Text(self.s.eaten_from(start)) + } else { + Token::Hyph + } + } + fn raw(&mut self) -> Token<'s> { let mut backticks = 1; while self.s.eat_if('`') { @@ -295,36 +343,6 @@ impl<'s> Tokens<'s> { }) } - fn backslash(&mut self) -> Token<'s> { - if let Some(c) = self.s.peek() { - match c { - // Backslash and comments. - '\\' | '/' | - // Parenthesis and hashtag. - '[' | ']' | '{' | '}' | '#' | - // Markup. - '*' | '_' | '=' | '~' | '`' | '$' => { - let start = self.s.index(); - self.s.eat_assert(c); - Token::Text(&self.s.eaten_from(start)) - } - 'u' if self.s.peek_nth(1) == Some('{') => { - self.s.eat_assert('u'); - self.s.eat_assert('{'); - Token::UnicodeEscape(UnicodeEscapeToken { - // Allow more than `ascii_hexdigit` for better error recovery. - sequence: self.s.eat_while(|c| c.is_ascii_alphanumeric()), - terminated: self.s.eat_if('}'), - }) - } - c if c.is_whitespace() => Token::Backslash, - _ => Token::Text("\\"), - } - } else { - Token::Backslash - } - } - fn ident(&mut self, start: usize) -> Token<'s> { self.s.eat_while(is_id_continue); match self.s.eaten_from(start) { @@ -474,6 +492,10 @@ mod tests { use Token::{Ident, *}; use TokenMode::{Code, Markup}; + const fn UnicodeEscape(sequence: &str, terminated: bool) -> Token { + Token::UnicodeEscape(UnicodeEscapeToken { sequence, terminated }) + } + const fn Raw(text: &str, backticks: usize, terminated: bool) -> Token { Token::Raw(RawToken { text, backticks, terminated }) } @@ -482,18 +504,14 @@ mod tests { Token::Math(MathToken { formula, display, terminated }) } - const fn UnicodeEscape(sequence: &str, terminated: bool) -> Token { - Token::UnicodeEscape(UnicodeEscapeToken { sequence, terminated }) + const fn Color(r: u8, g: u8, b: u8, a: u8) -> Token<'static> { + Token::Color(RgbaColor { r, g, b, a }) } const fn Str(string: &str, terminated: bool) -> Token { Token::Str(StrToken { string, terminated }) } - const fn Color(r: u8, g: u8, b: u8, a: u8) -> Token<'static> { - Token::Color(RgbaColor { r, g, b, a }) - } - /// Building blocks for suffix testing. /// /// We extend each test case with a collection of different suffixes to make @@ -605,15 +623,92 @@ mod tests { t!(Code: ")" => RightParen); } + #[test] + fn test_tokenize_whitespace() { + // Test basic whitespace. + t!(Both["a1/"]: "" => ); + t!(Both["a1/"]: " " => Space(0)); + t!(Both["a1/"]: " " => Space(0)); + t!(Both["a1/"]: "\t" => Space(0)); + t!(Both["a1/"]: " \t" => Space(0)); + t!(Both["a1/"]: "\u{202F}" => Space(0)); + + // Test newline counting. + t!(Both["a1/"]: "\n" => Space(1)); + t!(Both["a1/"]: "\n " => Space(1)); + t!(Both["a1/"]: " \n" => Space(1)); + t!(Both["a1/"]: " \n " => Space(1)); + t!(Both["a1/"]: "\r\n" => Space(1)); + t!(Both["a1/"]: " \n\t \n " => Space(2)); + t!(Both["a1/"]: "\n\r" => Space(2)); + t!(Both["a1/"]: " \r\r\n \x0D" => Space(3)); + } + + #[test] + fn test_tokenize_text() { + // Test basic text. + t!(Markup[" /"]: "hello" => Text("hello")); + t!(Markup[" /"]: "hello-world" => Text("hello"), Text("-"), Text("world")); + + // Test code symbols in text. + t!(Markup[" /"]: "a():\"b" => Text("a():\"b")); + t!(Markup[" /"]: ";:,|/+" => Text(";:,|/+")); + t!(Markup[" /"]: "#-a" => Text("#"), Text("-"), Text("a")); + t!(Markup[" "]: "#123" => Text("#"), Text("123")); + + // Test text ends. + t!(Markup[""]: "hello " => Text("hello"), Space(0)); + t!(Markup[""]: "hello~" => Text("hello"), Tilde); + } + + #[test] + fn test_tokenize_escape_sequences() { + // Test escapable symbols. + t!(Markup: r"\\" => Text(r"\")); + t!(Markup: r"\/" => Text("/")); + t!(Markup: r"\[" => Text("[")); + t!(Markup: r"\]" => Text("]")); + t!(Markup: r"\{" => Text("{")); + t!(Markup: r"\}" => Text("}")); + t!(Markup: r"\*" => Text("*")); + t!(Markup: r"\_" => Text("_")); + t!(Markup: r"\=" => Text("=")); + t!(Markup: r"\~" => Text("~")); + t!(Markup: r"\`" => Text("`")); + t!(Markup: r"\$" => Text("$")); + t!(Markup: r"\#" => Text("#")); + + // Test unescapable symbols. + t!(Markup[" /"]: r"\a" => Text(r"\"), Text("a")); + t!(Markup[" /"]: r"\u" => Text(r"\"), Text("u")); + t!(Markup[" /"]: r"\1" => Text(r"\"), Text("1")); + t!(Markup[" /"]: r"\:" => Text(r"\"), Text(":")); + t!(Markup[" /"]: r#"\""# => Text(r"\"), Text("\"")); + + // Test basic unicode escapes. + t!(Markup: r"\u{}" => UnicodeEscape("", true)); + t!(Markup: r"\u{2603}" => UnicodeEscape("2603", true)); + t!(Markup: r"\u{P}" => UnicodeEscape("P", true)); + + // Test unclosed unicode escapes. + t!(Markup[" /"]: r"\u{" => UnicodeEscape("", false)); + t!(Markup[" /"]: r"\u{1" => UnicodeEscape("1", false)); + t!(Markup[" /"]: r"\u{26A4" => UnicodeEscape("26A4", false)); + t!(Markup[" /"]: r"\u{1Q3P" => UnicodeEscape("1Q3P", false)); + t!(Markup: r"\u{1🏕}" => UnicodeEscape("1", false), Text("🏕"), RightBrace); + } + #[test] fn test_tokenize_markup_symbols() { // Test markup tokens. - t!(Markup[" a1"]: "*" => Star); - t!(Markup: "_" => Underscore); - t!(Markup[""]: "###" => Hashtag, Hashtag, Hashtag); - t!(Markup["a1/"]: "# " => Hashtag, Space(0)); - t!(Markup: "~" => Tilde); - t!(Markup[" "]: r"\" => Backslash); + t!(Markup[" a1"]: "*" => Star); + t!(Markup: "_" => Underscore); + t!(Markup[""]: "###" => Hashtag, Hashtag, Hashtag); + t!(Markup["a1/"]: "# " => Hashtag, Space(0)); + t!(Markup["a1/"]: "- " => Hyph, Space(0)); + t!(Markup: "~" => Tilde); + t!(Markup[" "]: r"\" => Backslash); + t!(Markup["a "]: r"a--" => Text("a"), HyphHyph); } #[test] @@ -654,71 +749,32 @@ mod tests { #[test] fn test_tokenize_keywords() { - let keywords = [ + // A list of a few (not all) keywords. + let list = [ ("let", Let), ("if", If), ("else", Else), ("for", For), ("in", In), - ("while", While), - ("break", Break), - ("continue", Continue), - ("return", Return), + ("import", Import), ]; - for &(s, t) in &keywords { + for &(s, t) in &list { t!(Markup[" "]: format!("#{}", s) => t); t!(Markup[" "]: format!("#{0}#{0}", s) => t, t); t!(Markup[" /"]: format!("# {}", s) => Token::Hashtag, Space(0), Text(s)); } - for &(s, t) in &keywords { + for &(s, t) in &list { t!(Code[" "]: s => t); t!(Markup[" /"]: s => Text(s)); } // Test simple identifier. t!(Markup[" "]: "#letter" => Ident("letter")); - t!(Markup[" "]: "#123" => Invalid("#123")); - t!(Code[" /"]: "falser" => Ident("falser")); - t!(Code[" /"]: "None" => Ident("None")); - t!(Code[" /"]: "True" => Ident("True")); - } - - #[test] - fn test_tokenize_whitespace() { - // Test basic whitespace. - t!(Both["a1/"]: "" => ); - t!(Both["a1/"]: " " => Space(0)); - t!(Both["a1/"]: " " => Space(0)); - t!(Both["a1/"]: "\t" => Space(0)); - t!(Both["a1/"]: " \t" => Space(0)); - t!(Both["a1/"]: "\u{202F}" => Space(0)); - - // Test newline counting. - t!(Both["a1/"]: "\n" => Space(1)); - t!(Both["a1/"]: "\n " => Space(1)); - t!(Both["a1/"]: " \n" => Space(1)); - t!(Both["a1/"]: " \n " => Space(1)); - t!(Both["a1/"]: "\r\n" => Space(1)); - t!(Both["a1/"]: " \n\t \n " => Space(2)); - t!(Both["a1/"]: "\n\r" => Space(2)); - t!(Both["a1/"]: " \r\r\n \x0D" => Space(3)); - } - - #[test] - fn test_tokenize_text() { - // Test basic text. - t!(Markup[" /"]: "hello" => Text("hello")); - t!(Markup[" /"]: "hello-world" => Text("hello-world")); - - // Test code symbols in text. - t!(Markup[" /"]: "a():\"b" => Text("a():\"b")); - t!(Markup[" /"]: ";:,|/+-" => Text(";:,|/+-")); - - // Test text ends. - t!(Markup[""]: "hello " => Text("hello"), Space(0)); - t!(Markup[""]: "hello~" => Text("hello"), Tilde); + t!(Code[" /"]: "falser" => Ident("falser")); + t!(Code[" /"]: "None" => Ident("None")); + t!(Code[" /"]: "True" => Ident("True")); } #[test] @@ -764,43 +820,6 @@ mod tests { t!(Markup[""]: r"$[ ]\\$" => Math(r" ]\\$", true, false)); } - #[test] - fn test_tokenize_escape_sequences() { - // Test escapable symbols. - t!(Markup: r"\\" => Text(r"\")); - t!(Markup: r"\/" => Text("/")); - t!(Markup: r"\[" => Text("[")); - t!(Markup: r"\]" => Text("]")); - t!(Markup: r"\{" => Text("{")); - t!(Markup: r"\}" => Text("}")); - t!(Markup: r"\*" => Text("*")); - t!(Markup: r"\_" => Text("_")); - t!(Markup: r"\=" => Text("=")); - t!(Markup: r"\~" => Text("~")); - t!(Markup: r"\`" => Text("`")); - t!(Markup: r"\$" => Text("$")); - t!(Markup: r"\#" => Text("#")); - - // Test unescapable symbols. - t!(Markup[" /"]: r"\a" => Text(r"\"), Text("a")); - t!(Markup[" /"]: r"\u" => Text(r"\"), Text("u")); - t!(Markup[" /"]: r"\1" => Text(r"\"), Text("1")); - t!(Markup[" /"]: r"\:" => Text(r"\"), Text(":")); - t!(Markup[" /"]: r#"\""# => Text(r"\"), Text("\"")); - - // Test basic unicode escapes. - t!(Markup: r"\u{}" => UnicodeEscape("", true)); - t!(Markup: r"\u{2603}" => UnicodeEscape("2603", true)); - t!(Markup: r"\u{P}" => UnicodeEscape("P", true)); - - // Test unclosed unicode escapes. - t!(Markup[" /"]: r"\u{" => UnicodeEscape("", false)); - t!(Markup[" /"]: r"\u{1" => UnicodeEscape("1", false)); - t!(Markup[" /"]: r"\u{26A4" => UnicodeEscape("26A4", false)); - t!(Markup[" /"]: r"\u{1Q3P" => UnicodeEscape("1Q3P", false)); - t!(Markup: r"\u{1🏕}" => UnicodeEscape("1", false), Text("🏕"), RightBrace); - } - #[test] fn test_tokenize_idents() { // Test valid identifiers. @@ -956,8 +975,7 @@ mod tests { t!(Code: "1p%" => Invalid("1p"), Invalid("%")); t!(Code: "1%%" => Percent(1.0), Invalid("%")); - // Test invalid keyword. - t!(Markup[" /"]: "#-" => Invalid("#-")); + // Test invalid color. t!(Code[" /"]: r"#letter" => Invalid(r"#letter")); } } diff --git a/src/pretty.rs b/src/pretty.rs index 49f6fd82..9987e506 100644 --- a/src/pretty.rs +++ b/src/pretty.rs @@ -17,8 +17,8 @@ where p.finish() } -/// Pretty print an item with a node map and return the resulting string. -pub fn pretty_with_map(item: &T, map: &NodeMap) -> String +/// Pretty print an item with a expression map and return the resulting string. +pub fn pretty_with_map(item: &T, map: &ExprMap) -> String where T: PrettyWithMap + ?Sized, { @@ -33,10 +33,10 @@ pub trait Pretty { fn pretty(&self, p: &mut Printer); } -/// Pretty print an item with a node map that applies to it. +/// Pretty print an item with an expression map that applies to it. pub trait PrettyWithMap { /// Pretty print this item into the given printer. - fn pretty_with_map(&self, p: &mut Printer, map: Option<&NodeMap>); + fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>); } impl Pretty for T @@ -104,7 +104,7 @@ impl Write for Printer { } impl PrettyWithMap for Tree { - fn pretty_with_map(&self, p: &mut Printer, map: Option<&NodeMap>) { + fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>) { for node in self { node.pretty_with_map(p, map); } @@ -112,20 +112,21 @@ impl PrettyWithMap for Tree { } impl PrettyWithMap for Node { - fn pretty_with_map(&self, p: &mut Printer, map: Option<&NodeMap>) { + fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>) { match self { // TODO: Handle escaping. Self::Text(text) => p.push_str(text), Self::Space => p.push(' '), - Self::Strong(_) => p.push('*'), - Self::Emph(_) => p.push('_'), Self::Linebreak(_) => p.push_str(r"\"), Self::Parbreak(_) => p.push_str("\n\n"), - Self::Heading(heading) => heading.pretty_with_map(p, map), + Self::Strong(_) => p.push('*'), + Self::Emph(_) => p.push('_'), Self::Raw(raw) => raw.pretty(p), + Self::Heading(heading) => heading.pretty_with_map(p, map), + Self::List(list) => list.pretty_with_map(p, map), Self::Expr(expr) => { if let Some(map) = map { - let value = &map[&(self as *const _)]; + let value = &map[&(expr as *const _)]; value.pretty(p); } else { if expr.has_short_form() { @@ -138,15 +139,6 @@ impl PrettyWithMap for Node { } } -impl PrettyWithMap for HeadingNode { - fn pretty_with_map(&self, p: &mut Printer, map: Option<&NodeMap>) { - for _ in 0 .. self.level { - p.push('#'); - } - self.contents.pretty_with_map(p, map); - } -} - impl Pretty for RawNode { fn pretty(&self, p: &mut Printer) { // Find out how many backticks we need. @@ -203,6 +195,23 @@ impl Pretty for RawNode { } } +impl PrettyWithMap for HeadingNode { + fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>) { + for _ in 0 .. self.level { + p.push('#'); + } + p.push(' '); + self.body.pretty_with_map(p, map); + } +} + +impl PrettyWithMap for ListNode { + fn pretty_with_map(&self, p: &mut Printer, map: Option<&ExprMap>) { + p.push_str("- "); + self.body.pretty_with_map(p, map); + } +} + impl Pretty for Expr { fn pretty(&self, p: &mut Printer) { match self { @@ -664,9 +673,8 @@ mod tests { roundtrip("\\ "); roundtrip("\n\n"); roundtrip("hi"); - - // Heading. roundtrip("# *Ok*"); + roundtrip("- Ok"); // Raw. roundtrip("``"); diff --git a/src/syntax/node.rs b/src/syntax/node.rs index 5f76b56a..b4684d0b 100644 --- a/src/syntax/node.rs +++ b/src/syntax/node.rs @@ -17,70 +17,16 @@ pub enum Node { Strong(Span), /// Emphasized text was enabled / disabled: `_`. Emph(Span), - /// A section heading: `= Introduction`. - Heading(HeadingNode), /// A raw block with optional syntax highlighting: `` `...` ``. Raw(RawNode), + /// A section heading: `= Introduction`. + Heading(HeadingNode), + /// A single list item: `- ...`. + List(ListNode), /// An expression. Expr(Expr), } -impl Node { - // The names of the corresponding library functions. - pub const LINEBREAK: &'static str = "linebreak"; - pub const PARBREAK: &'static str = "parbreak"; - pub const STRONG: &'static str = "strong"; - pub const EMPH: &'static str = "emph"; - pub const HEADING: &'static str = "heading"; - pub const RAW: &'static str = "raw"; - - /// Desugar markup into a function call. - pub fn desugar(&self) -> Option { - match *self { - Self::Text(_) => None, - Self::Space => None, - Self::Linebreak(span) => Some(call(span, Self::LINEBREAK)), - Self::Parbreak(span) => Some(call(span, Self::PARBREAK)), - Self::Strong(span) => Some(call(span, Self::STRONG)), - Self::Emph(span) => Some(call(span, Self::EMPH)), - Self::Heading(ref heading) => Some(heading.desugar()), - Self::Raw(ref raw) => Some(raw.desugar()), - Self::Expr(_) => None, - } - } -} - -/// A section heading: `= Introduction`. -#[derive(Debug, Clone, PartialEq)] -pub struct HeadingNode { - /// The source code location. - pub span: Span, - /// The section depth (numer of equals signs). - pub level: usize, - /// The contents of the heading. - pub contents: Rc, -} - -impl HeadingNode { - pub const LEVEL: &'static str = "level"; - pub const BODY: &'static str = "body"; - - /// Desugar into a function call. - pub fn desugar(&self) -> CallExpr { - let Self { span, level, ref contents } = *self; - let mut call = call(span, Node::HEADING); - call.args.items.push(CallArg::Named(Named { - name: ident(span, Self::LEVEL), - expr: Expr::Int(span, level as i64), - })); - call.args.items.push(CallArg::Pos(Expr::Template(TemplateExpr { - span, - tree: Rc::clone(&contents), - }))); - call - } -} - /// A raw block with optional syntax highlighting: `` `...` ``. /// /// Raw blocks start with 1 or 3+ backticks and end with the same number of @@ -158,38 +104,22 @@ pub struct RawNode { pub block: bool, } -impl RawNode { - pub const LANG: &'static str = "lang"; - pub const BLOCK: &'static str = "block"; - pub const TEXT: &'static str = "text"; - - /// Desugar into a function call. - pub fn desugar(&self) -> CallExpr { - let Self { span, ref lang, ref text, block } = *self; - let mut call = call(span, Node::RAW); - if let Some(lang) = lang { - call.args.items.push(CallArg::Named(Named { - name: ident(span, Self::LANG), - expr: Expr::Str(span, lang.string.clone()), - })); - } - call.args.items.push(CallArg::Named(Named { - name: ident(span, Self::BLOCK), - expr: Expr::Bool(span, block), - })); - call.args.items.push(CallArg::Pos(Expr::Str(span, text.clone()))); - call - } +/// A section heading: `= Introduction`. +#[derive(Debug, Clone, PartialEq)] +pub struct HeadingNode { + /// The source code location. + pub span: Span, + /// The section depth (numer of equals signs). + pub level: usize, + /// The contents of the heading. + pub body: Rc, } -fn call(span: Span, name: &str) -> CallExpr { - CallExpr { - span, - callee: Box::new(Expr::Ident(Ident { span, string: name.into() })), - args: CallArgs { span, items: vec![] }, - } -} - -fn ident(span: Span, string: &str) -> Ident { - Ident { span, string: string.into() } +/// A single list item: `- ...`. +#[derive(Debug, Clone, PartialEq)] +pub struct ListNode { + /// The source code location. + pub span: Span, + /// The contents of the list item. + pub body: Tree, } diff --git a/src/syntax/token.rs b/src/syntax/token.rs index 538d81b7..9098f176 100644 --- a/src/syntax/token.rs +++ b/src/syntax/token.rs @@ -24,6 +24,10 @@ pub enum Token<'s> { Hashtag, /// A tilde: `~`. Tilde, + /// Two hyphens: `--`. + HyphHyph, + /// Three hyphens: `---`. + HyphHyphHyph, /// A backslash followed by nothing or whitespace: `\`. Backslash, /// A comma: `,`. @@ -103,15 +107,15 @@ pub enum Token<'s> { Space(usize), /// A consecutive non-markup string. Text(&'s str), + /// A slash and the letter "u" followed by a hexadecimal unicode entity + /// enclosed in curly braces: `\u{1F5FA}`. + UnicodeEscape(UnicodeEscapeToken<'s>), /// An arbitrary number of backticks followed by inner contents, terminated /// with the same number of backticks: `` `...` ``. Raw(RawToken<'s>), /// One or two dollar signs followed by inner contents, terminated with the /// same number of dollar signs. Math(MathToken<'s>), - /// A slash and the letter "u" followed by a hexadecimal unicode entity - /// enclosed in curly braces: `\u{1F5FA}`. - UnicodeEscape(UnicodeEscapeToken<'s>), /// An identifier: `center`. Ident(&'s str), /// A boolean: `true`, `false`. @@ -204,6 +208,8 @@ impl<'s> Token<'s> { Self::Underscore => "underscore", Self::Hashtag => "hashtag", Self::Tilde => "tilde", + Self::HyphHyph => "en dash", + Self::HyphHyphHyph => "em dash", Self::Backslash => "backslash", Self::Comma => "comma", Self::Semicolon => "semicolon", @@ -242,9 +248,9 @@ impl<'s> Token<'s> { Self::Using => "keyword `using`", Self::Space(_) => "space", Self::Text(_) => "text", + Self::UnicodeEscape(_) => "unicode escape sequence", Self::Raw(_) => "raw block", Self::Math(_) => "math formula", - Self::UnicodeEscape(_) => "unicode escape sequence", Self::Ident(_) => "identifier", Self::Bool(_) => "boolean", Self::Int(_) => "integer", diff --git a/src/syntax/visit.rs b/src/syntax/visit.rs index 40d8e664..86481d4e 100644 --- a/src/syntax/visit.rs +++ b/src/syntax/visit.rs @@ -52,16 +52,25 @@ visit! { match node { Node::Text(_) => {} Node::Space => {} - Node::Strong(_) => {} Node::Linebreak(_) => {} Node::Parbreak(_) => {} + Node::Strong(_) => {} Node::Emph(_) => {} - Node::Heading(heading) => v.visit_tree(&heading.contents), Node::Raw(_) => {} - Node::Expr(expr) => v.visit_expr(expr), + Node::Heading(n) => v.visit_heading(n), + Node::List(n) => v.visit_list(n), + Node::Expr(n) => v.visit_expr(n), } } + fn visit_heading(v, node: &HeadingNode) { + v.visit_tree(&node.body); + } + + fn visit_list(v, node: &ListNode) { + v.visit_tree(&node.body); + } + fn visit_expr(v, node: &Expr) { match node { Expr::None(_) => {} diff --git a/tests/ref/code/include.png b/tests/ref/code/include.png index 909a364335884d7f427aabd203c05dd3d8d23779..e1494643282c320caca40e23c9f17867b8868041 100644 GIT binary patch literal 31078 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 o=YK=Od0&=QLGeGDwF_`kam(TLTWH7XQWF{-Mf zW^q=L+Go#@re=*^f4}?ho_jve^LfAj`#jI*pVuqV$WVuknV%T|05&~cEfW9$L4I^R z?8gG)q_$K60N$jhrG7tXikdg#z5I$xTZKX5|3d%`;ywb-IQd~moC29omJb0ILVRfE z&^2wdRd5}0TLI6Mfx_P zu~ann4mtAtM8JsY zDoq)_g#;gnLy1j<@aQmwqOcnfRMHbUHx>~;S$Ii_(67ngLZzqj#whxR=wM0ZIPxzPpoLLo(fEY>WYQ9pssGC(q0Ri;&O+7Sa= zR7x#e0sPbaF}MJ_dP&!t&S< zD^(8dJt&VJNij6n5VF5sOua@`xcHWGO0Flc+l>Yxpk^69PU(UnQ_f?+$Af~P02uk* zceP8hpVZ5AX}oz_`fX8yfD*LiH$|H_-BxI>GLAWuRqt5kB5mEcJE%#K5ii2)A?H|t zu!dPa4rrN0ifaCpCORip0@B77uCe8)Ei8Q0;N(-Ye3-^>zVuthTom*3fsK(1j?ER( z**(dkNftEWjaLZVA6=ImQl9&Qeg_(Xj~G;9p!B^$sib88>yEJfo~*RmI`#E90Aj9L znXHq$`2J_O8o9le}gkZEEn zR(C=0$NVc6s)PX7v(Lnk=E1fQI#|{AgSjSZ%L$wEU?Nlix~zArTuIU}!gK=k`s7|x zmMuTrY+#yg@TVB`yO(+iXRZA0kt{J5Cl$M%l@le6X*n%{+*HiGl;)`+Y`V4PToTgv z_PfvBdMGjPf=1Y^DQYqe{kgp3$*sCOC)J3&pk9hQD2TrDO=~lI`dXASof^=;JWUOl z+1dKWiV$?QR#2^_wC;Ybv-w&RdX>_T^!A;pWL@T8aD99f)-wC339MRuw_)_2Jq>g79wiHAZ0 z*H6pUigF{cSL6=v@{k5s~DIdKlHE7!}+udugJ z5sU6Hk;#OfFl4uoVO#Nwmqi&Lt*@D~t@rnK>;nfC}^^#fi#eOv~H0J4je4eW5At`>!7&NF8ERNRLUrB&F-LYj^5N@$)_FJM7w+b25k)YwaTV5i~ zV=h6L$24;tu@s42$~zBSCSVE9CgPNq-Q^fdBkyGNd+dugZ#MCD;XsL6W}*XiTvUZHx0^dzIOA)lLlji zLn;_-FD}|K7l}cq|01*XF|;dhCDjc|l!0y}rlOS|PbsZjaHZR-aLu`|7jBHT=?$D` zBIuz3x(~y7!G#R%r&rw=u&3V@V@{Fz-vY$Ejy@rD={2FMgU%otAENGCE{Q>1!f8<0 z$L+z+e-q*Z7DZUw|Fb$a$P3EcOCf3C>ZP+^9ZG4>gX@k2X}0G?Xn5N)FCwvIcFl8ExDevx4Dj-BEiT zS`IqhBKk*>QNXG)l*wmYgxV*fGN1Z7ogUG8S;pudyFdSmnT>|-v1x4RKA3<3F-o5}LCR=A=jA%OBop`UZXnUj;T%ksum=(WyjOaFbwrHVZ2*20cyv!2$| z%mh&m`4t6q)b`q_t9WN8CTjGOm#FFf2PK|WHfhaUTn*!;a&iy*@^BkKVg+mPI!g=@ zy~#`FCntmBI1@B~8P^459HLAV20X1N^UXQ@{o;!W$kS9wo*#LRf%GO~qem-sT?v8LqTbnG+U zGp^L1yy>e;HUt-sb+h`E{z=0h-q*C@3etN&*CjbB-WmZH+Hrk0CI!={eiKCauZOzX zT@O#Refnal6+vsrudGUZTH%T}Fh5YeN1Ez6iCFYVh11s`&0$0Jbez?pBg`1Co9~B=9*|r} zI~Jq~YvN?DZgnA9@n$|)|NY=;YcuNxFa6T5Zhvt0YCaLZ5(N+(7;qNK+7cr0o(_Ma zZEvhOG4YUP*_=TIStzvnJtFu!qEa)zOK^wp^A2f>Y1Mu2Y8y-OX8rAt^owOzPOV{) zCLZTgbD|&>M#xv}9Jynq$|Un#EM`xfex!F;l|c(c_kJO1TqM-u0~&ne{{@?W2s9r( i{KKvOk*w{8GY%mu9OswWNB94ya(Wm;tr`ux=)VCX9I$r) literal 3390 zcmZ{ncTf}Dw#5@d2_TT5NEIO@3Ic+NQdJTX2)*h^kzS>D0*DEsG(kEjT}nVe5FvEP zMLubQ8c-=3S};Ipg3<$z_q{js-o110oS8jm??2DkYkq4bm>TQyaEWjM00166EZQ6Z z0J5IkcfcnFK;;klax!PrLnAH2Cs%*WhLm>j<7bxu>UiE_&}YK;lS3ga0>ZS^P1RF1 zOgS$h5gj{mGx?%LA1C1L0pm44`+WIN5&F_4JcN?QD$PoDl0~lFAFKQ|GIKsD(G+?K zg{cG!l)x-w|GDu$6PtOn$vWksKu;dWbDe-9$xljR=Ya7QX(Q^yzq(q7Z_g0{&BG~c z{ot8iQ0~TcRFEI1B55ZZ&H4C~xF|B`oeh;*ab+hP@T2pwoa?-GPYJZ4BP3kU&%TjC z40V-bH2)~+W9_Kvz7NpKJbZp*z;)g%+gVCzfV@n=1uB}z_HM}lmnhq#G@yo7?xc@@ zeo+M*+2ra*6bl6xp+CTaBU!L+;{21!l;AXHsYa&eN0W07$rLM&>H5iWbyZmer#z=l zUt5_m2=1zpKyH(Jp*aBf%sz!ZEtxDki1e1nX&}4QilbCmAiYl@jcl;Vy!g-mNQI+x z_#nM$@Yk}^+~_QSP$~j+xk>gZ&|FaRnd}=L+Siqf*v0ub&>FZzIR3jD-|9L@hOV=wu!A=j-^>JohoS}MB?kwuXL}mOT57U%9nOBbn9Y0VTci?R zwf;qJA~JB%QKK{>o^+2>R~PVpl}^PAhi1t|H_gCPr`WtX>Qxtc-da62zzW0DZMv;D z$3H^UE%`pzgVCah8tzuVQ8Ot1P${9qw(c7v1McxII-wcshqwEg699ZK@GyduirE*C zpHEzNf7=7A1uX~)&yObNEY&DgYZk~OdwVYNKT8DcB4Qz^yZKvqP`z;cWq{coI{(6Y z;tI->hcjx=UGKoaimXz=(IKn-iu*u);z3`_F46bZcuM!Rqcbdx+xEKSCV!4qWA>^e z-xVRjKF4*`VU^(> zU$Ip7JzJ7l=;r4}Uhr_ypvRu6LA?`|I{RCXwWl*b_7imqRx=#~8N9L_sd9VBa>~8u zM_!^GX4)ohqX0bAsm+vT!BM+favC|VoIfr3UHlSc)g6-UxUN&wYIINwHok++F<=k3 z+gf-&Zv4%QHK2^~=LPl~BjjPb!WOrde=p8>L&=`xe4eUC zBxx)@=q7w`JSe&@7f2QNY{lID>z(I#;Bh?H1&pPcxvdQD)|Ba#EV&kGEF52Xecc&V zIPVM{X;_e@S9IT0SxxF2It{S?ne$kht|YQ{`cEpy^Pf2ERKxAF0Z8bGP`krK- zm!MQbVm78WO||Bk59d11@4C&gZkgxIH1N`mFs#mlGlV*%Vz)>W0nT`)gIyo6uumBi zJyK>dqy7=!nKuJ;u}D_ghlG-4%RiW<=P%3e{4*W?mm9jseub^P=CeJW8m3xpVgkT9 z&4Qw78xvUtzZ;zPZu#r6>1&l>O`Zhhj-71@J?fxBd(JPGRE-eJSaTW4j^^gWWzxP4 zPJX!(d{D^zcEqH+%=d)J(_CM#o)(Q1j=5946~R#V({-NB`OW)0_$={Ksjz#MsM~! zgTc5OnqKFH%J&XiUt0jq7w7v7(bh1nNOW3eJR(G?OiFU58MidYj$y()gbyrf``vO_SL4Ymz2Ba;jG8<6+TR5;vu~`|% z=xCFzoeEPc3UTw9t3K_r#B>8-l{)u5A?<#j2KD9k3?EHq+|I5mtUHiqk#pK!Hg65l zs*_BTSG&V(90ye016-_&BX_!<+Kh1U9xJR6L$7;fS(4tb$T)By`(54DCx+Z=(n;pp z)#$s3*9-UL^h8>})IodhROtPXkZxL7$5-CyCZ2j)F+2-Js8f^3*4q}>$`$#`4bwe0 z@3`N$w27Q{%O8%8`Oc@}qlb8fOaA0V`miT=_H8q(e(Q_44_`Y4ffgxMDmD!eeIG)k7b$BB*0o!KLA82QueWQ^zpoUj$qjbBhNV>;8KNS95eESs`ecZ z<_+T1^}|{O9rEfXRTQ5MxbNMIO(!xjY2ucJ8)48Rmxeu`4q3Jp2>54p1cT!OR^6&vz$kDcr!z^D&rTilmrUtdKM?oP)NNHhB5gSw{uS^L?Eb zH113aXTWi$VEQAb=-i)(vbo;wq+$%(xJvVq~qia((f3)?P8-)6DBVAdrdd==97 zUYTMtnx=pIm=|^5#p@Ifx`c}NNFy=Iq_8wfhEgbNw5n71_Q=q z#&y4qhey2>rAaGJ5heF0C??lgG|DGT5k|z_ z&weBt^^2UFy;}B5LFy1;_V52SimgYibWw>GhxF-0llI>_!4IF)W69H-2-ZGze@aYlLg_Qf*&2VUxTvEUEO-fE}n_A;Ma^==Xq5B+y3p6ijND`m_qWk$QMo`JMIu>OV!YHI5`B#Ye$adiZ0T2b n`(J{`|3#8Rng1uDW9Ts`u*)LXz+yG@zk`t;#u)t?dt^@%QLo+lH&;$agXb3?NkSawi^xhFr zdJ&K+MT+z)9f8BW5>Wkq4G<_7lAf9JT-scbNNMD?4BM*sb zj>)++qR`in47z69+F z8Q@l5`o`m;?R*GBE?t<#38uA2r-8iCe!CS?Tzq3 z0e34Aop?2OK0`x;VRf36jRxg5db{9$6E#tSHBQmQf(l2ZxUCX25j;?WvMzU>b8Jew ze(l#NypWmc!$vH?iK~k5*=EdmPml@|#mTsvv`fd%L8doXp$06+I1SQVf6PMy$oblx z8ErE6d!aDckA_I2jn}iCBYMgzpcooPklbvi_1!vZxMhMa9x3x0L`su<(>b60T=3(Z zz%3FVo1TTqoqP0s`d>$Sq{$L@cIKsF1dXZW`F6RR)K?RIoZzf@dzNqsk`t}ocnqx7 zRwCYuxXKb*F|K!#De}=Wr(eIvd_kWYBQu~(e$8AbzKrnlie4>K4pvxK^QmP9qS^j+ zqW_NsR$0OAZ+KTqkk&~#e63p}+@4jnnsY$~Hi~(wH+1Z^D?JnfA8$NfpzK@KSq+(` zyHp<4m-hTYkb1xQ4Ygy1bqOe2vXW#A25yx4bmfhW%5SNeFxiKpb*BC-LMLCyGvegYM77EK zhC1l*ZRvxn5bE9vCk>kPw5A4KU z4MztO+KG{{1~Dxf(C7_`!}8K%_PG%J$|NQ%7z(w4LA6@k>54v zf}2Vr{%v{xudLUELibAB{P_UMkW=fLZ<_RYLkiHSF1@Rp@?Cm(^8UN-!+S=#xEYHd zwPUDhk%}NsSXwxAI8NieqU>b=ld@(v@wWipQuZk&;DST=X8rTBDHPOgzy}3{IC{V2 z)$$O=5r0{8>^RbA1g>c8i9xk7cOBg*NEGoIJz!Vg%K+12{r!;o06_exbN*QpoKh`> z?Y^0VgbTS`f-8yKD@Kc3nYVCV z2DY%&LH**V5CS?yujFnB-@C^TE2;6Nz0`PrG@Cf^#`&W{jMzKdm0G+hD77@meCr7d zif6p3iJ~pKwK!_S72Z*{{p52ub*RzDsbx-;>rWxLYPSb4#B7ytyS=$OQ${WVP0S*k!TRT!mCH4SaQ5jn>;2%M zzgHo{hY6ZV8kXU~Fr9C670|YOlJ`DqQsJG2UAd+=u}gL@@vLZd5pI_=%)gO0Q+sn=vxg>Us<(Tdj+UJ;}bAy&?}xq)!8)AbC|;-Q$F zvLU@M?JiRlx~Cmk9e4gxZ_qhzWc;`3^-puHsTbAvf8$`I&#~m+mPOMY*s45h*9Pj* zQqe$NQ(8DulQ?^@EpvXvy=FB`^RoD&#!s*$S~`eyy#B=nslN9F3Vi2ADLkFvn!{2x z&EM=Gc0?|+h}ADs#fVK+KpzRuvTJZbj#IqGP>U}bnBaRfUmYTmAr*o(RrA1&+i7UnXhLnjyO7qcF6OKn8m$H#kI+kqO{%xa;c>R!Jz3M1hqvT={? z_%&e&-KO19I3by-(QZE-+(-(*?)_bby0dxFEDaOS-ojnx8MGTxoO8BbLWgPvML|^p zOUxp>cGR%yB?u^2UEj*27Yt{NNIDoBPB5o6RV;hG;U`cC!sUoKjg^W*seg_aZeIZw z?pIny&nhW=&<+dMuBK*o-o_g+^=y|adGeJFIjLnn4Fmwp>AKCsbyKWo>}r;0Yz8Ih zl3`a0E$FgPwQWAtoZ|*m&-`M2AiDsoP}fk8Ify)2d)n%3VOzO7p=>E>l~MEFBrP8) z^8cEh|CCE%01%vbrb6hHZcX)A)1-&zm4J{zD*>0RG*~6xgv^B=ib48YSp|JQ6)U?u z8ObmGz7OhKrDzuK&S<)h-5f2n0}u;;C!-`B!qD|&4({+4`IRC6k^HqY5kTYPJUi&n zAslJ-)zUP$2*1V{+7RDEus@Lp3M3B~bzDg*b+G9A_x=2cu&|8 zbs7Iq6q@D6#qJ~|$O!ijHwH7JE`iqI7DEBBF06(W2_DsyOmWRw?cI+m>Mt9Jy7d4U z12V>0wEsljc{E!M%YVO$8t=X*Wqx#pV03SSM6pS4?=EbbUsdfo;2j%E%)(#Dmx9rUp; zbynx3V_9%2B!-hX;zOg21D_`w*B^>PIF};1B-HKpXNzvIq99Wrp0*tq^_J|n(iXVH z?576SP&J8k__jXej#ftI3?`aykFaK4FRYbtl-xyyo|eh&Og3ltqDKCXzMHu-tKe`L zr`)*~nw&Z4cO~Rz$?t+lonk7!k>=)RSGZJ5Q2nBf4t{xZ*~V^3SYKjD0{_l({;ivG znnd9X<2|#a=Ks(53<^ieBnLd`KemH%+&SXjPc=9Z0p8tb&3tJR@$~HR%6#$ru`L_G znF9o?F}qphS)hyUqCf|C{l*m>OuO&8G00yH3$k1O$=O7zvc9&SH&ZJ_$c0Wt;()1&l`WL5N@|th4DIqamlqV_U4f3Oa~PT7<)#Pk z^7@}Ol?xAJpd-zzP7SRA@V<9|bEKNKrZ}0x1{QP^!Pp@R4GuebSBF9z*E`<#6xGIM>oP8B&6BGi9q{PMFAak;&Ol8ZQ+CN1ef=s(l>DS z-2Aqsd`p~KdoiM-Le}K>LE}afgWSm@j-=YVY~?R(!1{kKKvb+{e%8=e`-z)dqT5BO z#M<_*1Eu@^=`|OclJrHNG~n_Dblx4>0L(vxND$YeroaZA|L+H$;f=C_Rk_+gP(-5$ zr|4I(L`t5)(r{auh6C{xQ1NO@y$?cG^D9>(GdK}b5zY5+ST>Ota$qM3l1{0$uJIj7 zM@qzV-TF&QeulSK2`WD~GB0(!sH)J9-gbP}T`!=eAUl{U4(41=WVrSEF=xNkqFP9t z&=Mu%YPA)B5FJEd$Qr-<@|>?dNl`KH8qu?eady#*9+<~U(3Fe2{n8sJ&w=0eJlnwH z4ZH7u@sjvCMTgHo@;NYx1mtqO?C;qzXU;N_iYOhON%l!i%?cOt5e-49NTR&G-SAHj ze;ofdGKf0}b4>uq)NeH=ANB0117)?kN7T-Z@&Ivl8|lAh3|DG9lhy_FAF*JX`qG2z zRP|sa%d97A6Wzny&`^Z?S4+*huFZgEu7O4a#UF-(62i7Ntx%!+5K?UOu!}b1Ndx%U2N%1L!NPy8GSrZQuyy zuc(0BFj)lr%-;^!^J5d3$QT@JfzG#5ULa5#zNTF)um8?L=>x z-vYmeUOdn6tszKpa#;9cUD*L=VN))$4mRm(WjO4)x$=Sq!hCQTMoRuve02Np%oXll z11XL(sK57Yz7QcI-gEEJmq=(Pn?-&!su}>7LuTAn6x^*PMJcmgn0vGuAbz z{SSNpyi%-TM0L9*(_*wZllW)`FEdZaP{Z6I{V;Vaaw>CQ?r>|q*lO2yVR3FxH-D%~ z|B0_+_WtL%j~A1DB&1H?Opb|=l2<#v9woRBgMKvO{~bGpq7IlKjQ@yNXG}Z_qW|8n5z+|L6=cllgn{NMDd(qVRRnt5~BE_>H{H*bkCq14Cw2Yaurff96h@7B<&xy=NQ?zI~MF^}NL-RRl zT6#5wA#d`=QBuwuC^WtOc&m;CXzUy$h(R6(j{GHyPK7tRRF`AIveMR5PM1GH^KUKe z!_}<+UV=ohxAW+d>rL3V7PfYei;Pn`OQ$wmxLZ3*kWy;%{SM^QV9?CunE?7l1y9R- z!uwuHK{`q~6L7}rfY5C&Ad9V^Qgrlr4YfXBuidOsmf$c=Cu0C3827-R$Gl=A?CdUI-g*KSXs~^3H zGqY&micHeop1OsD|9aU`mP)h=bDM-1hwu z0L^8((s1ADQARBAwR`7NOix#W50|i&0hr2jel?_*a9}F;{%N;H9mhzvReVO2&%-8U zkK(t4#wsvwX7bf92g!QU&iWW5$=Q3~leU5K7aa9p;AaEGQT?~3yiLm+tujU6Z<}qh z8eeDHNBv*EZBN}iR!X3H5nSJ^Pi(WYN6sCTDB26!-?FG1t=epIO>f|PP#AjiyI9}7 z?bVv^>x`i{cnTV*ekl&ucr9^wY{iu9c|eD-A#y-kR4)ovHOKcEwa(gPbGqtX%?ehO z3BQ1RBnLPv#eHz9-BIQsDr0Tz`G@N%mTfgmj*8fXJhAHWn~q{G6KmPj=WrrP3o(e4 zxV}AaN@-N32+Vz;z&)RX)0m1Y!^qk)JIJB3?L+HvRaehn|93 zOe|E~g6;B*m)3Y`3}caKdYF&fk5Q>tF;@a9$QrsG6k+z0ciPa-W<;z!+34a9$eTeP z%Hnd9G>8eplaAC{*WOu3@FzDat{5T*elK16F*a%u?Db>1GVzNe{mjdo^|ZG1uV?vw@`{&SVQp8Q9cY8d8kD%|4MX1ztu`oY zokoa?CO78NQf!rwR;)@q$%|{a4%UWtyUYEvELQR%m_P>ve2#%=`YnNZ%vZYC1c1Qo@rbG{Bc^K%;K+hU8rzzw#1deagI<)D10mS?NqqniNjVfRDy@7og>0C+wSK(nMd^KdIh6Fsz%{QO2dDE@ zn8Y0NDj?5T0G_M8rGs3zE@d=vTk&{p-3f9Acz?Lo4O^-uoDI6d`&d8N1=nFtU+mjP zKCQXyD+yfmf**)h5B!)I7n!esWtncs-LN*yoYOH51rE05HO$0KZ~1@Hvno@ZE= z{P!~Y7n&&&Kdi6CZ5cv4Y_-|m89W!y8hu=#E(=Nc`utL&W0T#6Je%r<>=SC#m#l{8 zT3J_Laj=5~+Fcf!Tho?V@&gMfx+gc{&&J%ZzKGsCmD-Jlx2!Se2K*j5sex+8EBw6$ zxZPBD2}&zGX55f>`0D}8)RpfqRoKB1H51Ktz&smjm6{>x;IzlRvw`-@uGv7;(d%+B zQ5m$OkyyxMS-t2GymOAZe7j=QhbJ=Rzgc5cx9-f|?LtQ`)(zQUx*CT#Ff>kLVd9`m z{tFDgTRQ)x1^sJi*i?W5W+#hNPZc2K_3z=2HO*O89SUeGS~82OyT7T$8(*9vI|_!0 z6-gsJ`t8rxA2QsX#JQr&WPjCUgP^NlCqvvk>{8!NSr7bFRa|cfg^IcVO}u?`hQRbK z=C*IU48oOR&X#p1bLV9@MSN)>$$r*8Q-U^r=R2kcE!dqoq3s!t+*euogoJtQz>^)% zz>uEAxkrx}zdSQso5CR-+Ic1M=xnF-<{fsJm@~Ah99j6m5W)VaUpwT_5kpv~L6WGHwfagsdC=jk*0icxDWyNzUkwc2bp|f5}sM zg>S+26YbVQL;2TE!*yNi1^xW!eqLXVf4Q;xPl)5q4x9`jTwZaGoUd41HgXI!DSu(b zDx&DVCzx}#0vwW^UjBPqRU30 zvC4TRzNo9o4Q2;hG4PZJ7EK{xyxng$ECKGqo{b;-npAK}4qTpA8wU6_dQ8Y_8!eAi zgz|Q0Z(9P+^k*tdv(zZwHlI`U#7rJ^(d>D%aZNY~6c|f6pXp}nML^GjGDga2@TLiL zppHMXTEa!<=4m~40Fq750X|P1Vh(h!lvIoIICTNX$qK)VsI!tcN$z8IfVs)3+ul?S z3fP`*p##N>LRT}541Pkspq&5ukMo|MZ{c1?w#r?t1UrKEJZtxF0dw4coMLC{tKH#) z=j_)*KJW@q#(lx+TQeINv8Gh4i!D79JC}{KI}-bfNSJ9B)zSTfJ?~eKaudJxqR=vT z#e~QumGJ^5f9^XS9{mYYhHMv-ONNZGH=D-hzyE&gH}O9vh`<+- hp7D<;Vg#MhY_fd8$XZmio$otA`Z~ti`6zVge*mLqeEI+Y literal 5301 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 D*xjK4 diff --git a/tests/ref/markup/lists.png b/tests/ref/markup/lists.png new file mode 100644 index 0000000000000000000000000000000000000000..815e51056515c57169d79c987babe107e97e5605 GIT binary patch literal 14750 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 ZLd>E~l8q)lo%ySlcv06#r(7Es^*^VMowoo0 literal 8225 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 HAOrso2t+#B diff --git a/tests/ref/markup/strong.png b/tests/ref/markup/strong.png index ce96d6a2df7b7fc2ca9fc7143d6759adfc670a7c..cc80690cb1761b30ba326e7e47324a0d9be55be4 100644 GIT binary patch literal 2401 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 Ue1De~{h$A!j4ZFeF>p=z7d#P5)c^nh diff --git a/tests/typ/code/include.typ b/tests/typ/code/include.typ index 945a041d..8080c6e8 100644 --- a/tests/typ/code/include.typ +++ b/tests/typ/code/include.typ @@ -13,7 +13,7 @@ // Expression as a file name. #let chap2 = include "import" + "able/chap" + "2.typ" -_ -- Intermission -- _ +-- _Intermission_ -- #chap2 { diff --git a/tests/typ/markup/basic.typ b/tests/typ/markup/basic.typ index 24c23e64..01582ceb 100644 --- a/tests/typ/markup/basic.typ +++ b/tests/typ/markup/basic.typ @@ -1,20 +1,10 @@ // Test basic markup. --- -#let linebreak() = [ - // Inside the old line break definition is still active. - #square(length: 3pt, fill: black) \ -] - A \ B \ C --- -// Paragraph breaks don't exist! -#let parbreak() = [ ] - -No more - -paragraph breaks +Paragraph breaks for you! diff --git a/tests/typ/markup/emph.typ b/tests/typ/markup/emph.typ index 8e25e7d3..048097a1 100644 --- a/tests/typ/markup/emph.typ +++ b/tests/typ/markup/emph.typ @@ -9,15 +9,3 @@ Partly em_phas_ized. // Scoped to body. #rect[_Scoped] to body. - ---- -#let emph = strong -_Strong_ - -#let emph() = "Hi" -_, _! - -#let emph = "hi" - -// Error: 1-2 expected function, found string -_ diff --git a/tests/typ/markup/heading.typ b/tests/typ/markup/heading.typ index 56f48bae..cffa6ed4 100644 --- a/tests/typ/markup/heading.typ +++ b/tests/typ/markup/heading.typ @@ -4,38 +4,21 @@ // Different number of hashtags. // Valid levels. -# 1 -### 2 -###### 6 +# Level 1 +### Level 2 +###### Level 6 // Too many hashtags. // Warning: 1-8 should not exceed depth 6 -####### 7 - ---- -// Heading continuation over linebreak. - -// Code blocks continue heading. -# A{ - "B" -} - -// Function call continues heading. -# #rect[ - A -] B - -// Without some kind of block, headings end at a line break. -# A -B +####### Level 7 --- // Heading vs. no heading. // Parsed as headings if at start of the context. -/**/ # Ok -{[## Ok]} -#rect[### Ok] +/**/ # Level 1 +{[## Level 2]} +#rect[### Level 3] // Not at the start of the context. No # heading @@ -44,9 +27,16 @@ No # heading \# No heading --- -// Make small, but double heading. -#let heading(contents) = heading(contents + contents, level: 6) +// While indented at least as much as the start, the heading continues. -// The new heading's argument list doesn't contain `level`. -// Error: 1-11 unexpected argument -### Twice. +# This + is + indented. + +# This + is not. + +// Code blocks continue heading. +# A { + "B" +} diff --git a/tests/typ/markup/lists.typ b/tests/typ/markup/lists.typ new file mode 100644 index 00000000..5c464ab8 --- /dev/null +++ b/tests/typ/markup/lists.typ @@ -0,0 +1,45 @@ +// Test lists. + +--- +_Shopping list_ +- Apples +- Potatoes +- Juice + +--- +- First level. + - Second level. + + There are multiple paragraphs. + - Third level. + + Still the same bullet point. + - Still level 2. +- At the top. + +--- +- Works + - Also with four spaces + - Or two tabs + +--- + - Top-level indent +- is fine. + +--- +Tightly +- surrounded +- by two +paragraphs. + +--- + - A + - B + - C + - D + +--- +- Level 1 + - Level [ +2 through template +] diff --git a/tests/typ/markup/raw.typ b/tests/typ/markup/raw.typ index cae3d261..005d413e 100644 --- a/tests/typ/markup/raw.typ +++ b/tests/typ/markup/raw.typ @@ -45,14 +45,6 @@ def hi(): print("Hi!") ``` ---- -// Make everything block-level. -#let raw(text) = raw(text, block: true) - -// The new raw's argument list doesn't contain `block`. -// Error: 6-10 unexpected argument -This `is` block-level. - --- // Unterminated. // Error: 2:1 expected backtick(s) diff --git a/tests/typ/markup/strong.typ b/tests/typ/markup/strong.typ index b487d06d..36695c48 100644 --- a/tests/typ/markup/strong.typ +++ b/tests/typ/markup/strong.typ @@ -9,15 +9,3 @@ Partly str*ength*ened. // Scoped to body. #rect[*Scoped] to body. - ---- -#let strong = emph -*Emph* - -#let strong() = "Bye" -*, *! - -#let strong = 123 - -// Error: 1-2 expected function, found integer -*