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:
Noah Hellman 2023-02-26 00:32:04 +01:00
parent 7133de94bb
commit 3d42820001

View file

@ -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() {