Skip to content

AST Structure

The SevenMark parser produces an Abstract Syntax Tree (AST) composed of Element nodes. This page documents the element types, expression system, and supporting types.

Element Enum

Every parsed node is a variant of the Element enum. Elements are grouped by category:

Basic Text

VariantDescription
TextPlain text content
CommentComment block (not rendered)
EscapeEscaped character (\*, \[, etc.)
ErrorUnparseable content (error recovery)

Text Styles

VariantDescription
Bold**text**
Italic*text*
Underline__text__
Strikethrough~~text~~
Superscript^^text^^
Subscript,,text,,

All text style variants share the same TextStyleElement structure with span, parameters, and children fields.

Block Elements

VariantDescription
LiteralRaw content block {{{ text }}}
StyledStyled block {{{ #param text }}}
TableTable structure {{{#table ...}}}
ListOrdered/unordered list {{{#list ...}}}
FoldCollapsible section {{{#fold ...}}}
BlockQuoteQuote block {{{#quote ...}}}
CodeCode block {{{#code ...}}}
TeXMath expression {{{#tex ...}}}
RubyRuby annotation {{{#ruby ...}}}
FootnoteFootnote definition {{{#footnote ...}}}

Line Elements

VariantDescription
HeaderHeading (#, ##, ..., ######)
HLineHorizontal rule (---)
SoftBreakSingle newline (paragraph continues)
HardBreakDouble newline (paragraph break)

Wiki Elements

VariantDescription
IncludeInclude another document {{{#include ...}}}
CategoryCategory assignment {{{#category ...}}}
RedirectPage redirect {{{#redirect ...}}}
DefineVariable definition {{{#define ...}}}
IfConditional block {{{#if ...}}}

Media Elements

VariantDescription
MediaInternal media [[file:...]]
ExternalMediaExternal embed [[#youtube ...]], [[#spotify ...]], etc.

Macros

VariantDescription
VariableVariable reference [var(name)]
MentionUser/discussion mention <@uuid> or <#uuid>
TimeNowCurrent time [now]
AgeAge calculation [age(date)]
NullNo-op macro [null]
FootnoteRefFootnote reference [footnote(id)]

Common Element Fields

Most elements share these fields:

rust
struct SomeElement {
    pub span: Span,           // byte offsets (start, end)
    pub parameters: Parameters, // #key="value" pairs
    pub children: Vec<Element>, // nested elements
}

Span

rust
pub struct Span {
    pub start: usize,  // start byte offset in source
    pub end: usize,    // end byte offset in source
}

Every element records its position in the source text via Span. When serialized with the include_locations feature, these appear in JSON output.

Parameters

rust
pub struct Parameter {
    pub span: Span,
    pub key: String,
    pub value: Vec<Element>,  // parsed value (may contain macros)
}

pub type Parameters = BTreeMap<String, Parameter>;

Parameters are stored as a BTreeMap keyed by parameter name. The value is a parsed AST (not just a raw string), allowing macros like [var(name)] inside parameter values.

Expression Enum (Conditionals)

The {{{#if}}} element uses an expression tree for its condition:

VariantDescription
OrLogical OR (||)
AndLogical AND (&&)
NotLogical NOT (!)
ComparisonComparison (==, !=, >, <, >=, <=)
FunctionCallType conversion (int(), len(), str())
StringLiteralQuoted string value
NumberLiteralInteger value
BoolLiteraltrue or false
Nullnull literal
GroupParenthesized sub-expression
ElementEmbedded AST element (e.g., [var(name)])

Operators

Comparison operators:

KindSyntax
Equal==
NotEqual!=
GreaterThan>
LessThan<
GreaterEqual>=
LessEqual<=

Logical operators:

KindSyntax
Or||
And&&
Not!

Table Types

Tables have a multi-level type hierarchy to support conditional rows and cells:

TableElement
  └── children: Vec<TableRowItem>
        ├── Row(TableRowElement)
        │     └── children: Vec<TableCellItem>
        │           ├── Cell(TableCellElement)
        │           └── Conditional(ConditionalTableCells)
        └── Conditional(ConditionalTableRows)

TableElement

rust
pub struct TableElement {
    pub span: Span,
    pub parameters: Parameters,
    pub children: Vec<TableRowItem>,
}

TableRowItem

rust
pub enum TableRowItem {
    Row(TableRowElement),
    Conditional(ConditionalTableRows),
}

TableCellItem

rust
pub enum TableCellItem {
    Cell(TableCellElement),
    Conditional(ConditionalTableCells),
}

List Types

Lists follow a similar pattern to tables for conditional support:

ListElement
  └── children: Vec<ListContentItem>
        ├── Item(ListItemElement)
        └── Conditional(ConditionalListItems)

ListElement

rust
pub struct ListElement {
    pub span: Span,
    pub kind: String,           // list type ("1", "a", "A", "i", "I")
    pub parameters: Parameters,
    pub children: Vec<ListContentItem>,
}

ListContentItem

rust
pub enum ListContentItem {
    Item(ListItemElement),
    Conditional(ConditionalListItems),
}

Mention Types

rust
pub enum MentionType {
    Discussion,  // <#uuid>
    User,        // <@uuid>
}

JSON Serialization Example

Given this input:

sevenmark
# Hello **World**

A paragraph with *italic* text.

The serialized AST (simplified) looks like:

json
[
  {
    "Header": {
      "level": 1,
      "children": [
        { "Text": { "value": "Hello " } },
        { "Bold": { "children": [{ "Text": { "value": "World" } }] } }
      ]
    }
  },
  { "HardBreak": {} },
  {
    "Text": { "value": "A paragraph with " }
  },
  {
    "Italic": {
      "children": [{ "Text": { "value": "italic" } }]
    }
  },
  {
    "Text": { "value": " text." }
  }
]

Each element is serialized as an object with the variant name as key. The Span fields only appear when the include_locations feature is enabled.