Cleanup after switching to charred

feature/epub-rendering
trivernis 4 years ago
parent cb327180c6
commit 63c060e0a2

2
Cargo.lock generated

@ -571,7 +571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "snekdown" name = "snekdown"
version = "0.17.0" version = "0.18.0"
dependencies = [ dependencies = [
"charred 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",

@ -1,6 +1,6 @@
[package] [package]
name = "snekdown" name = "snekdown"
version = "0.17.0" version = "0.18.0"
authors = ["trivernis <trivernis@protonmail.com>"] authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018" edition = "2018"
license-file = "LICENSE" license-file = "LICENSE"

@ -1,11 +1,9 @@
use super::ParseResult;
use crate::elements::tokens::*; use crate::elements::tokens::*;
use crate::elements::{Block, CodeBlock, Import, List, ListItem, Paragraph, Quote, Section, Table}; 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::inline::ParseInline;
use crate::parser::line::ParseLine; use crate::parser::line::ParseLine;
use crate::utils::parsing::{ParseError, ParseResult};
use crate::Parser; use crate::Parser;
use charred::tapemachine::{TapeError, TapeResult};
pub(crate) trait ParseBlock { pub(crate) trait ParseBlock {
fn parse_block(&mut self) -> ParseResult<Block>; fn parse_block(&mut self) -> ParseResult<Block>;
@ -77,7 +75,7 @@ impl ParseBlock for Parser {
} }
return Err(self.ctm.rewind_with_error(start_index)); 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()?; let mut header = self.parse_header()?;
header.size = size; header.size = size;
self.section_nesting = size; self.section_nesting = size;
@ -108,12 +106,12 @@ impl ParseBlock for Parser {
self.ctm.seek_whitespace(); self.ctm.seek_whitespace();
self.ctm self.ctm
.assert_sequence(&SQ_CODE_BLOCK, Some(start_index))?; .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], &[])?; 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], &[])?; let text = self.ctm.get_string_until_sequence(&[&SQ_CODE_BLOCK], &[])?;
for _ in 0..2 { for _ in 0..2 {
self.ctm.seek_one(); self.ctm.seek_one()?;
} }
Ok(CodeBlock { Ok(CodeBlock {
@ -251,12 +249,12 @@ impl ParseBlock for Parser {
fn parse_table(&mut self) -> ParseResult<Table> { fn parse_table(&mut self) -> ParseResult<Table> {
let header = self.parse_row()?; let header = self.parse_row()?;
if self.ctm.check_char(&LB) { if self.ctm.check_char(&LB) {
self.ctm.seek_one(); self.ctm.seek_one()?;
} }
let seek_index = self.ctm.get_index(); let seek_index = self.ctm.get_index();
let mut table = Table::new(header); let mut table = Table::new(header);
while let Ok(_) = self.ctm.seek_one() { 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) { if !self.ctm.check_any(&[MINUS, PIPE]) || self.ctm.check_char(&LB) {
break; break;
} }
@ -292,7 +290,7 @@ impl ParseBlock for Parser {
return Err(self.ctm.rewind_with_error(start_index)); return Err(self.ctm.rewind_with_error(start_index));
} }
if self.ctm.check_char(&IMPORT_CLOSE) { if self.ctm.check_char(&IMPORT_CLOSE) {
self.ctm.seek_one(); self.ctm.seek_one()?;
} }
// parser success // parser success

@ -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<char>;
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<String, ParseError>;
fn get_string_until_sequence(
&mut self,
break_at: &[&[char]],
err_at: &[char],
) -> Result<String, ParseError>;
fn get_string_until_or_revert(
&mut self,
break_et: &[char],
err_at: &[char],
revert_index: usize,
) -> ParseResult<String>;
}
/*
impl CharStateMachine for Parser {
/// Increments the current index and returns the
/// char at the indexes position
#[inline]
fn next_char(&mut self) -> Option<char> {
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<String, ParseError> {
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<String, ParseError> {
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<String> {
if let Ok(string) = self.get_string_until(break_at, err_at) {
Ok(string)
} else {
Err(self.revert_with_error(revert_index))
}
}
}
*/

@ -1,11 +1,10 @@
use super::charstate::CharStateMachine; use super::{ParseError, ParseResult};
use crate::elements::tokens::*; use crate::elements::tokens::*;
use crate::elements::*; use crate::elements::*;
use crate::parser::block::ParseBlock; use crate::parser::block::ParseBlock;
use crate::references::bibliography::BibReference; use crate::references::bibliography::BibReference;
use crate::references::configuration::keys::BIB_REF_DISPLAY; use crate::references::configuration::keys::BIB_REF_DISPLAY;
use crate::references::templates::{GetTemplateVariables, Template, TemplateVariable}; use crate::references::templates::{GetTemplateVariables, Template, TemplateVariable};
use crate::utils::parsing::{ParseError, ParseResult};
use crate::Parser; use crate::Parser;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -93,7 +92,7 @@ impl ParseInline for Parser {
/// parses an image url /// parses an image url
fn parse_image(&mut self) -> ParseResult<Image> { fn parse_image(&mut self) -> ParseResult<Image> {
let start_index = self.ctm.get_index(); 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.assert_char(&IMG_START, Some(start_index))?;
self.ctm.seek_one()?; self.ctm.seek_one()?;
@ -112,27 +111,27 @@ impl ParseInline for Parser {
// parses an url // parses an url
fn parse_url(&mut self, short_syntax: bool) -> ParseResult<Url> { fn parse_url(&mut self, short_syntax: bool) -> ParseResult<Url> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.seek_any(&INLINE_WHITESPACE); self.ctm.seek_any(&INLINE_WHITESPACE)?;
let mut description = String::new(); let mut description = String::new();
if self.ctm.check_char(&DESC_OPEN) { if self.ctm.check_char(&DESC_OPEN) {
self.ctm.seek_one(); self.ctm.seek_one()?;
description = description =
self.ctm self.ctm
.get_string_until_any_or_rewind(&[DESC_CLOSE], &[LB], start_index)?; .get_string_until_any_or_rewind(&[DESC_CLOSE], &[LB], start_index)?;
} else if !short_syntax { } else if !short_syntax {
return Err(self.ctm.rewind_with_error(start_index)); 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.assert_char(&URL_OPEN, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
self.ctm.seek_any(&INLINE_WHITESPACE); self.ctm.seek_any(&INLINE_WHITESPACE)?;
let url = self let url = self
.ctm .ctm
.get_string_until_any_or_rewind(&[URL_CLOSE], &[LB], start_index)?; .get_string_until_any_or_rewind(&[URL_CLOSE], &[LB], start_index)?;
self.ctm.seek_one(); self.ctm.seek_one()?;
if description.is_empty() { if description.is_empty() {
Ok(Url::new(None, url)) Ok(Url::new(None, url))
@ -145,7 +144,7 @@ impl ParseInline for Parser {
fn parse_checkbox(&mut self) -> ParseResult<Checkbox> { fn parse_checkbox(&mut self) -> ParseResult<Checkbox> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.assert_char(&CHECK_OPEN, Some(start_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) { let checked = if self.ctm.check_char(&CHECK_CHECKED) {
true true
} else if self.ctm.check_char(&SPACE) { } else if self.ctm.check_char(&SPACE) {
@ -153,9 +152,9 @@ impl ParseInline for Parser {
} else { } else {
return Err(self.ctm.rewind_with_error(start_index)); 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.assert_char(&CHECK_CLOSE, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
Ok(Checkbox { value: checked }) Ok(Checkbox { value: checked })
} }
@ -164,10 +163,10 @@ impl ParseInline for Parser {
fn parse_bold(&mut self) -> ParseResult<BoldText> { fn parse_bold(&mut self) -> ParseResult<BoldText> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.assert_sequence(&BOLD, Some(start_index))?; self.ctm.assert_sequence(&BOLD, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let inline = self.parse_inline()?; let inline = self.parse_inline()?;
self.ctm.assert_sequence(&BOLD, Some(start_index))?; self.ctm.assert_sequence(&BOLD, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
Ok(BoldText { Ok(BoldText {
value: Box::new(inline), value: Box::new(inline),
@ -190,12 +189,12 @@ impl ParseInline for Parser {
fn parse_monospace(&mut self) -> ParseResult<MonospaceText> { fn parse_monospace(&mut self) -> ParseResult<MonospaceText> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.assert_char(&BACKTICK, Some(start_index))?; self.ctm.assert_char(&BACKTICK, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let content = self let content = self
.ctm .ctm
.get_string_until_any_or_rewind(&[BACKTICK, LB], &[], start_index)?; .get_string_until_any_or_rewind(&[BACKTICK, LB], &[], start_index)?;
self.ctm.assert_char(&BACKTICK, Some(start_index))?; self.ctm.assert_char(&BACKTICK, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
Ok(MonospaceText { value: content }) Ok(MonospaceText { value: content })
} }
@ -215,11 +214,11 @@ impl ParseInline for Parser {
fn parse_emoji(&mut self) -> ParseResult<Emoji> { fn parse_emoji(&mut self) -> ParseResult<Emoji> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.assert_char(&EMOJI, Some(start_index))?; self.ctm.assert_char(&EMOJI, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let name = self let name = self
.ctm .ctm
.get_string_until_any_or_rewind(&[EMOJI], &[SPACE, LB], start_index)?; .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()) { if let Some(emoji) = gh_emoji::get(name.as_str()) {
let emoji_char = *emoji.chars().collect::<Vec<char>>().first().unwrap(); let emoji_char = *emoji.chars().collect::<Vec<char>>().first().unwrap();
Ok(Emoji { Ok(Emoji {
@ -236,13 +235,13 @@ impl ParseInline for Parser {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm self.ctm
.assert_sequence(&SQ_COLOR_START, Some(start_index))?; .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( let color = self.ctm.get_string_until_any_or_rewind(
&[COLOR_CLOSE], &[COLOR_CLOSE],
&[SPACE, LB, SEMICOLON], &[SPACE, LB, SEMICOLON],
start_index, start_index,
)?; )?;
self.ctm.seek_one(); self.ctm.seek_one()?;
if color.is_empty() { if color.is_empty() {
return Err(self.ctm.err()); return Err(self.ctm.err());
} }
@ -256,11 +255,11 @@ impl ParseInline for Parser {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm self.ctm
.assert_sequence(&SQ_BIBREF_START, Some(start_index))?; .assert_sequence(&SQ_BIBREF_START, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let key = let key =
self.ctm self.ctm
.get_string_until_any_or_rewind(&[BIBREF_CLOSE], &[SPACE, LB], start_index)?; .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( let ref_entry = Arc::new(RwLock::new(BibReference::new(
key, key,
self.document.config.get_ref_entry(BIB_REF_DISPLAY), self.document.config.get_ref_entry(BIB_REF_DISPLAY),
@ -276,19 +275,19 @@ impl ParseInline for Parser {
fn parse_template_variable(&mut self) -> ParseResult<Arc<RwLock<TemplateVariable>>> { fn parse_template_variable(&mut self) -> ParseResult<Arc<RwLock<TemplateVariable>>> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.assert_char(&TEMP_VAR_OPEN, Some(start_index))?; self.ctm.assert_char(&TEMP_VAR_OPEN, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let prefix = let prefix =
self.ctm self.ctm
.get_string_until_any_or_rewind(&[TEMP_VAR_OPEN], &[LB], start_index)?; .get_string_until_any_or_rewind(&[TEMP_VAR_OPEN], &[LB], start_index)?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let name = let name =
self.ctm self.ctm
.get_string_until_any_or_rewind(&[TEMP_VAR_CLOSE], &[LB], start_index)?; .get_string_until_any_or_rewind(&[TEMP_VAR_CLOSE], &[LB], start_index)?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let suffix = let suffix =
self.ctm self.ctm
.get_string_until_any_or_rewind(&[TEMP_VAR_CLOSE], &[LB], start_index)?; .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 { Ok(Arc::new(RwLock::new(TemplateVariable {
value: None, value: None,
name, name,
@ -325,7 +324,7 @@ impl ParseInline for Parser {
fn parse_inline_metadata(&mut self) -> ParseResult<InlineMetadata> { fn parse_inline_metadata(&mut self) -> ParseResult<InlineMetadata> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.assert_char(&META_OPEN, Some(start_index))?; self.ctm.assert_char(&META_OPEN, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let mut values = HashMap::new(); let mut values = HashMap::new();
while let Ok((key, value)) = self.parse_metadata_pair() { while let Ok((key, value)) = self.parse_metadata_pair() {
@ -336,7 +335,7 @@ impl ParseInline for Parser {
} }
} }
if self.ctm.check_char(&META_CLOSE) { if self.ctm.check_char(&META_CLOSE) {
self.ctm.seek_one(); self.ctm.seek_one()?;
} }
if values.len() == 0 { if values.len() == 0 {
// if there was a linebreak (the metadata wasn't closed) or there is no inner data // 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 /// parses a key-value metadata pair
fn parse_metadata_pair(&mut self) -> Result<(String, MetadataValue), ParseError> { 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 let name = self
.ctm .ctm
.get_string_until_any(&[META_CLOSE, EQ, SPACE, LB], &[])?; .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); let mut value = MetadataValue::Bool(true);
if self.ctm.check_char(&EQ) { if self.ctm.check_char(&EQ) {
self.ctm.seek_one(); self.ctm.seek_one()?;
self.ctm.seek_any(&INLINE_WHITESPACE); self.ctm.seek_any(&INLINE_WHITESPACE)?;
if let Ok(ph) = self.parse_placeholder() { if let Ok(ph) = self.parse_placeholder() {
value = MetadataValue::Placeholder(ph); value = MetadataValue::Placeholder(ph);
} else if let Ok(template) = self.parse_template() { } else if let Ok(template) = self.parse_template() {
@ -368,7 +367,7 @@ impl ParseInline for Parser {
let parse_until = if quoted_string { let parse_until = if quoted_string {
let quote_start = self.ctm.get_current(); let quote_start = self.ctm.get_current();
self.ctm.seek_one(); self.ctm.seek_one()?;
vec![quote_start, META_CLOSE, LB] vec![quote_start, META_CLOSE, LB]
} else { } else {
vec![META_CLOSE, LB, SPACE] vec![META_CLOSE, LB, SPACE]
@ -377,12 +376,12 @@ impl ParseInline for Parser {
let raw_value = self.ctm.get_string_until_any(&parse_until, &[])?; let raw_value = self.ctm.get_string_until_any(&parse_until, &[])?;
if self.ctm.check_any(&QUOTES) { if self.ctm.check_any(&QUOTES) {
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) { if self.ctm.check_char(&COMMA) {
self.ctm.seek_one(); self.ctm.seek_one()?;
} }
value = if quoted_string { value = if quoted_string {
@ -408,7 +407,7 @@ impl ParseInline for Parser {
fn parse_placeholder(&mut self) -> ParseResult<Arc<RwLock<Placeholder>>> { fn parse_placeholder(&mut self) -> ParseResult<Arc<RwLock<Placeholder>>> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.assert_sequence(&SQ_PHOLDER_START, None)?; self.ctm.assert_sequence(&SQ_PHOLDER_START, None)?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let name = if let Ok(name_str) = self let name = if let Ok(name_str) = self
.ctm .ctm
@ -418,7 +417,7 @@ impl ParseInline for Parser {
} else { } else {
return Err(self.ctm.rewind_with_error(start_index)); 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() { let metadata = if let Ok(meta) = self.parse_inline_metadata() {
Some(meta) Some(meta)
@ -437,7 +436,7 @@ impl ParseInline for Parser {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.assert_char(&TEMPLATE, None)?; self.ctm.assert_char(&TEMPLATE, None)?;
self.ctm.seek_one(); self.ctm.seek_one()?;
if self.ctm.check_char(&TEMPLATE) { if self.ctm.check_char(&TEMPLATE) {
return Err(self.ctm.rewind_with_error(start_index)); return Err(self.ctm.rewind_with_error(start_index));
@ -458,7 +457,7 @@ impl ParseInline for Parser {
self.block_break_at.clear(); self.block_break_at.clear();
self.inline_break_at.clear(); self.inline_break_at.clear();
self.ctm.assert_char(&TEMPLATE, Some(start_index))?; self.ctm.assert_char(&TEMPLATE, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let vars: HashMap<String, Arc<RwLock<TemplateVariable>>> = elements let vars: HashMap<String, Arc<RwLock<TemplateVariable>>> = elements
.iter() .iter()

@ -1,9 +1,8 @@
use super::ParseResult;
use crate::elements::tokens::*; use crate::elements::tokens::*;
use crate::elements::{Cell, Centered, Header, Line, ListItem, Row, Ruler, TextLine}; use crate::elements::{Cell, Centered, Header, Line, ListItem, Row, Ruler, TextLine};
use crate::parser::charstate::CharStateMachine;
use crate::parser::inline::ParseInline; use crate::parser::inline::ParseInline;
use crate::references::bibliography::BibEntry; use crate::references::bibliography::BibEntry;
use crate::utils::parsing::{ParseError, ParseResult};
use crate::Parser; use crate::Parser;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -53,7 +52,7 @@ impl ParseLine for Parser {
/// parses a single list item defined with - /// parses a single list item defined with -
fn parse_list_item(&mut self) -> ParseResult<ListItem> { fn parse_list_item(&mut self) -> ParseResult<ListItem> {
let start_index = self.ctm.get_index(); 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; let level = self.ctm.get_index() - start_index;
self.ctm self.ctm
.assert_any(&LIST_SPECIAL_CHARS, Some(start_index))?; .assert_any(&LIST_SPECIAL_CHARS, Some(start_index))?;
@ -66,7 +65,7 @@ impl ParseLine for Parser {
if !self.ctm.check_any(&INLINE_WHITESPACE) { if !self.ctm.check_any(&INLINE_WHITESPACE) {
return Err(self.ctm.rewind_with_error(start_index)); 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) { if self.ctm.check_char(&MINUS) {
return Err(self.ctm.rewind_with_error(start_index)); return Err(self.ctm.rewind_with_error(start_index));
} }
@ -79,15 +78,15 @@ impl ParseLine for Parser {
/// parses a table row/head /// parses a table row/head
fn parse_row(&mut self) -> ParseResult<Row> { fn parse_row(&mut self) -> ParseResult<Row> {
let start_index = self.ctm.get_index(); 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.assert_char(&PIPE, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
if self.ctm.check_char(&PIPE) { if self.ctm.check_char(&PIPE) {
return Err(self.ctm.rewind_with_error(start_index)); return Err(self.ctm.rewind_with_error(start_index));
} }
self.inline_break_at.push(PIPE); self.inline_break_at.push(PIPE);
self.ctm.seek_any(&INLINE_WHITESPACE); self.ctm.seek_any(&INLINE_WHITESPACE)?;
let mut row = Row::new(); let mut row = Row::new();
loop { loop {
let mut element = TextLine::new(); let mut element = TextLine::new();
@ -101,19 +100,19 @@ impl ParseLine for Parser {
text: Line::Text(element), text: Line::Text(element),
}); });
if self.ctm.check_char(&PIPE) { if self.ctm.check_char(&PIPE) {
self.ctm.seek_one(); self.ctm.seek_one()?;
} }
if self.ctm.check_char(&LB) || self.ctm.check_eof() { if self.ctm.check_char(&LB) || self.ctm.check_eof() {
break; break;
} }
self.ctm.seek_any(&INLINE_WHITESPACE); self.ctm.seek_any(&INLINE_WHITESPACE)?;
} }
self.inline_break_at.clear(); self.inline_break_at.clear();
if self.ctm.check_char(&PIPE) { 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 { if row.cells.len() > 0 {
Ok(row) Ok(row)
@ -124,16 +123,17 @@ impl ParseLine for Parser {
fn parse_bib_entry(&mut self) -> ParseResult<Arc<RwLock<BibEntry>>> { fn parse_bib_entry(&mut self) -> ParseResult<Arc<RwLock<BibEntry>>> {
let start_index = self.ctm.get_index(); 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.assert_char(&BIB_KEY_OPEN, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let key = let key =
self.ctm self.ctm
.get_string_until_any_or_rewind(&[BIB_KEY_CLOSE], &[LB, SPACE], start_index)?; .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.assert_char(&BIB_DATA_START, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
self.ctm.seek_any(&INLINE_WHITESPACE); self.ctm.seek_any(&INLINE_WHITESPACE)?;
let entry = if let Ok(meta) = self.parse_inline_metadata() { let entry = if let Ok(meta) = self.parse_inline_metadata() {
BibEntry::from_metadata(key, Box::new(meta), &self.document.config) BibEntry::from_metadata(key, Box::new(meta), &self.document.config)
} else { } else {
@ -155,7 +155,7 @@ impl ParseLine for Parser {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm self.ctm
.assert_sequence(&SQ_CENTERED_START, Some(start_index))?; .assert_sequence(&SQ_CENTERED_START, Some(start_index))?;
self.ctm.seek_one(); self.ctm.seek_one()?;
let line = self.parse_text_line()?; let line = self.parse_text_line()?;
Ok(Centered { line }) Ok(Centered { line })
@ -164,16 +164,16 @@ impl ParseLine for Parser {
/// parses a ruler /// parses a ruler
fn parse_ruler(&mut self) -> ParseResult<Ruler> { fn parse_ruler(&mut self) -> ParseResult<Ruler> {
let start_index = self.ctm.get_index(); 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))?; self.ctm.assert_sequence(&SQ_RULER, Some(start_index))?;
while !self.ctm.check_char(&LB) { while !self.ctm.check_char(&LB) {
self.ctm.seek_one(); self.ctm.seek_one()?;
} }
Ok(Ruler {}) Ok(Ruler {})
} }
/// Parses a line of text /// Parses a line of text
fn parse_text_line(&mut self) -> Result<TextLine, ParseError> { fn parse_text_line(&mut self) -> ParseResult<TextLine> {
let mut text = TextLine::new(); let mut text = TextLine::new();
while let Ok(subtext) = self.parse_inline() { while let Ok(subtext) = self.parse_inline() {
text.add_subtext(subtext); text.add_subtext(subtext);
@ -183,7 +183,7 @@ impl ParseLine for Parser {
} }
if self.ctm.check_char(&LB) { if self.ctm.check_char(&LB) {
self.ctm.seek_one(); self.ctm.seek_one()?;
} }
if text.subtext.len() > 0 || !self.ctm.check_eof() { if text.subtext.len() > 0 || !self.ctm.check_eof() {

@ -1,13 +1,11 @@
pub(crate) mod block; pub(crate) mod block;
pub(crate) mod charstate;
pub(crate) mod inline; pub(crate) mod inline;
pub(crate) mod line; pub(crate) mod line;
use self::block::ParseBlock; use self::block::ParseBlock;
use crate::elements::{Document, ImportAnchor}; use crate::elements::{Document, ImportAnchor};
use crate::references::configuration::Configuration; use crate::references::configuration::Configuration;
use crate::utils::parsing::{ParseError, ParseResult}; use charred::tapemachine::{CharTapeMachine, TapeError, TapeResult};
use charred::tapemachine::CharTapeMachine;
use colored::*; use colored::*;
use crossbeam_utils::sync::WaitGroup; use crossbeam_utils::sync::WaitGroup;
use std::fs::File; use std::fs::File;
@ -17,6 +15,9 @@ use std::path::PathBuf;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::thread; use std::thread;
pub type ParseResult<T> = TapeResult<T>;
pub type ParseError = TapeError;
pub struct Parser { pub struct Parser {
pub(crate) ctm: CharTapeMachine, pub(crate) ctm: CharTapeMachine,
section_nesting: u8, section_nesting: u8,
@ -29,7 +30,6 @@ pub struct Parser {
pub(crate) block_break_at: Vec<char>, pub(crate) block_break_at: Vec<char>,
pub(crate) inline_break_at: Vec<char>, pub(crate) inline_break_at: Vec<char>,
pub(crate) document: Document, pub(crate) document: Document,
pub(crate) reader: Box<dyn BufRead>,
pub(crate) parse_variables: bool, pub(crate) parse_variables: bool,
} }
@ -95,19 +95,11 @@ impl Parser {
if let Some(path) = path.clone() { if let Some(path) = path.clone() {
paths.lock().unwrap().push(path.clone()) paths.lock().unwrap().push(path.clone())
} }
let mut text = Vec::new(); let mut text = String::new();
let mut current_char = ' '; reader
for _ in 0..8 { .read_to_string(&mut text)
let mut buf = String::new(); .expect("Failed to read file");
if let Ok(_) = reader.read_line(&mut buf) {
text.append(&mut buf.chars().collect::<Vec<char>>());
} else {
break;
}
}
if let Some(ch) = text.get(0) {
current_char = *ch
}
let document = Document::new(!is_child); let document = Document::new(!is_child);
Self { Self {
sections: Vec::new(), sections: Vec::new(),
@ -117,11 +109,10 @@ impl Parser {
paths, paths,
wg: WaitGroup::new(), wg: WaitGroup::new(),
is_child, is_child,
ctm: CharTapeMachine::new(text), ctm: CharTapeMachine::new(text.chars().collect()),
inline_break_at: Vec::new(), inline_break_at: Vec::new(),
block_break_at: Vec::new(), block_break_at: Vec::new(),
document, document,
reader,
parse_variables: false, parse_variables: false,
} }
} }
@ -130,14 +121,6 @@ impl Parser {
self.document.config = config; 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 /// Returns the import paths of the parser
pub fn get_paths(&self) -> Vec<PathBuf> { pub fn get_paths(&self) -> Vec<PathBuf> {
self.paths.lock().unwrap().clone() self.paths.lock().unwrap().clone()

@ -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_export]
macro_rules! parse { macro_rules! parse {
($str:expr) => { ($str:expr) => {
Parser::new($str.to_string(), None).parse() Parser::new($str.to_string(), None).parse()
}; };
} }
pub type ParseResult<T> = TapeResult<T>;
pub type ParseError = TapeError;
/*
#[derive(Debug)]
pub struct ParseError {
index: usize,
message: Option<String>,
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
}
}
}
*/

Loading…
Cancel
Save