diff --git a/Cargo.lock b/Cargo.lock index fb86618..1beea10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,7 +571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "snekdown" -version = "0.17.0" +version = "0.18.0" dependencies = [ "charred 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 5faca6b..ac63c3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snekdown" -version = "0.17.0" +version = "0.18.0" authors = ["trivernis "] edition = "2018" license-file = "LICENSE" diff --git a/src/parser/block.rs b/src/parser/block.rs index 247f421..b1882a8 100644 --- a/src/parser/block.rs +++ b/src/parser/block.rs @@ -1,11 +1,9 @@ +use super::ParseResult; use crate::elements::tokens::*; use crate::elements::{Block, CodeBlock, Import, List, ListItem, Paragraph, Quote, Section, Table}; -use crate::parser::charstate::CharStateMachine; use crate::parser::inline::ParseInline; use crate::parser::line::ParseLine; -use crate::utils::parsing::{ParseError, ParseResult}; use crate::Parser; -use charred::tapemachine::{TapeError, TapeResult}; pub(crate) trait ParseBlock { fn parse_block(&mut self) -> ParseResult; @@ -77,7 +75,7 @@ impl ParseBlock for Parser { } return Err(self.ctm.rewind_with_error(start_index)); } - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; let mut header = self.parse_header()?; header.size = size; self.section_nesting = size; @@ -108,12 +106,12 @@ impl ParseBlock for Parser { self.ctm.seek_whitespace(); self.ctm .assert_sequence(&SQ_CODE_BLOCK, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let language = self.ctm.get_string_until_any(&[LB], &[])?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let text = self.ctm.get_string_until_sequence(&[&SQ_CODE_BLOCK], &[])?; for _ in 0..2 { - self.ctm.seek_one(); + self.ctm.seek_one()?; } Ok(CodeBlock { @@ -251,12 +249,12 @@ impl ParseBlock for Parser { fn parse_table(&mut self) -> ParseResult { let header = self.parse_row()?; if self.ctm.check_char(&LB) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } let seek_index = self.ctm.get_index(); let mut table = Table::new(header); while let Ok(_) = self.ctm.seek_one() { - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; if !self.ctm.check_any(&[MINUS, PIPE]) || self.ctm.check_char(&LB) { break; } @@ -292,7 +290,7 @@ impl ParseBlock for Parser { return Err(self.ctm.rewind_with_error(start_index)); } if self.ctm.check_char(&IMPORT_CLOSE) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } // parser success diff --git a/src/parser/charstate.rs b/src/parser/charstate.rs deleted file mode 100644 index 163247c..0000000 --- a/src/parser/charstate.rs +++ /dev/null @@ -1,345 +0,0 @@ -use crate::elements::tokens::{LB, SPECIAL_ESCAPE}; -use crate::utils::parsing::{ParseError, ParseResult}; -use crate::Parser; - -pub trait CharStateMachine { - fn next_char(&mut self) -> Option; - fn skip_char(&mut self); - fn revert_to(&mut self, index: usize) -> Result<(), ParseError>; - fn revert_with_error(&mut self, index: usize) -> ParseError; - fn seek_inline_whitespace(&mut self); - fn seek_whitespace(&mut self); - fn seek_until_linebreak(&mut self); - fn check_seek_inline_whitespace(&mut self) -> bool; - fn check_escaped(&self) -> bool; - fn check_special(&self, character: &char) -> bool; - fn check_special_group(&self, group: &[char]) -> bool; - 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, - group: &[char], - revert_index: usize, - ) -> Result<(), ParseError>; - fn assert_special_sequence( - &mut self, - sequence: &[char], - revert_index: usize, - ) -> Result<(), ParseError>; - fn assert_special_sequence_group( - &mut self, - sequences: &[&[char]], - revert_index: usize, - ) -> Result<(), ParseError>; - fn get_string_until( - &mut self, - break_at: &[char], - err_at: &[char], - ) -> Result; - fn get_string_until_sequence( - &mut self, - break_at: &[&[char]], - err_at: &[char], - ) -> Result; - fn get_string_until_or_revert( - &mut self, - break_et: &[char], - err_at: &[char], - revert_index: usize, - ) -> ParseResult; -} -/* -impl CharStateMachine for Parser { - /// Increments the current index and returns the - /// char at the indexes position - #[inline] - fn next_char(&mut self) -> Option { - self.index += 1; - self.previous_char = self.current_char; - if (self.text.len() - 1) <= self.index { - for _ in 0..8 { - let mut buf = String::new(); - if let Ok(_) = self.reader.read_line(&mut buf) { - self.text.append(&mut buf.chars().collect()) - } else { - break; - } - } - } - self.current_char = *self.text.get(self.index)?; - - Some(self.current_char) - } - - /// skips to the next char - #[inline] - fn skip_char(&mut self) { - self.next_char(); - } - - /// Returns to an index position - #[inline] - fn revert_to(&mut self, index: usize) -> Result<(), ParseError> { - if let Some(char) = self.text.get(index) { - self.index = index; - self.current_char = *char; - if index > self.text.len() { - if let Some(ch) = self.text.get(index - 1) { - self.previous_char = *ch; - } - } - Ok(()) - } else { - Err(ParseError::new_with_message(index, "failed to revert")) - } - } - - /// reverts and returns a parse error - #[inline] - fn revert_with_error(&mut self, index: usize) -> ParseError { - let err = ParseError::new(self.index); - - if let Err(revert_err) = self.revert_to(index) { - revert_err - } else { - err - } - } - - /// Skips characters until it encounters a character - /// that isn't an inline whitespace character - fn seek_inline_whitespace(&mut self) { - if self.current_char.is_whitespace() && !self.check_linebreak() { - while let Some(next_char) = self.next_char() { - if !next_char.is_whitespace() || self.check_linebreak() { - break; - } - } - } - } - - /// Skips characters until it encounters a character - /// that isn't a whitespace character - fn seek_whitespace(&mut self) { - if self.current_char.is_whitespace() { - while let Some(next_char) = self.next_char() { - if !next_char.is_whitespace() { - break; - } - } - } - } - - /// seeks until it encounters a linebreak character - fn seek_until_linebreak(&mut self) { - if self.check_special(&LB) { - self.skip_char(); - return; - } - while let Some(_) = self.next_char() { - if self.check_special(&LB) { - self.skip_char(); - return; - } - } - } - - /// seeks inline whitespaces and returns if there - /// were seeked whitespaces - fn check_seek_inline_whitespace(&mut self) -> bool { - let start_index = self.index; - self.seek_inline_whitespace(); - self.index > start_index - } - - /// checks if the input character is escaped - #[inline] - fn check_escaped(&self) -> bool { - if self.index == 0 { - return false; - } - if self.previous_char == SPECIAL_ESCAPE { - return true; - } - return false; - } - - /// checks if the current character is the given input character and not escaped - #[inline] - fn check_special(&self, character: &char) -> bool { - self.current_char == *character && !self.check_escaped() - } - - /// checks if the current character is part of the given group - fn check_special_group(&self, chars: &[char]) -> bool { - chars.contains(&self.current_char) && !self.check_escaped() - } - - /// checks if the next characters match a special sequence - fn check_special_sequence(&mut self, sequence: &[char]) -> bool { - let start_index = self.index; - if self.check_escaped() { - self.revert_to(start_index).unwrap(); - return false; - } - for sq_character in sequence { - if self.current_char != *sq_character { - let _ = self.revert_to(start_index); - return false; - } - if self.next_char() == None { - let _ = self.revert_to(start_index); - return false; - } - } - if self.index > 0 { - self.revert_to(self.index - 1).unwrap(); - } - - true - } - - /// checks if the next chars are a special sequence - fn check_special_sequence_group(&mut self, sequences: &[&[char]]) -> bool { - for sequence in sequences { - if self.check_special_sequence(*sequence) { - return true; - } - } - - false - } - - /// returns if the current character is a linebreak character - /// Note: No one likes CRLF - #[inline] - fn check_linebreak(&self) -> bool { - 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) { - Ok(()) - } else { - Err(self.revert_with_error(revert_index)) - } - } - - #[inline] - fn assert_special_group( - &mut self, - group: &[char], - revert_index: usize, - ) -> Result<(), ParseError> { - if self.check_special_group(group) { - Ok(()) - } else { - Err(self.revert_with_error(revert_index)) - } - } - - fn assert_special_sequence( - &mut self, - sequence: &[char], - revert_index: usize, - ) -> Result<(), ParseError> { - if self.check_special_sequence(sequence) { - Ok(()) - } else { - Err(self.revert_with_error(revert_index)) - } - } - - fn assert_special_sequence_group( - &mut self, - sequences: &[&[char]], - revert_index: usize, - ) -> Result<(), ParseError> { - if self.check_special_sequence_group(sequences) { - Ok(()) - } else { - Err(self.revert_with_error(revert_index)) - } - } - - /// returns the string until a specific - fn get_string_until( - &mut self, - break_at: &[char], - err_at: &[char], - ) -> Result { - let start_index = self.index; - let mut result = String::new(); - if self.check_special_group(break_at) { - return Ok(result); - } else if self.check_special_group(err_at) { - return Err(ParseError::new(self.index)); - } - - result.push(self.current_char); - while let Some(ch) = self.next_char() { - if self.check_special_group(break_at) || self.check_special_group(err_at) { - break; - } - result.push(ch); - } - - if self.check_special_group(err_at) { - Err(self.revert_with_error(start_index)) - } else { - Ok(result) - } - } - - /// Returns the string until a specific end sequence or an error character - fn get_string_until_sequence( - &mut self, - break_at: &[&[char]], - err_at: &[char], - ) -> Result { - let start_index = self.index; - let mut result = String::new(); - if self.check_special_sequence_group(break_at) { - return Ok(result); - } else if self.check_special_group(err_at) { - return Err(ParseError::new(self.index)); - } - - result.push(self.current_char); - while let Some(ch) = self.next_char() { - if self.check_special_sequence_group(break_at) || self.check_special_group(err_at) { - break; - } - result.push(ch); - } - - if self.check_special_group(err_at) { - Err(self.revert_with_error(start_index)) - } else { - Ok(result) - } - } - - /// returns the string until a specific character or reverts back to the given position - fn get_string_until_or_revert( - &mut self, - break_at: &[char], - err_at: &[char], - revert_index: usize, - ) -> ParseResult { - if let Ok(string) = self.get_string_until(break_at, err_at) { - Ok(string) - } else { - Err(self.revert_with_error(revert_index)) - } - } -} -*/ diff --git a/src/parser/inline.rs b/src/parser/inline.rs index 8d4d1c2..92e9880 100644 --- a/src/parser/inline.rs +++ b/src/parser/inline.rs @@ -1,11 +1,10 @@ -use super::charstate::CharStateMachine; +use super::{ParseError, ParseResult}; use crate::elements::tokens::*; use crate::elements::*; use crate::parser::block::ParseBlock; use crate::references::bibliography::BibReference; use crate::references::configuration::keys::BIB_REF_DISPLAY; use crate::references::templates::{GetTemplateVariables, Template, TemplateVariable}; -use crate::utils::parsing::{ParseError, ParseResult}; use crate::Parser; use std::collections::HashMap; use std::sync::{Arc, RwLock}; @@ -93,7 +92,7 @@ impl ParseInline for Parser { /// parses an image url fn parse_image(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; self.ctm.assert_char(&IMG_START, Some(start_index))?; self.ctm.seek_one()?; @@ -112,27 +111,27 @@ impl ParseInline for Parser { // parses an url fn parse_url(&mut self, short_syntax: bool) -> ParseResult { let start_index = self.ctm.get_index(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; let mut description = String::new(); if self.ctm.check_char(&DESC_OPEN) { - self.ctm.seek_one(); + self.ctm.seek_one()?; description = self.ctm .get_string_until_any_or_rewind(&[DESC_CLOSE], &[LB], start_index)?; } else if !short_syntax { return Err(self.ctm.rewind_with_error(start_index)); } - self.ctm.seek_one(); + self.ctm.seek_one()?; self.ctm.assert_char(&URL_OPEN, Some(start_index))?; - self.ctm.seek_one(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_one()?; + self.ctm.seek_any(&INLINE_WHITESPACE)?; let url = self .ctm .get_string_until_any_or_rewind(&[URL_CLOSE], &[LB], start_index)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; if description.is_empty() { Ok(Url::new(None, url)) @@ -145,7 +144,7 @@ impl ParseInline for Parser { fn parse_checkbox(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); self.ctm.assert_char(&CHECK_OPEN, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let checked = if self.ctm.check_char(&CHECK_CHECKED) { true } else if self.ctm.check_char(&SPACE) { @@ -153,9 +152,9 @@ impl ParseInline for Parser { } else { return Err(self.ctm.rewind_with_error(start_index)); }; - self.ctm.seek_one(); + self.ctm.seek_one()?; self.ctm.assert_char(&CHECK_CLOSE, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; Ok(Checkbox { value: checked }) } @@ -164,10 +163,10 @@ impl ParseInline for Parser { fn parse_bold(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); self.ctm.assert_sequence(&BOLD, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let inline = self.parse_inline()?; self.ctm.assert_sequence(&BOLD, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; Ok(BoldText { value: Box::new(inline), @@ -190,12 +189,12 @@ impl ParseInline for Parser { fn parse_monospace(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); self.ctm.assert_char(&BACKTICK, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let content = self .ctm .get_string_until_any_or_rewind(&[BACKTICK, LB], &[], start_index)?; self.ctm.assert_char(&BACKTICK, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; Ok(MonospaceText { value: content }) } @@ -215,11 +214,11 @@ impl ParseInline for Parser { fn parse_emoji(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); self.ctm.assert_char(&EMOJI, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let name = self .ctm .get_string_until_any_or_rewind(&[EMOJI], &[SPACE, LB], start_index)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; if let Some(emoji) = gh_emoji::get(name.as_str()) { let emoji_char = *emoji.chars().collect::>().first().unwrap(); Ok(Emoji { @@ -236,13 +235,13 @@ impl ParseInline for Parser { let start_index = self.ctm.get_index(); self.ctm .assert_sequence(&SQ_COLOR_START, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let color = self.ctm.get_string_until_any_or_rewind( &[COLOR_CLOSE], &[SPACE, LB, SEMICOLON], start_index, )?; - self.ctm.seek_one(); + self.ctm.seek_one()?; if color.is_empty() { return Err(self.ctm.err()); } @@ -256,11 +255,11 @@ impl ParseInline for Parser { let start_index = self.ctm.get_index(); self.ctm .assert_sequence(&SQ_BIBREF_START, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let key = self.ctm .get_string_until_any_or_rewind(&[BIBREF_CLOSE], &[SPACE, LB], start_index)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let ref_entry = Arc::new(RwLock::new(BibReference::new( key, self.document.config.get_ref_entry(BIB_REF_DISPLAY), @@ -276,19 +275,19 @@ impl ParseInline for Parser { fn parse_template_variable(&mut self) -> ParseResult>> { let start_index = self.ctm.get_index(); self.ctm.assert_char(&TEMP_VAR_OPEN, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let prefix = self.ctm .get_string_until_any_or_rewind(&[TEMP_VAR_OPEN], &[LB], start_index)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let name = self.ctm .get_string_until_any_or_rewind(&[TEMP_VAR_CLOSE], &[LB], start_index)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let suffix = self.ctm .get_string_until_any_or_rewind(&[TEMP_VAR_CLOSE], &[LB], start_index)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; Ok(Arc::new(RwLock::new(TemplateVariable { value: None, name, @@ -325,7 +324,7 @@ impl ParseInline for Parser { fn parse_inline_metadata(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); self.ctm.assert_char(&META_OPEN, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let mut values = HashMap::new(); while let Ok((key, value)) = self.parse_metadata_pair() { @@ -336,7 +335,7 @@ impl ParseInline for Parser { } } if self.ctm.check_char(&META_CLOSE) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } if values.len() == 0 { // if there was a linebreak (the metadata wasn't closed) or there is no inner data @@ -349,16 +348,16 @@ impl ParseInline for Parser { /// parses a key-value metadata pair fn parse_metadata_pair(&mut self) -> Result<(String, MetadataValue), ParseError> { - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; let name = self .ctm .get_string_until_any(&[META_CLOSE, EQ, SPACE, LB], &[])?; - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; let mut value = MetadataValue::Bool(true); if self.ctm.check_char(&EQ) { - self.ctm.seek_one(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_one()?; + self.ctm.seek_any(&INLINE_WHITESPACE)?; if let Ok(ph) = self.parse_placeholder() { value = MetadataValue::Placeholder(ph); } else if let Ok(template) = self.parse_template() { @@ -368,7 +367,7 @@ impl ParseInline for Parser { let parse_until = if quoted_string { let quote_start = self.ctm.get_current(); - self.ctm.seek_one(); + self.ctm.seek_one()?; vec![quote_start, META_CLOSE, LB] } else { vec![META_CLOSE, LB, SPACE] @@ -377,12 +376,12 @@ impl ParseInline for Parser { let raw_value = self.ctm.get_string_until_any(&parse_until, &[])?; if self.ctm.check_any("ES) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; if self.ctm.check_char(&COMMA) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } value = if quoted_string { @@ -408,7 +407,7 @@ impl ParseInline for Parser { fn parse_placeholder(&mut self) -> ParseResult>> { let start_index = self.ctm.get_index(); self.ctm.assert_sequence(&SQ_PHOLDER_START, None)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let name = if let Ok(name_str) = self .ctm @@ -418,7 +417,7 @@ impl ParseInline for Parser { } else { return Err(self.ctm.rewind_with_error(start_index)); }; - self.ctm.seek_one(); + self.ctm.seek_one()?; let metadata = if let Ok(meta) = self.parse_inline_metadata() { Some(meta) @@ -437,7 +436,7 @@ impl ParseInline for Parser { let start_index = self.ctm.get_index(); self.ctm.assert_char(&TEMPLATE, None)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; if self.ctm.check_char(&TEMPLATE) { return Err(self.ctm.rewind_with_error(start_index)); @@ -458,7 +457,7 @@ impl ParseInline for Parser { self.block_break_at.clear(); self.inline_break_at.clear(); self.ctm.assert_char(&TEMPLATE, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let vars: HashMap>> = elements .iter() diff --git a/src/parser/line.rs b/src/parser/line.rs index e8e734a..2faafab 100644 --- a/src/parser/line.rs +++ b/src/parser/line.rs @@ -1,9 +1,8 @@ +use super::ParseResult; use crate::elements::tokens::*; use crate::elements::{Cell, Centered, Header, Line, ListItem, Row, Ruler, TextLine}; -use crate::parser::charstate::CharStateMachine; use crate::parser::inline::ParseInline; use crate::references::bibliography::BibEntry; -use crate::utils::parsing::{ParseError, ParseResult}; use crate::Parser; use std::sync::{Arc, RwLock}; @@ -53,7 +52,7 @@ impl ParseLine for Parser { /// parses a single list item defined with - fn parse_list_item(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; let level = self.ctm.get_index() - start_index; self.ctm .assert_any(&LIST_SPECIAL_CHARS, Some(start_index))?; @@ -66,7 +65,7 @@ impl ParseLine for Parser { if !self.ctm.check_any(&INLINE_WHITESPACE) { return Err(self.ctm.rewind_with_error(start_index)); } - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; if self.ctm.check_char(&MINUS) { return Err(self.ctm.rewind_with_error(start_index)); } @@ -79,15 +78,15 @@ impl ParseLine for Parser { /// parses a table row/head fn parse_row(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; self.ctm.assert_char(&PIPE, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; if self.ctm.check_char(&PIPE) { return Err(self.ctm.rewind_with_error(start_index)); } self.inline_break_at.push(PIPE); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; let mut row = Row::new(); loop { let mut element = TextLine::new(); @@ -101,19 +100,19 @@ impl ParseLine for Parser { text: Line::Text(element), }); if self.ctm.check_char(&PIPE) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } if self.ctm.check_char(&LB) || self.ctm.check_eof() { break; } - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; } self.inline_break_at.clear(); if self.ctm.check_char(&PIPE) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } - self.ctm.seek_one(); + self.ctm.seek_one()?; if row.cells.len() > 0 { Ok(row) @@ -124,16 +123,17 @@ impl ParseLine for Parser { fn parse_bib_entry(&mut self) -> ParseResult>> { let start_index = self.ctm.get_index(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; self.ctm.assert_char(&BIB_KEY_OPEN, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let key = self.ctm .get_string_until_any_or_rewind(&[BIB_KEY_CLOSE], &[LB, SPACE], start_index)?; - self.ctm.seek_one(); + self.ctm.seek_one()?; self.ctm.assert_char(&BIB_DATA_START, Some(start_index))?; - self.ctm.seek_one(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_one()?; + self.ctm.seek_any(&INLINE_WHITESPACE)?; + let entry = if let Ok(meta) = self.parse_inline_metadata() { BibEntry::from_metadata(key, Box::new(meta), &self.document.config) } else { @@ -155,7 +155,7 @@ impl ParseLine for Parser { let start_index = self.ctm.get_index(); self.ctm .assert_sequence(&SQ_CENTERED_START, Some(start_index))?; - self.ctm.seek_one(); + self.ctm.seek_one()?; let line = self.parse_text_line()?; Ok(Centered { line }) @@ -164,16 +164,16 @@ impl ParseLine for Parser { /// parses a ruler fn parse_ruler(&mut self) -> ParseResult { let start_index = self.ctm.get_index(); - self.ctm.seek_any(&INLINE_WHITESPACE); + self.ctm.seek_any(&INLINE_WHITESPACE)?; self.ctm.assert_sequence(&SQ_RULER, Some(start_index))?; while !self.ctm.check_char(&LB) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } Ok(Ruler {}) } /// Parses a line of text - fn parse_text_line(&mut self) -> Result { + fn parse_text_line(&mut self) -> ParseResult { let mut text = TextLine::new(); while let Ok(subtext) = self.parse_inline() { text.add_subtext(subtext); @@ -183,7 +183,7 @@ impl ParseLine for Parser { } if self.ctm.check_char(&LB) { - self.ctm.seek_one(); + self.ctm.seek_one()?; } if text.subtext.len() > 0 || !self.ctm.check_eof() { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index c1c866d..4d1c1c4 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,13 +1,11 @@ pub(crate) mod block; -pub(crate) mod charstate; pub(crate) mod inline; pub(crate) mod line; use self::block::ParseBlock; use crate::elements::{Document, ImportAnchor}; use crate::references::configuration::Configuration; -use crate::utils::parsing::{ParseError, ParseResult}; -use charred::tapemachine::CharTapeMachine; +use charred::tapemachine::{CharTapeMachine, TapeError, TapeResult}; use colored::*; use crossbeam_utils::sync::WaitGroup; use std::fs::File; @@ -17,6 +15,9 @@ use std::path::PathBuf; use std::sync::{Arc, Mutex, RwLock}; use std::thread; +pub type ParseResult = TapeResult; +pub type ParseError = TapeError; + pub struct Parser { pub(crate) ctm: CharTapeMachine, section_nesting: u8, @@ -29,7 +30,6 @@ pub struct Parser { pub(crate) block_break_at: Vec, pub(crate) inline_break_at: Vec, pub(crate) document: Document, - pub(crate) reader: Box, pub(crate) parse_variables: bool, } @@ -95,19 +95,11 @@ impl Parser { if let Some(path) = path.clone() { paths.lock().unwrap().push(path.clone()) } - let mut text = Vec::new(); - let mut current_char = ' '; - for _ in 0..8 { - let mut buf = String::new(); - if let Ok(_) = reader.read_line(&mut buf) { - text.append(&mut buf.chars().collect::>()); - } else { - break; - } - } - if let Some(ch) = text.get(0) { - current_char = *ch - } + let mut text = String::new(); + reader + .read_to_string(&mut text) + .expect("Failed to read file"); + let document = Document::new(!is_child); Self { sections: Vec::new(), @@ -117,11 +109,10 @@ impl Parser { paths, wg: WaitGroup::new(), is_child, - ctm: CharTapeMachine::new(text), + ctm: CharTapeMachine::new(text.chars().collect()), inline_break_at: Vec::new(), block_break_at: Vec::new(), document, - reader, parse_variables: false, } } @@ -130,14 +121,6 @@ impl Parser { self.document.config = config; } - /// Returns the text of the parser as a string - fn get_text(&self) -> String { - self.ctm - .get_text() - .iter() - .fold("".to_string(), |a, b| format!("{}{}", a, b)) - } - /// Returns the import paths of the parser pub fn get_paths(&self) -> Vec { self.paths.lock().unwrap().clone() diff --git a/src/utils/parsing.rs b/src/utils/parsing.rs index faffd95..d89de44 100644 --- a/src/utils/parsing.rs +++ b/src/utils/parsing.rs @@ -1,87 +1,6 @@ -use charred::tapemachine::{TapeError, TapeResult}; -use colored::*; -use std::error::Error; -use std::fmt; -use std::fmt::{Display, Formatter}; - #[macro_export] macro_rules! parse { ($str:expr) => { Parser::new($str.to_string(), None).parse() }; } - -pub type ParseResult = TapeResult; -pub type ParseError = TapeError; - -/* -#[derive(Debug)] -pub struct ParseError { - index: usize, - message: Option, - pub(crate) eof: bool, -} -impl Display for ParseError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - if let Some(message) = &self.message { - write!( - f, - "{}", - format!("Parse Error at index {}: {}", self.index, message).red() - ) - } else { - write!( - f, - "{}", - format!("Parse Error at index {}", self.index).red() - ) - } - } -} -impl Error for ParseError {} -impl ParseError { - pub fn new(index: usize) -> Self { - Self { - index, - message: None, - eof: false, - } - } - - pub fn new_with_message(index: usize, message: &str) -> Self { - Self { - index, - message: Some(message.to_string()), - eof: false, - } - } - - pub fn eof(index: usize) -> Self { - Self { - index, - message: Some("EOF".to_string()), - eof: true, - } - } - - pub fn set_message(&mut self, message: &str) { - self.message = Some(message.to_string()); - } - - pub fn get_position(&self, content: &str) -> Option<(usize, usize)> { - if content.len() <= self.index { - return None; - } - let split_content = content.split_at(self.index); - let line_number = split_content.0.lines().count() as usize; - - if let Some(line) = split_content.0.lines().last() { - let inline_position = line.len(); - - Some((line_number, inline_position)) - } else { - None - } - } -} -*/