inline: get rid of verbatim state
This commit is contained in:
parent
8957907141
commit
81a4edb884
2 changed files with 82 additions and 97 deletions
177
src/inline.rs
177
src/inline.rs
|
@ -63,8 +63,6 @@ pub struct Parser<I> {
|
||||||
lexer: lex::Lexer<I>,
|
lexer: lex::Lexer<I>,
|
||||||
/// Span of current event.
|
/// Span of current event.
|
||||||
span: Span,
|
span: Span,
|
||||||
/// The kind, opener_len and opener_event of the current verbatim container if within one.
|
|
||||||
verbatim: Option<(Container, usize, usize)>,
|
|
||||||
/// Stack with kind and index of _potential_ openers for typesetting containers.
|
/// Stack with kind and index of _potential_ openers for typesetting containers.
|
||||||
typesets: Vec<(Container, usize)>,
|
typesets: Vec<(Container, usize)>,
|
||||||
/// Stack with index of _potential_ span/link openers.
|
/// Stack with index of _potential_ span/link openers.
|
||||||
|
@ -80,7 +78,6 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
|
||||||
Self {
|
Self {
|
||||||
lexer: lex::Lexer::new(chars),
|
lexer: lex::Lexer::new(chars),
|
||||||
span: Span::new(0, 0),
|
span: Span::new(0, 0),
|
||||||
verbatim: None,
|
|
||||||
typesets: Vec::new(),
|
typesets: Vec::new(),
|
||||||
spans: Vec::new(),
|
spans: Vec::new(),
|
||||||
events: std::collections::VecDeque::new(),
|
events: std::collections::VecDeque::new(),
|
||||||
|
@ -118,18 +115,54 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_verbatim(&mut self, first: &lex::Token) -> Option<Event> {
|
fn parse_verbatim(&mut self, first: &lex::Token) -> Option<Event> {
|
||||||
self.verbatim
|
match first.kind {
|
||||||
.map(|(kind, opener_len, opener_event)| {
|
lex::Kind::Seq(lex::Sequence::Dollar) => {
|
||||||
assert_eq!(self.events[opener_event].kind, EventKind::Enter(kind));
|
let math_opt = (first.len <= 2)
|
||||||
let kind = if matches!(first.kind, lex::Kind::Seq(lex::Sequence::Backtick))
|
.then(|| {
|
||||||
&& first.len == opener_len
|
if let Some(lex::Token {
|
||||||
|
kind: lex::Kind::Seq(lex::Sequence::Backtick),
|
||||||
|
len,
|
||||||
|
}) = self.peek()
|
||||||
|
{
|
||||||
|
Some((
|
||||||
|
if first.len == 2 {
|
||||||
|
DisplayMath
|
||||||
|
} else {
|
||||||
|
InlineMath
|
||||||
|
},
|
||||||
|
*len,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.flatten();
|
||||||
|
if math_opt.is_some() {
|
||||||
|
self.eat(); // backticks
|
||||||
|
}
|
||||||
|
math_opt
|
||||||
|
}
|
||||||
|
lex::Kind::Seq(lex::Sequence::Backtick) => Some((Verbatim, first.len)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
.map(|(mut kind, opener_len)| {
|
||||||
|
let opener_event = self.events.len();
|
||||||
|
self.events.push_back(Event {
|
||||||
|
kind: EventKind::Enter(kind),
|
||||||
|
span: self.span,
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut span_inner = Span::empty_at(self.span.end());
|
||||||
|
|
||||||
|
while let Some(t) = self.eat() {
|
||||||
|
if matches!(t.kind, lex::Kind::Seq(lex::Sequence::Backtick)) && t.len == opener_len
|
||||||
{
|
{
|
||||||
self.verbatim = None;
|
if matches!(kind, Verbatim)
|
||||||
let kind = if matches!(kind, Verbatim)
|
|
||||||
&& matches!(
|
&& matches!(
|
||||||
self.lexer.peek().map(|t| &t.kind),
|
self.lexer.peek().map(|t| &t.kind),
|
||||||
Some(lex::Kind::Open(Delimiter::BraceEqual))
|
Some(lex::Kind::Open(Delimiter::BraceEqual))
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
let mut ahead = self.lexer.inner().clone();
|
let mut ahead = self.lexer.inner().clone();
|
||||||
let mut end = false;
|
let mut end = false;
|
||||||
let len = (&mut ahead)
|
let len = (&mut ahead)
|
||||||
|
@ -146,64 +179,28 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
|
||||||
if len > 0 && end {
|
if len > 0 && end {
|
||||||
self.lexer = lex::Lexer::new(ahead);
|
self.lexer = lex::Lexer::new(ahead);
|
||||||
let span_format = Span::by_len(self.span.end() + "{=".len(), len);
|
let span_format = Span::by_len(self.span.end() + "{=".len(), len);
|
||||||
self.events[opener_event].kind = EventKind::Enter(RawFormat);
|
kind = RawFormat;
|
||||||
|
self.events[opener_event].kind = EventKind::Enter(kind);
|
||||||
self.events[opener_event].span = span_format;
|
self.events[opener_event].span = span_format;
|
||||||
self.span = span_format;
|
self.span = span_format;
|
||||||
RawFormat
|
|
||||||
} else {
|
|
||||||
Verbatim
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
kind
|
|
||||||
};
|
|
||||||
EventKind::Exit(kind)
|
|
||||||
} else {
|
|
||||||
EventKind::Str
|
|
||||||
};
|
|
||||||
Event {
|
|
||||||
kind,
|
|
||||||
span: self.span,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
match first.kind {
|
|
||||||
lex::Kind::Seq(lex::Sequence::Dollar) => {
|
|
||||||
let math_opt = (first.len <= 2)
|
|
||||||
.then(|| {
|
|
||||||
if let Some(lex::Token {
|
|
||||||
kind: lex::Kind::Seq(lex::Sequence::Backtick),
|
|
||||||
len,
|
|
||||||
}) = self.peek()
|
|
||||||
{
|
|
||||||
Some((
|
|
||||||
if first.len == 2 {
|
|
||||||
DisplayMath
|
|
||||||
} else {
|
|
||||||
InlineMath
|
|
||||||
},
|
|
||||||
*len,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.flatten();
|
|
||||||
if math_opt.is_some() {
|
|
||||||
self.eat(); // backticks
|
|
||||||
}
|
|
||||||
math_opt
|
|
||||||
}
|
}
|
||||||
lex::Kind::Seq(lex::Sequence::Backtick) => Some((Verbatim, first.len)),
|
break;
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
.map(|(kind, opener_len)| {
|
span_inner = span_inner.extend(t.len);
|
||||||
self.verbatim = Some((kind, opener_len, self.events.len()));
|
self.reset_span();
|
||||||
Event {
|
}
|
||||||
kind: EventKind::Enter(kind),
|
|
||||||
span: self.span,
|
self.events.push_back(Event {
|
||||||
}
|
kind: EventKind::Str,
|
||||||
})
|
span: span_inner,
|
||||||
})
|
});
|
||||||
|
|
||||||
|
Event {
|
||||||
|
kind: EventKind::Exit(kind),
|
||||||
|
span: self.span,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_span(&mut self, first: &lex::Token) -> Option<Event> {
|
fn parse_span(&mut self, first: &lex::Token) -> Option<Event> {
|
||||||
|
@ -339,7 +336,6 @@ impl<I: Iterator<Item = char> + Clone> Iterator for Parser<I> {
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while self.events.is_empty()
|
while self.events.is_empty()
|
||||||
|| !self.typesets.is_empty()
|
|| !self.typesets.is_empty()
|
||||||
|| self.verbatim.is_some() // might be raw format
|
|
||||||
|| self // for merge
|
|| self // for merge
|
||||||
.events
|
.events
|
||||||
.back()
|
.back()
|
||||||
|
@ -352,38 +348,27 @@ impl<I: Iterator<Item = char> + Clone> Iterator for Parser<I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.events
|
self.events.pop_front().map(|e| {
|
||||||
.pop_front()
|
if matches!(e.kind, EventKind::Str) {
|
||||||
.map(|e| {
|
// merge str events
|
||||||
if matches!(e.kind, EventKind::Str) {
|
let mut span = e.span;
|
||||||
// merge str events
|
while self
|
||||||
let mut span = e.span;
|
.events
|
||||||
while self
|
.front()
|
||||||
.events
|
.map_or(false, |ev| matches!(ev.kind, EventKind::Str))
|
||||||
.front()
|
{
|
||||||
.map_or(false, |ev| matches!(ev.kind, EventKind::Str))
|
let ev = self.events.pop_front().unwrap();
|
||||||
{
|
assert_eq!(span.end(), ev.span.start());
|
||||||
let ev = self.events.pop_front().unwrap();
|
span = span.union(ev.span);
|
||||||
assert_eq!(span.end(), ev.span.start());
|
|
||||||
span = span.union(ev.span);
|
|
||||||
}
|
|
||||||
Event {
|
|
||||||
kind: EventKind::Str,
|
|
||||||
span,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
e
|
|
||||||
}
|
}
|
||||||
})
|
Event {
|
||||||
.or_else(|| {
|
kind: EventKind::Str,
|
||||||
self.verbatim.map(|(kind, _, _)| {
|
span,
|
||||||
self.verbatim = None;
|
}
|
||||||
Event {
|
} else {
|
||||||
kind: EventKind::Exit(kind),
|
e
|
||||||
span: self.span,
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -502,7 +502,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn raw_inline() {
|
fn raw_inline() {
|
||||||
test_parse!(
|
test_parse!(
|
||||||
"`raw\nraw`{=format}",
|
"``raw\nraw``{=format}",
|
||||||
Start(Paragraph, Attributes::none()),
|
Start(Paragraph, Attributes::none()),
|
||||||
Start(RawInline { format: "format" }, Attributes::none()),
|
Start(RawInline { format: "format" }, Attributes::none()),
|
||||||
Str("raw\nraw"),
|
Str("raw\nraw"),
|
||||||
|
|
Loading…
Reference in a new issue