From cb8f469853139030436caadf97a4509653255f76 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sat, 6 Jun 2020 10:23:55 +0200 Subject: [PATCH] Fix EOF handling --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/parsing/charstate.rs | 7 ++++++- src/parsing/inline.rs | 7 ++++++- src/parsing/parser.rs | 33 ++++++++++++++------------------- src/parsing/utils.rs | 11 +++++++++++ 6 files changed, 39 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa225e8..ac1ac8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -566,7 +566,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "snekdown" -version = "0.12.2" +version = "0.12.3" dependencies = [ "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 7a12f35..79bd153 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snekdown" -version = "0.12.2" +version = "0.12.3" authors = ["trivernis "] edition = "2018" license-file = "LICENSE" diff --git a/src/parsing/charstate.rs b/src/parsing/charstate.rs index c5d0933..80af84a 100644 --- a/src/parsing/charstate.rs +++ b/src/parsing/charstate.rs @@ -17,6 +17,7 @@ pub trait CharStateMachine { fn check_special_sequence(&mut self, sequence: &[char]) -> bool; fn check_special_sequence_group(&mut self, sequences: &[&[char]]) -> bool; fn check_linebreak(&self) -> bool; + fn check_eof(&self) -> bool; fn assert_special(&mut self, character: &char, revert_index: usize) -> Result<(), ParseError>; fn assert_special_group( &mut self, @@ -66,7 +67,7 @@ impl CharStateMachine for Parser { /// skips to the next char #[inline] fn skip_char(&mut self) { - let _ = self.next_char(); + self.next_char(); } /// Returns to an index position @@ -209,6 +210,10 @@ impl CharStateMachine for Parser { self.current_char == LB && !self.check_escaped() } + fn check_eof(&self) -> bool { + self.index >= (self.text.len() - 1) + } + #[inline] fn assert_special(&mut self, character: &char, revert_index: usize) -> Result<(), ParseError> { if self.check_special(character) { diff --git a/src/parsing/inline.rs b/src/parsing/inline.rs index 0f3415a..77ceba9 100644 --- a/src/parsing/inline.rs +++ b/src/parsing/inline.rs @@ -26,6 +26,8 @@ impl ParseInline for Parser { fn parse_inline(&mut self) -> ParseResult { if self.check_special(&PIPE) || self.check_linebreak() { Err(ParseError::new(self.index)) + } else if self.check_eof() { + Err(ParseError::eof(self.index)) } else if let Ok(image) = self.parse_image() { Ok(Inline::Image(image)) } else if let Ok(url) = self.parse_url(false) { @@ -197,7 +199,10 @@ impl ParseInline for Parser { if characters.len() > 0 { Ok(PlainText { value: characters }) } else { - Err(ParseError::new(self.index)) + Err(ParseError::new_with_message( + self.index, + "no plaintext characters parsed", + )) } } diff --git a/src/parsing/parser.rs b/src/parsing/parser.rs index cb4d618..fb73845 100644 --- a/src/parsing/parser.rs +++ b/src/parsing/parser.rs @@ -13,15 +13,6 @@ use std::path::Path; use std::sync::{Arc, Mutex}; use std::thread; -macro_rules! parse_option { - ($option:expr, $index:expr) => { - if let Some(_) = $option { - } else { - return Err(ParseError::new($index)); - } - }; -} - pub struct Parser { pub(crate) index: usize, pub(crate) text: Vec, @@ -58,8 +49,7 @@ impl Parser { paths: Arc>>, is_child: bool, ) -> Self { - let mut text: Vec = text.chars().collect(); - text.append(&mut vec!['\n', ' ']); // it fixes stuff and I don't know why. + let text: Vec = text.chars().collect(); let current_char = text.get(0).unwrap().clone(); if let Some(path) = path.clone() { let path_info = Path::new(&path); @@ -167,6 +157,9 @@ impl Parser { match self.parse_block() { Ok(block) => self.document.add_element(block), Err(err) => { + if err.eof { + break; + } if let Some(path) = &self.path { if let Some(position) = err.get_position(&self.get_text()) { println!( @@ -439,7 +432,7 @@ impl Parser { return Err(self.revert_with_error(start_index)); } if self.check_special(&IMPORT_CLOSE) { - parse_option!(self.next_char(), self.index); + self.skip_char(); } // parsing success @@ -613,7 +606,7 @@ impl Parser { let mut element = TextLine::new(); while let Ok(inline) = self.parse_inline() { element.subtext.push(inline); - if self.check_linebreak() || self.check_special(&PIPE) { + if self.check_linebreak() || self.check_special(&PIPE) || self.check_eof() { break; } } @@ -623,7 +616,7 @@ impl Parser { if self.check_special(&PIPE) { self.skip_char(); } - if self.check_linebreak() { + if self.check_linebreak() || self.check_eof() { break; } self.seek_inline_whitespace(); @@ -709,17 +702,19 @@ impl Parser { let mut text = TextLine::new(); while let Ok(subtext) = self.parse_inline() { text.add_subtext(subtext); - let current_index = self.index; - if self.next_char() == None { + if self.check_eof() { break; } - self.revert_to(current_index)?; } if self.check_linebreak() { - parse_option!(self.next_char(), self.index); + self.skip_char(); } - Ok(text) + if text.subtext.len() > 0 || !self.check_eof() { + Ok(text) + } else { + Err(ParseError::eof(self.index)) + } } } diff --git a/src/parsing/utils.rs b/src/parsing/utils.rs index 0732872..507a7e9 100644 --- a/src/parsing/utils.rs +++ b/src/parsing/utils.rs @@ -9,6 +9,7 @@ pub type ParseResult = Result; pub struct ParseError { index: usize, message: Option, + pub(crate) eof: bool, } impl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -33,6 +34,7 @@ impl ParseError { Self { index, message: None, + eof: false, } } @@ -40,6 +42,15 @@ impl ParseError { Self { index, message: Some(message.to_string()), + eof: false, + } + } + + pub fn eof(index: usize) -> Self { + Self { + index, + message: Some("EOF".to_string()), + eof: true, } }