Move the affiliated keywords parser inside the specific element parsers.
We need access to the affiliated keywords to do things like set the name of the element, and only half the element parsers are allowed to have affiliated keywords, so it makes sense to move it inside the specific parsers.
This commit is contained in:
@@ -3,9 +3,12 @@ use nom::bytes::complete::is_not;
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::line_ending;
|
||||
use nom::combinator::eof;
|
||||
use nom::multi::many0;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use crate::context::parser_with_context;
|
||||
use crate::context::RefContext;
|
||||
use crate::error::Res;
|
||||
use crate::parser::util::get_consumed;
|
||||
@@ -14,9 +17,11 @@ use crate::types::DiarySexp;
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
pub(crate) fn diary_sexp<'b, 'g, 'r, 's>(
|
||||
_context: RefContext<'b, 'g, 'r, 's>,
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, DiarySexp<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
start_of_line(input)?;
|
||||
let (remaining, _clock) = tag("%%(")(input)?;
|
||||
let (remaining, _contents) = is_not("\r\n")(remaining)?;
|
||||
@@ -27,6 +32,7 @@ pub(crate) fn diary_sexp<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
DiarySexp {
|
||||
source: source.into(),
|
||||
name: None, // TODO
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ use nom::character::complete::space0;
|
||||
use nom::combinator::eof;
|
||||
use nom::combinator::not;
|
||||
use nom::combinator::recognize;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use crate::context::parser_with_context;
|
||||
use crate::context::ContextElement;
|
||||
@@ -41,6 +43,8 @@ pub(crate) fn drawer<'b, 'g, 'r, 's>(
|
||||
"Cannot nest objects of the same element".into(),
|
||||
))));
|
||||
}
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
start_of_line(input)?;
|
||||
let (remaining, _leading_whitespace) = space0(input)?;
|
||||
let (remaining, (_open_colon, drawer_name, _close_colon, _new_line)) = tuple((
|
||||
@@ -90,7 +94,8 @@ pub(crate) fn drawer<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
Drawer {
|
||||
source: source.into(),
|
||||
name: drawer_name.into(),
|
||||
name: None, // TODO
|
||||
drawer_name: drawer_name.into(),
|
||||
children,
|
||||
},
|
||||
))
|
||||
|
||||
@@ -17,6 +17,7 @@ use nom::multi::many_till;
|
||||
use nom::sequence::preceded;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use crate::context::parser_with_context;
|
||||
use crate::context::ContextElement;
|
||||
@@ -47,6 +48,9 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>(
|
||||
"Cannot nest objects of the same element".into(),
|
||||
))));
|
||||
}
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
|
||||
start_of_line(input)?;
|
||||
let (remaining, _leading_whitespace) = space0(input)?;
|
||||
let (remaining, (_, name, parameters, _, _)) = tuple((
|
||||
@@ -97,7 +101,8 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
DynamicBlock {
|
||||
source: source.into(),
|
||||
name: name.into(),
|
||||
name: None, // TODO
|
||||
block_name: name.into(),
|
||||
parameters: parameters.map(|val| val.into()),
|
||||
children,
|
||||
},
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use nom::branch::alt;
|
||||
use nom::combinator::map;
|
||||
use nom::combinator::not;
|
||||
use nom::multi::many0;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::clock::clock;
|
||||
use super::comment::comment;
|
||||
@@ -79,8 +76,6 @@ fn _element<'b, 'g, 'r, 's>(
|
||||
let paragraph_matcher = parser_with_context!(paragraph)(context);
|
||||
let latex_environment_matcher = parser_with_context!(latex_environment)(context);
|
||||
|
||||
// TODO: Affiliated keywords cannot be on comments, clocks, headings, inlinetasks, items, node properties, planning, property drawers, sections, and table rows
|
||||
let (remaining, mut affiliated_keywords) = many0(affiliated_keyword_matcher)(input)?;
|
||||
let (remaining, mut element) = match alt((
|
||||
map(plain_list_matcher, Element::PlainList),
|
||||
greater_block_matcher,
|
||||
@@ -100,28 +95,20 @@ fn _element<'b, 'g, 'r, 's>(
|
||||
map(horizontal_rule_matcher, Element::HorizontalRule),
|
||||
map(latex_environment_matcher, Element::LatexEnvironment),
|
||||
map(babel_keyword_matcher, Element::BabelCall),
|
||||
map(
|
||||
map(
|
||||
tuple((not(affiliated_keyword_matcher), keyword_matcher)),
|
||||
|(_, kw)| kw,
|
||||
),
|
||||
Element::Keyword,
|
||||
),
|
||||
))(remaining)
|
||||
map(keyword_matcher, Element::Keyword),
|
||||
))(input)
|
||||
{
|
||||
the_ok @ Ok(_) => the_ok,
|
||||
Err(_) => {
|
||||
if can_be_paragraph {
|
||||
match map(paragraph_matcher, Element::Paragraph)(remaining) {
|
||||
match map(paragraph_matcher, Element::Paragraph)(input) {
|
||||
the_ok @ Ok(_) => the_ok,
|
||||
Err(_) => {
|
||||
// TODO: Because this function expects a single element, if there are multiple affiliated keywords before an element that cannot have affiliated keywords, we end up re-parsing the affiliated keywords many times.
|
||||
affiliated_keywords.clear();
|
||||
map(affiliated_keyword_matcher, Element::Keyword)(input)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
affiliated_keywords.clear();
|
||||
map(affiliated_keyword_matcher, Element::Keyword)(input)
|
||||
}
|
||||
}
|
||||
@@ -149,6 +136,7 @@ fn _detect_element<'b, 'g, 'r, 's>(
|
||||
input: OrgSource<'s>,
|
||||
can_be_paragraph: bool,
|
||||
) -> Res<OrgSource<'s>, ()> {
|
||||
// TODO: What about affiliated keywords in the detect_* functions?
|
||||
if alt((
|
||||
parser_with_context!(detect_plain_list)(context),
|
||||
detect_footnote_definition,
|
||||
|
||||
@@ -10,6 +10,7 @@ use nom::multi::many0;
|
||||
use nom::sequence::preceded;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use super::util::only_space1;
|
||||
use super::util::org_line_ending;
|
||||
@@ -26,6 +27,8 @@ pub(crate) fn fixed_width_area<'b, 'g, 'r, 's>(
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, FixedWidthArea<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
let fixed_width_area_line_matcher = parser_with_context!(fixed_width_area_line)(context);
|
||||
let exit_matcher = parser_with_context!(exit_matcher_parser)(context);
|
||||
let (remaining, _first_line) = fixed_width_area_line_matcher(input)?;
|
||||
@@ -37,6 +40,7 @@ pub(crate) fn fixed_width_area<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
FixedWidthArea {
|
||||
source: source.into(),
|
||||
name: None, // TODO
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use nom::multi::many1;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use super::util::include_input;
|
||||
use super::util::WORD_CONSTITUENT_CHARACTERS;
|
||||
@@ -41,6 +42,8 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>(
|
||||
"Cannot nest objects of the same element".into(),
|
||||
))));
|
||||
}
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
start_of_line(input)?;
|
||||
// Cannot be indented.
|
||||
let (remaining, (_, lbl, _, _, _)) = tuple((
|
||||
@@ -85,6 +88,7 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
FootnoteDefinition {
|
||||
source: source.into(),
|
||||
name: None, // TODO
|
||||
label: lbl.into(),
|
||||
children: children.into_iter().map(|(_, item)| item).collect(),
|
||||
},
|
||||
|
||||
@@ -17,6 +17,7 @@ use nom::multi::many_till;
|
||||
use nom::sequence::preceded;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use super::util::in_section;
|
||||
use crate::context::parser_with_context;
|
||||
@@ -45,6 +46,8 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>(
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, Element<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
start_of_line(input)?;
|
||||
let (remaining, _leading_whitespace) = space0(input)?;
|
||||
let (remaining, (_begin, name)) = tuple((
|
||||
@@ -75,7 +78,11 @@ fn center_block<'b, 'g, 'r, 's>(
|
||||
greater_block_body(context, input, original_input, "center", "center block")?;
|
||||
Ok((
|
||||
remaining,
|
||||
Element::CenterBlock(CenterBlock { source, children }),
|
||||
Element::CenterBlock(CenterBlock {
|
||||
source,
|
||||
name: None, // TODO
|
||||
children,
|
||||
}),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -89,7 +96,11 @@ fn quote_block<'b, 'g, 'r, 's>(
|
||||
greater_block_body(context, input, original_input, "quote", "quote block")?;
|
||||
Ok((
|
||||
remaining,
|
||||
Element::QuoteBlock(QuoteBlock { source, children }),
|
||||
Element::QuoteBlock(QuoteBlock {
|
||||
source,
|
||||
name: None, // TODO
|
||||
children,
|
||||
}),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -122,8 +133,9 @@ fn _special_block<'c, 'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
Element::SpecialBlock(SpecialBlock {
|
||||
source,
|
||||
name: None, // TODO
|
||||
children,
|
||||
name,
|
||||
block_type: name,
|
||||
parameters: parameters.map(|(_, parameters)| Into::<&str>::into(parameters)),
|
||||
}),
|
||||
))
|
||||
|
||||
@@ -5,10 +5,13 @@ use nom::character::complete::space0;
|
||||
use nom::combinator::eof;
|
||||
use nom::combinator::recognize;
|
||||
use nom::combinator::verify;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many1_count;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use crate::context::parser_with_context;
|
||||
use crate::context::RefContext;
|
||||
use crate::error::Res;
|
||||
use crate::parser::util::start_of_line;
|
||||
@@ -16,9 +19,11 @@ use crate::types::HorizontalRule;
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
pub(crate) fn horizontal_rule<'b, 'g, 'r, 's>(
|
||||
_context: RefContext<'b, 'g, 'r, 's>,
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, HorizontalRule<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
start_of_line(input)?;
|
||||
let (remaining, rule) = recognize(tuple((
|
||||
space0,
|
||||
@@ -30,6 +35,7 @@ pub(crate) fn horizontal_rule<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
HorizontalRule {
|
||||
source: rule.into(),
|
||||
name: None, // TODO
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@@ -13,11 +13,13 @@ use nom::combinator::not;
|
||||
use nom::combinator::peek;
|
||||
use nom::combinator::recognize;
|
||||
use nom::combinator::verify;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::org_source::BracketDepth;
|
||||
use super::org_source::OrgSource;
|
||||
use crate::context::parser_with_context;
|
||||
use crate::context::Matcher;
|
||||
use crate::context::RefContext;
|
||||
use crate::error::CustomError;
|
||||
@@ -61,6 +63,7 @@ fn _filtered_keyword<'s, F: Matcher>(
|
||||
remaining,
|
||||
Keyword {
|
||||
source: consumed_input.into(),
|
||||
name: None, // TODO
|
||||
key: parsed_key.into(),
|
||||
value: "".into(),
|
||||
},
|
||||
@@ -78,6 +81,7 @@ fn _filtered_keyword<'s, F: Matcher>(
|
||||
remaining,
|
||||
Keyword {
|
||||
source: consumed_input.into(),
|
||||
name: None, // TODO
|
||||
key: parsed_key.into(),
|
||||
value: parsed_value.into(),
|
||||
},
|
||||
@@ -86,9 +90,11 @@ fn _filtered_keyword<'s, F: Matcher>(
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
pub(crate) fn keyword<'b, 'g, 'r, 's>(
|
||||
_context: RefContext<'b, 'g, 'r, 's>,
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, Keyword<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
filtered_keyword(regular_keyword_key)(input)
|
||||
}
|
||||
|
||||
@@ -102,14 +108,17 @@ pub(crate) fn affiliated_keyword<'b, 'g, 'r, 's>(
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
pub(crate) fn babel_call_keyword<'b, 'g, 'r, 's>(
|
||||
_context: RefContext<'b, 'g, 'r, 's>,
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, BabelCall<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
let (remaining, kw) = filtered_keyword(babel_call_key)(input)?;
|
||||
Ok((
|
||||
remaining,
|
||||
BabelCall {
|
||||
source: kw.source,
|
||||
name: None, // TODO
|
||||
key: kw.key,
|
||||
value: kw.value,
|
||||
},
|
||||
|
||||
@@ -8,9 +8,11 @@ use nom::character::complete::space0;
|
||||
use nom::combinator::eof;
|
||||
use nom::combinator::peek;
|
||||
use nom::combinator::recognize;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use super::util::get_consumed;
|
||||
use crate::context::parser_with_context;
|
||||
@@ -29,6 +31,8 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>(
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, LatexEnvironment<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
start_of_line(input)?;
|
||||
let (remaining, _leading_whitespace) = space0(input)?;
|
||||
let (remaining, (_opening, name, _open_close_brace, _ws, _line_ending)) = tuple((
|
||||
@@ -54,6 +58,7 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
LatexEnvironment {
|
||||
source: source.into(),
|
||||
name: None, // TODO
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ use nom::branch::alt;
|
||||
use nom::combinator::eof;
|
||||
use nom::combinator::recognize;
|
||||
use nom::combinator::verify;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many1;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::element_parser::detect_element;
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::org_source::OrgSource;
|
||||
use super::util::blank_line;
|
||||
use super::util::get_consumed;
|
||||
@@ -26,6 +28,9 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>(
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, Paragraph<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
|
||||
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||
class: ExitClass::Gamma,
|
||||
exit_matcher: ¶graph_end,
|
||||
|
||||
@@ -19,6 +19,7 @@ use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::element_parser::element;
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::object_parser::standard_set_object;
|
||||
use super::org_source::OrgSource;
|
||||
use super::util::include_input;
|
||||
@@ -78,6 +79,9 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>(
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, PlainList<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
|
||||
let contexts = [
|
||||
ContextElement::Context("plain list"),
|
||||
ContextElement::ConsumeTrailingWhitespace(true),
|
||||
@@ -150,6 +154,7 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
PlainList {
|
||||
source: source.into(),
|
||||
name: None, // TODO
|
||||
list_type: first_item_list_type.expect("Plain lists require at least one element."),
|
||||
children: children.into_iter().map(|(_start, item)| item).collect(),
|
||||
},
|
||||
|
||||
@@ -120,7 +120,7 @@ fn node_property<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
NodeProperty {
|
||||
source: source.into(),
|
||||
name: Into::<&str>::into(name),
|
||||
property_name: Into::<&str>::into(name),
|
||||
value: None,
|
||||
},
|
||||
))
|
||||
@@ -133,7 +133,7 @@ fn node_property<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
NodeProperty {
|
||||
source: source.into(),
|
||||
name: Into::<&str>::into(name),
|
||||
property_name: Into::<&str>::into(name),
|
||||
value: Some(value.into()),
|
||||
},
|
||||
))
|
||||
|
||||
@@ -13,6 +13,7 @@ use nom::multi::many1;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
use super::keyword::affiliated_keyword;
|
||||
use super::keyword::table_formula_keyword;
|
||||
use super::object_parser::table_cell_set_object;
|
||||
use super::org_source::OrgSource;
|
||||
@@ -38,6 +39,8 @@ pub(crate) fn org_mode_table<'b, 'g, 'r, 's>(
|
||||
context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, Table<'s>> {
|
||||
let (input, affiliated_keywords) =
|
||||
many0(parser_with_context!(affiliated_keyword)(context))(input)?;
|
||||
start_of_line(input)?;
|
||||
peek(tuple((space0, tag("|"))))(input)?;
|
||||
|
||||
@@ -68,6 +71,7 @@ pub(crate) fn org_mode_table<'b, 'g, 'r, 's>(
|
||||
remaining,
|
||||
Table {
|
||||
source: source.into(),
|
||||
name: None, // TODO
|
||||
formulas,
|
||||
children,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user