From 9357ac62788fead1cc34c5aa1b2fa282ad1d2c8f Mon Sep 17 00:00:00 2001 From: PoiScript Date: Fri, 3 May 2019 01:56:12 +0800 Subject: [PATCH] fix(parser): next_obj & real_inline --- src/objects/emphasis.rs | 22 ++++++++++------------ src/parser.rs | 30 +++++++++++++++--------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/objects/emphasis.rs b/src/objects/emphasis.rs index 4df7f5f..0181544 100644 --- a/src/objects/emphasis.rs +++ b/src/objects/emphasis.rs @@ -3,24 +3,22 @@ use memchr::memchr; #[inline] /// returns offset -pub fn parse(src: &str, marker: u8) -> Option { - debug_assert!(src.len() >= 3); +pub fn parse(text: &str, marker: u8) -> Option { + 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 { || 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); diff --git a/src/parser.rs b/src/parser.rs index 94c4df6..07123b0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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> { 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 {