diff options
| author | Philipp A | 2018-11-16 15:15:37 +0100 | 
|---|---|---|
| committer | Philipp A | 2018-11-16 15:15:37 +0100 | 
| commit | 8f8270f4b4745087dcddba60b23d88d6f3fa4fb6 (patch) | |
| tree | 904b25c7d2a33234bf9947308f8c59d354418034 | |
| parent | 6316d8374655ff3debe33defc7697844fc8a7cb6 (diff) | |
| download | rust-rst-8f8270f4b4745087dcddba60b23d88d6f3fa4fb6.tar.bz2 | |
First doctree conversion code
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/bin.rs | 8 | ||||
| -rw-r--r-- | src/parser.rs | 82 | ||||
| -rw-r--r-- | src/parser/tests.rs | 2 | 
4 files changed, 84 insertions, 10 deletions
| @@ -21,6 +21,8 @@ name = "rst"  path = "src/bin.rs"  [dependencies] +failure = '0.1.3' +failure_derive = '0.1.3'  url = '1.7.2'  bitflags = '1.0.4'  unicode_categories = '0.1.1' @@ -1,13 +1,12 @@ +pub mod document_tree;  pub mod parser; -use pest::Parser;  use structopt::StructOpt;  use clap::{_clap_count_exprs, arg_enum};  use quicli::{main, fs::read_file, prelude::Verbosity}; -use self::parser::{RstParser, Rule, serialize::PairsWrap}; - +use self::parser::serialize_json;  arg_enum! {      #[derive(Debug)] @@ -29,9 +28,8 @@ struct Cli {  main!(|args: Cli, log_level: verbosity| {      let content = read_file(args.file)?; -    let parsed = RstParser::parse(Rule::document, &content)?;      let stdout = std::io::stdout();      match args.format { -        Format::json => serde_json::to_writer(stdout, &PairsWrap(parsed))?, +        Format::json => serialize_json(&content, stdout)?,      }  }); diff --git a/src/parser.rs b/src/parser.rs index 026024a..fa12b3e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3,8 +3,82 @@ pub mod serialize;  #[cfg(test)]  pub mod tests; -use pest_derive::Parser; +mod pest_rst { +    use pest_derive::Parser; +     +    #[derive(Parser)] +    #[grammar = "rst.pest"] +    pub struct RstParser; +} +use self::pest_rst::Rule; -#[derive(Parser)] -#[grammar = "rst.pest"] -pub struct RstParser; +use std::io::Write; + +use failure::Error; +use failure_derive::Fail; + +use pest::Parser; + +use crate::document_tree::{ +    HasChildren, +    elements::{ +        Document, +        Title, +    }, +    element_categories::{ +        StructuralSubElement +    }, +}; + + +#[derive(Debug, Fail)] +enum ConversionError { +    #[fail(display = "unknown rule: {:?}", rule)] +    UnknownRuleError { +        rule: Rule, +    }, +} + + +fn convert_ssubel(pair: pest::iterators::Pair<Rule>) -> Result<StructuralSubElement, Error> { +    match pair.as_rule() { +        Rule::title => Ok(convert_title(pair).into()), +        rule => Err(ConversionError::UnknownRuleError { rule }.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; +    for p in pair.into_inner() { +        match p.as_rule() { +            Rule::line => title = Some(p.as_str()), +            Rule::adornments => adornment_char = Some(p.as_str().chars().next().expect("Empty adornment?")), +            rule => panic!("Unexpected rule in title: {:?}", rule), +        }; +    } +    // TODO adornment char +    Title::with_children(vec![ +        title.expect("No text in title").into() +    ]) +} + + +/// tokens to Document tree. resolves sections, but not references +pub fn parse(source: &str) -> Result<Document, Error> { +    let pairs = pest_rst::RstParser::parse(pest_rst::Rule::document, source)?; +    let structural_elems = pairs.map(convert_ssubel).collect::<Result<_, _>>()?; +    Ok(Document::with_children(structural_elems)) +} + + +/// 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))?; +    Ok(()) +} diff --git a/src/parser/tests.rs b/src/parser/tests.rs index 243cb26..40af5ac 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -1,6 +1,6 @@  use pest::consumes_to;  use pest::parses_to; -use super::{RstParser, Rule}; +use super::pest_rst::{RstParser, Rule};  #[test]  fn plain() { | 
