use super::*;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Nonprim {
Tuple,
Cntr,
Seq,
Map,
None,
}
pub fn pattern_match_delimited<'a, E: ParseError<&'a str>>(
orig: &'a str,
) -> IResult<&'a str, Nonprim, E> {
#[derive(PartialEq)]
enum Ident {
Prim,
Nonprim,
None,
};
let (i, ident_) = opt(ident(true))(orig)?;
let (i, ident_) = if ident_.is_some() {
(i, Ident::Prim)
} else {
let (i, ident__) = opt(ident(false))(orig)?;
if ident__.is_some() {
(i, Ident::Nonprim)
} else {
(orig, Ident::None)
}
};
let (i, _) = multiline_whitespace(i)?;
let next = i.chars().next().unwrap_or(' ');
let mut r = if next == '[' {
Nonprim::Seq
} else if next == '{' {
Nonprim::Map
} else if next == '(' {
if (ident_ == Ident::None || ident_ == Ident::Prim) && unit_value::<E>(i).is_ok() {
Nonprim::None
} else if recognise_field_assign(multiline_whitespace(&i[1..])?.0) {
Nonprim::Cntr
} else {
Nonprim::Tuple
}
} else {
Nonprim::None
};
if r != Nonprim::None && ident_ == Ident::Prim {
r = Nonprim::None;
}
Ok((orig, r))
}
pub fn pattern_match_verbose<'a, E: ParseError<&'a str>>(
orig: &'a str,
) -> IResult<&'a str, bool, E> {
let (i, _) = multiline_whitespace(orig)?;
let is = recognise_field_assign(i);
let is = is
|| preceded::<_, _, _, (), _, _>(
char('['),
terminated(
ignore_inline_whitespace(valid_name),
ignore_inline_whitespace(char(']')),
),
)(i)
.is_ok();
let is = is
|| preceded::<_, _, _, (), _, _>(
tag("[["),
terminated(
ignore_inline_whitespace(valid_name),
ignore_inline_whitespace(tag("]]")),
),
)(i)
.is_ok();
Ok((orig, is))
}
pub fn recognise_concise(i: &str) -> bool {
const SKIP: &str = " \t\r";
i.chars()
.skip_while(|&c| SKIP.contains(c))
.next()
.map(|c| c == '\n')
.unwrap_or(false)
}
pub fn recognise_field_assign(i: &str) -> bool {
preceded::<_, _, _, (), _, _>(field_name, terminated(inline_whitespace, char('=')))(i).is_ok()
}
#[cfg(test)]
mod tests {
use super::*;
use nom::error::VerboseError;
macro_rules! test {
( $ex:expr, $($x:literal ),* ) => {{
$(
let r = pattern_match_delimited::<VerboseError<_>>($x);
assert_eq!(r, Ok(($x, $ex)));
)*
}};
}
#[test]
fn test_pat_match_none() {
test!(
Nonprim::None,
"123456",
"-123456",
"-3.14e-314",
"()",
"a = 123",
r#""Hello, world!""#,
"true",
"false",
"b91':C!WEH#L4R'"
);
}
#[test]
fn test_pat_match_seq() {
test!(
Nonprim::Seq,
"[1,2,3]",
"[\n1,2,3\n]",
"Hello [1,2,3]",
"Hello [\n1,2,3\n]",
"Hello[1,2,3]",
"Hello[\n1,2,3\n]"
);
}
#[test]
fn test_pat_match_map() {
test!(
Nonprim::Map,
"{1:2, 3:4, 5:6}",
"{\n1:2\n3:4\n5:6\n}",
"Hello {1:2, 3:4, 5:6}",
"Hello {\n1:2\n3:4\n5:6\n}",
"Hello{1:2, 3:4, 5:6}",
"Hello{\n1:2\n3:4\n5:6\n}"
);
}
#[test]
fn test_pat_match_tuple() {
test!(
Nonprim::Tuple,
"(1,2,3)",
"(\n1,2,3\n)",
"Hello (1,2,3)",
"Hello (\n1,2,3\n)",
"Hello(1,2,3)",
"Hello(\n1,2,3\n)"
);
}
#[test]
fn test_pat_match_cntr() {
test!(
Nonprim::Cntr,
"(a=1, 2, 3)",
"(\na = 1,2,3\n)",
"Hello (a = 1,2,3)",
"Hello (\na=1,2,3\n)",
"Hello(_a=1,2,3)",
"Hello(\na \t\t\t =1,2,3\n)"
);
}
}