Almost working implementation for brackets, stuck on last test

This commit is contained in:
Mathieu David 2016-08-01 19:52:24 +02:00
parent 50bf00c167
commit 8ff39850a9
2 changed files with 66 additions and 5 deletions

View File

@ -19,7 +19,7 @@ clap = "2.2.1"
handlebars = "0.20.0" handlebars = "0.20.0"
rustc-serialize = "0.3.18" rustc-serialize = "0.3.18"
pulldown-cmark = "0.0.8" pulldown-cmark = "0.0.8"
nom = "1.2.3" nom = "1.2.4"
# Watch feature # Watch feature
notify = { version = "2.5.5", optional = true } notify = { version = "2.5.5", optional = true }

View File

@ -1,4 +1,4 @@
use nom::{self, IResult, alphanumeric}; use nom::{self, IResult};
use std::str; use std::str;
use std::str::FromStr; use std::str::FromStr;
@ -15,6 +15,7 @@ fn link(i: &[u8]) -> IResult<&[u8], Link> {
} }
/// Parser for parsing the title part of the link: [title](destination) /// Parser for parsing the title part of the link: [title](destination)
/// ^^^^^^^
/// ///
/// From the Common Mark spec (http://spec.commonmark.org/0.26/#links): /// From the Common Mark spec (http://spec.commonmark.org/0.26/#links):
/// ///
@ -22,9 +23,42 @@ fn link(i: &[u8]) -> IResult<&[u8], Link> {
/// (a) they are backslash-escaped or /// (a) they are backslash-escaped or
/// (b) they appear as a matched pair of brackets, /// (b) they appear as a matched pair of brackets,
/// with an open bracket [, a sequence of zero or more inlines, and a close bracket ]. /// with an open bracket [, a sequence of zero or more inlines, and a close bracket ].
/// ^^^^^^^ ///
fn link_text(i: &[u8]) -> IResult<&[u8], String> { fn link_text(i: &[u8]) -> IResult<&[u8], String> {
map_res!(i, map_res!(delimited!(char!('['), is_not!("[]"), char!(']')), str::from_utf8), FromStr::from_str) map_res!(i,
map_res!(
delimited!(
// Begin with '['
char!('['),
// Followed by anything that is not '[' or ']'
// Make sure to allow escaped brackets and balanced brackets
recognize!(many1!(alt!(not_unescaped_bracket | balanced_brackets))),
// End with ']'
char!(']')
),
str::from_utf8
),
FromStr::from_str
)
}
#[cfg_attr(rustfmt, rustfmt_skip)]
fn balanced_brackets(i: &[u8]) -> IResult<&[u8], &[u8]> {
recognize!(i,
delimited!(
// Begin with '['
char!('['),
// Followed by anything that is not '[' or ']'
// Make sure to allow escaped brackets and balanced brackets
many0!(alt!(not_unescaped_bracket | balanced_brackets)),
// End with ']'
char!(']')
)
)
}
fn not_unescaped_bracket(i: &[u8]) -> IResult<&[u8], &[u8]> {
escaped!(i, is_not!("\\[]"), '\\', is_a_bytes!(&b"[]"[..]))
} }
/// Parser for parsing the destination part of the link: [title](destination) /// Parser for parsing the destination part of the link: [title](destination)
@ -37,6 +71,33 @@ fn link_destination(i: &[u8]) -> IResult<&[u8], String> {
mod tests { mod tests {
use nom::{self, IResult}; use nom::{self, IResult};
use nom::Err::{NodePosition, Position};
use nom::ErrorKind::Escaped;
// Tests not_unescaped_bracket
#[test]
fn not_unescaped_bracket() {
assert_eq!(super::not_unescaped_bracket(b"a"), IResult::Done(&b""[..], &b"a"[..]));
assert_eq!(super::not_unescaped_bracket(b"-"), IResult::Done(&b""[..], &b"-"[..]));
assert_eq!(super::not_unescaped_bracket(b"\\["), IResult::Done(&b""[..], &b"\\["[..]));
assert_eq!(super::not_unescaped_bracket(b"]"), IResult::Error(NodePosition(Escaped, &[93][..], Box::new(Position(Escaped, &[93][..])))));
}
// Tests for balanced brackets
#[test]
fn balanced_brackets() {
assert_eq!(super::balanced_brackets(b"[a]"), nom::IResult::Done(&b""[..], &b"[a]"[..]));
}
#[test]
fn balanced_brackets_empty() {
assert_eq!(super::balanced_brackets(b"[]"), nom::IResult::Done(&b""[..], &b"[]"[..]));
}
#[test]
fn balanced_brackets_nested() {
assert_eq!(super::balanced_brackets(b"[abc[a]]"), nom::IResult::Done(&b""[..], &b"[abc[a]]"[..]));
}
// Tests for link_text // Tests for link_text
@ -66,6 +127,6 @@ mod tests {
#[test] #[test]
fn link_text_brackets() { fn link_text_brackets() {
assert_eq!(super::link_text(b"[Intro[]]"), nom::IResult::Done(&b""[..], String::from("Intro[]"))); assert_eq!(super::link_text(b"[Intro[]]"), nom::IResult::Done(&b""[..], String::from("Intro[]")));
assert_eq!(super::link_text(br"[Intro\[]"), nom::IResult::Done(&b""[..], String::from("Intro["))); assert_eq!(super::link_text(br"[Intro\]]"), nom::IResult::Done(&b""[..], String::from("Intro[")));
} }
} }