fix(parser): next_obj & real_inline

This commit is contained in:
PoiScript 2019-05-03 01:56:12 +08:00
parent eaf40dcc87
commit 9357ac6278
2 changed files with 25 additions and 27 deletions

View file

@ -3,24 +3,22 @@ use memchr::memchr;
#[inline]
/// returns offset
pub fn parse(src: &str, marker: u8) -> Option<usize> {
debug_assert!(src.len() >= 3);
pub fn parse(text: &str, marker: u8) -> Option<usize> {
debug_assert!(text.len() >= 3);
let bytes = src.as_bytes();
let bytes = text.as_bytes();
if bytes[1].is_ascii_whitespace() {
return None;
}
let end = memchr(marker, &bytes[1..])
.map(|i| i + 1)
.filter(|&i| count(&bytes[1..i], b'\n') < 2)?;
let end = memchr(marker, &bytes[1..]).filter(|&i| count(&bytes[1..i + 1], b'\n') < 2)?;
if bytes[end - 1].is_ascii_whitespace() {
if bytes[end].is_ascii_whitespace() {
return None;
}
if let Some(&post) = bytes.get(end + 1) {
if let Some(&post) = bytes.get(end + 2) {
if post == b' '
|| post == b'-'
|| post == b'.'
@ -33,12 +31,12 @@ pub fn parse(src: &str, marker: u8) -> Option<usize> {
|| post == b')'
|| post == b'}'
{
Some(end)
Some(end + 2)
} else {
None
}
} else {
Some(end)
Some(end + 2)
}
}
@ -48,8 +46,8 @@ mod tests {
fn parse() {
use super::parse;
assert_eq!(parse("*bold*", b'*'), Some("*bold".len()));
assert_eq!(parse("*bo\nld*", b'*'), Some("*bo\nld".len()));
assert_eq!(parse("*bold*", b'*'), Some("*bold*".len()));
assert_eq!(parse("*bo\nld*", b'*'), Some("*bo\nld*".len()));
assert_eq!(parse("*bold*a", b'*'), None);
assert_eq!(parse("*bold*", b'/'), None);
assert_eq!(parse("*bold *", b'*'), None);

View file

@ -4,7 +4,7 @@ use crate::{elements::*, headline::*, objects::*};
use jetscii::bytes;
use memchr::memchr_iter;
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
enum Container {
Headline(usize),
Section(usize),
@ -445,7 +445,9 @@ impl<'a> Parser<'a> {
});
debug_assert!(
off <= text.len() && limit <= text.len() && end <= text.len(),
(limit == 0 && end == 0)
|| (limit == 1 && end == 1)
|| (off <= limit && limit <= end && end <= text.len()),
"{} <= {} <= {} <= {}",
off,
limit,
@ -453,8 +455,6 @@ impl<'a> Parser<'a> {
text.len()
);
self.off += off;
match obj {
Event::UnderlineBeg => self.push_stack(Container::Underline, limit, end),
Event::StrikeBeg => self.push_stack(Container::Strike, limit, end),
@ -463,6 +463,8 @@ impl<'a> Parser<'a> {
_ => (),
}
self.off += off;
obj
}
@ -488,11 +490,8 @@ impl<'a> Parser<'a> {
}
}
b'<' => Timestamp::parse_active(text)
.map(|(timestamp, off)| (Event::Timestamp(timestamp), off, 0, 0))
.or_else(|| {
Timestamp::parse_diary(text)
.map(|(timestamp, off)| (Event::Timestamp(timestamp), off, 0, 0))
}),
.or_else(|| Timestamp::parse_diary(text))
.map(|(timestamp, off)| (Event::Timestamp(timestamp), off, 0, 0)),
b'[' => {
if text[1..].starts_with("fn:") {
FnRef::parse(text).map(|(fn_ref, off)| (Event::FnRef(fn_ref), off, 0, 0))
@ -514,16 +513,16 @@ impl<'a> Parser<'a> {
}
}
fn next_inline(&mut self, text: &'a str) -> Option<(Event<'a>, usize, usize, usize)> {
fn next_inline(&self, text: &'a str) -> Option<(Event<'a>, usize, usize, usize)> {
match text.as_bytes()[0] {
b'*' => emphasis::parse(text, b'*').map(|end| (Event::BoldBeg, 1, end - 1, end)),
b'+' => emphasis::parse(text, b'+').map(|end| (Event::StrikeBeg, 1, end - 1, end)),
b'/' => emphasis::parse(text, b'/').map(|end| (Event::ItalicBeg, 1, end - 1, end)),
b'_' => emphasis::parse(text, b'_').map(|end| (Event::UnderlineBeg, 1, end - 1, end)),
b'=' => emphasis::parse(text, b'=')
.map(|end| (Event::Verbatim(&text[1..end]), end + 1, 0, 0)),
.map(|end| (Event::Verbatim(&text[1..end - 1]), end, 0, 0)),
b'~' => {
emphasis::parse(text, b'~').map(|end| (Event::Code(&text[1..end]), end + 1, 0, 0))
emphasis::parse(text, b'~').map(|end| (Event::Code(&text[1..end - 1]), end, 0, 0))
}
b's' if text.starts_with("src_") => {
InlineSrc::parse(text).map(|(src, off)| (Event::InlineSrc(src), off, 0, 0))
@ -568,10 +567,7 @@ impl<'a> Iterator for Parser<'a> {
fn next(&mut self) -> Option<Event<'a>> {
if let Some(&(container, limit, end)) = self.stack.last() {
let tail = &self.text[self.off..limit];
// eprint!("{:1$}", ' ', self.stack_depth());
// eprintln!("{:?} {:?} {:?}", container, tail, self.next_item);
debug_assert!(
self.off <= limit && limit <= end && end <= self.text.len(),
@ -582,6 +578,10 @@ impl<'a> Iterator for Parser<'a> {
self.text.len()
);
let tail = &self.text[self.off..limit];
// eprintln!("{:?} {:?} {:?}", container, tail, self.next_item);
Some(match container {
Container::Headline(beg) => {
if self.off >= limit {