summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/ast.rs17
-rw-r--r--src/syntax/kind.rs7
-rw-r--r--src/syntax/lexer.rs12
-rw-r--r--src/syntax/parser.rs13
4 files changed, 35 insertions, 14 deletions
diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs
index 2fdedbcf..8e48358d 100644
--- a/src/syntax/ast.rs
+++ b/src/syntax/ast.rs
@@ -101,7 +101,7 @@ pub enum Expr {
Link(Link),
/// A label: `<intro>`.
Label(Label),
- /// A reference: `@target`.
+ /// A reference: `@target`, `@target[..]`.
Ref(Ref),
/// A section heading: `= Introduction`.
Heading(Heading),
@@ -604,14 +604,23 @@ impl Label {
}
node! {
- /// A reference: `@target`.
+ /// A reference: `@target`, `@target[..]`.
Ref
}
impl Ref {
/// Get the target.
- pub fn get(&self) -> &str {
- self.0.text().trim_start_matches('@')
+ pub fn target(&self) -> &str {
+ self.0
+ .children()
+ .find(|node| node.kind() == SyntaxKind::RefMarker)
+ .map(|node| node.text().trim_start_matches('@'))
+ .unwrap_or_default()
+ }
+
+ /// Get the supplement.
+ pub fn supplement(&self) -> Option<ContentBlock> {
+ self.0.cast_last_match()
}
}
diff --git a/src/syntax/kind.rs b/src/syntax/kind.rs
index 47b5da31..ce3ae744 100644
--- a/src/syntax/kind.rs
+++ b/src/syntax/kind.rs
@@ -36,8 +36,10 @@ pub enum SyntaxKind {
Link,
/// A label: `<intro>`.
Label,
- /// A reference: `@target`.
+ /// A reference: `@target`, `@target[..]`.
Ref,
+ /// Introduces a reference: `@target`.
+ RefMarker,
/// A section heading: `= Introduction`.
Heading,
/// Introduces a section heading: `=`, `==`, ...
@@ -324,12 +326,14 @@ impl SyntaxKind {
Self::Parbreak => "paragraph break",
Self::Escape => "escape sequence",
Self::Shorthand => "shorthand",
+ Self::SmartQuote => "smart quote",
Self::Strong => "strong content",
Self::Emph => "emphasized content",
Self::Raw => "raw block",
Self::Link => "link",
Self::Label => "label",
Self::Ref => "reference",
+ Self::RefMarker => "reference marker",
Self::Heading => "heading",
Self::HeadingMarker => "heading marker",
Self::ListItem => "list item",
@@ -358,7 +362,6 @@ impl SyntaxKind {
Self::Star => "star",
Self::Underscore => "underscore",
Self::Dollar => "dollar sign",
- Self::SmartQuote => "smart quote",
Self::Plus => "plus",
Self::Minus => "minus",
Self::Slash => "slash",
diff --git a/src/syntax/lexer.rs b/src/syntax/lexer.rs
index 919cce69..8e27d98d 100644
--- a/src/syntax/lexer.rs
+++ b/src/syntax/lexer.rs
@@ -172,7 +172,7 @@ impl Lexer<'_> {
'h' if self.s.eat_if("ttps://") => self.link(),
'0'..='9' => self.numbering(start),
'<' if self.s.at(is_id_continue) => self.label(),
- '@' if self.s.at(is_id_continue) => self.reference(),
+ '@' => self.ref_marker(),
'.' if self.s.eat_if("..") => SyntaxKind::Shorthand,
'-' if self.s.eat_if("--") => SyntaxKind::Shorthand,
@@ -297,6 +297,11 @@ impl Lexer<'_> {
self.text()
}
+ fn ref_marker(&mut self) -> SyntaxKind {
+ self.s.eat_while(is_id_continue);
+ SyntaxKind::RefMarker
+ }
+
fn label(&mut self) -> SyntaxKind {
let label = self.s.eat_while(is_id_continue);
if label.is_empty() {
@@ -310,11 +315,6 @@ impl Lexer<'_> {
SyntaxKind::Label
}
- fn reference(&mut self) -> SyntaxKind {
- self.s.eat_while(is_id_continue);
- SyntaxKind::Ref
- }
-
fn text(&mut self) -> SyntaxKind {
macro_rules! table {
($(|$c:literal)*) => {
diff --git a/src/syntax/parser.rs b/src/syntax/parser.rs
index 201d78fa..127a89d5 100644
--- a/src/syntax/parser.rs
+++ b/src/syntax/parser.rs
@@ -104,8 +104,7 @@ fn markup_expr(p: &mut Parser, at_start: &mut bool) {
| SyntaxKind::SmartQuote
| SyntaxKind::Raw
| SyntaxKind::Link
- | SyntaxKind::Label
- | SyntaxKind::Ref => p.eat(),
+ | SyntaxKind::Label => p.eat(),
SyntaxKind::Hashtag => embedded_code_expr(p),
SyntaxKind::Star => strong(p),
@@ -114,6 +113,7 @@ fn markup_expr(p: &mut Parser, at_start: &mut bool) {
SyntaxKind::ListMarker if *at_start => list_item(p),
SyntaxKind::EnumMarker if *at_start => enum_item(p),
SyntaxKind::TermMarker if *at_start => term_item(p),
+ SyntaxKind::RefMarker => reference(p),
SyntaxKind::Dollar => formula(p),
SyntaxKind::LeftBracket
@@ -198,6 +198,15 @@ fn term_item(p: &mut Parser) {
p.wrap(m, SyntaxKind::TermItem);
}
+fn reference(p: &mut Parser) {
+ let m = p.marker();
+ p.assert(SyntaxKind::RefMarker);
+ if p.directly_at(SyntaxKind::LeftBracket) {
+ content_block(p);
+ }
+ p.wrap(m, SyntaxKind::Ref);
+}
+
fn whitespace_line(p: &mut Parser) {
while !p.newline() && p.current().is_trivia() {
p.eat();