summaryrefslogtreecommitdiff
path: root/src/syntax/node.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-10-10 22:41:56 +0200
committerLaurenz <laurmaedje@gmail.com>2020-10-10 22:41:56 +0200
commitc216a4fc26c72938ddad60bc5fe4fa9e45263b30 (patch)
tree0a563e3076a8d0724d0361b5d81a2b8d07d15cbe /src/syntax/node.rs
parent51bf3268ddf5db1bdd61e59bfb4a30f0463a4bfb (diff)
Flatten ast module back into syntax module 🌪
Diffstat (limited to 'src/syntax/node.rs')
-rw-r--r--src/syntax/node.rs118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/syntax/node.rs b/src/syntax/node.rs
new file mode 100644
index 00000000..102ef3b5
--- /dev/null
+++ b/src/syntax/node.rs
@@ -0,0 +1,118 @@
+//! Syntax tree nodes.
+
+use super::*;
+
+/// A syntax node, which encompasses a single logical entity of parsed source
+/// code.
+#[derive(Debug, Clone, PartialEq)]
+pub enum SynNode {
+ /// Whitespace containing less than two newlines.
+ Space,
+ /// Plain text.
+ Text(String),
+
+ /// A forced line break.
+ Linebreak,
+ /// A paragraph break.
+ Parbreak,
+ /// Emphasized text was enabled / disabled.
+ Emph,
+ /// Strong text was enabled / disabled.
+ Strong,
+
+ /// A section heading.
+ Heading(NodeHeading),
+ /// An optionally syntax-highlighted raw block.
+ Raw(NodeRaw),
+
+ /// An expression.
+ Expr(Expr),
+}
+
+/// A section heading.
+#[derive(Debug, Clone, PartialEq)]
+pub struct NodeHeading {
+ /// The section depth (how many hashtags minus 1).
+ pub level: Spanned<u8>,
+ /// The contents of the heading.
+ pub contents: SynTree,
+}
+
+/// A raw block, rendered in monospace with optional syntax highlighting.
+///
+/// Raw blocks start with an arbitrary number of backticks and end with the same
+/// number of backticks. If you want to include a sequence of backticks in a raw
+/// block, simply surround the block with more backticks.
+///
+/// When using at least two backticks, an optional language tag may follow
+/// directly after the backticks. This tag defines which language to
+/// syntax-highlight the text in. Apart from the language tag and some
+/// whitespace trimming discussed below, everything inside a raw block is
+/// rendered verbatim, in particular, there are no escape sequences.
+///
+/// # Examples
+/// - Raw text is surrounded by backticks.
+/// ```typst
+/// `raw`
+/// ```
+/// - An optional language tag may follow directly at the start when the block
+/// is surrounded by at least two backticks.
+/// ```typst
+/// ``rust println!("hello!")``;
+/// ```
+/// - Blocks can span multiple lines. Two backticks suffice to be able to
+/// specify the language tag, but three are fine, too.
+/// ```typst
+/// ``rust
+/// loop {
+/// find_yak().shave();
+/// }
+/// ``
+/// ```
+/// - Start with a space to omit the language tag (the space will be trimmed
+/// from the output) and use more backticks to allow backticks in the raw
+/// text.
+/// `````typst
+/// ```` This contains ```backticks``` and has no leading & trailing spaces. ````
+/// `````
+///
+/// # Trimming
+/// If we would always render the raw text between the backticks exactly as
+/// given, a few things would become problematic or even impossible:
+/// - Typical multiline code blocks (like in the example above) would have an
+/// additional newline before and after the code.
+/// - Raw text wrapped in more than one backtick could not exist without
+/// leading whitespace since the first word would be interpreted as a
+/// language tag.
+/// - A single backtick without surrounding spaces could not exist as raw text
+/// since it would be interpreted as belonging to the opening or closing
+/// backticks.
+///
+/// To fix these problems, we trim text in multi-backtick blocks as follows:
+/// - We trim a single space or a sequence of whitespace followed by a newline
+/// at the start.
+/// - We trim a single space or a newline followed by a sequence of whitespace
+/// at the end.
+///
+/// With these rules, a single raw backtick can be produced by the sequence
+/// ``` `` ` `` ```, ``` `` unhighlighted text `` ``` has no surrounding
+/// spaces and multiline code blocks don't have extra empty lines. Note that
+/// you can always force leading or trailing whitespace simply by adding more
+/// spaces.
+#[derive(Debug, Clone, PartialEq)]
+pub struct NodeRaw {
+ /// An optional identifier specifying the language to syntax-highlight in.
+ pub lang: Option<Ident>,
+ /// The lines of raw text, determined as the raw string between the
+ /// backticks trimmed according to the above rules and split at newlines.
+ pub lines: Vec<String>,
+ /// Whether the element can be layouted inline.
+ ///
+ /// - When true, it will be layouted integrated within the surrounding
+ /// paragraph.
+ /// - When false, it will be separated into its own paragraph.
+ ///
+ /// Single-backtick blocks are always inline-level. Multi-backtick blocks
+ /// are inline-level when they contain no newlines.
+ pub inline: bool,
+}