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 /src | |
| parent | 6316d8374655ff3debe33defc7697844fc8a7cb6 (diff) | |
| download | rust-rst-8f8270f4b4745087dcddba60b23d88d6f3fa4fb6.tar.bz2 | |
First doctree conversion code
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin.rs | 8 | ||||
| -rw-r--r-- | src/parser.rs | 82 | ||||
| -rw-r--r-- | src/parser/tests.rs | 2 |
3 files changed, 82 insertions, 10 deletions
@@ -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() { |
