From a2f689ce0dc79844583d04485d412dadec040545 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Mon, 5 Feb 2018 19:41:47 -0600 Subject: [PATCH] Cleanup and formatting. * Unused code warnings. * Ran cargo fmt. --- src/build.rs | 18 +++++--- src/convert/json.rs | 14 +++--- src/lib.rs | 108 ++++++++++++++++++++++---------------------- src/parse.rs | 18 -------- src/tokenizer.rs | 6 ++- 5 files changed, 78 insertions(+), 86 deletions(-) diff --git a/src/build.rs b/src/build.rs index e868fb7..5d06032 100644 --- a/src/build.rs +++ b/src/build.rs @@ -661,7 +661,8 @@ impl Builder { v.insert((count, expr_result)); count += 1; } - Entry::Occupied(mut v) => { // overriding field here. + Entry::Occupied(mut v) => { + // overriding field here. // Ensure that the new type matches the old type. let src_val = v.get().clone(); if src_val.1.type_equal(&expr_result) { @@ -681,12 +682,17 @@ impl Builder { // We want to maintain our order for the fields to make comparing tuples // easier in later code. So we sort by the field order before constructing a new tuple. new_fields.sort_by(|a, b| { - let ta = a.1.clone(); let tb = b.1.clone(); ta.0.cmp(&tb.0) + let ta = a.1.clone(); + let tb = b.1.clone(); + ta.0.cmp(&tb.0) }); - return Ok(Rc::new(Val::Tuple(new_fields.iter().map(|a| { - let first = a.0.clone(); let t = a.1.clone(); - (first, t.1) - }).collect()))); + return Ok(Rc::new(Val::Tuple(new_fields.iter() + .map(|a| { + let first = a.0.clone(); + let t = a.1.clone(); + (first, t.1) + }) + .collect()))); } Err(Box::new(error::Error::new(format!("Expected Tuple got {}", v), error::ErrorType::TypeFail, diff --git a/src/convert/json.rs b/src/convert/json.rs index 0816061..0cd73c9 100644 --- a/src/convert/json.rs +++ b/src/convert/json.rs @@ -33,7 +33,9 @@ impl JsonConverter { Ok(serde_json::Value::Array(v)) } - fn convert_tuple(&self, items: &Vec<(ast::Positioned, Rc)>) -> Result { + fn convert_tuple(&self, + items: &Vec<(ast::Positioned, Rc)>) + -> Result { 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))); @@ -50,7 +52,7 @@ impl JsonConverter { 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, @@ -58,20 +60,20 @@ impl JsonConverter { 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)); @@ -83,4 +85,4 @@ impl Converter for JsonConverter { fn convert(&self, v: Rc, mut w: Box) -> Result<()> { self.write(&v, &mut w) } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 14cd6f5..04a8762 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,22 +14,22 @@ // #![feature(trace_macros,log_syntax)] //! # ucg, A universal configuration grammar. -//! +//! //! Ucg defines a common grammar for describing a collection of configuration values. //! ucg allows you to specify configuration values with a syntax that that is immutable, //! comoposable with copy-on-write semantics, and safe. -//! +//! //! ## Example -//! +//! //! ```ucg //! // named bindings //! let host = "mysql.internal.net"; //! let port = 8080 -//! -//! // format strings +//! +//! // format strings //! let connstr = "mysql://@:@" % (host, port); //! -//! // tuples +//! // tuples //! let dbconf = { //! connstr = connstr, //! database = "mydb", @@ -37,17 +37,17 @@ //! tables = ["posts", "comments", "users"], //! }; //! ``` -//! +//! //! ## Syntax -//! +//! //! ucg is a safe language with type inference that tries to guarantee that it will halt. //! A valid ucg file is composesed of a series of statements. Statements are any valid //! ucg expression terminated by a semicolon. -//! +//! //! ### Reserved words -//! +//! //! The following words are reserved in ucg and can't be used as named bindings. -//! +//! //! * let //! * import //! * as @@ -55,50 +55,50 @@ //! * macro //! //! ### Primitive types -//! +//! //! ucg has a relatively simple syntax with 3 primitive types, Int, Float, and String. -//! +//! //! * Int, is any integer number. //! * Float is any number with a decimal point. -//! +//! //! ```ucg //! 1.0; // A typical float. //! 1. // You can leave off the 0 after the decimal point. //! .1 // the leading 0 is also optional. //! ``` -//! +//! //! * String is any quoted text. backslashes within a string escape the next preceding //! character. -//! +//! //! ``` ucg //! "foo"; // a smiple string //! "I'm a \"fine\" looking string"; // escaped quotes in a string. //! ``` //! //! ### Complex types -//! +//! //! ucg has two complex data types, Lists and Tuples. -//! +//! //! * List's start are surrounded with square brackets `[ ]` and have comma separated elements. -//! +//! //! ```ucg //! [1, 2, 3]; // A simple list of numbers. //! -//! [[1, 2], [3, 4]] // A deep list with embedded lists inside. +//! [[1, 2], [3, 4]] // A deep list with embedded lists inside. //! ``` -//! +//! //! Lists are 0 indexed and you can index into them using the dotted selector syntax. -//! +//! //! ```ucg //! let mylist = [0, 1, 2, 3]; -//! +//! //! let zero = mylist.0; //! ``` -//! +//! //! * Tuple's are an ordered collection of name, value pairs. They are bounded by curly braces `{ }` //! and contain name = value pairs separated by commas. Trailing commas are permitted. The name must //! be a bareword without quotes. -//! +//! //! ```ucg //! let mytuple = { //! field1 = "value1", @@ -111,17 +111,17 @@ //! ```ucg //! let field = mytuple.fields1; //! ``` -//! +//! //! ### Expressions -//! +//! //! #### Selectors -//! +//! //! Selectors are references to a bound value in ucg. They can index arbitrarily deep into either tuples or lists. //! The head of a selector can be any expression that resolves to a tuple or list. Optionally a selector can also be //! followed by either a bareword to index a tuple field or an integer to index a list position. -//! +//! //! The simplest selector is just a reference to a bound value by name. -//! +//! //! ```ucg //! let mytuple = { //! field1 = "a string", @@ -129,7 +129,7 @@ //! subfield1 = 1, //! }]; //! }; -//! +//! //! mytuple.field2.0; // descend into a deeply nested tuple and array. //! ``` //! @@ -138,59 +138,59 @@ //! ucg supports the following operators, +, -, *, /; Each one is type safe and infers the types from the values they operate on. //! The operators expect both the left and right operands to be of the same type. All of the operators are valid on integers and floats. //! The + operator can additionally concatenate strings or arrays. -//! +//! //! ```ucg //! 1 + 1; // result is 2 //! "foo " + "bar" // result is "foo bar" //! [1,2] + [3,4]; // result is [1,2,3,4] -//! ``` -//! +//! ``` +//! //! #### Conditional data. -//! +//! //! ucg supports a limited form of conditional selection of data using the select expression. A select expression starts with the select //! keyword and is followed by a an expression resolving to a string naming the field to select, an expression resolving to the default value, //! and a tuple to select the field from. If the field selected is not in the tuple then the default value will be used. -//! +//! //! ```ucg //! let want = "baz"; -//! +//! //! // field default //! select want, "quux", { //! baz = "foo", //! fuzz = "bang", //! }; // result will be "foo" //! -//! // field default +//! // field default //! select "quack", "quux", { //! baz = "foo", //! fuzz = "bang", //! }; // result will be "quux" //! ``` -//! +//! //! #### Macros -//! +//! //! Macros look like functions but they are resolved at compile time and configurations don't execute so they never appear in output. //! They are useful for constructing tuples of a certain shape or otherwise promoting data reuse. You define a macro with the macro //! keyword followed by the arguments in parentheses and then a tuple. -//! +//! //! ```ucg //! let myfunc = macro (arg1, arg2) { //! host = arg1, //! port = arg2, //! connstr = "couchdb://@:@" % (arg1, arg2), //! } -//! +//! //! let my dbconf = myfunc("couchdb.example.org", "9090"); -//! +//! //! let my dbhost = dbconf.host; //! ``` -//! +//! //! macros always resolve to a tuple. If you want to get a single value out you can use selector syntax to retrieve it. -//! +//! //! ### Statements -//! +//! //! There are 3 kinds of statements in a ucg configuration file. expression statements, let statements, and import statements. -//! +//! //! * expression statements //! The simplest and least useful is the expression statements. It is any valid expression followed by a semicolon. //! @@ -199,27 +199,27 @@ //! 4 / 2; //! "foo"; //! "foo" + "bar"; -//! ``` +//! ``` //! //! Despite the fact that these are valid the results are thrown away and can essentially be considered a noop. If we //! ever create a repl for ucg statements they may prove more useful. -//! +//! //! * Let statements //! The let expression binds the result of any valid expression to a name. It starts with the let keyword and is followed by -//! the name of the binding, =, and a valid ucg expression. -//! +//! the name of the binding, =, and a valid ucg expression. +//! //! ```ucg //! let name = "foo"; //! ``` -//! +//! //! * Import statement //! The import statement imports the contents of another ucg file into the current file with a name. The imported files bound //! values are exposed as a tuple in the referencing file. It starts with the import keyword and is followed by a quoted path //! to the ucg file, they keyword as, and a name for the imported values. -//! +//! //! ```ucg //! import "dbconfigs.ucg" as dbconfigs; -//! +//! //! let mysqlconf = dbconfigs.mysql; //! ``` #[macro_use] diff --git a/src/parse.rs b/src/parse.rs index 7cecccb..4af6789 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -677,24 +677,6 @@ mod test { } } - macro_rules! assert_incomplete { - ($parsemac:ident( $i:expr )) => { - assert_incomplete!($i, $parsemac) - }; - ($i:expr, $f:expr) => { - { - let input = LocatedSpan::new($i); - match tokenize(input) { - Err(_) => assert!(false), - Ok(val) => { - let result = $f(TokenIter{source: val.as_slice()}); - assert!(result.is_incomplete(), format!("Not Incomplete: {:?}", result)); - }, - } - } - } - } - macro_rules! assert_error { ($parsemac:ident( $i:expr )) => { assert_error!($i, $parsemac) diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 8a66e7e..7cebe2e 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -40,9 +40,11 @@ fn escapequoted(input: Span) -> nom::IResult { let mut frag = String::new(); let mut escape = false; for (i, c) in input.iter_indices() { - if c == '\\' && ! escape { // eat this slash and set our escaping sentinel + if c == '\\' && !escape { + // eat this slash and set our escaping sentinel escape = true; - } else if c == '"' && !escape { // Bail if this is an unescaped " + } else if c == '"' && !escape { + // Bail if this is an unescaped " // we exit here. return nom::IResult::Done(input.slice(i..), frag); } else {