inline: add ControlFlow enum
needed to indicate that more input is needed this is needed only for multiline attributes that require backtracking
This commit is contained in:
parent
7133de94bb
commit
3d42820001
1 changed files with 44 additions and 30 deletions
|
@ -9,6 +9,7 @@ use lex::Symbol;
|
||||||
|
|
||||||
use Atom::*;
|
use Atom::*;
|
||||||
use Container::*;
|
use Container::*;
|
||||||
|
use ControlFlow::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Atom {
|
pub enum Atom {
|
||||||
|
@ -224,6 +225,15 @@ pub struct Parser<'s> {
|
||||||
pub(crate) store_cowstrs: Vec<CowStr<'s>>,
|
pub(crate) store_cowstrs: Vec<CowStr<'s>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ControlFlow {
|
||||||
|
/// At least one event has been emitted, continue parsing the line.
|
||||||
|
Continue,
|
||||||
|
/// Next line is needed to emit an event.
|
||||||
|
Next,
|
||||||
|
/// Parsing of the line is completed.
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'s> Parser<'s> {
|
impl<'s> Parser<'s> {
|
||||||
pub fn new(src: &'s str) -> Self {
|
pub fn new(src: &'s str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -248,18 +258,18 @@ impl<'s> Parser<'s> {
|
||||||
self.store_cowstrs.clear();
|
self.store_cowstrs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_sp(&mut self, kind: EventKind, span: Span) -> Option<()> {
|
fn push_sp(&mut self, kind: EventKind, span: Span) -> Option<ControlFlow> {
|
||||||
self.events.push_back(Event { kind, span });
|
self.events.push_back(Event { kind, span });
|
||||||
Some(())
|
Some(Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, kind: EventKind) -> Option<()> {
|
fn push(&mut self, kind: EventKind) -> Option<ControlFlow> {
|
||||||
self.push_sp(kind, self.input.span)
|
self.push_sp(kind, self.input.span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_event(&mut self) -> Option<()> {
|
fn parse_event(&mut self) -> ControlFlow {
|
||||||
self.input.reset_span();
|
self.input.reset_span();
|
||||||
self.input.eat().map(|first| {
|
if let Some(first) = self.input.eat() {
|
||||||
self.parse_verbatim(&first)
|
self.parse_verbatim(&first)
|
||||||
.or_else(|| self.parse_attributes(&first))
|
.or_else(|| self.parse_attributes(&first))
|
||||||
.or_else(|| self.parse_autolink(&first))
|
.or_else(|| self.parse_autolink(&first))
|
||||||
|
@ -267,13 +277,15 @@ impl<'s> Parser<'s> {
|
||||||
.or_else(|| self.parse_footnote_reference(&first))
|
.or_else(|| self.parse_footnote_reference(&first))
|
||||||
.or_else(|| self.parse_container(&first))
|
.or_else(|| self.parse_container(&first))
|
||||||
.or_else(|| self.parse_atom(&first))
|
.or_else(|| self.parse_atom(&first))
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| self.push(EventKind::Str).unwrap())
|
||||||
self.push(EventKind::Str);
|
} else if self.input.last() {
|
||||||
})
|
Done
|
||||||
})
|
} else {
|
||||||
|
Next
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_verbatim(&mut self, first: &lex::Token) -> Option<()> {
|
fn parse_verbatim(&mut self, first: &lex::Token) -> Option<ControlFlow> {
|
||||||
if let Some(VerbatimState {
|
if let Some(VerbatimState {
|
||||||
event_opener,
|
event_opener,
|
||||||
len_opener,
|
len_opener,
|
||||||
|
@ -335,7 +347,7 @@ impl<'s> Parser<'s> {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
return Some(()); // skip whitespace
|
return Some(Continue); // skip whitespace
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*non_whitespace_encountered = true;
|
*non_whitespace_encountered = true;
|
||||||
|
@ -343,7 +355,7 @@ impl<'s> Parser<'s> {
|
||||||
}
|
}
|
||||||
self.push(EventKind::Str);
|
self.push(EventKind::Str);
|
||||||
};
|
};
|
||||||
Some(())
|
Some(Continue)
|
||||||
} else {
|
} else {
|
||||||
let (ty, len_opener) = match first.kind {
|
let (ty, len_opener) = match first.kind {
|
||||||
lex::Kind::DollarBacktick(l) if first.len - l as usize == 1 => {
|
lex::Kind::DollarBacktick(l) if first.len - l as usize == 1 => {
|
||||||
|
@ -368,7 +380,7 @@ impl<'s> Parser<'s> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_attributes(&mut self, first: &lex::Token) -> Option<()> {
|
fn parse_attributes(&mut self, first: &lex::Token) -> Option<ControlFlow> {
|
||||||
if first.kind == lex::Kind::Open(Delimiter::Brace) {
|
if first.kind == lex::Kind::Open(Delimiter::Brace) {
|
||||||
let mut ahead = self.input.lexer.ahead().chars();
|
let mut ahead = self.input.lexer.ahead().chars();
|
||||||
let (mut attr_len, mut has_attr) = attr::valid(std::iter::once('{').chain(&mut ahead));
|
let (mut attr_len, mut has_attr) = attr::valid(std::iter::once('{').chain(&mut ahead));
|
||||||
|
@ -394,14 +406,14 @@ impl<'s> Parser<'s> {
|
||||||
} else {
|
} else {
|
||||||
self.push_sp(EventKind::Placeholder, self.input.span.empty_before());
|
self.push_sp(EventKind::Placeholder, self.input.span.empty_before());
|
||||||
}
|
}
|
||||||
return Some(());
|
return Some(Continue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_autolink(&mut self, first: &lex::Token) -> Option<()> {
|
fn parse_autolink(&mut self, first: &lex::Token) -> Option<ControlFlow> {
|
||||||
if first.kind == lex::Kind::Sym(Symbol::Lt) {
|
if first.kind == lex::Kind::Sym(Symbol::Lt) {
|
||||||
let mut ahead = self.input.lexer.ahead().chars();
|
let mut ahead = self.input.lexer.ahead().chars();
|
||||||
let mut end = false;
|
let mut end = false;
|
||||||
|
@ -433,7 +445,7 @@ impl<'s> Parser<'s> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_symbol(&mut self, first: &lex::Token) -> Option<()> {
|
fn parse_symbol(&mut self, first: &lex::Token) -> Option<ControlFlow> {
|
||||||
if first.kind == lex::Kind::Sym(Symbol::Colon) {
|
if first.kind == lex::Kind::Sym(Symbol::Colon) {
|
||||||
let mut ahead = self.input.lexer.ahead().chars();
|
let mut ahead = self.input.lexer.ahead().chars();
|
||||||
let mut end = false;
|
let mut end = false;
|
||||||
|
@ -454,13 +466,13 @@ impl<'s> Parser<'s> {
|
||||||
self.input.span = self.input.span.after(len);
|
self.input.span = self.input.span.after(len);
|
||||||
self.push(EventKind::Atom(Symbol));
|
self.push(EventKind::Atom(Symbol));
|
||||||
self.input.span = self.input.span.after(1);
|
self.input.span = self.input.span.after(1);
|
||||||
return Some(());
|
return Some(Continue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_footnote_reference(&mut self, first: &lex::Token) -> Option<()> {
|
fn parse_footnote_reference(&mut self, first: &lex::Token) -> Option<ControlFlow> {
|
||||||
if first.kind == lex::Kind::Open(Delimiter::Bracket)
|
if first.kind == lex::Kind::Open(Delimiter::Bracket)
|
||||||
&& matches!(
|
&& matches!(
|
||||||
self.input.peek(),
|
self.input.peek(),
|
||||||
|
@ -497,13 +509,13 @@ impl<'s> Parser<'s> {
|
||||||
self.input.span = self.input.span.after(len);
|
self.input.span = self.input.span.after(len);
|
||||||
self.push(EventKind::Atom(FootnoteReference));
|
self.push(EventKind::Atom(FootnoteReference));
|
||||||
self.input.span = self.input.span.after(1);
|
self.input.span = self.input.span.after(1);
|
||||||
return Some(());
|
return Some(Continue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_container(&mut self, first: &lex::Token) -> Option<()> {
|
fn parse_container(&mut self, first: &lex::Token) -> Option<ControlFlow> {
|
||||||
self.openers
|
self.openers
|
||||||
.iter()
|
.iter()
|
||||||
.rposition(|(o, _)| o.closed_by(first.kind))
|
.rposition(|(o, _)| o.closed_by(first.kind))
|
||||||
|
@ -642,7 +654,7 @@ impl<'s> Parser<'s> {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
self.events.drain(e_opener..);
|
self.events.drain(e_opener..);
|
||||||
Some(())
|
Some(Continue)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -713,7 +725,7 @@ impl<'s> Parser<'s> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_atom(&mut self, first: &lex::Token) -> Option<()> {
|
fn parse_atom(&mut self, first: &lex::Token) -> Option<ControlFlow> {
|
||||||
let atom = match first.kind {
|
let atom = match first.kind {
|
||||||
lex::Kind::Newline => Softbreak,
|
lex::Kind::Newline => Softbreak,
|
||||||
lex::Kind::Hardbreak => Hardbreak,
|
lex::Kind::Hardbreak => Hardbreak,
|
||||||
|
@ -747,7 +759,7 @@ impl<'s> Parser<'s> {
|
||||||
self.push_sp(EventKind::Atom(atom), self.input.span.with_len(l));
|
self.push_sp(EventKind::Atom(atom), self.input.span.with_len(l));
|
||||||
self.input.span = self.input.span.skip(l);
|
self.input.span = self.input.span.skip(l);
|
||||||
});
|
});
|
||||||
return Some(());
|
return Some(Continue);
|
||||||
}
|
}
|
||||||
lex::Kind::Open(Delimiter::BraceQuote1) => Quote {
|
lex::Kind::Open(Delimiter::BraceQuote1) => Quote {
|
||||||
ty: QuoteType::Single,
|
ty: QuoteType::Single,
|
||||||
|
@ -981,16 +993,18 @@ impl<'s> Iterator for Parser<'s> {
|
||||||
.back()
|
.back()
|
||||||
.map_or(false, |ev| matches!(ev.kind, EventKind::Str))
|
.map_or(false, |ev| matches!(ev.kind, EventKind::Str))
|
||||||
{
|
{
|
||||||
if self.parse_event().is_none() {
|
match self.parse_event() {
|
||||||
if self.input.last() {
|
Continue => {}
|
||||||
break;
|
Done => break,
|
||||||
} else if let Some(l) = self.input.ahead.pop_front() {
|
Next => {
|
||||||
|
if let Some(l) = self.input.ahead.pop_front() {
|
||||||
self.input.set_current_line(l);
|
self.input.set_current_line(l);
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// automatically close unclosed verbatim
|
// automatically close unclosed verbatim
|
||||||
if let Some(VerbatimState { event_opener, .. }) = self.verbatim.take() {
|
if let Some(VerbatimState { event_opener, .. }) = self.verbatim.take() {
|
||||||
|
|
Loading…
Reference in a new issue