summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/mod.rs30
-rw-r--r--src/parse/tokens.rs31
2 files changed, 48 insertions, 13 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index a997421e..0737d4ca 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -175,18 +175,24 @@ fn markup_indented(p: &mut Parser, min_indent: usize) {
_ => false,
});
+ let marker = p.marker();
let mut at_start = false;
- p.perform(NodeKind::Markup { min_indent }, |p| {
- while !p.eof() {
- if let Some(NodeKind::Space { newlines: (1 ..) }) = p.peek() {
- if p.column(p.current_end()) < min_indent {
- break;
- }
- }
- markup_node(p, &mut at_start);
+ while !p.eof() {
+ match p.peek() {
+ Some(NodeKind::Space { newlines: (1 ..) })
+ if p.column(p.current_end()) < min_indent =>
+ {
+ break;
+ }
+ Some(NodeKind::Label(_)) => break,
+ _ => {}
}
- });
+
+ markup_node(p, &mut at_start);
+ }
+
+ marker.end(p, NodeKind::Markup { min_indent });
}
/// Parse a markup node.
@@ -212,16 +218,18 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
// Text and markup.
NodeKind::Text(_)
+ | NodeKind::Linebreak { .. }
| NodeKind::NonBreakingSpace
| NodeKind::Shy
| NodeKind::EnDash
| NodeKind::EmDash
| NodeKind::Ellipsis
| NodeKind::Quote { .. }
- | NodeKind::Linebreak { .. }
+ | NodeKind::Escape(_)
| NodeKind::Raw(_)
| NodeKind::Math(_)
- | NodeKind::Escape(_) => {
+ | NodeKind::Label(_)
+ | NodeKind::Ref(_) => {
p.eat();
}
diff --git a/src/parse/tokens.rs b/src/parse/tokens.rs
index be107f3c..e004dd37 100644
--- a/src/parse/tokens.rs
+++ b/src/parse/tokens.rs
@@ -148,8 +148,10 @@ impl<'s> Tokens<'s> {
'*' if !self.in_word() => NodeKind::Star,
'_' if !self.in_word() => NodeKind::Underscore,
'`' => self.raw(),
- '$' => self.math(),
'=' => NodeKind::Eq,
+ '$' => self.math(),
+ '<' => self.label(),
+ '@' => self.reference(),
c if c == '.' || c.is_ascii_digit() => self.numbering(start, c),
// Plain text.
@@ -277,7 +279,9 @@ impl<'s> Tokens<'s> {
// Parenthesis and hashtag.
'[' | ']' | '{' | '}' | '#' |
// Markup.
- '~' | '\'' | '"' | '*' | '_' | '`' | '$' | '=' | '-' | '.' => {
+ '~' | '-' | '.' | ':' |
+ '\'' | '"' | '*' | '_' | '`' | '$' | '=' |
+ '<' | '>' | '@' => {
self.s.expect(c);
NodeKind::Escape(c)
}
@@ -453,6 +457,29 @@ impl<'s> Tokens<'s> {
}
}
+ fn label(&mut self) -> NodeKind {
+ let label = self.s.eat_while(is_id_continue);
+ if self.s.eat_if('>') {
+ if !label.is_empty() {
+ NodeKind::Label(label.into())
+ } else {
+ NodeKind::Error(SpanPos::Full, "label cannot be empty".into())
+ }
+ } else {
+ self.terminated = false;
+ NodeKind::Error(SpanPos::End, "expected closing angle bracket".into())
+ }
+ }
+
+ fn reference(&mut self) -> NodeKind {
+ let label = self.s.eat_while(is_id_continue);
+ if !label.is_empty() {
+ NodeKind::Ref(label.into())
+ } else {
+ NodeKind::Error(SpanPos::Full, "label cannot be empty".into())
+ }
+ }
+
fn ident(&mut self, start: usize) -> NodeKind {
self.s.eat_while(is_id_continue);
match self.s.from(start) {