Implement the second parsing pass.
This commit is contained in:
parent
ef2c351696
commit
bd04451d58
@ -96,8 +96,35 @@ pub fn document(input: &str) -> Res<&str, Document> {
|
||||
let initial_context: ContextTree<'_, '_> = ContextTree::new();
|
||||
let document_context =
|
||||
initial_context.with_additional_node(ContextElement::DocumentRoot(input));
|
||||
let zeroth_section_matcher = parser_with_context!(zeroth_section)(&document_context);
|
||||
let heading_matcher = parser_with_context!(heading)(&document_context);
|
||||
let (remaining, document) = _document(&document_context, input)?;
|
||||
{
|
||||
// If there are radio targets in this document then we need to parse the entire document again with the knowledge of the radio targets.
|
||||
let all_radio_targets: Vec<&Vec<Object<'_>>> = document
|
||||
.iter_tokens()
|
||||
.filter_map(|tkn| match tkn {
|
||||
Token::Object(obj) => Some(obj),
|
||||
_ => None,
|
||||
})
|
||||
.filter_map(|obj| match obj {
|
||||
Object::RadioTarget(rt) => Some(rt),
|
||||
_ => None,
|
||||
})
|
||||
.map(|rt| &rt.children)
|
||||
.collect();
|
||||
if !all_radio_targets.is_empty() {
|
||||
let document_context = document_context
|
||||
.with_additional_node(ContextElement::RadioTarget(all_radio_targets));
|
||||
let (remaining, document) = _document(&document_context, input)?;
|
||||
return Ok((remaining, document));
|
||||
}
|
||||
}
|
||||
Ok((remaining, document))
|
||||
}
|
||||
|
||||
#[tracing::instrument(ret, level = "debug")]
|
||||
pub fn _document<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Document<'s>> {
|
||||
let zeroth_section_matcher = parser_with_context!(zeroth_section)(context);
|
||||
let heading_matcher = parser_with_context!(heading)(context);
|
||||
let (remaining, _blank_lines) = many0(blank_line)(input)?;
|
||||
let (remaining, zeroth_section) = opt(zeroth_section_matcher)(remaining)?;
|
||||
let (remaining, children) = many0(heading_matcher)(remaining)?;
|
||||
@ -268,14 +295,13 @@ impl<'s> Document<'s> {
|
||||
|
||||
impl<'s> Heading<'s> {
|
||||
pub fn iter_tokens<'r>(&'r self) -> impl Iterator<Item = Token<'r, 's>> {
|
||||
self.title.iter().map(Token::Object).chain(self.children.iter().map(
|
||||
|de| {
|
||||
match de {
|
||||
self.title
|
||||
.iter()
|
||||
.map(Token::Object)
|
||||
.chain(self.children.iter().map(|de| match de {
|
||||
DocumentElement::Heading(obj) => Token::Heading(obj),
|
||||
DocumentElement::Section(obj) => Token::Section(obj),
|
||||
}
|
||||
}
|
||||
))
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ pub enum ContextElement<'r, 's> {
|
||||
/// If any are found, this will force a 2nd parse through the
|
||||
/// org-mode document since text needs to be re-parsed to look for
|
||||
/// radio links matching the contents of radio targets.
|
||||
RadioTarget(Vec<Vec<Object<'s>>>),
|
||||
RadioTarget(Vec<&'r Vec<Object<'s>>>),
|
||||
}
|
||||
|
||||
pub struct ExitMatcherNode<'r> {
|
||||
|
Loading…
Reference in New Issue
Block a user