diff --git a/src/parser/babel_call.rs b/src/parser/babel_call.rs index 79731cf..c4bf312 100644 --- a/src/parser/babel_call.rs +++ b/src/parser/babel_call.rs @@ -15,10 +15,14 @@ use nom::sequence::tuple; use nom::InputTake; use super::keyword::affiliated_keyword; +use super::org_source::BracketDepth; use super::util::get_name; use super::util::start_of_line; use super::OrgSource; +use crate::context::Matcher; use crate::context::RefContext; +use crate::error::CustomError; +use crate::error::MyError; use crate::error::Res; use crate::parser::util::get_consumed; use crate::parser::util::org_line_ending; @@ -125,20 +129,37 @@ fn inside_header<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn arguments<'s>(input: OrgSource<'s>) -> Res, Option>> { - let (remaining, _) = tag("(")(input)?; + balanced_bracket( + |i| tag("(")(i), + |i| peek(tag(")"))(i), + |i| recognize(tuple((space0, org_line_ending)))(i), + |i| tag(")")(i), + |s| s.get_parenthesis_depth(), + )(input) - let (remaining, contents) = opt(verify( - recognize(many_till( - anychar, - alt(( - peek(recognize(one_of(")"))), - recognize(tuple((space0, org_line_ending))), - )), - )), - |s| s.len() > 0, - ))(remaining)?; - let (remaining, _) = tag(")")(remaining)?; - Ok((remaining, contents)) + // impl_balanced_bracket( + // input, + // |i| tag("(")(i), + // |i| peek(tag(")"))(i), + // |i| recognize(tuple((space0, org_line_ending)))(i), + // |i| tag(")")(i), + // |s| s.get_parenthesis_depth(), + // ) + + // let (remaining, _) = tag("(")(input)?; + + // let (remaining, contents) = opt(verify( + // recognize(many_till( + // anychar, + // alt(( + // peek(recognize(one_of(")"))), + // recognize(tuple((space0, org_line_ending))), + // )), + // )), + // |s| s.len() > 0, + // ))(remaining)?; + // let (remaining, _) = tag(")")(remaining)?; + // Ok((remaining, contents)) } #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] @@ -150,6 +171,80 @@ fn end_header<'s>(input: OrgSource<'s>) -> Res, OrgSource<'s>> { )(remaining) } +fn balanced_bracket< + O: Matcher, + S: Matcher, + F: Matcher, + E: Matcher, + D: for<'ss> Fn(OrgSource<'ss>) -> BracketDepth, +>( + opening_parser: O, + stop_parser: S, + fail_parser: F, + end_parser: E, + depth_function: D, +) -> impl for<'s> Fn(OrgSource<'s>) -> Res, Option>> { + move |input| { + impl_balanced_bracket::<&O, &S, &F, &E, &D>( + input, + &opening_parser, + &stop_parser, + &fail_parser, + &end_parser, + &depth_function, + ) + } +} + +fn impl_balanced_bracket< + 's, + O: Matcher, + S: Matcher, + F: Matcher, + E: Matcher, + D: for<'ss> Fn(OrgSource<'ss>) -> BracketDepth, +>( + input: OrgSource<'s>, + opening_parser: O, + stop_parser: S, + fail_parser: F, + end_parser: E, + depth_function: D, +) -> Res, Option>> { + let (mut remaining, _) = opening_parser(input)?; + let contents_start = remaining; + let original_depth = depth_function(remaining); + + loop { + let bracket_depth = depth_function(remaining); + if bracket_depth == original_depth { + let (remain, stop_result) = opt(&stop_parser)(remaining)?; + remaining = remain; + if stop_result.is_some() { + break; + } + } + + if fail_parser(remaining).is_ok() { + return Err(nom::Err::Error(CustomError::MyError(MyError( + "Fail parser matched.", + )))); + } + + let (remain, _) = anychar(remaining)?; + remaining = remain; + } + let contents_end = remaining; + + let (remaining, _) = end_parser(remaining)?; + let contents = if contents_start != contents_end { + Some(contents_start.get_until(contents_end)) + } else { + None + }; + Ok((remaining, contents)) +} + #[cfg(test)] mod tests { use nom::combinator::opt;