diff options
| author | Philipp A | 2018-11-20 00:48:06 +0100 | 
|---|---|---|
| committer | Philipp A | 2018-11-20 00:48:06 +0100 | 
| commit | d9ff9626417ab29cfa7054ad755052d3e5a08f5b (patch) | |
| tree | 7ba5253cbad2975ec7eae1551723ed1126454fb6 | |
| parent | b136f04bc225380a6aa5daa28075eafd767a4a98 (diff) | |
| download | rust-rst-d9ff9626417ab29cfa7054ad755052d3e5a08f5b.tar.bz2 | |
Serializing document trees!
| -rw-r--r-- | src/document_tree/attribute_types.rs | 4 | ||||
| -rw-r--r-- | src/document_tree/extra_attributes.rs | 4 | ||||
| -rw-r--r-- | src/parser.rs | 65 | ||||
| -rw-r--r-- | src/parser/serialize.rs | 36 | ||||
| -rw-r--r-- | src/rst.pest | 8 | 
5 files changed, 66 insertions, 51 deletions
| diff --git a/src/document_tree/attribute_types.rs b/src/document_tree/attribute_types.rs index 1f3c466..9ad66be 100644 --- a/src/document_tree/attribute_types.rs +++ b/src/document_tree/attribute_types.rs @@ -16,8 +16,8 @@ impl Default for FixedSpace { fn default() -> FixedSpace { FixedSpace::Preserve  #[derive(Debug,Serialize)] pub enum AlignH { Left, Center, Right}  #[derive(Debug,Serialize)] pub enum AlignHV { Top, Middle, Bottom, Left, Center, Right } -#[derive(Debug,Serialize)] pub struct ID(String); -#[derive(Debug,Serialize)] pub struct NameToken(String); +#[derive(Debug,Serialize)] pub struct ID(pub String); +#[derive(Debug,Serialize)] pub struct NameToken(pub String);  #[derive(Debug,Serialize)]  pub enum Measure { diff --git a/src/document_tree/extra_attributes.rs b/src/document_tree/extra_attributes.rs index 9cd097d..80fe045 100644 --- a/src/document_tree/extra_attributes.rs +++ b/src/document_tree/extra_attributes.rs @@ -54,7 +54,7 @@ impl_extra!(LiteralBlock { space: FixedSpace });  impl_extra!(DoctestBlock { space: FixedSpace });  impl_extra!(SubstitutionDefinition { ltrim: Option<bool>, rtrim: Option<bool> });  impl_extra!(Comment { space: FixedSpace }); -impl_extra!(Target { refuri: Option<Url>, refid: Option<ID>, refname: Vec<NameToken>, anonymous: Option<bool> }); +impl_extra!(Target { refuri: Option<Url>, refid: Option<ID>, refname: Vec<NameToken>, anonymous: bool });  impl_extra!(Raw { space: FixedSpace, format: Vec<NameToken> });  impl_extra!(#[derive(Debug)] Image {  	align: Option<AlignHV>, @@ -85,7 +85,7 @@ impl_extra!(SubstitutionReference { refname: Vec<NameToken> });  impl_extra!(Problematic { refid: Option<ID> });  //also have non-inline versions. Inline image is no figure child, inline target has content -impl_extra!(TargetInline { refuri: Option<Url>, refid: Option<ID>, refname: Vec<NameToken>, anonymous: Option<bool> }); +impl_extra!(TargetInline { refuri: Option<Url>, refid: Option<ID>, refname: Vec<NameToken>, anonymous: bool });  impl_extra!(RawInline { space: FixedSpace, format: Vec<NameToken> });  impl_extra!(#[derive(Debug)] ImageInline {  	align: Option<AlignHV>, diff --git a/src/parser.rs b/src/parser.rs index 93e2cc1..69ead45 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,5 +1,4 @@  pub mod token; -pub mod serialize;  #[cfg(test)]  pub mod tests; @@ -14,9 +13,9 @@ use self::pest_rst::Rule;  use std::io::Write; +use url::Url;  use failure::Error;  use failure_derive::Fail; -  use pest::Parser;  use crate::document_tree::{ @@ -24,10 +23,17 @@ use crate::document_tree::{      elements::{          Document,          Title, +        Paragraph, +        Target, +        Attention, Hint, Note, Caution, Danger, Error as ErrorEl, Important, Tip, Warning      },      element_categories::{ -        StructuralSubElement +        StructuralSubElement, +        SubStructure, +        BodyElement,      }, +    attribute_types::ID, +    extra_attributes,  }; @@ -41,13 +47,24 @@ enum ConversionError {  fn convert_ssubel(pair: pest::iterators::Pair<Rule>) -> Result<StructuralSubElement, Error> { +    // TODO: This is just a proof of concep. Keep closely to DTD in final version!      match pair.as_rule() {          Rule::title => Ok(convert_title(pair).into()), +        Rule::paragraph => Ok(to_ssub(Paragraph::with_children(vec![pair.as_str().into()]))), +        Rule::target => Ok(to_ssub(convert_target(pair)?)), +        Rule::admonition_gen => Ok(to_ssub(convert_admonition_gen(pair)?)),          rule => Err(ConversionError::UnknownRuleError { rule }.into()),      }  } +fn to_ssub<E>(elem: E) -> StructuralSubElement where E: Into<BodyElement> { +    let belm: BodyElement = elem.into(); +    let sstruc: SubStructure = belm.into(); +    sstruc.into() +} + +  fn convert_title(pair: pest::iterators::Pair<pest_rst::Rule>) -> Title {      let mut title: Option<&str> = None;      let mut _adornment_char: Option<char> = None; @@ -64,6 +81,41 @@ fn convert_title(pair: pest::iterators::Pair<pest_rst::Rule>) -> Title {      ])  } +fn convert_target(pair: pest::iterators::Pair<pest_rst::Rule>) -> Result<Target, Error> { +    let mut attrs = extra_attributes::Target { +        anonymous: false, +        ..Default::default() +    }; +    for p in pair.into_inner() { +        match p.as_rule() { +            // TODO: or is it refnames? +            Rule::target_name_uq | Rule::target_name_qu => attrs.refid = Some(ID(p.as_str().to_owned())), +            Rule::link_target => attrs.refuri = Some(Url::parse(p.as_str())?), +            rule => panic!("Unexpected rule in target: {:?}", rule), +        } +    } +    Ok(Target::new(Default::default(), attrs)) +} + +fn convert_admonition_gen(pair: pest::iterators::Pair<pest_rst::Rule>) -> Result<BodyElement, Error> { +    let mut iter = pair.into_inner(); +    let typ = iter.next().unwrap().as_str(); +    // TODO: in reality it contains body elements. +    let children: Vec<BodyElement> = iter.map(|p| Paragraph::with_children(vec![p.as_str().into()]).into()).collect(); +    Ok(match typ { +        "attention" => Attention::with_children(children).into(), +        "hint"      =>      Hint::with_children(children).into(), +        "note"      =>      Note::with_children(children).into(), +        "caution"   =>   Caution::with_children(children).into(), +        "danger"    =>    Danger::with_children(children).into(), +        "error"     =>   ErrorEl::with_children(children).into(), +        "important" => Important::with_children(children).into(), +        "tip"       =>       Tip::with_children(children).into(), +        "warning"   =>   Warning::with_children(children).into(), +        typ         => panic!("Unknown admontion type {}!", typ), +    }) +} +  /// tokens to Document tree. resolves sections, but not references  pub fn parse(source: &str) -> Result<Document, Error> { @@ -75,10 +127,7 @@ pub fn parse(source: &str) -> Result<Document, Error> {  /// only until we can serialize DocumentTrees  pub fn serialize_json<W>(source: &str, stream: W) -> Result<(), Error> where W: Write { -    use self::pest_rst::{RstParser, Rule}; -    use self::serialize::PairsWrap; -     -    let parsed = RstParser::parse(Rule::document, source)?; -    serde_json::to_writer(stream, &PairsWrap(parsed))?; +    let parsed = parse(source)?; +    serde_json::to_writer(stream, &parsed)?;      Ok(())  } diff --git a/src/parser/serialize.rs b/src/parser/serialize.rs deleted file mode 100644 index 260084f..0000000 --- a/src/parser/serialize.rs +++ /dev/null @@ -1,36 +0,0 @@ -use pest::{RuleType, iterators::{Pair, Pairs}}; -use serde::{ -    Serialize, -    Serializer, -    ser::{ -        SerializeSeq, -        SerializeStruct, -    }, -}; - -pub struct PairsWrap<'i, R>(pub Pairs<'i, R>); -pub struct PairWrap <'i, R>(pub Pair <'i, R>); - -impl<'i, R> Serialize for PairsWrap<'i, R> where R: RuleType { -    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer { -        let mut seq = serializer.serialize_seq(None)?; -        for pair in self.0.clone() { -            seq.serialize_element(&PairWrap(pair))?; -        } -        seq.end() -    } -} - -impl<'i, R> Serialize for PairWrap<'i, R> where R: RuleType { -    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer { -        let mut state = serializer.serialize_struct("Pair", 3)?; -        state.serialize_field("rule", &format!("{:?}", self.0.as_rule()))?; -        let tokens: Vec<_> = self.0.clone().tokens().collect(); -        if tokens.len() > 2 { -            state.serialize_field("inner", &PairsWrap(self.0.clone().into_inner()))?; -        } else { -            state.serialize_field("content", self.0.as_str())?; -        } -        state.end() -    } -} diff --git a/src/rst.pest b/src/rst.pest index 6608203..cd3baaf 100644 --- a/src/rst.pest +++ b/src/rst.pest @@ -14,6 +14,7 @@ block    = _{ PEEK[..] ~ hanging_block }  // This is d  hanging_block = _{      admonition +    | admonition_gen      | target      | title      | bullet_list @@ -37,10 +38,11 @@ hanging_block = _{  // | plain  } -// Admonition. A block type +// Admonition. A block type. The generic one has a title -admonition       =  { ".." ~ PUSH(" "+) ~ admonition_type ~ "::" ~ (blank_line | line) ~ blank_line* ~ admonition_body? ~ DROP } -admonition_type  =  { "attention" | "caution" | "danger" | "error" | "hint" | "important" | "note" | "tip" | "warning" | "admonition" } +admonition       =  { ".." ~ PUSH(" "+) ~ "admonition::"          ~               line  ~ blank_line* ~ admonition_body? ~ DROP } +admonition_gen   =  { ".." ~ PUSH(" "+) ~  admonition_type ~ "::" ~ (blank_line | line) ~ blank_line* ~ admonition_body? ~ DROP } +admonition_type  =  { "attention" | "caution" | "danger" | "error" | "hint" | "important" | "note" | "tip" | "warning" }  admonition_body  = _{ PEEK[..-1] ~ PUSH("  " ~ POP) ~ hanging_block ~ block* } //TODO: merge with other directives?  // Target. A block type | 
