blob: 10c888ed7a0e67a2705644992801f961fecad88b [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2024 Boeing
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Boeing - initial API and implementation
**********************************************************************/
use applicability::applic_tag::ApplicabilityTagTypes;
use applicability_parser_types::{
applic_tokens::ApplicTokens,
applicability_parser_syntax_tag::{
ApplicabilityParserSyntaxTag, ApplicabilitySyntaxTag, ApplicabilitySyntaxTagNot,
},
};
use nom::{
branch::alt,
character::complete::line_ending,
combinator::{map, opt},
multi::many0,
sequence::tuple,
IResult,
};
use crate::tag_parser::applicability_tag;
use super::{
config_text::{
else_config_text_parser, end_config_text_parser, not_config_text_parser,
start_config_text_parser,
},
end::end_tag_parser,
next::next_inner,
};
///
/// Parse End:
/// End Configuration
/// Line Ending
fn parse_end<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
) -> impl FnMut(
&'a str,
) -> IResult<
&str,
(
&str,
Vec<ApplicabilityParserSyntaxTag>,
(Option<&str>, Option<&str>),
),
> {
map(
tuple((
opt(end_config_parser(
custom_start_comment_syntax,
custom_end_comment_syntax,
)),
opt(line_ending),
)),
|s: (Option<&str>, Option<&str>)| (s.1.unwrap_or(""), vec![], s),
)
}
fn config_tag_parser<'a>(
starting_parser: impl FnMut(&'a str) -> IResult<&str, &str>,
custom_end_comment_syntax: &'a str,
) -> impl FnMut(&'a str) -> IResult<&'a str, Vec<ApplicTokens>> {
applicability_tag(starting_parser, end_tag_parser(custom_end_comment_syntax))
}
fn config_contents_parser<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
starting_parser: impl FnMut(&'a str) -> IResult<&str, &str>,
) -> impl FnMut(
&'a str,
) -> IResult<
&'a str,
(
Vec<ApplicTokens>,
Option<&str>,
Vec<ApplicabilityParserSyntaxTag>,
),
> {
let tag_parser = config_tag_parser(starting_parser, custom_end_comment_syntax);
let content_parser = parse_config_inner(custom_start_comment_syntax, custom_end_comment_syntax);
tuple((tag_parser, opt(line_ending), content_parser))
}
///
/// "Configuration Else"
/// Configuration Inner
/// Parse End
/// alt((Parse Else, Parse End))
fn else_parser<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
) -> impl FnMut(
&'a str,
) -> IResult<
&'a str,
(
&str,
Vec<ApplicabilityParserSyntaxTag>,
(Option<&str>, Option<&str>),
),
> {
let end_parser = tuple((
opt(end_config_parser(
custom_start_comment_syntax,
custom_end_comment_syntax,
)),
opt(line_ending),
));
tuple((
else_config_parser(custom_start_comment_syntax, custom_end_comment_syntax),
parse_config_inner(custom_start_comment_syntax, custom_end_comment_syntax),
//note the following parser is equivalent to parse_end...just not using parse_end to not cause type explosion
end_parser,
))
}
fn config_parser<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
starting_parser: impl FnMut(&'a str) -> IResult<&str, &str>,
) -> impl FnMut(
&'a str,
) -> IResult<
&'a str,
(
(
Vec<ApplicTokens>,
Option<&str>,
Vec<ApplicabilityParserSyntaxTag>,
),
(
&'a str,
Vec<ApplicabilityParserSyntaxTag>,
(Option<&str>, Option<&str>),
),
),
> {
let parse_else_or_end = alt((
else_parser(custom_start_comment_syntax, custom_end_comment_syntax),
parse_end(custom_start_comment_syntax, custom_end_comment_syntax),
));
tuple((
config_contents_parser(
custom_start_comment_syntax,
custom_end_comment_syntax,
starting_parser,
),
parse_else_or_end,
))
}
pub fn parse_config<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
) -> impl FnMut(&'a str) -> IResult<&'a str, ApplicabilityParserSyntaxTag> {
let combined_parser = config_parser(
custom_start_comment_syntax,
custom_end_comment_syntax,
start_config_text_parser(custom_start_comment_syntax),
);
map(
combined_parser,
|(
(tokens, _ln1, contents),
(_potential_else, else_contents, (_potential_end1, _potential_end2)),
)| {
ApplicabilityParserSyntaxTag::Tag(ApplicabilitySyntaxTag(
tokens,
contents,
ApplicabilityTagTypes::Configuration,
else_contents,
))
},
)
}
#[cfg(test)]
mod parse_config_tests {
use applicability::applic_tag::{ApplicabilityTag, ApplicabilityTagTypes};
use applicability_parser_types::{
applic_tokens::{
ApplicTokens, ApplicabilityAndTag, ApplicabilityNoTag, ApplicabilityOrTag,
},
applicability_parser_syntax_tag::{ApplicabilityParserSyntaxTag, ApplicabilitySyntaxTag},
};
use super::parse_config;
#[test]
fn simple_config() {
let mut parser = parse_config("``", "``");
assert_eq!(
parser("`` Configuration[SOMETHING] \n Some Text Here \n`` End Configuration ``"),
Ok((
"",
ApplicabilityParserSyntaxTag::Tag(ApplicabilitySyntaxTag(
vec![ApplicTokens::NoTag(ApplicabilityNoTag(ApplicabilityTag {
tag: "SOMETHING".to_string(),
value: "Included".to_string()
}))],
vec![ApplicabilityParserSyntaxTag::Text(
"Some Text Here \n".to_string()
),],
ApplicabilityTagTypes::Configuration,
vec![]
))
))
)
}
#[test]
fn anded_config() {
let mut parser = parse_config("``", "``");
assert_eq!(
parser("`` Configuration[SOMETHING & SOMETHING_ELSE] \n Some Text Here \n`` End Configuration ``"),
Ok((
"",
ApplicabilityParserSyntaxTag::Tag(ApplicabilitySyntaxTag(
vec![ApplicTokens::NoTag(ApplicabilityNoTag(ApplicabilityTag {
tag: "SOMETHING".to_string(),
value: "Included".to_string()
})),
ApplicTokens::And(ApplicabilityAndTag(ApplicabilityTag {
tag: "SOMETHING_ELSE".to_string(),
value: "Included".to_string()
}))],
vec![ApplicabilityParserSyntaxTag::Text("Some Text Here \n".to_string()),],
ApplicabilityTagTypes::Configuration,
vec![]
))
))
)
}
#[test]
fn ored_config() {
let mut parser = parse_config("``", "``");
assert_eq!(
parser("`` Configuration[SOMETHING | SOMETHING_ELSE] \n Some Text Here \n`` End Configuration ``"),
Ok((
"",
ApplicabilityParserSyntaxTag::Tag(ApplicabilitySyntaxTag(
vec![ApplicTokens::NoTag(ApplicabilityNoTag(ApplicabilityTag {
tag: "SOMETHING".to_string(),
value: "Included".to_string()
})),
ApplicTokens::Or(ApplicabilityOrTag(ApplicabilityTag {
tag: "SOMETHING_ELSE".to_string(),
value: "Included".to_string()
}))],
vec![ApplicabilityParserSyntaxTag::Text("Some Text Here \n".to_string()),],
ApplicabilityTagTypes::Configuration,
vec![]
))
))
)
}
}
pub fn parse_config_not<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
) -> impl FnMut(&'a str) -> IResult<&'a str, ApplicabilityParserSyntaxTag> {
let combined_parser = config_parser(
custom_start_comment_syntax,
custom_end_comment_syntax,
not_config_text_parser(custom_start_comment_syntax),
);
map(
combined_parser,
|(
(tokens, _ln1, contents),
(_potential_else, else_contents, (_potential_end1, _potential_end2)),
)| {
ApplicabilityParserSyntaxTag::TagNot(ApplicabilitySyntaxTagNot(
tokens,
contents,
ApplicabilityTagTypes::Configuration,
else_contents,
))
},
)
}
#[cfg(test)]
mod parse_config_not_tests {
use applicability::applic_tag::{ApplicabilityTag, ApplicabilityTagTypes};
use applicability_parser_types::{
applic_tokens::{
ApplicTokens, ApplicabilityAndTag, ApplicabilityNoTag, ApplicabilityOrTag,
},
applicability_parser_syntax_tag::{
ApplicabilityParserSyntaxTag, ApplicabilitySyntaxTagNot,
},
};
use super::parse_config_not;
#[test]
fn simple_config() {
let mut parser = parse_config_not("``", "``");
assert_eq!(
parser("`` Configuration Not[SOMETHING] \n Some Text Here \n`` End Configuration ``"),
Ok((
"",
ApplicabilityParserSyntaxTag::TagNot(ApplicabilitySyntaxTagNot(
vec![ApplicTokens::NoTag(ApplicabilityNoTag(ApplicabilityTag {
tag: "SOMETHING".to_string(),
value: "Included".to_string()
}))],
vec![ApplicabilityParserSyntaxTag::Text(
"Some Text Here \n".to_string()
),],
ApplicabilityTagTypes::Configuration,
vec![]
))
))
)
}
#[test]
fn anded_config() {
let mut parser = parse_config_not("``", "``");
assert_eq!(
parser(
"`` Configuration Not[SOMETHING & SOMETHING_ELSE] \n Some Text Here \n`` End Configuration ``"
),
Ok((
"",
ApplicabilityParserSyntaxTag::TagNot(ApplicabilitySyntaxTagNot(
vec![ApplicTokens::NoTag(ApplicabilityNoTag(ApplicabilityTag {
tag: "SOMETHING".to_string(),
value: "Included".to_string()
})),
ApplicTokens::And(ApplicabilityAndTag(ApplicabilityTag {
tag: "SOMETHING_ELSE".to_string(),
value: "Included".to_string()
}))],
vec![ApplicabilityParserSyntaxTag::Text("Some Text Here \n".to_string()),],
ApplicabilityTagTypes::Configuration,
vec![]
))
))
)
}
#[test]
fn ored_config() {
let mut parser = parse_config_not("``", "``");
assert_eq!(
parser(
"`` Configuration Not[SOMETHING | SOMETHING_ELSE] \n Some Text Here \n`` End Configuration ``"
),
Ok((
"",
ApplicabilityParserSyntaxTag::TagNot(ApplicabilitySyntaxTagNot(
vec![ApplicTokens::NoTag(ApplicabilityNoTag(ApplicabilityTag {
tag: "SOMETHING".to_string(),
value: "Included".to_string()
})),
ApplicTokens::Or(ApplicabilityOrTag(ApplicabilityTag {
tag: "SOMETHING_ELSE".to_string(),
value: "Included".to_string()
}))],
vec![ApplicabilityParserSyntaxTag::Text("Some Text Here \n".to_string()),],
ApplicabilityTagTypes::Configuration,
vec![]
))
))
)
}
}
fn end_config_parser<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
) -> impl FnMut(&'a str) -> IResult<&'a str, &str> {
end_config_text_parser(custom_start_comment_syntax, custom_end_comment_syntax)
}
fn else_config_parser<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
) -> impl FnMut(&'a str) -> IResult<&'a str, &str> {
else_config_text_parser(custom_start_comment_syntax, custom_end_comment_syntax)
}
fn parse_config_inner<'a>(
custom_start_comment_syntax: &'a str,
custom_end_comment_syntax: &'a str,
) -> impl FnMut(&'a str) -> IResult<&'a str, Vec<ApplicabilityParserSyntaxTag>> {
many0(next_inner(
custom_start_comment_syntax,
custom_end_comment_syntax,
))
}