mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
Add json as an output type.
* Uses serde_json * Doesn't handle macro values very well. * Handles maps and lists just fine. * doesn't pretty print the values though.
This commit is contained in:
parent
97c97ced55
commit
5fba06d71f
@ -14,6 +14,7 @@ version = "^3.2"
|
||||
[dependencies]
|
||||
nom_locate = "^0.1.1"
|
||||
clap = "~2.26.0"
|
||||
serde_json = "~1.0.9"
|
||||
|
||||
[lib]
|
||||
name = "ucglib"
|
||||
|
3
TODO.md
3
TODO.md
@ -5,11 +5,12 @@
|
||||
You should be able to ask the compiler to tell you any value or set of values in the
|
||||
compiled configuration.
|
||||
|
||||
## Translation Language (Experiemental)
|
||||
## Translation Language (Experimental)
|
||||
|
||||
For some configuration file formats we need a way to specify a particular
|
||||
organiztion for a given configuration structure. Some options here could be
|
||||
|
||||
* Simple data export (json)
|
||||
* A Functional Transform similar to xslt or css transforms.
|
||||
* A Templating language
|
||||
* Annotations.
|
||||
|
@ -25,9 +25,7 @@ impl FlagConverter {
|
||||
pub fn new() -> Self {
|
||||
FlagConverter {}
|
||||
}
|
||||
}
|
||||
|
||||
impl FlagConverter {
|
||||
fn write(&self, v: &Val, w: &mut Write) -> Result<()> {
|
||||
match v {
|
||||
&Val::Float(ref f) => {
|
||||
@ -45,6 +43,10 @@ impl FlagConverter {
|
||||
}
|
||||
&Val::Tuple(ref flds) => {
|
||||
for &(ref name, ref val) in flds.iter() {
|
||||
if val.is_tuple() {
|
||||
eprintln!("Skipping embedded tuple...");
|
||||
return Ok(());
|
||||
}
|
||||
try!(write!(w, "--{} ", name.val));
|
||||
// TODO(jwall): What if the value is a tuple?
|
||||
try!(self.write(&val, w));
|
||||
@ -61,6 +63,6 @@ impl FlagConverter {
|
||||
|
||||
impl Converter for FlagConverter {
|
||||
fn convert(&self, v: Rc<Val>, mut w: Box<Write>) -> Result<()> {
|
||||
return self.write(&v, &mut w);
|
||||
self.write(&v, &mut w)
|
||||
}
|
||||
}
|
||||
|
86
src/convert/json.rs
Normal file
86
src/convert/json.rs
Normal file
@ -0,0 +1,86 @@
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::io::Write;
|
||||
use std::io::Result;
|
||||
|
||||
use serde_json;
|
||||
|
||||
use ast;
|
||||
use build::Val;
|
||||
use convert::traits::Converter;
|
||||
|
||||
pub struct JsonConverter {}
|
||||
|
||||
impl JsonConverter {
|
||||
pub fn new() -> Self {
|
||||
JsonConverter {}
|
||||
}
|
||||
|
||||
fn convert_list(&self, items: &Vec<Rc<Val>>) -> Result<serde_json::Value> {
|
||||
let mut v = Vec::new();
|
||||
for val in items.iter() {
|
||||
v.push(try!(self.convert_value(val)));
|
||||
}
|
||||
Ok(serde_json::Value::Array(v))
|
||||
}
|
||||
|
||||
fn convert_tuple(&self, items: &Vec<(ast::Positioned<String>, Rc<Val>)>) -> Result<serde_json::Value> {
|
||||
let mut mp = serde_json::Map::new();
|
||||
for &(ref k, ref v) in items.iter() {
|
||||
mp.entry(k.val.clone()).or_insert(try!(self.convert_value(v)));
|
||||
}
|
||||
Ok(serde_json::Value::Object(mp))
|
||||
}
|
||||
|
||||
fn convert_value(&self, v: &Val) -> Result<serde_json::Value> {
|
||||
let jsn_val = match v {
|
||||
&Val::Float(f) => {
|
||||
let n = match serde_json::Number::from_f64(f) {
|
||||
Some(n) => n,
|
||||
// In theory this should never happen. But on the off chance that it does...
|
||||
None => panic!("Float is too large or Not a Number {}", f),
|
||||
};
|
||||
serde_json::Value::Number(n)
|
||||
},
|
||||
&Val::Int(i) => {
|
||||
let n = match serde_json::Number::from_f64(i as f64) {
|
||||
Some(n) => n,
|
||||
// In theory this should never happen. But on the off chance that it does...
|
||||
None => panic!("Float is too large or Not a Number {}", i),
|
||||
};
|
||||
serde_json::Value::Number(n)
|
||||
},
|
||||
&Val::String(ref s) => serde_json::Value::String(s.clone()),
|
||||
&Val::Macro(_) => {
|
||||
// TODO(jwall): We probably want to actually skip this but for now
|
||||
// we'll use null
|
||||
eprintln!("Skipping macro encoding as null...");
|
||||
serde_json::Value::Null
|
||||
},
|
||||
&Val::List(ref l) => try!(self.convert_list(l)),
|
||||
&Val::Tuple(ref t) => try!(self.convert_tuple(t)),
|
||||
};
|
||||
Ok(jsn_val)
|
||||
}
|
||||
|
||||
fn write(&self, v: &Val, w: &mut Write) -> Result<()> {
|
||||
let jsn_val = try!(self.convert_value(v));
|
||||
try!(serde_json::to_writer(w, &jsn_val));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Converter for JsonConverter {
|
||||
fn convert(&self, v: Rc<Val>, mut w: Box<Write>) -> Result<()> {
|
||||
self.write(&v, &mut w)
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
pub mod flags;
|
||||
pub mod json;
|
||||
pub mod traits;
|
||||
|
||||
use std::io;
|
||||
@ -29,6 +30,9 @@ impl ConverterRunner {
|
||||
if typ == "flags" {
|
||||
return Ok(ConverterRunner { converter: Box::new(flags::FlagConverter::new()) });
|
||||
}
|
||||
if typ == "json" {
|
||||
return Ok(ConverterRunner { converter: Box::new(json::JsonConverter::new()) });
|
||||
}
|
||||
return Err(format!("Unknown Target output type: {}", typ));
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
extern crate nom;
|
||||
#[macro_use]
|
||||
extern crate nom_locate;
|
||||
extern crate serde_json;
|
||||
|
||||
#[macro_use]
|
||||
pub mod ast;
|
||||
|
@ -34,7 +34,7 @@ fn do_flags<'a>() -> clap::ArgMatches<'a> {
|
||||
(@subcommand build =>
|
||||
(about: "Compile a specific ucg file.")
|
||||
(@arg sym: --sym +takes_value "Specify a specific let binding in the ucg file to output.")
|
||||
(@arg target: --target -t +required +takes_value "Target output type.")
|
||||
(@arg target: --target -t +required +takes_value "Target output type. (flags, json)")
|
||||
(@arg out: --out -o +takes_value "Output file to write to.")
|
||||
(@arg INPUT: +required "Input ucg file to build.")
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user