Rename SyntaxTree to Markup

Also `SyntaxNode` -> `MarkupNode`.
This commit is contained in:
Laurenz 2021-09-15 12:43:57 +02:00
parent c18321a4c2
commit 5de791d9e6
9 changed files with 98 additions and 99 deletions

View File

@ -1,4 +1,4 @@
//! Evaluation of syntax trees into modules. //! Evaluation of markup into modules.
#[macro_use] #[macro_use]
mod array; mod array;
@ -46,9 +46,9 @@ use crate::util::RefMutExt;
use crate::Context; use crate::Context;
/// Evaluate a parsed source file into a module. /// Evaluate a parsed source file into a module.
pub fn eval(ctx: &mut Context, source: SourceId, ast: &SyntaxTree) -> TypResult<Module> { pub fn eval(ctx: &mut Context, source: SourceId, markup: &Markup) -> TypResult<Module> {
let mut ctx = EvalContext::new(ctx, source); let mut ctx = EvalContext::new(ctx, source);
let template = ast.eval(&mut ctx)?; let template = markup.eval(&mut ctx)?;
Ok(Module { scope: ctx.scopes.top, template }) Ok(Module { scope: ctx.scopes.top, template })
} }
@ -159,7 +159,7 @@ pub trait Eval {
fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output>; fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output>;
} }
impl Eval for SyntaxTree { impl Eval for Markup {
type Output = Template; type Output = Template;
fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> { fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> {
@ -253,7 +253,7 @@ impl Eval for TemplateExpr {
type Output = Template; type Output = Template;
fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> { fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> {
self.tree.eval(ctx) self.body.eval(ctx)
} }
} }

View File

@ -7,13 +7,13 @@ use crate::layout::{ParChild, ParNode, StackChild, StackNode};
use crate::syntax::*; use crate::syntax::*;
use crate::util::BoolExt; use crate::util::BoolExt;
/// Walk a syntax node and fill the currently built template. /// Walk markup, filling the currently built template.
pub trait Walk { pub trait Walk {
/// Walk the node. /// Walk the node.
fn walk(&self, ctx: &mut EvalContext) -> TypResult<()>; fn walk(&self, ctx: &mut EvalContext) -> TypResult<()>;
} }
impl Walk for SyntaxTree { impl Walk for Markup {
fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
for node in self.iter() { for node in self.iter() {
node.walk(ctx)?; node.walk(ctx)?;
@ -22,7 +22,7 @@ impl Walk for SyntaxTree {
} }
} }
impl Walk for SyntaxNode { impl Walk for MarkupNode {
fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> {
match self { match self {
Self::Space => ctx.template.space(), Self::Space => ctx.template.space(),

View File

@ -2,25 +2,26 @@
//! //!
//! # Steps //! # Steps
//! - **Parsing:** The parsing step first transforms a plain string into an //! - **Parsing:** The parsing step first transforms a plain string into an
//! [iterator of tokens][tokens]. This token stream is [parsed] into a [syntax //! [iterator of tokens][tokens]. This token stream is [parsed] into [markup].
//! tree]. The structures describing the tree can be found in the [syntax] //! The syntactical structures describing markup and embedded code can be
//! module. //! found in the [syntax] module.
//! - **Evaluation:** The next step is to [evaluate] the syntax tree. This //! - **Evaluation:** The next step is to [evaluate] the markup. This produces a
//! produces a [module], consisting of a scope of values that were exported by //! [module], consisting of a scope of values that were exported by the code
//! the module and a template with the contents of the module. This template //! and a template with the contents of the module. This template can be
//! can be [instantiated] in a state to produce a layout tree, a high-level, //! [instantiated] in a state to produce a layout tree, a high-level, fully
//! fully styled representation of the document. The nodes of this tree are //! styled representation of the document. The nodes of this tree are
//! self-contained and order-independent and thus much better suited for //! self-contained and order-independent and thus much better suited for
//! layouting than a syntax tree. //! layouting than the raw markup.
//! - **Layouting:** Next, the tree is [layouted] into a portable version of the //! - **Layouting:** Next, the tree is [layouted] into a portable version of the
//! typeset document. The output of this is a collection of [`Frame`]s (one //! typeset document. The output of this is a collection of [`Frame`]s (one
//! per page), ready for exporting. //! per page), ready for exporting.
//! - **Exporting:** The finished layout can be exported into a supported //! - **Exporting:** The finished layout can be exported into a supported
//! format. Currently, the only supported output format is [PDF]. //! format. Currently, the only supported output format is [PDF].
//! //!
//! [tokens]: parse::Tokens //! [tokens]: parse::Tokens
//! [parsed]: parse::parse //! [parsed]: parse::parse
//! [syntax tree]: syntax::SyntaxTree //! [markup]: syntax::Markup
//! [evaluate]: eval::eval //! [evaluate]: eval::eval
//! [module]: eval::Module //! [module]: eval::Module
//! [instantiated]: eval::Template::to_tree //! [instantiated]: eval::Template::to_tree
@ -57,7 +58,7 @@ use crate::layout::{EvictionPolicy, LayoutCache};
use crate::layout::{Frame, LayoutTree}; use crate::layout::{Frame, LayoutTree};
use crate::loading::Loader; use crate::loading::Loader;
use crate::source::{SourceId, SourceStore}; use crate::source::{SourceId, SourceStore};
use crate::syntax::SyntaxTree; use crate::syntax::Markup;
/// The core context which holds the loader, configuration and cached artifacts. /// The core context which holds the loader, configuration and cached artifacts.
pub struct Context { pub struct Context {
@ -99,8 +100,8 @@ impl Context {
&self.state &self.state
} }
/// Parse a source file and return the resulting syntax tree. /// Parse a source file and return the resulting markup.
pub fn parse(&mut self, id: SourceId) -> TypResult<SyntaxTree> { pub fn parse(&mut self, id: SourceId) -> TypResult<Markup> {
parse::parse(self.sources.get(id)) parse::parse(self.sources.get(id))
} }

View File

@ -18,31 +18,31 @@ use crate::syntax::*;
use crate::util::EcoString; use crate::util::EcoString;
/// Parse a source file. /// Parse a source file.
pub fn parse(source: &SourceFile) -> TypResult<SyntaxTree> { pub fn parse(source: &SourceFile) -> TypResult<Markup> {
let mut p = Parser::new(source); let mut p = Parser::new(source);
let tree = tree(&mut p); let markup = markup(&mut p);
let errors = p.finish(); let errors = p.finish();
if errors.is_empty() { if errors.is_empty() {
Ok(tree) Ok(markup)
} else { } else {
Err(Box::new(errors)) Err(Box::new(errors))
} }
} }
/// Parse a syntax tree. /// Parse markup.
fn tree(p: &mut Parser) -> SyntaxTree { fn markup(p: &mut Parser) -> Markup {
tree_while(p, true, &mut |_| true) markup_while(p, true, &mut |_| true)
} }
/// Parse a syntax tree that stays right of the given column. /// Parse markup that stays right of the given column.
fn tree_indented(p: &mut Parser, column: usize) -> SyntaxTree { fn markup_indented(p: &mut Parser, column: usize) -> Markup {
p.eat_while(|t| match t { p.eat_while(|t| match t {
Token::Space(n) => n == 0, Token::Space(n) => n == 0,
Token::LineComment(_) | Token::BlockComment(_) => true, Token::LineComment(_) | Token::BlockComment(_) => true,
_ => false, _ => false,
}); });
tree_while(p, false, &mut |p| match p.peek() { markup_while(p, false, &mut |p| match p.peek() {
Some(Token::Space(n)) if n >= 1 => p.column(p.next_end()) > column, Some(Token::Space(n)) if n >= 1 => p.column(p.next_end()) > column,
_ => true, _ => true,
}) })
@ -52,14 +52,14 @@ fn tree_indented(p: &mut Parser, column: usize) -> SyntaxTree {
/// ///
/// 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
/// beginning of a line or template are allowed. /// beginning of a line or template are allowed.
fn tree_while<F>(p: &mut Parser, mut at_start: bool, f: &mut F) -> SyntaxTree fn markup_while<F>(p: &mut Parser, mut at_start: bool, f: &mut F) -> Markup
where where
F: FnMut(&mut Parser) -> bool, F: FnMut(&mut Parser) -> bool,
{ {
let mut tree = vec![]; let mut tree = vec![];
while !p.eof() && f(p) { while !p.eof() && f(p) {
if let Some(node) = node(p, &mut at_start) { if let Some(node) = markup_node(p, &mut at_start) {
at_start &= matches!(node, SyntaxNode::Space | SyntaxNode::Parbreak(_)); at_start &= matches!(node, MarkupNode::Space | MarkupNode::Parbreak(_));
tree.push(node); tree.push(node);
} }
} }
@ -67,8 +67,8 @@ where
tree tree
} }
/// Parse a syntax node. /// Parse a markup node.
fn node(p: &mut Parser, at_start: &mut bool) -> Option<SyntaxNode> { fn markup_node(p: &mut Parser, at_start: &mut bool) -> Option<MarkupNode> {
let token = p.peek()?; let token = p.peek()?;
let span = p.peek_span(); let span = p.peek_span();
let node = match token { let node = match token {
@ -76,23 +76,23 @@ fn node(p: &mut Parser, at_start: &mut bool) -> Option<SyntaxNode> {
Token::Space(newlines) => { Token::Space(newlines) => {
*at_start |= newlines > 0; *at_start |= newlines > 0;
if newlines < 2 { if newlines < 2 {
SyntaxNode::Space MarkupNode::Space
} else { } else {
SyntaxNode::Parbreak(span) MarkupNode::Parbreak(span)
} }
} }
// Text. // Text.
Token::Text(text) => SyntaxNode::Text(text.into()), Token::Text(text) => MarkupNode::Text(text.into()),
Token::Tilde => SyntaxNode::Text("\u{00A0}".into()), Token::Tilde => MarkupNode::Text("\u{00A0}".into()),
Token::HyphHyph => SyntaxNode::Text("\u{2013}".into()), Token::HyphHyph => MarkupNode::Text("\u{2013}".into()),
Token::HyphHyphHyph => SyntaxNode::Text("\u{2014}".into()), Token::HyphHyphHyph => MarkupNode::Text("\u{2014}".into()),
Token::UnicodeEscape(t) => SyntaxNode::Text(unicode_escape(p, t)), Token::UnicodeEscape(t) => MarkupNode::Text(unicode_escape(p, t)),
// Markup. // Markup.
Token::Backslash => SyntaxNode::Linebreak(span), Token::Backslash => MarkupNode::Linebreak(span),
Token::Star => SyntaxNode::Strong(span), Token::Star => MarkupNode::Strong(span),
Token::Underscore => SyntaxNode::Emph(span), Token::Underscore => MarkupNode::Emph(span),
Token::Raw(t) => raw(p, t), Token::Raw(t) => raw(p, t),
Token::Eq if *at_start => return Some(heading(p)), Token::Eq if *at_start => return Some(heading(p)),
Token::Hyph if *at_start => return Some(list_node(p)), Token::Hyph if *at_start => return Some(list_node(p)),
@ -100,7 +100,7 @@ fn node(p: &mut Parser, at_start: &mut bool) -> Option<SyntaxNode> {
// Line-based markup that is not currently at the start of the line. // Line-based markup that is not currently at the start of the line.
Token::Eq | Token::Hyph | Token::Numbering(_) => { Token::Eq | Token::Hyph | Token::Numbering(_) => {
SyntaxNode::Text(p.peek_src().into()) MarkupNode::Text(p.peek_src().into())
} }
// Hashtag + keyword / identifier. // Hashtag + keyword / identifier.
@ -121,12 +121,12 @@ fn node(p: &mut Parser, at_start: &mut bool) -> Option<SyntaxNode> {
} }
p.end_group(); p.end_group();
return expr.map(SyntaxNode::Expr); return expr.map(MarkupNode::Expr);
} }
// Block and template. // Block and template.
Token::LeftBrace => return Some(SyntaxNode::Expr(block(p, false))), Token::LeftBrace => return Some(MarkupNode::Expr(block(p, false))),
Token::LeftBracket => return Some(SyntaxNode::Expr(template(p))), Token::LeftBracket => return Some(MarkupNode::Expr(template(p))),
// Comments. // Comments.
Token::LineComment(_) | Token::BlockComment(_) => { Token::LineComment(_) | Token::BlockComment(_) => {
@ -163,17 +163,17 @@ fn unicode_escape(p: &mut Parser, token: UnicodeEscapeToken) -> EcoString {
} }
/// Handle a raw block. /// Handle a raw block.
fn raw(p: &mut Parser, token: RawToken) -> SyntaxNode { fn raw(p: &mut Parser, token: RawToken) -> MarkupNode {
let span = p.peek_span(); let span = p.peek_span();
let raw = resolve::resolve_raw(span, token.text, token.backticks); let raw = resolve::resolve_raw(span, token.text, token.backticks);
if !token.terminated { if !token.terminated {
p.error(span.end, "expected backtick(s)"); p.error(span.end, "expected backtick(s)");
} }
SyntaxNode::Raw(Box::new(raw)) MarkupNode::Raw(Box::new(raw))
} }
/// Parse a heading. /// Parse a heading.
fn heading(p: &mut Parser) -> SyntaxNode { fn heading(p: &mut Parser) -> MarkupNode {
let start = p.next_start(); let start = p.next_start();
let column = p.column(start); let column = p.column(start);
p.eat_assert(Token::Eq); p.eat_assert(Token::Eq);
@ -185,11 +185,11 @@ fn heading(p: &mut Parser) -> SyntaxNode {
} }
if level > 6 { if level > 6 {
return SyntaxNode::Text(p.get(start .. p.prev_end()).into()); return MarkupNode::Text(p.get(start .. p.prev_end()).into());
} }
let body = tree_indented(p, column); let body = markup_indented(p, column);
SyntaxNode::Heading(Box::new(HeadingNode { MarkupNode::Heading(Box::new(HeadingNode {
span: p.span_from(start), span: p.span_from(start),
level, level,
body, body,
@ -197,21 +197,21 @@ fn heading(p: &mut Parser) -> SyntaxNode {
} }
/// Parse a single list item. /// Parse a single list item.
fn list_node(p: &mut Parser) -> SyntaxNode { fn list_node(p: &mut Parser) -> MarkupNode {
let start = p.next_start(); let start = p.next_start();
let column = p.column(start); let column = p.column(start);
p.eat_assert(Token::Hyph); p.eat_assert(Token::Hyph);
let body = tree_indented(p, column); let body = markup_indented(p, column);
SyntaxNode::List(Box::new(ListNode { span: p.span_from(start), body })) MarkupNode::List(Box::new(ListNode { span: p.span_from(start), body }))
} }
/// Parse a single enum item. /// Parse a single enum item.
fn enum_node(p: &mut Parser, number: Option<usize>) -> SyntaxNode { fn enum_node(p: &mut Parser, number: Option<usize>) -> MarkupNode {
let start = p.next_start(); let start = p.next_start();
let column = p.column(start); let column = p.column(start);
p.eat_assert(Token::Numbering(number)); p.eat_assert(Token::Numbering(number));
let body = tree_indented(p, column); let body = markup_indented(p, column);
SyntaxNode::Enum(Box::new(EnumNode { MarkupNode::Enum(Box::new(EnumNode {
span: p.span_from(start), span: p.span_from(start),
number, number,
body, body,
@ -521,9 +521,9 @@ fn idents(p: &mut Parser, items: Vec<CallArg>) -> Vec<Ident> {
// Parse a template block: `[...]`. // Parse a template block: `[...]`.
fn template(p: &mut Parser) -> Expr { fn template(p: &mut Parser) -> Expr {
p.start_group(Group::Bracket, TokenMode::Markup); p.start_group(Group::Bracket, TokenMode::Markup);
let tree = tree(p); let tree = markup(p);
let span = p.end_group(); let span = p.end_group();
Expr::Template(Box::new(TemplateExpr { span, tree })) Expr::Template(Box::new(TemplateExpr { span, body: tree }))
} }
/// Parse a code block: `{...}`. /// Parse a code block: `{...}`.

View File

@ -1,7 +1,8 @@
use std::rc::Rc; use std::rc::Rc;
use super::*; use super::{Ident, Markup, Span, Token};
use crate::geom::{AngularUnit, LengthUnit}; use crate::geom::{AngularUnit, LengthUnit};
use crate::util::EcoString;
/// An expression. /// An expression.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -170,7 +171,7 @@ pub struct TemplateExpr {
/// The source code location. /// The source code location.
pub span: Span, pub span: Span,
/// The contents of the template. /// The contents of the template.
pub tree: SyntaxTree, pub body: Markup,
} }
/// A grouped expression: `(1 + 2)`. /// A grouped expression: `(1 + 2)`.

View File

@ -1,8 +1,12 @@
use super::*; use super::{Expr, Ident, Span};
use crate::util::EcoString;
/// A syntax node, encompassing a single logical entity of parsed source code. /// The syntactical root capable of representing a full parsed document.
pub type Markup = Vec<MarkupNode>;
/// A single piece of markup.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum SyntaxNode { pub enum MarkupNode {
/// Whitespace containing less than two newlines. /// Whitespace containing less than two newlines.
Space, Space,
/// A forced line break: `\`. /// A forced line break: `\`.
@ -50,7 +54,7 @@ pub struct HeadingNode {
/// The section depth (numer of equals signs). /// The section depth (numer of equals signs).
pub level: usize, pub level: usize,
/// The contents of the heading. /// The contents of the heading.
pub body: SyntaxTree, pub body: Markup,
} }
/// An item in an unordered list: `- ...`. /// An item in an unordered list: `- ...`.
@ -59,7 +63,7 @@ pub struct ListNode {
/// The source code location. /// The source code location.
pub span: Span, pub span: Span,
/// The contents of the list item. /// The contents of the list item.
pub body: SyntaxTree, pub body: Markup,
} }
/// An item in an enumeration (ordered list): `1. ...`. /// An item in an enumeration (ordered list): `1. ...`.
@ -70,5 +74,5 @@ pub struct EnumNode {
/// The number, if any. /// The number, if any.
pub number: Option<usize>, pub number: Option<usize>,
/// The contents of the list item. /// The contents of the list item.
pub body: SyntaxTree, pub body: Markup,
} }

View File

@ -2,7 +2,7 @@
mod expr; mod expr;
mod ident; mod ident;
mod node; mod markup;
mod pretty; mod pretty;
mod span; mod span;
mod token; mod token;
@ -10,14 +10,7 @@ pub mod visit;
pub use expr::*; pub use expr::*;
pub use ident::*; pub use ident::*;
pub use node::*; pub use markup::*;
pub use pretty::*; pub use pretty::*;
pub use span::*; pub use span::*;
pub use token::*; pub use token::*;
use crate::util::EcoString;
/// The abstract syntax tree.
///
/// This type can represent a full parsed document.
pub type SyntaxTree = Vec<SyntaxNode>;

View File

@ -75,7 +75,7 @@ impl Write for Printer {
} }
} }
impl Pretty for SyntaxTree { impl Pretty for Markup {
fn pretty(&self, p: &mut Printer) { fn pretty(&self, p: &mut Printer) {
for node in self { for node in self {
node.pretty(p); node.pretty(p);
@ -83,7 +83,7 @@ impl Pretty for SyntaxTree {
} }
} }
impl Pretty for SyntaxNode { impl Pretty for MarkupNode {
fn pretty(&self, p: &mut Printer) { fn pretty(&self, p: &mut Printer) {
match self { match self {
// TODO: Handle escaping. // TODO: Handle escaping.
@ -266,7 +266,7 @@ impl Pretty for Named {
impl Pretty for TemplateExpr { impl Pretty for TemplateExpr {
fn pretty(&self, p: &mut Printer) { fn pretty(&self, p: &mut Printer) {
p.push('['); p.push('[');
self.tree.pretty(p); self.body.pretty(p);
p.push(']'); p.push(']');
} }
} }

View File

@ -1,6 +1,6 @@
//! Mutable and immutable syntax tree traversal. //! Mutable and immutable syntax tree traversal.
use crate::syntax::*; use super::*;
/// Implement the immutable and the mutable visitor version. /// Implement the immutable and the mutable visitor version.
macro_rules! impl_visitors { macro_rules! impl_visitors {
@ -78,25 +78,25 @@ macro_rules! impl_visitor {
} }
impl_visitors! { impl_visitors! {
visit_tree(v, tree: SyntaxTree) { visit_tree(v, markup: Markup) {
for node in tree { for node in markup {
v.visit_node(node); v.visit_node(node);
} }
} }
visit_node(v, node: SyntaxNode) { visit_node(v, node: MarkupNode) {
match node { match node {
SyntaxNode::Space => {} MarkupNode::Space => {}
SyntaxNode::Linebreak(_) => {} MarkupNode::Linebreak(_) => {}
SyntaxNode::Parbreak(_) => {} MarkupNode::Parbreak(_) => {}
SyntaxNode::Strong(_) => {} MarkupNode::Strong(_) => {}
SyntaxNode::Emph(_) => {} MarkupNode::Emph(_) => {}
SyntaxNode::Text(_) => {} MarkupNode::Text(_) => {}
SyntaxNode::Raw(_) => {} MarkupNode::Raw(_) => {}
SyntaxNode::Heading(n) => v.visit_heading(n), MarkupNode::Heading(n) => v.visit_heading(n),
SyntaxNode::List(n) => v.visit_list(n), MarkupNode::List(n) => v.visit_list(n),
SyntaxNode::Enum(n) => v.visit_enum(n), MarkupNode::Enum(n) => v.visit_enum(n),
SyntaxNode::Expr(n) => v.visit_expr(n), MarkupNode::Expr(n) => v.visit_expr(n),
} }
} }
@ -149,7 +149,7 @@ impl_visitors! {
visit_template(v, template: TemplateExpr) { visit_template(v, template: TemplateExpr) {
v.visit_enter(); v.visit_enter();
v.visit_tree(r!(template.tree)); v.visit_tree(r!(template.body));
v.visit_exit(); v.visit_exit();
} }