From 06e7d81088e33d7ee03e7088e1ec2289e9c2bf5c Mon Sep 17 00:00:00 2001 From: Philipp A Date: Fri, 3 Jan 2020 16:43:21 +0100 Subject: Added code block directive --- parser/Cargo.toml | 2 +- parser/src/conversion/block.rs | 19 +++++++++++++++++++ parser/src/rst.pest | 32 +++++++++++++------------------- parser/src/tests.rs | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 20 deletions(-) (limited to 'parser') diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 997cc35..a423fbe 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'rst_parser' -version = '0.3.0' +version = '0.3.1' authors = ['Philipp A. '] edition = '2018' description = 'a reStructuredText parser' diff --git a/parser/src/conversion/block.rs b/parser/src/conversion/block.rs index ab18c48..64aa33e 100644 --- a/parser/src/conversion/block.rs +++ b/parser/src/conversion/block.rs @@ -53,6 +53,7 @@ fn convert_body_elem(pair: Pair) -> Result { Rule::admonition_gen => convert_admonition_gen(pair)?.into(), Rule::image => convert_image::(pair)?.into(), Rule::bullet_list => convert_bullet_list(pair)?.into(), + Rule::code_directive => convert_code_directive(pair)?.into(), rule => unimplemented!("unhandled rule {:?}", rule), }) } @@ -200,3 +201,21 @@ fn convert_bullet_item(pair: Pair) -> Result { } Ok(e::ListItem::with_children(children)) } + +fn convert_code_directive(pair: Pair) -> Result { + let mut iter = pair.into_inner(); + let (lang, code) = match (iter.next().unwrap(), iter.next()) { + (lang, Some(code)) => (Some(lang), code), + (code, None) => (None, code), + }; + let children = code.into_inner().map(|l| match l.as_rule() { + Rule::code_line => l.as_str(), + Rule::code_line_blank => "\n", + _ => unreachable!(), + }.into()).collect(); + let mut code_block = e::LiteralBlock::with_children(children); + if let Some(lang) = lang { + code_block.classes_mut().push(lang.as_str().to_owned()); + }; + Ok(code_block) +} diff --git a/parser/src/rst.pest b/parser/src/rst.pest index f3a1516..18708c2 100644 --- a/parser/src/rst.pest +++ b/parser/src/rst.pest @@ -15,6 +15,7 @@ block = _{ PEEK[..] ~ hanging_block } hanging_block = _{ substitution_def | image_directive + | code_directive | admonition | admonition_gen | target @@ -24,17 +25,10 @@ hanging_block = _{ // TODO: implement all those things: // | block_quote // | verbatim -// | image ✓ -// | code_block // | doctest_block -// | admonition ✓ -// | target ✓ // | horizontal_rule -// | title ✓ // | table // | ordered_list -// | bullet_list ✓ -// | paragraph ✓ // | plain } @@ -86,9 +80,20 @@ image_opt_block = _{ PEEK[..-1] ~ PUSH(" " ~ POP) ~ image_option } //TODO: merg image_option = { ":" ~ image_opt_name ~ ":" ~ line } image_opt_name = { common_opt_name | "alt" | "height" | "width" | "scale" | "align" | "target" } +// Code block. A directive + +code_directive = { + ".." ~ PUSH(" "+) ~ "code" ~ "-block"? ~ "::" ~ (" "+ ~ source)? ~ NEWLINE ~ + blank_line+ ~ PEEK[..-1] ~ PUSH(" " ~ POP) ~ code_block ~ DROP +} +source = { (!NEWLINE ~ ANY)+ } +code_block = { code_line ~ (code_line_blank* ~ PEEK[..] ~ code_line)* } +code_line_blank = { " "* ~ NEWLINE } +code_line = { (!NEWLINE ~ ANY)+ ~ NEWLINE } + // Admonition. A directive. The generic one has a title -admonition = { ".." ~ PUSH(" "+) ~ ^"admonition::" ~ line ~ blank_line* ~ admonition_content? ~ DROP } +admonition = { ".." ~ PUSH(" "+) ~ ^"admonition::" ~ line ~ blank_line* ~ admonition_content? ~ DROP } admonition_gen = { ".." ~ PUSH(" "+) ~ admonition_type ~ "::" ~ (blank_line | line) ~ blank_line* ~ admonition_content? ~ DROP } admonition_type = { ^"attention" | ^"caution" | ^"danger" | ^"error" | ^"hint" | ^"important" | ^"note" | ^"tip" | ^"warning" } admonition_content = _{ PEEK[..-1] ~ PUSH(" " ~ POP) ~ hanging_block ~ block* } //TODO: merge with other directives? @@ -272,11 +277,6 @@ marker = _{ (bullet_marker | "..") ~ " " } -// code_block = { -// ".. code" ~ "-block"? ~ ":: " ~ source ~ blank_line ~ -// NEWLINE ~ verbatim_chunk+ -// } - // doctest_block = { (doctest_line+ ~ (!(">" | blank_line) ~ line)*)+ } // block_quote_raw = { ":" ~ blank_line ~ NEWLINE ~ nonblank_indented_line+ } @@ -290,12 +290,6 @@ marker = _{ (bullet_marker | "..") ~ " " } // block_quote = { block_quote_chunk+ } -// nonblank_indented_line = { !blank_line ~ indented_line } - -// verbatim_chunk = { blank_line* ~ nonblank_indented_line+ } - -// verbatim = { verbatim_chunk+ } - // horizontal_rule = { // ( "=" ~ sp ~ "=" ~ sp ~ "=" ~ (sp ~ "=")* // | "-" ~ sp ~ "-" ~ sp ~ "-" ~ (sp ~ "-")* diff --git a/parser/src/tests.rs b/parser/src/tests.rs index 1ef965a..b4da633 100644 --- a/parser/src/tests.rs +++ b/parser/src/tests.rs @@ -136,6 +136,41 @@ fn admonitions() { }; } +#[allow(clippy::cognitive_complexity)] +#[test] +fn code() { + parses_to! { + parser: RstParser, + input: "\ +.. code:: + + Single line + +.. code-block:: python + + print('x') + + # second line + +The end +", + rule: Rule::document, + tokens: [ + code_directive(0, 26, [ + code_block(14, 26, [ code_line(14, 26) ]), + ]), + code_directive(27, 83, [ + source(43, 49), + code_block(54, 83, [ + code_line(54, 65), + code_line_blank(65, 66), + code_line(69, 83), + ]), + ]), + paragraph(84, 91, [ str(84, 91) ]), + ] + }; +} #[allow(clippy::cognitive_complexity)] #[test] -- cgit v1.2.3