diff options
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | src/bin.rs | 5 | ||||
| -rw-r--r-- | src/parser/mod.rs | 3 | ||||
| -rw-r--r-- | src/parser/serialize.rs | 36 | ||||
| -rw-r--r-- | src/rst.pest | 10 | 
5 files changed, 48 insertions, 9 deletions
| @@ -26,8 +26,9 @@ bitflags = '1.0.4'  unicode_categories = '0.1.1'  pest = '2.0.2'  pest_derive = '2.0.1' +serde = '1.0.80' +serde_json = '1.0.32'  quicli = '0.3.1'  structopt = '0.2.12' -structopt-derive = '0.2.12'  clap = '2.32.0' @@ -6,7 +6,7 @@ use structopt::StructOpt;  use clap::{_clap_count_exprs, arg_enum};  use quicli::{main, fs::read_file, prelude::Verbosity}; -use self::parser::{RstParser, Rule}; +use self::parser::{RstParser, Rule, serialize::PairsWrap};  arg_enum! { @@ -30,7 +30,8 @@ struct Cli {  main!(|args: Cli, log_level: verbosity| {      let content = read_file(args.file)?;      let parsed = RstParser::parse(Rule::doc, &content)?; +    let stdout = std::io::stdout();      match args.format { -        Format::json => println!("{}", parsed.to_string()) +        Format::json => serde_json::to_writer(stdout, &PairsWrap(parsed))?,      }  }); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 2ae47cb..26470e8 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,10 +1,11 @@  pub mod token; +pub mod serialize;  #[allow(unused_imports)]  use pest::consumes_to;  #[allow(unused_imports)]  use pest::parses_to; -use pest_derive::*; +use pest_derive::Parser;  #[derive(Parser)]  #[grammar = "rst.pest"] diff --git a/src/parser/serialize.rs b/src/parser/serialize.rs new file mode 100644 index 0000000..260084f --- /dev/null +++ b/src/parser/serialize.rs @@ -0,0 +1,36 @@ +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 f087c2e..9f92ef7 100644 --- a/src/rst.pest +++ b/src/rst.pest @@ -444,7 +444,7 @@ code = { ticks_2 ~ ( (!"`" ~ nonspacechar)+ | "_" | !ticks_2 ~ "`" | !(sp ~ tick  raw_html = { (html_comment | html_block_script | html_tag) } -blank_line = { sp ~ NEWLINE } +blank_line = _{ sp ~ NEWLINE }  quoted = {      "\"" ~ (!"\"" ~ ANY)* ~ "\"" | @@ -483,16 +483,16 @@ hex_entity = { "&#" ~ ("X"|"x") ~ ('0'..'9' | 'a'..'f' | 'A'..'F')+ ~ ";" }  dec_entity = { "&#" ~ ASCII_DIGIT+ ~ ";" }  char_entity = { "&" ~ ASCII_ALPHANUMERIC+ ~ ";" } -nonindent_space = { "  " | " " | "" } -indent = { "\t" | "   " } +nonindent_space = _{ "  " | " " | "" } +indent = _{ "\t" | "   " }  indented_line = { indent ~ line }  optionally_indented_line = { indent? ~ line }  doctest_line = { ">>> " ~ raw_line } -line = { raw_line } +line = _{ raw_line } -raw_line = { (!NEWLINE ~ ANY)* ~ NEWLINE | (!EOI ~ ANY)+ ~ EOI } +raw_line = _{ (!NEWLINE ~ ANY)* ~ NEWLINE | (!EOI ~ ANY)+ ~ EOI }  skip_block = {      html_block | | 
