use crate::parser;
use crate::test_util::compare;
use super::expand_macros;
#[test]
fn test_comma() {
let grammar = parser::parse_grammar(
r#"
grammar;
Comma<E>: Vec<E> =
<v:(<E> ",")*> <e:E?> =>
v.into_iter().chain(e.into_iter()).collect();
Ids = Comma<"Id">;
"#,
)
.unwrap();
let actual = expand_macros(grammar, 20).unwrap();
let expected = parser::parse_grammar(
r##"
grammar;
Ids = `Comma<"Id">`;
`Comma<"Id">`: Vec<#"Id"#> =
<v:`(<"Id"> ",")*`> <e:`"Id"?`> => v.into_iter().chain(e.into_iter()).collect();
#[inline]
`"Id"?`: Option<#"Id"#> = {
"Id" => Some(<>),
=> None
};
#[inline]
`(<"Id"> ",")*`: alloc::vec::Vec<#`(<"Id"> ",")`#> = {
=> alloc::vec![],
<v:`(<"Id"> ",")+`> => v,
};
#[inline]
`(<"Id"> ",")`: #"Id"# = {
<"Id"> "," => <>,
};
`(<"Id"> ",")+`: alloc::vec::Vec<#`(<"Id"> ",")`#> = {
`(<"Id"> ",")` => alloc::vec![<>],
<v:`(<"Id"> ",")+`> <e:`(<"Id"> ",")`> => { let mut v = v; v.push(e); v },
};
"##,
)
.unwrap();
compare(actual, expected);
}
#[test]
fn test_if_match() {
let grammar = parser::parse_grammar(
r#"
grammar;
Expr<E> = {
"A" if E == "A*C",
"B" if E ~~ "^A*C$",
"C" if E != "A*C",
"D" if E !~ "^A*C$"
};
Expr1 = Expr<"A*C">;
Expr2 = Expr<"AAC">;
Expr3 = Expr<"ABC">;
"#,
)
.unwrap();
let actual = expand_macros(grammar, 20).unwrap();
let expected = parser::parse_grammar(
r#"
grammar;
Expr1 = `Expr<"A*C">`;
Expr2 = `Expr<"AAC">`;
Expr3 = `Expr<"ABC">`;
`Expr<"ABC">` = { "C", "D" };
`Expr<"AAC">` = { "B", "C" };
`Expr<"A*C">` = { "A", "D" };
"#,
)
.unwrap();
compare(actual, expected);
}
#[test]
fn test_lookahead() {
let grammar = parser::parse_grammar(
r#"
grammar;
Expr = @L;
"#,
)
.unwrap();
let actual = expand_macros(grammar, 20).unwrap();
let expected = parser::parse_grammar(
r#"
grammar;
Expr = `@L`;
#[inline] `@L` = =>@L;
"#,
)
.unwrap();
compare(actual, expected);
}
#[test]
fn test_excessive_recursion() {
let grammar = parser::parse_grammar(
r#"
grammar;
A<I> = { "x" I "y" I "z", A<("." I)> }
pub P = A<()>;
"#,
)
.unwrap();
assert!(expand_macros(grammar, 20).is_err());
let grammar2 = parser::parse_grammar(
r#"
grammar;
A<I> = { "a" B<("." I)> };
B<I> = { "b" C<("," I)> };
C<I> = { "c" I };
pub D = A<"d"> B<"d"> C<"d">;
"#,
)
.unwrap();
assert!(expand_macros(grammar2.clone(), 2).is_err());
assert!(expand_macros(grammar2, 3).is_ok());
}