Implement the second parsing pass.

This commit is contained in:
Tom Alexander 2023-07-14 19:06:58 -04:00
parent ef2c351696
commit bd04451d58
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 37 additions and 11 deletions

View File

@ -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),
}
}
))
}))
}
}

View File

@ -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> {