diff options
| author | Andreu Botella | 2019-10-23 09:29:24 +0200 |
|---|---|---|
| committer | Philipp A | 2019-10-23 09:29:24 +0200 |
| commit | 10cc972f2e4b99e6d3082970ee6982bfee5211c0 (patch) | |
| tree | 038f7199c2a27e89df55d7e15ddea1b1e8781341 | |
| parent | 7d38186a0ae3222b6de9bc91290a87d0e4564e18 (diff) | |
| download | rust-rst-10cc972f2e4b99e6d3082970ee6982bfee5211c0.tar.bz2 | |
Resolving substitutions. (#9)
| -rw-r--r-- | src/parser/conversion.rs | 17 | ||||
| -rw-r--r-- | src/parser/conversion/block.rs | 7 | ||||
| -rw-r--r-- | src/parser/conversion/inline.rs | 23 | ||||
| -rw-r--r-- | src/parser/simplify.rs | 197 | ||||
| -rw-r--r-- | src/rst.pest | 4 |
5 files changed, 186 insertions, 62 deletions
diff --git a/src/parser/conversion.rs b/src/parser/conversion.rs index 5154f40..32461bf 100644 --- a/src/parser/conversion.rs +++ b/src/parser/conversion.rs @@ -72,6 +72,23 @@ pub fn convert_document(pairs: Pairs<Rule>) -> Result<e::Document, Error> { Ok(e::Document::with_children(toplevel)) } +/// Normalizes a name in terms of whitespace. Equivalent to docutils's +/// `docutils.nodes.whitespace_normalize_name`. +pub fn whitespace_normalize_name(name: &str) -> String { + // Python's string.split() defines whitespace differently than Rust does. + let split_iter = name.split( + |ch: char| ch.is_whitespace() || (ch >= '\x1C' && ch <= '\x1F') + ).filter(|split| !split.is_empty()); + let mut ret = String::new(); + for split in split_iter { + if !ret.is_empty() { + ret.push(' '); + } + ret.push_str(split); + } + ret +} + #[cfg(test)] mod tests { diff --git a/src/parser/conversion/block.rs b/src/parser/conversion/block.rs index 714b410..9552539 100644 --- a/src/parser/conversion/block.rs +++ b/src/parser/conversion/block.rs @@ -6,13 +6,14 @@ use crate::document_tree::{ elements as e, element_categories as c, extra_attributes as a, + attribute_types as at }; use crate::parser::{ pest_rst::Rule, pair_ext_parse::PairExt, }; -use super::inline::convert_inline; +use super::{whitespace_normalize_name, inline::convert_inline}; #[derive(PartialEq)] @@ -92,14 +93,14 @@ fn convert_target(pair: Pair<Rule>) -> Result<e::Target, Error> { fn convert_substitution_def(pair: Pair<Rule>) -> Result<e::SubstitutionDefinition, Error> { let mut pairs = pair.into_inner(); - let name = pairs.next().unwrap().as_str(); // Rule::substitution_name + let name = whitespace_normalize_name(pairs.next().unwrap().as_str()); // Rule::substitution_name let inner_pair = pairs.next().unwrap(); let inner: c::TextOrInlineElement = match inner_pair.as_rule() { Rule::image => convert_image::<e::ImageInline>(inner_pair)?.into(), rule => panic!("Unknown substitution rule {:?}", rule), }; let mut subst_def = e::SubstitutionDefinition::with_children(vec![inner]); - subst_def.names_mut().push(name.into()); + subst_def.names_mut().push(at::NameToken(name)); Ok(subst_def) } diff --git a/src/parser/conversion/inline.rs b/src/parser/conversion/inline.rs index c30b71d..50a6258 100644 --- a/src/parser/conversion/inline.rs +++ b/src/parser/conversion/inline.rs @@ -6,6 +6,7 @@ use crate::document_tree::{ elements as e, element_categories as c, extra_attributes as a, + attribute_types as at }; use crate::parser::{ @@ -13,11 +14,14 @@ use crate::parser::{ // pair_ext_parse::PairExt, }; +use super::whitespace_normalize_name; + pub fn convert_inline(pair: Pair<Rule>) -> Result<c::TextOrInlineElement, Error> { Ok(match pair.as_rule() { - Rule::str => pair.as_str().into(), - Rule::reference => convert_reference(pair)?.into(), + Rule::str => pair.as_str().into(), + Rule::reference => convert_reference(pair)?.into(), + Rule::substitution_ref => convert_substitution(pair)?.into(), rule => unimplemented!("unknown rule {:?}", rule), }) } @@ -42,3 +46,18 @@ fn convert_reference(pair: Pair<Rule>) -> Result<e::Reference, Error> { a::Reference { name, refuri, refid, refname } )) } + +fn convert_substitution(pair: Pair<Rule>) -> Result<e::SubstitutionReference, Error> { + let concrete = pair.into_inner().next().unwrap(); + match concrete.as_rule() { + Rule::substitution_name => { + let name = whitespace_normalize_name(concrete.as_str()); + Ok(a::ExtraAttributes::with_extra( + a::SubstitutionReference { + refname: vec![at::NameToken(name)] + } + )) + } + _ => unreachable!() + } +} diff --git a/src/parser/simplify.rs b/src/parser/simplify.rs index 8f699e4..bb47760 100644 --- a/src/parser/simplify.rs +++ b/src/parser/simplify.rs @@ -25,24 +25,55 @@ use crate::target::Target; use crate::document_tree::{ Document, HasChildren, - attribute_types::ID, + attribute_types::{ID, NameToken}, elements as e, element_categories as c, }; -enum MaybeDirectTarget { - IndirectTarget(ID), - DirectTarget(Target), +#[derive(Debug)] +enum NamedTargetType { + NumberedFootnote(usize), + LabeledFootnote(usize), + Citation, + InternalLink, + ExternalLink(Target), + IndirectLink(NameToken), + SectionTitle +} +impl NamedTargetType { + fn is_implicit_target(&self) -> bool { + match self { + NamedTargetType::SectionTitle => true, + _ => false + } + } +} + +#[derive(Clone, Debug)] +struct Substitution { + content: e::ImageInline, + // If `ltrim` is true and the sibling before the reference is a text node, + // the text node gets right-trimmed. Same for `rtrim` with the sibling after + // getting left-trimmed. + ltrim: bool, + rtrim: bool +} + +#[derive(Default, Debug)] +struct TargetsCollected { + named_targets: HashMap<NameToken, NamedTargetType>, + substitutions: HashMap<String, Substitution>, + normalized_substitutions: HashMap<String, Substitution> } trait ResolvableRefs { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>); - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self; + fn populate_targets(&self, refs: &mut TargetsCollected); + fn resolve_refs(self, refs: &TargetsCollected) -> Self; } pub fn resolve_references(mut doc: Document) -> Document { - let mut references = HashMap::new(); + let mut references: TargetsCollected = Default::default(); for c in doc.children() { c.populate_targets(&mut references); } @@ -50,32 +81,32 @@ pub fn resolve_references(mut doc: Document) -> Document { Document::with_children(new) } -fn sub_pop<P, C>(parent: &P, refs: &mut HashMap<&ID, Target>) where P: HasChildren<C>, C: ResolvableRefs { +fn sub_pop<P, C>(parent: &P, refs: &mut TargetsCollected) where P: HasChildren<C>, C: ResolvableRefs { for c in parent.children() { c.populate_targets(refs); } } -fn sub_res<P, C>(mut parent: P, refs: &HashMap<&ID, Target>) -> P where P: e::Element + HasChildren<C>, C: ResolvableRefs { - let new: Vec<_> = parent.children_mut().drain(..).map(|c| c.resolve_refs(&refs)).collect(); +fn sub_res<P, C>(mut parent: P, refs: &TargetsCollected) -> P where P: e::Element + HasChildren<C>, C: ResolvableRefs { + let new: Vec<_> = parent.children_mut().drain(..).map(|c| c.resolve_refs(refs)).collect(); parent.children_mut().extend(new); parent } -fn sub_sub_pop<P, C1, C2>(parent: &P, refs: &mut HashMap<&ID, Target>) where P: HasChildren<C1>, C1: HasChildren<C2>, C2: ResolvableRefs { +fn sub_sub_pop<P, C1, C2>(parent: &P, refs: &mut TargetsCollected) where P: HasChildren<C1>, C1: HasChildren<C2>, C2: ResolvableRefs { for c in parent.children() { sub_pop(c, refs); } } -fn sub_sub_res<P, C1, C2>(mut parent: P, refs: &HashMap<&ID, Target>) -> P where P: e::Element + HasChildren<C1>, C1: e::Element + HasChildren<C2>, C2: ResolvableRefs { +fn sub_sub_res<P, C1, C2>(mut parent: P, refs: &TargetsCollected) -> P where P: e::Element + HasChildren<C1>, C1: e::Element + HasChildren<C2>, C2: ResolvableRefs { let new: Vec<_> = parent.children_mut().drain(..).map(|c| sub_res(c, refs)).collect(); parent.children_mut().extend(new); parent } impl ResolvableRefs for c::StructuralSubElement { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::StructuralSubElement::*; match self { Title(e) => sub_pop(&**e, refs), @@ -85,7 +116,7 @@ impl ResolvableRefs for c::StructuralSubElement { SubStructure(e) => e.populate_targets(refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::StructuralSubElement::*; match self { Title(e) => sub_res(*e, refs).into(), @@ -98,7 +129,7 @@ impl ResolvableRefs for c::StructuralSubElement { } impl ResolvableRefs for c::SubStructure { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubStructure::*; match self { Topic(e) => sub_pop(&**e, refs), @@ -110,7 +141,7 @@ impl ResolvableRefs for c::SubStructure { BodyElement(e) => e.populate_targets(refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubStructure::*; match self { Topic(e) => sub_res(*e, refs).into(), @@ -123,7 +154,8 @@ impl ResolvableRefs for c::SubStructure { } impl ResolvableRefs for c::BodyElement { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { + use crate::document_tree::extra_attributes::ExtraAttributes; use c::BodyElement::*; match self { Paragraph(e) => sub_pop(&**e, refs), @@ -133,8 +165,30 @@ impl ResolvableRefs for c::BodyElement { // TODO }, Rubric(e) => sub_pop(&**e, refs), - SubstitutionDefinition(e) => sub_pop(&**e, refs), - Comment(e) => sub_pop(&**e, refs), + SubstitutionDefinition(e) => { + use e::Element; + let subst_content = if let [c::TextOrInlineElement::ImageInline(content)] = &e.children()[..] { + content.as_ref() + } else { + panic!("Unexpected substitution contents.") + }; + let subst = Substitution { + content: subst_content.clone(), + ltrim: e.extra().ltrim, + rtrim: e.extra().rtrim + }; + for NameToken(name) in e.names() { + if refs.substitutions.contains_key(name) { + // TODO: Duplicate substitution name (level 3 system message). + } + // Intentionally overriding any previous values. + refs.substitutions.insert(name.clone(), subst.clone()); + refs.normalized_substitutions.insert(name.to_lowercase(), subst.clone()); + } + }, + Comment(e) => { + // TODO + }, Pending(e) => { // TODO }, @@ -173,7 +227,7 @@ impl ResolvableRefs for c::BodyElement { Table(e) => sub_pop(&**e, refs) } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::BodyElement::*; match self { Paragraph(e) => sub_res(*e, refs).into(), @@ -181,8 +235,8 @@ impl ResolvableRefs for c::BodyElement { DoctestBlock(e) => sub_res(*e, refs).into(), MathBlock(e) => MathBlock(e), Rubric(e) => sub_res(*e, refs).into(), - SubstitutionDefinition(e) => sub_res(*e, refs).into(), - Comment(e) => sub_res(*e, refs).into(), + SubstitutionDefinition(e) => SubstitutionDefinition(e), + Comment(e) => Comment(e), Pending(e) => Pending(e), Target(e) => Target(e), Raw(e) => Raw(e), @@ -216,7 +270,7 @@ impl ResolvableRefs for c::BodyElement { } impl ResolvableRefs for c::BibliographicElement { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::BibliographicElement::*; match self { Author(e) => sub_pop(&**e, refs), @@ -232,7 +286,7 @@ impl ResolvableRefs for c::BibliographicElement { Field(e) => sub_pop(&**e, refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::BibliographicElement::*; match self { Author(e) => sub_res(*e, refs).into(), @@ -251,7 +305,7 @@ impl ResolvableRefs for c::BibliographicElement { } impl ResolvableRefs for c::TextOrInlineElement { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::TextOrInlineElement::*; match self { c::TextOrInlineElement::String(e) => { @@ -286,7 +340,7 @@ impl ResolvableRefs for c::TextOrInlineElement { } } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::TextOrInlineElement::*; match self { c::TextOrInlineElement::String(e) => c::TextOrInlineElement::String(e), @@ -296,7 +350,38 @@ impl ResolvableRefs for c::TextOrInlineElement { Reference(e) => sub_res(*e, refs).into(), FootnoteReference(e) => sub_res(*e, refs).into(), CitationReference(e) => sub_res(*e, refs).into(), - SubstitutionReference(e) => sub_res(*e, refs).into(), + SubstitutionReference(e) => { + use crate::document_tree::extra_attributes::ExtraAttributes; + if e.extra().refname.len() != 1 { + panic!("Expected exactly one name in a substitution reference."); + } + let name = e.extra().refname[0].0.clone(); + let substitution = refs.substitutions.get(&name).or_else(|| { + refs.normalized_substitutions.get(&name.to_lowercase()) + }); + match substitution { + Some(Substitution {content, ltrim, rtrim}) => { + // TODO: Check if the substitution would expand circularly + // (level 3 system message). + // TODO: Ltrim and rtrim. + ImageInline(Box::new(content.clone())) + }, + None => { + // Undefined substitution name (level 3 system message). + // TODO: This replaces the reference by a Problematic node. + // The corresponding SystemMessage node should go in a generated + // section with class "system-messages" at the end of the document. + use crate::document_tree::{Problematic, element_categories::TextOrInlineElement}; + let mut replacement: Box<Problematic> = Box::new(Default::default()); + replacement.children_mut().push( + TextOrInlineElement::String(Box::new(format!("|{}|", name))) + ); + // TODO: Create an ID for replacement for the system_message to reference. + // TODO: replacement.refid pointing to the system_message. + Problematic(replacement) + } + } + }, TitleReference(e) => sub_res(*e, refs).into(), Abbreviation(e) => sub_res(*e, refs).into(), Acronym(e) => sub_res(*e, refs).into(), @@ -314,7 +399,7 @@ impl ResolvableRefs for c::TextOrInlineElement { } impl ResolvableRefs for c::AuthorInfo { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::AuthorInfo::*; match self { Author(e) => sub_pop(&**e, refs), @@ -323,7 +408,7 @@ impl ResolvableRefs for c::AuthorInfo { Contact(e) => sub_pop(&**e, refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::AuthorInfo::*; match self { Author(e) => sub_res(*e, refs).into(), @@ -335,14 +420,14 @@ impl ResolvableRefs for c::AuthorInfo { } impl ResolvableRefs for c::DecorationElement { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::DecorationElement::*; match self { Header(e) => sub_pop(&**e, refs), Footer(e) => sub_pop(&**e, refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::DecorationElement::*; match self { Header(e) => sub_res(*e, refs).into(), @@ -352,14 +437,14 @@ impl ResolvableRefs for c::DecorationElement { } impl ResolvableRefs for c::SubTopic { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubTopic::*; match self { Title(e) => sub_pop(&**e, refs), BodyElement(e) => e.populate_targets(refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubTopic::*; match self { Title(e) => sub_res(*e, refs).into(), @@ -369,7 +454,7 @@ impl ResolvableRefs for c::SubTopic { } impl ResolvableRefs for c::SubSidebar { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubSidebar::*; match self { Topic(e) => sub_pop(&**e, refs), @@ -378,7 +463,7 @@ impl ResolvableRefs for c::SubSidebar { BodyElement(e) => e.populate_targets(refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubSidebar::*; match self { Topic(e) => sub_res(*e, refs).into(), @@ -390,7 +475,7 @@ impl ResolvableRefs for c::SubSidebar { } impl ResolvableRefs for c::SubDLItem { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubDLItem::*; match self { Term(e) => sub_pop(&**e, refs), @@ -398,7 +483,7 @@ impl ResolvableRefs for c::SubDLItem { Definition(e) => sub_pop(&**e, refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubDLItem::*; match self { Term(e) => sub_res(*e, refs).into(), @@ -409,14 +494,14 @@ impl ResolvableRefs for c::SubDLItem { } impl ResolvableRefs for c::SubField { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubField::*; match self { FieldName(e) => sub_pop(&**e, refs), FieldBody(e) => sub_pop(&**e, refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubField::*; match self { FieldName(e) => sub_res(*e, refs).into(), @@ -426,14 +511,14 @@ impl ResolvableRefs for c::SubField { } impl ResolvableRefs for c::SubOptionListItem { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubOptionListItem::*; match self { OptionGroup(e) => sub_sub_pop(&**e, refs), Description(e) => sub_pop(&**e, refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubOptionListItem::*; match self { OptionGroup(e) => sub_sub_res(*e, refs).into(), @@ -443,7 +528,7 @@ impl ResolvableRefs for c::SubOptionListItem { } impl ResolvableRefs for c::SubOption { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubOption::*; match self { OptionString(e) => { @@ -454,7 +539,7 @@ impl ResolvableRefs for c::SubOption { }, } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubOption::*; match self { OptionString(e) => OptionString(e), @@ -464,14 +549,14 @@ impl ResolvableRefs for c::SubOption { } impl ResolvableRefs for c::SubLineBlock { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubLineBlock::*; match self { LineBlock(e) => sub_pop(&**e, refs), Line(e) => sub_pop(&**e, refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubLineBlock::*; match self { LineBlock(e) => sub_res(*e, refs).into(), @@ -481,14 +566,14 @@ impl ResolvableRefs for c::SubLineBlock { } impl ResolvableRefs for c::SubBlockQuote { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubBlockQuote::*; match self { Attribution(e) => sub_pop(&**e, refs), BodyElement(e) => e.populate_targets(refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubBlockQuote::*; match self { Attribution(e) => sub_res(*e, refs).into(), @@ -498,14 +583,14 @@ impl ResolvableRefs for c::SubBlockQuote { } impl ResolvableRefs for c::SubFootnote { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubFootnote::*; match self { Label(e) => sub_pop(&**e, refs), BodyElement(e) => e.populate_targets(refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubFootnote::*; match self { Label(e) => sub_res(*e, refs).into(), @@ -515,7 +600,7 @@ impl ResolvableRefs for c::SubFootnote { } impl ResolvableRefs for c::SubFigure { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubFigure::*; match self { Caption(e) => sub_pop(&**e, refs), @@ -523,7 +608,7 @@ impl ResolvableRefs for c::SubFigure { BodyElement(e) => e.populate_targets(refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubFigure::*; match self { Caption(e) => sub_res(*e, refs).into(), @@ -534,14 +619,14 @@ impl ResolvableRefs for c::SubFigure { } impl ResolvableRefs for c::SubTable { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubTable::*; match self { Title(e) => sub_pop(&**e, refs), TableGroup(e) => sub_pop(&**e, refs), } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubTable::*; match self { Title(e) => sub_res(*e, refs).into(), @@ -551,7 +636,7 @@ impl ResolvableRefs for c::SubTable { } impl ResolvableRefs for c::SubTableGroup { - fn populate_targets(&self, refs: &mut HashMap<&ID, Target>) { + fn populate_targets(&self, refs: &mut TargetsCollected) { use c::SubTableGroup::*; match self { TableColspec(e) => { @@ -569,7 +654,7 @@ impl ResolvableRefs for c::SubTableGroup { }, } } - fn resolve_refs(self, refs: &HashMap<&ID, Target>) -> Self { + fn resolve_refs(self, refs: &TargetsCollected) -> Self { use c::SubTableGroup::*; match self { TableColspec(e) => TableColspec(e), @@ -585,4 +670,4 @@ impl ResolvableRefs for c::SubTableGroup { }, } } -}
\ No newline at end of file +} diff --git a/src/rst.pest b/src/rst.pest index 9934f44..b9c60e9 100644 --- a/src/rst.pest +++ b/src/rst.pest @@ -101,6 +101,7 @@ blank_line = _{ !marker ~ !inline ~ " "* ~ NEWLINE } inlines = _{ !marker ~ inline+ ~ ( NEWLINE ~ (PEEK[..] ~ !marker ~ inline+ ~ NEWLINE)+ )? } inline = _{ reference + | substitution_ref | str // link ✓ // | str ✓ @@ -121,7 +122,7 @@ inline = _{ // | symbol } -str = { (!(NEWLINE | reference) ~ ANY)+ } +str = { (!(NEWLINE | reference | substitution_ref) ~ ANY)+ } // inline links reference = { reference_target | reference_explicit | reference_auto } @@ -144,6 +145,7 @@ reference_embedded_source = { ( !("<"|":"|"`") ~ ( " " | nonspacechar | blank_li reference_auto_url = { ASCII_ALPHA+ ~ "://" ~ (!(NEWLINE|">") ~ ANY)+ } reference_auto_email = { "<" ~ "mailto:"? ~ (ASCII_ALPHANUMERIC|"-"|"+"|"_"|"."|"/"|"!"|"%"|"~"|"$")+ ~ "@" ~ (!(NEWLINE | ">") ~ ANY)+ ~ ">" } +substitution_ref = { "|" ~ substitution_name ~ "|" } /* * character classes |
