aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp A2018-11-20 00:48:06 +0100
committerPhilipp A2018-11-20 00:48:06 +0100
commitd9ff9626417ab29cfa7054ad755052d3e5a08f5b (patch)
tree7ba5253cbad2975ec7eae1551723ed1126454fb6
parentb136f04bc225380a6aa5daa28075eafd767a4a98 (diff)
downloadrust-rst-d9ff9626417ab29cfa7054ad755052d3e5a08f5b.tar.bz2
Serializing document trees!
-rw-r--r--src/document_tree/attribute_types.rs4
-rw-r--r--src/document_tree/extra_attributes.rs4
-rw-r--r--src/parser.rs65
-rw-r--r--src/parser/serialize.rs36
-rw-r--r--src/rst.pest8
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