Skip to content

Commit

Permalink
inline: add ControlFlow enum
Browse files Browse the repository at this point in the history
needed to indicate that more input is needed

this is needed only for multiline attributes that require backtracking
  • Loading branch information
hellux committed Mar 20, 2023
1 parent 53a192b commit bb65a06
Showing 1 changed file with 44 additions and 30 deletions.
74 changes: 44 additions & 30 deletions src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use lex::Symbol;

use Atom::*;
use Container::*;
use ControlFlow::*;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Atom {
Expand Down Expand Up @@ -220,6 +221,15 @@ pub struct Parser<'s> {
verbatim: Option<VerbatimState>,
}

pub enum ControlFlow {
/// At least one event has been emitted, continue parsing the line.
Continue,
/// More lines are needed to emit an event.
More,
/// Parsing of the line is completed.
Done,
}

impl<'s> Parser<'s> {
pub fn new(src: &'s str) -> Self {
Self {
Expand All @@ -242,18 +252,18 @@ impl<'s> Parser<'s> {
debug_assert!(self.verbatim.is_none());
}

fn push_sp(&mut self, kind: EventKind<'s>, span: Span) -> Option<()> {
fn push_sp(&mut self, kind: EventKind<'s>, span: Span) -> Option<ControlFlow> {
self.events.push_back(Event { kind, span });
Some(())
Some(Continue)
}

fn push(&mut self, kind: EventKind<'s>) -> Option<()> {
fn push(&mut self, kind: EventKind<'s>) -> Option<ControlFlow> {
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.eat().map(|first| {
if let Some(first) = self.input.eat() {
let ctrl = self
.parse_verbatim(&first)
.or_else(|| self.parse_attributes(&first))
Expand All @@ -262,19 +272,21 @@ impl<'s> Parser<'s> {
.or_else(|| self.parse_footnote_reference(&first))
.or_else(|| self.parse_container(&first))
.or_else(|| self.parse_atom(&first))
.unwrap_or_else(|| {
self.push(EventKind::Str);
});
.unwrap_or_else(|| self.push(EventKind::Str).unwrap());

if matches!(first.kind, lex::Kind::Newline) {
self.input.span_line = Span::new(self.input.span.end(), self.input.span_line.end());
}

ctrl
})
} else if self.input.last() {
Done
} else {
More
}
}

fn parse_verbatim(&mut self, first: &lex::Token) -> Option<()> {
fn parse_verbatim(&mut self, first: &lex::Token) -> Option<ControlFlow> {
if let Some(VerbatimState {
event_opener,
len_opener,
Expand Down Expand Up @@ -336,15 +348,15 @@ impl<'s> Parser<'s> {
)
})
{
return Some(()); // skip whitespace
return Some(Continue); // skip whitespace
}
} else {
*non_whitespace_encountered = true;
*non_whitespace_last = Some((first.kind, self.events.len() + 1));
}
self.push(EventKind::Str);
};
Some(())
Some(Continue)
} else {
let (ty, len_opener) = match first.kind {
lex::Kind::DollarBacktick(l) if first.len - l as usize == 1 => {
Expand All @@ -369,7 +381,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) {
let mut ahead = self.input.lexer.ahead().chars();
let (mut attr_len, mut has_attr) = attr::valid(std::iter::once('{').chain(&mut ahead));
Expand All @@ -395,14 +407,14 @@ impl<'s> Parser<'s> {
} else {
self.push_sp(EventKind::Placeholder, self.input.span.empty_before());
}
return Some(());
return Some(Continue);
}
}

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) {
let mut ahead = self.input.lexer.ahead().chars();
let mut end = false;
Expand Down Expand Up @@ -434,7 +446,7 @@ impl<'s> Parser<'s> {
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) {
let mut ahead = self.input.lexer.ahead().chars();
let mut end = false;
Expand All @@ -455,13 +467,13 @@ impl<'s> Parser<'s> {
self.input.span = self.input.span.after(len);
self.push(EventKind::Atom(Symbol));
self.input.span = self.input.span.after(1);
return Some(());
return Some(Continue);
}
}
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)
&& matches!(
self.input.peek(),
Expand Down Expand Up @@ -498,13 +510,13 @@ impl<'s> Parser<'s> {
self.input.span = self.input.span.after(len);
self.push(EventKind::Atom(FootnoteReference));
self.input.span = self.input.span.after(1);
return Some(());
return Some(Continue);
}
}
None
}

fn parse_container(&mut self, first: &lex::Token) -> Option<()> {
fn parse_container(&mut self, first: &lex::Token) -> Option<ControlFlow> {
self.openers
.iter()
.rposition(|(o, _)| o.closed_by(first.kind))
Expand Down Expand Up @@ -631,7 +643,7 @@ impl<'s> Parser<'s> {
span: span_spec,
};
self.events.drain(e_opener..);
Some(())
Some(Continue)
}
};

Expand Down Expand Up @@ -702,7 +714,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 {
lex::Kind::Newline => Softbreak,
lex::Kind::Hardbreak => Hardbreak,
Expand Down Expand Up @@ -736,7 +748,7 @@ impl<'s> Parser<'s> {
self.push_sp(EventKind::Atom(atom), self.input.span.with_len(l));
self.input.span = self.input.span.skip(l);
});
return Some(());
return Some(Continue);
}
lex::Kind::Open(Delimiter::BraceQuote1) => Quote {
ty: QuoteType::Single,
Expand Down Expand Up @@ -970,13 +982,15 @@ impl<'s> Iterator for Parser<'s> {
.back()
.map_or(false, |ev| matches!(ev.kind, EventKind::Str))
{
if self.parse_event().is_none() {
if self.input.last() {
break;
} else if let Some(l) = self.input.ahead.pop_front() {
self.input.set_current_line(l);
} else {
return None;
match self.parse_event() {
Continue => {}
Done => break,
More => {
if let Some(l) = self.input.ahead.pop_front() {
self.input.set_current_line(l);
} else {
return None;
}
}
}
}
Expand Down

0 comments on commit bb65a06

Please sign in to comment.