Skip to content

Commit

Permalink
Add a Block enum type which will eventually represent all possible bl…
Browse files Browse the repository at this point in the history
…ock types in AsciiDoc (#13)
  • Loading branch information
scouten authored Dec 27, 2023
1 parent 63b90de commit 60c094d
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 3 deletions.
35 changes: 35 additions & 0 deletions src/blocks/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use nom::IResult;

use super::SimpleBlock;
use crate::{primitives::consume_empty_lines, Span};

/// Block elements form the main structure of an AsciiDoc document, starting
/// with the document itself.
///
/// A block element (aka block) is a discrete, line-oriented chunk of content in
/// an AsciiDoc document. Once parsed, that chunk of content becomes a block
/// element in the parsed document model. Certain blocks may contain other
/// blocks, so we say that blocks can be nested. The converter visits each block
/// in turn, in document order, converting it to a corresponding chunk of
/// output.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Block<'a> {
/// A block that’s treated as contiguous lines of paragraph text (and
/// subject to normal substitutions) (e.g., a paragraph block).
Simple(SimpleBlock<'a>),
}

impl<'a> Block<'a> {
#[allow(dead_code)]
/// Parse a block of any type and return a `Block` that describes it.
///
/// Consumes any blank lines before and after the block.
pub(crate) fn parse(i: Span<'a>) -> IResult<Span, Self> {
let i = consume_empty_lines(i);

// TEMPORARY: So far, we only know SimpleBlock.
// Later we'll start to try to discern other block types.
let (rem, simple_block) = SimpleBlock::parse(i)?;
Ok((rem, Self::Simple(simple_block)))
}
}
6 changes: 5 additions & 1 deletion src/blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@
//! in turn, in document order, converting it to a corresponding chunk of
//! output.
pub(crate) mod simple;
mod block;
pub use block::Block;

mod simple;
pub use simple::SimpleBlock;
95 changes: 95 additions & 0 deletions src/tests/blocks/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
mod simple {
use nom::{
error::{Error, ErrorKind},
Err,
};

use crate::{
blocks::{Block, SimpleBlock},
Span,
};

#[test]
fn empty_source() {
let expected_err = Err::Error(Error::new(Span::new("", true), ErrorKind::TakeTill1));

let actual_err = Block::parse(Span::new("", true)).unwrap_err();

assert_eq!(expected_err, actual_err);
}

#[test]
fn only_spaces() {
let err = Block::parse(Span::new(" ", true)).unwrap_err();

let Err::Error(e) = err else {
panic!("Expected Err::Error: {err:#?}");
};

assert_eq!(e.code, ErrorKind::TakeTill1);

let span = e.input;
assert_eq!(span.data(), &"");
assert_eq!(span.line(), 1);
assert_eq!(span.col(), 5);
}

#[test]
fn single_line() {
let expected = Block::Simple(SimpleBlock {
inlines: vec![Span::new("abc", true)],
});

let (rem, block) = Block::parse(Span::new("abc", true)).unwrap();

assert_eq!(rem.line(), 1);
assert_eq!(rem.col(), 4);
assert_eq!(*rem.data(), "");

assert_eq!(block, expected);
}

#[test]
fn multiple_lines() {
let (rem, block) = Block::parse(Span::new("abc\ndef", true)).unwrap();

assert_eq!(rem.line(), 2);
assert_eq!(rem.col(), 4);
assert_eq!(*rem.data(), "");

let Block::Simple(block) = block;
// else { // ADD THIS ONCE WE HAVE OTHER BLOCK TYPES
//panic!("Expected a SimpleBlock: {block:#?}");
//};

assert_eq!(block.inlines.len(), 2);

assert_eq!(block.inlines[0].line(), 1);
assert_eq!(block.inlines[0].col(), 1);
assert_eq!(*block.inlines[0].data(), "abc");

assert_eq!(block.inlines[1].line(), 2);
assert_eq!(block.inlines[1].col(), 1);
assert_eq!(*block.inlines[1].data(), "def");
}

#[test]
fn consumes_blank_lines_after() {
let expected = SimpleBlock {
inlines: vec![Span::new("abc", true)],
};

let (rem, block) = Block::parse(Span::new("abc\n\ndef", true)).unwrap();

assert_eq!(rem.line(), 3);
assert_eq!(rem.col(), 1);
assert_eq!(*rem.data(), "def");

let Block::Simple(block) = block;
// else { // ADD THIS ONCE WE HAVE OTHER BLOCK TYPES
//panic!("Expected a SimpleBlock: {block:#?}");
//};

assert_eq!(block, expected);
}
}
3 changes: 2 additions & 1 deletion src/tests/blocks/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub(crate) mod simple;
mod block;
mod simple;
2 changes: 1 addition & 1 deletion src/tests/blocks/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use nom::{
Err,
};

use crate::{blocks::simple::SimpleBlock, Span};
use crate::{blocks::SimpleBlock, Span};

#[test]
fn empty_source() {
Expand Down

0 comments on commit 60c094d

Please sign in to comment.