From 2a86e4db0bb3894d1cc3b94e1a1af31a6cd87b80 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 14 Mar 2023 22:33:22 +0100 Subject: Reference supplements --- src/syntax/ast.rs | 17 +++++++++++++---- src/syntax/kind.rs | 7 +++++-- src/syntax/lexer.rs | 12 ++++++------ src/syntax/parser.rs | 13 +++++++++++-- 4 files changed, 35 insertions(+), 14 deletions(-) (limited to 'src/syntax') 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: ``. 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 { + 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: ``. 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(); -- cgit v1.2.3