Add parsing of file regex, active regex, many and many_active functions

This commit is contained in:
Oliver Hamlet
2018-10-03 17:15:34 +01:00
parent dfb41233bd
commit abdc841c15
2 changed files with 79 additions and 17 deletions
+70 -5
View File
@@ -1,9 +1,8 @@
use std::path::{Path, PathBuf};
use std::str;
use nom::{Context, Err, ErrorKind, IResult};
use regex::Regex;
use nom::IResult;
use super::Error;
@@ -32,6 +31,12 @@ pub enum Function {
const INVALID_PATH_CHARS: &str = "\":*?<>|\\"; // \ is treated as invalid to distinguish regex strings.
const INVALID_REGEX_PATH_CHARS: &str = "\"<>";
fn parse_regex(input: &str) -> IResult<&str, Regex> {
Regex::new(input)
.map(|r| ("", r))
.map_err(|e| Err::Failure(Context::Code(input, ErrorKind::Custom(1))))
}
impl Function {
pub fn eval(&self) -> Result<bool, Error> {
// TODO: Handle all variants.
@@ -44,15 +49,27 @@ impl Function {
pub fn parse(input: &str) -> IResult<&str, Function> {
// TODO: Handle all variants.
// TODO: Paths may not contain :*?"<>|
do_parse!(
input,
function: alt!(
function:
alt!(
delimited!(tag!("file(\""), is_not!(INVALID_PATH_CHARS), tag!("\")")) => {
|path| Function::FilePath(PathBuf::from(path))
} |
delimited!(tag!("file(\""), flat_map!(is_not!(INVALID_REGEX_PATH_CHARS), parse_regex), tag!("\"")) => {
|r| Function::FileRegex(r)
} |
delimited!(tag!("active(\""), is_not!(INVALID_PATH_CHARS), tag!("\")")) => {
|path| Function::ActivePath(PathBuf::from(path))
} |
delimited!(tag!("active(\""), flat_map!(is_not!(INVALID_REGEX_PATH_CHARS), parse_regex), tag!("\"")) => {
|r| Function::ActiveRegex(r)
} |
delimited!(tag!("many(\""), flat_map!(is_not!(INVALID_REGEX_PATH_CHARS), parse_regex), tag!("\"")) => {
|r| Function::Many(r)
} |
delimited!(tag!("many_active(\""), flat_map!(is_not!(INVALID_REGEX_PATH_CHARS), parse_regex), tag!("\"")) => {
|r| Function::ManyActive(r)
}
) >> (function)
)
@@ -74,7 +91,19 @@ mod tests {
}
#[test]
fn function_parse_should_parse_an_active_function() {
fn function_parse_should_parse_a_file_regex_function() {
let result = Function::parse("file(\"Cargo.*\")").unwrap().1;
match result {
Function::FileRegex(r) => {
assert_eq!(Regex::new("Cargo.*").unwrap().as_str(), r.as_str())
}
_ => panic!("Expected a file regex function"),
}
}
#[test]
fn function_parse_should_parse_an_active_path_function() {
let result = Function::parse("active(\"Cargo.toml\")").unwrap().1;
match result {
@@ -83,6 +112,42 @@ mod tests {
}
}
#[test]
fn function_parse_should_parse_an_active_regex_function() {
let result = Function::parse("active(\"Cargo.*\")").unwrap().1;
match result {
Function::ActiveRegex(r) => {
assert_eq!(Regex::new("Cargo.*").unwrap().as_str(), r.as_str())
}
_ => panic!("Expected an active regex function"),
}
}
#[test]
fn function_parse_should_parse_a_many_function() {
let result = Function::parse("many(\"Cargo.*\")").unwrap().1;
match result {
Function::Many(r) => {
assert_eq!(Regex::new("Cargo.*").unwrap().as_str(), r.as_str())
}
_ => panic!("Expected a many function"),
}
}
#[test]
fn function_parse_should_parse_a_many_active_function() {
let result = Function::parse("many_active(\"Cargo.*\")").unwrap().1;
match result {
Function::ManyActive(r) => {
assert_eq!(Regex::new("Cargo.*").unwrap().as_str(), r.as_str())
}
_ => panic!("Expected a many active function"),
}
}
#[test]
fn function_file_path_eval_should_return_true_if_the_file_exists_relative_to_the_data_path() {
let function = Function::FilePath(PathBuf::from("Cargo.toml"));
+9 -12
View File
@@ -114,8 +114,7 @@ mod tests {
#[test]
fn expression_parse_should_handle_a_single_compound_condition() {
let result = Expression::parse("file(\"Cargo.toml\")")
.unwrap().1;
let result = Expression::parse("file(\"Cargo.toml\")").unwrap().1;
match result.0.as_slice() {
[CompoundCondition(_)] => {}
@@ -126,7 +125,8 @@ mod tests {
#[test]
fn expression_parse_should_handle_multiple_compound_conditions() {
let result = Expression::parse("file(\"Cargo.toml\") or file(\"Cargo.toml\")")
.unwrap().1;
.unwrap()
.1;
match result.0.as_slice() {
[CompoundCondition(_), CompoundCondition(_)] => {}
@@ -139,8 +139,7 @@ mod tests {
#[test]
fn compound_condition_parse_should_handle_a_single_condition() {
let result = CompoundCondition::parse("file(\"Cargo.toml\")")
.unwrap().1;
let result = CompoundCondition::parse("file(\"Cargo.toml\")").unwrap().1;
match result.0.as_slice() {
[Condition::Function(Function::FilePath(f))] => {
@@ -156,7 +155,8 @@ mod tests {
#[test]
fn compound_condition_parse_should_handle_multiple_conditions() {
let result = CompoundCondition::parse("file(\"Cargo.toml\") and file(\"README.md\")")
.unwrap().1;
.unwrap()
.1;
match result.0.as_slice() {
[Condition::Function(Function::FilePath(f1)), Condition::Function(Function::FilePath(f2))] =>
@@ -173,8 +173,7 @@ mod tests {
#[test]
fn condition_parse_should_handle_a_function() {
let result = Condition::parse("file(\"Cargo.toml\")")
.unwrap().1;
let result = Condition::parse("file(\"Cargo.toml\")").unwrap().1;
match result {
Condition::Function(Function::FilePath(f)) => {
@@ -189,8 +188,7 @@ mod tests {
#[test]
fn condition_parse_should_handle_a_inverted_function() {
let result = Condition::parse("not file(\"Cargo.toml\")")
.unwrap().1;
let result = Condition::parse("not file(\"Cargo.toml\")").unwrap().1;
match result {
Condition::InvertedFunction(Function::FilePath(f)) => {
@@ -205,8 +203,7 @@ mod tests {
#[test]
fn condition_parse_should_handle_an_expression_in_parentheses() {
let result = Condition::parse("(not file(\"Cargo.toml\"))")
.unwrap().1;
let result = Condition::parse("(not file(\"Cargo.toml\"))").unwrap().1;
match result {
Condition::Expression(_) => {}