Add code block parsing

pull/1/head
trivernis 5 years ago
parent 110109c882
commit 2204f93cf3

@ -4,6 +4,7 @@ pub enum Block {
Paragraph(Paragraph), Paragraph(Paragraph),
List(List), List(List),
Table(Table), Table(Table),
CodeBlock(CodeBlock),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -69,8 +70,8 @@ pub struct Cell {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CodeBlock { pub struct CodeBlock {
language: String, pub(crate) language: String,
code: String, pub(crate) code: String,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

@ -120,10 +120,36 @@ impl Parser {
chars.contains(&self.current_char) && !self.check_escaped() chars.contains(&self.current_char) && !self.check_escaped()
} }
/// returns if the current character is a linebreak character
/// Note: No one likes CRLF
pub fn check_linebreak(&self) -> bool { pub fn check_linebreak(&self) -> bool {
self.current_char == LB && !self.check_escaped() self.current_char == LB && !self.check_escaped()
} }
/// checks if the next characters match a special sequence
pub fn check_special_sequence(&mut self, sequence: &[char]) -> Result<(), ParseError> {
let start_index = self.index;
self.seek_whitespace();
for sq_character in sequence {
if !self.check_special(sq_character) {
let err = ParseError::new(self.index);
self.revert_to(start_index)?;
// should work
return Err(err);
}
if self.next_char() == None {
let err = ParseError::new(self.index);
self.revert_to(start_index)?;
return Err(err);
}
}
if self.index > 0 {
self.revert_to(self.index - 1)?;
}
Ok(())
}
/// parses the given text into a document /// parses the given text into a document
pub fn parse(&mut self) -> Document { pub fn parse(&mut self) -> Document {
let mut document = Document::new(); let mut document = Document::new();
@ -153,6 +179,8 @@ impl Parser {
Block::List(list) Block::List(list)
} else if let Ok(table) = self.parse_table() { } else if let Ok(table) = self.parse_table() {
Block::Table(table) Block::Table(table)
} else if let Ok(code_block) = self.parse_code_block() {
Block::CodeBlock(code_block)
} else if let Ok(paragraph) = self.parse_paragraph() { } else if let Ok(paragraph) = self.parse_paragraph() {
Block::Paragraph(paragraph) Block::Paragraph(paragraph)
} else { } else {
@ -202,6 +230,7 @@ impl Parser {
} }
} }
/// parses the header of a section
fn parse_header(&mut self) -> Result<Header, ParseError> { fn parse_header(&mut self) -> Result<Header, ParseError> {
Ok(Header { Ok(Header {
size: 0, size: 0,
@ -209,6 +238,30 @@ impl Parser {
}) })
} }
/// parses a code block
fn parse_code_block(&mut self) -> Result<CodeBlock, ParseError> {
let mut language = String::new();
self.check_special_sequence(&SQ_CODE_BLOCK)?;
while let Some(character) = self.next_char() {
if self.check_linebreak() {
break;
}
language.push(character);
}
let mut text = String::new();
while let Some(character) = self.next_char() {
if let Ok(_) = self.check_special_sequence(&SQ_CODE_BLOCK) {
break;
}
text.push(character);
}
Ok(CodeBlock {
language,
code: text,
})
}
/// Parses a paragraph /// Parses a paragraph
fn parse_paragraph(&mut self) -> Result<Paragraph, ParseError> { fn parse_paragraph(&mut self) -> Result<Paragraph, ParseError> {
let mut paragraph = Paragraph::new(); let mut paragraph = Paragraph::new();

@ -27,3 +27,7 @@ pub(crate) const BLOCK_SPECIAL_CHARS: [char; 4] = [HASH, MINUS, BACKTICK, PIPE];
pub(crate) const INLINE_SPECIAL_CHARS: [char; 6] = [LB, ASTERISK, UNDERSCR, TILDE, PIPE, BACKTICK]; pub(crate) const INLINE_SPECIAL_CHARS: [char; 6] = [LB, ASTERISK, UNDERSCR, TILDE, PIPE, BACKTICK];
pub(crate) const LIST_SPECIAL_CHARS: [char; 4] = [MINUS, PLUS, ASTERISK, O]; pub(crate) const LIST_SPECIAL_CHARS: [char; 4] = [MINUS, PLUS, ASTERISK, O];
// sequences
pub(crate) const SQ_CODE_BLOCK: [char; 3] = [BACKTICK, BACKTICK, BACKTICK];

Loading…
Cancel
Save