cargo fmt pass with the new rustfmt-preview

This commit is contained in:
Jeremy Wall 2018-02-15 19:55:43 -06:00
parent f105d93c14
commit bafe5b3c30
7 changed files with 1052 additions and 738 deletions

View File

@ -25,7 +25,7 @@ use std::hash::Hasher;
use std::hash::Hash;
/// Encodes a parsing error with position information and a helpful description.
#[derive(Debug,PartialEq)]
#[derive(Debug, PartialEq)]
pub struct ParseError {
pub pos: Position,
pub description: String,
@ -33,11 +33,11 @@ pub struct ParseError {
impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f,
"Parsing Error {} at line: {} column: {}",
self.description,
self.pos.line,
self.pos.column)
write!(
f,
"Parsing Error {} at line: {} column: {}",
self.description, self.pos.line, self.pos.column
)
}
}
@ -47,7 +47,6 @@ impl std::error::Error for ParseError {
}
}
macro_rules! enum_type_equality {
( $slf:ident, $r:expr, $( $l:pat ),* ) => {
match $slf {
@ -65,10 +64,10 @@ macro_rules! enum_type_equality {
}
/// Represents a line and a column position in UCG code.
///
///
/// It is used for generating error messages mostly. Most all
/// parts of the UCG AST have a positioned associated with them.
#[derive(Debug,PartialEq,Eq,Clone,PartialOrd,Ord,Hash)]
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
pub struct Position {
pub line: usize,
pub column: usize,
@ -85,7 +84,7 @@ impl Position {
}
/// Defines the types of tokens in UCG syntax.
#[derive(Debug,PartialEq,Eq,Clone,PartialOrd,Ord,Hash)]
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
pub enum TokenType {
END,
WS,
@ -99,9 +98,9 @@ pub enum TokenType {
// FIXME(jwall): We should probably implement copy for this.
/// Defines a Token representing a building block of UCG syntax.
///
///
/// Token's are passed to the parser stage to be parsed into an AST.
#[derive(Debug,PartialEq,Eq,Clone,PartialOrd,Ord,Hash)]
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
pub struct Token {
pub typ: TokenType,
pub fragment: String,
@ -146,27 +145,27 @@ macro_rules! make_tok {
( EOF => $l:expr, $c:expr ) => {
Token::new("", TokenType::END, $l, $c)
};
( WS => $l:expr, $c:expr ) => {
Token::new("", TokenType::WS, $l, $c)
};
( CMT => $e:expr, $l:expr, $c:expr ) => {
Token::new($e, TokenType::COMMENT, $l, $c)
};
( QUOT => $e:expr, $l:expr, $c:expr ) => {
Token::new($e, TokenType::QUOTED, $l, $c)
};
( PUNCT => $e:expr, $l:expr, $c:expr ) => {
Token::new($e, TokenType::PUNCT, $l, $c)
};
( DIGIT => $e:expr, $l:expr, $c:expr ) => {
Token::new($e, TokenType::DIGIT, $l, $c)
};
( $e:expr, $l:expr, $c:expr ) => {
Token::new($e, TokenType::BAREWORD, $l, $c)
};
@ -182,7 +181,7 @@ macro_rules! make_expr {
( $e:expr, $l:expr, $c:expr ) => {
Expression::Simple(Value::Symbol(Positioned::new($e.to_string(), $l, $c)))
};
( $e:expr => int, $l:expr, $c:expr ) => {
Expression::Simple(Value::Int(Positioned::new($e, $l, $c)))
};
@ -223,15 +222,15 @@ macro_rules! make_selector {
make_selector!($h => [ $( $item, )* ] => 1, 1)
}
};
( $h:expr => [ $( $item:expr ),* ] => $l:expr, $c:expr ) => {
{
let mut list: Vec<Token> = Vec::new();
$(
list.push($item);
)*
make_selector!($h, list, $l, $c)
}
};
@ -242,25 +241,25 @@ macro_rules! make_selector {
let mut col = 1;
let mut list: Vec<Token> = Vec::new();
$(
list.push(make_tok!($item, 1, col));
col += $item.len() + 1;
)*
// Shut up the lint about unused code;
assert!(col != 0);
make_selector!($h, list, 1, 1)
make_selector!($h, list, 1, 1)
}
};
( $h:expr => $( $item:expr ),* => $l:expr, $c:expr ) => {
{
let mut col = $c;
let mut list: Vec<Token> = Vec::new();
$(
list.push(make_tok!($item, $l, col));
col += $item.len() + 1;
@ -269,7 +268,7 @@ macro_rules! make_selector {
// Shut up the linter about unused code;
assert!(col != 0);
make_selector!($h, list, $l, $c)
make_selector!($h, list, $l, $c)
}
};
}
@ -290,7 +289,7 @@ macro_rules! make_selector {
/// let berry = {best = "strawberry", unique = "acai"}.best;
/// let third = ["uno", "dos", "tres"].1;
/// '''
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub struct SelectorList {
pub head: Box<Expression>,
pub tail: Option<Vec<Token>>,
@ -304,12 +303,12 @@ impl SelectorList {
}
/// An ordered list of Name = Value pairs.
///
///
/// This is usually used as the body of a tuple in the UCG AST.
pub type FieldList = Vec<(Token, Expression)>; // Token is expected to be a symbol
/// Encodes a selector expression in the UCG AST.
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub struct SelectorDef {
pub pos: Position,
pub sel: SelectorList,
@ -326,7 +325,7 @@ impl SelectorDef {
}
/// Represents a Value in the UCG parsed AST.
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub enum Value {
// Constant Values
Int(Positioned<i64>),
@ -397,19 +396,23 @@ impl Value {
/// Returns true if called on a Value that is the same type as itself.
pub fn type_equal(&self, target: &Self) -> bool {
enum_type_equality!(self, target, &Value::Int(_),
&Value::Float(_),
&Value::String(_),
&Value::Symbol(_),
&Value::Tuple(_),
&Value::List(_),
&Value::Selector(_))
enum_type_equality!(
self,
target,
&Value::Int(_),
&Value::Float(_),
&Value::String(_),
&Value::Symbol(_),
&Value::Tuple(_),
&Value::List(_),
&Value::Selector(_)
)
}
}
/// Represents an expansion of a Macro that is expected to already have been
/// defined.
#[derive(PartialEq,Debug,Clone)]
#[derive(PartialEq, Debug, Clone)]
pub struct CallDef {
pub macroref: SelectorDef,
pub arglist: Vec<Expression>,
@ -417,7 +420,7 @@ pub struct CallDef {
}
/// Encodes a select expression in the UCG AST.
#[derive(PartialEq,Debug,Clone)]
#[derive(PartialEq, Debug, Clone)]
pub struct SelectDef {
pub val: Box<Expression>,
pub default: Box<Expression>,
@ -428,7 +431,7 @@ pub struct SelectDef {
// TODO(jwall): This should have a way of rendering with position information.
/// Adds position information to any type `T`.
#[derive(Debug,Clone)]
#[derive(Debug, Clone)]
pub struct Positioned<T> {
pub pos: Position,
pub val: T,
@ -495,7 +498,7 @@ impl<'a> From<&'a Positioned<String>> for Positioned<String> {
/// A macro is a pure function over a tuple.
/// MacroDefs are not closures. They can not reference
/// any values except what is defined in their arguments.
#[derive(PartialEq,Debug,Clone)]
#[derive(PartialEq, Debug, Clone)]
pub struct MacroDef {
pub argdefs: Vec<Positioned<String>>,
pub fields: FieldList,
@ -512,10 +515,11 @@ impl MacroDef {
return false;
}
fn validate_value_symbols<'a>(&self,
stack: &mut Vec<&'a Expression>,
val: &'a Value)
-> HashSet<String> {
fn validate_value_symbols<'a>(
&self,
stack: &mut Vec<&'a Expression>,
val: &'a Value,
) -> HashSet<String> {
let mut bad_symbols = HashSet::new();
if let &Value::Symbol(ref name) = val {
if !self.symbol_is_in_args(&name.val) {
@ -572,11 +576,9 @@ impl MacroDef {
stack.push(expr);
}
}
&Expression::Call(ref def) => {
for expr in def.arglist.iter() {
stack.push(expr);
}
}
&Expression::Call(ref def) => for expr in def.arglist.iter() {
stack.push(expr);
},
&Expression::Simple(ref val) => {
let mut syms_set = self.validate_value_symbols(&mut stack, val);
bad_symbols.extend(syms_set.drain());
@ -597,7 +599,7 @@ impl MacroDef {
/// Specifies the types of binary operations supported in
/// UCG expression.
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub enum BinaryExprType {
Add,
Sub,
@ -606,7 +608,7 @@ pub enum BinaryExprType {
}
/// Represents an expression with a left and a right side.
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub struct BinaryOpDef {
pub kind: BinaryExprType,
pub left: Value,
@ -615,7 +617,7 @@ pub struct BinaryOpDef {
}
/// Encodes a tuple Copy expression in the UCG AST.
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub struct CopyDef {
pub selector: SelectorDef,
pub fields: FieldList,
@ -623,7 +625,7 @@ pub struct CopyDef {
}
/// Encodes a format expression in the UCG AST.
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub struct FormatDef {
pub template: String,
pub args: Vec<Expression>,
@ -631,14 +633,14 @@ pub struct FormatDef {
}
/// Encodes a list expression in the UCG AST.
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub struct ListDef {
pub elems: Vec<Expression>,
pub pos: Position,
}
/// Encodes a ucg expression. Expressions compute a value from.
#[derive(Debug,PartialEq,Clone)]
#[derive(Debug, PartialEq, Clone)]
pub enum Expression {
// Base Expression
Simple(Value),
@ -672,21 +674,21 @@ impl Expression {
}
/// Encodes a let statement in the UCG AST.
#[derive(Debug,PartialEq)]
#[derive(Debug, PartialEq)]
pub struct LetDef {
pub name: Token,
pub value: Expression,
}
/// Encodes an import statement in the UCG AST.
#[derive(Debug,PartialEq)]
#[derive(Debug, PartialEq)]
pub struct ImportDef {
pub path: Token,
pub name: Token,
}
/// Encodes a parsed statement in the UCG AST.
#[derive(Debug,PartialEq)]
#[derive(Debug, PartialEq)]
pub enum Statement {
// simple expression
Expression(Expression),
@ -707,12 +709,15 @@ mod ast_test {
let def = MacroDef {
argdefs: vec![value_node!("foo".to_string(), 1, 0)],
fields: vec![
(make_tok!("f1", 1, 1), Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add,
left: Value::Symbol(value_node!("foo".to_string(), 1, 1)),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
pos: Position::new(1, 0),
})),
(
make_tok!("f1", 1, 1),
Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add,
left: Value::Symbol(value_node!("foo".to_string(), 1, 1)),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
pos: Position::new(1, 0),
}),
),
],
pos: Position::new(1, 0),
};
@ -724,12 +729,15 @@ mod ast_test {
let def = MacroDef {
argdefs: vec![value_node!("foo".to_string(), 1, 0)],
fields: vec![
(make_tok!("f1", 1, 1), Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add,
left: Value::Symbol(value_node!("bar".to_string(), 1, 1)),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
pos: Position::new(1, 0),
})),
(
make_tok!("f1", 1, 1),
Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add,
left: Value::Symbol(value_node!("bar".to_string(), 1, 1)),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
pos: Position::new(1, 0),
}),
),
],
pos: Position::new(1, 0),
};
@ -743,13 +751,16 @@ mod ast_test {
let def = MacroDef {
argdefs: vec![value_node!("foo".to_string(), 1, 0)],
fields: vec![
(make_tok!("f1", 1, 1), Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add,
left: Value::Selector(make_selector!(make_expr!("foo", 1, 1) => [
(
make_tok!("f1", 1, 1),
Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add,
left: Value::Selector(make_selector!(make_expr!("foo", 1, 1) => [
make_tok!("quux", 1, 1) ] => 1, 1)),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
pos: Position::new(1, 0),
})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
pos: Position::new(1, 0),
}),
),
],
pos: Position::new(1, 0),
};
@ -761,13 +772,16 @@ mod ast_test {
let def = MacroDef {
argdefs: vec![value_node!("foo".to_string(), 1, 0)],
fields: vec![
(make_tok!("f1", 1, 1), Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add,
left: Value::Selector(make_selector!(make_expr!("bar", 1, 1) => [
(
make_tok!("f1", 1, 1),
Expression::Binary(BinaryOpDef {
kind: BinaryExprType::Add,
left: Value::Selector(make_selector!(make_expr!("bar", 1, 1) => [
make_tok!("quux", 1, 1) ] => 1, 1)),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
pos: Position::new(1, 0),
})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1, 1, 1)))),
pos: Position::new(1, 0),
}),
),
],
pos: Position::new(1, 0),
};

View File

@ -34,12 +34,14 @@ impl JsonConverter {
Ok(serde_json::Value::Array(v))
}
fn convert_tuple(&self,
items: &Vec<(ast::Positioned<String>, Rc<Val>)>)
-> Result<serde_json::Value> {
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)));
mp.entry(k.val.clone())
.or_insert(try!(self.convert_value(v)));
}
Ok(serde_json::Value::Object(mp))
}

View File

@ -75,10 +75,7 @@ impl fmt::Debug for Error {
write!(
w,
"{}: \"{}\" {}:{}",
self.err_type,
self.msg,
self.pos.line,
self.pos.column
self.err_type, self.msg, self.pos.line, self.pos.column
)
}
}
@ -88,10 +85,7 @@ impl fmt::Display for Error {
write!(
w,
"{}: \"{}\" {}:{}",
self.err_type,
self.msg,
self.pos.line,
self.pos.column
self.err_type, self.msg, self.pos.line, self.pos.column
)
}
}

View File

@ -35,7 +35,7 @@ impl<V: Into<String> + Clone> Formatter<V> {
}
/// Renders a formatter to a string or returns an error.
///
///
/// If the formatter has the wrong number of arguments for the number of replacements
/// it will return an error. Otherwise it will return the formatted string.
pub fn render(&self, pos: &Position) -> Result<String, Box<Error>> {
@ -45,10 +45,12 @@ impl<V: Into<String> + Clone> Formatter<V> {
for c in self.tmpl.chars() {
if c == '@' && !should_escape {
if count == self.args.len() {
return Err(Box::new(error::Error::new("Too few arguments to string \
formatter.",
error::ErrorType::FormatError,
pos.clone())));
return Err(Box::new(error::Error::new(
"Too few arguments to string \
formatter.",
error::ErrorType::FormatError,
pos.clone(),
)));
}
let arg = self.args[count].clone();
let strval = arg.into();
@ -61,10 +63,12 @@ impl<V: Into<String> + Clone> Formatter<V> {
}
}
if self.args.len() != count {
return Err(Box::new(error::Error::new("Too many arguments to string \
formatter.",
error::ErrorType::FormatError,
pos.clone())));
return Err(Box::new(error::Error::new(
"Too many arguments to string \
formatter.",
error::ErrorType::FormatError,
pos.clone(),
)));
}
return Ok(buf);
}
@ -78,30 +82,21 @@ mod test {
#[test]
fn test_format_happy_path() {
let formatter = Formatter::new("foo @ @ \\@", vec!["bar", "quux"]);
let pos = Position {
line: 0,
column: 0,
};
let pos = Position { line: 0, column: 0 };
assert_eq!(formatter.render(&pos).unwrap(), "foo bar quux @");
}
#[test]
fn test_format_happy_wrong_too_few_args() {
let formatter = Formatter::new("foo @ @ \\@", vec!["bar"]);
let pos = Position {
line: 0,
column: 0,
};
let pos = Position { line: 0, column: 0 };
assert!(formatter.render(&pos).is_err());
}
#[test]
fn test_format_happy_wrong_too_many_args() {
let formatter = Formatter::new("foo @ @ \\@", vec!["bar", "quux", "baz"]);
let pos = Position {
line: 0,
column: 0,
};
let pos = Position { line: 0, column: 0 };
assert!(formatter.render(&pos).is_err());
}
}

View File

@ -151,39 +151,39 @@
//! ```
//!
//! #### Copy expressions
//!
//!
//! ucg Tuples support a form of reuse with copy on write semantics. You can copy a tuple and selectively overwrite fields or add new
//! fields to it with the copy expression. To perform a copy first reference the tuple by a bound name and then use `{ field = value, ... }`
//! syntax to copy with overridden fields or add completely new fields. When replacing a preexisting field with a new value you cannot
//! change the type of the field. This allows you to define a typed shape for a tuple with default values and then provide new values for
//! some or all of the fields while still enforcing the same types for those fields. Adding completely new fields has no such restriction.
//!
//!
//! ```ucg
//! let base = {
//! field1 = "value1",
//! field2 = 100,
//! field3 = 5.6,
//! };
//!
//!
//! let overridden = base{
//! field1 = "new value"
//! };
//!
//!
//! let expanded = base{
//! field2 = 200,
//! field3 = "look ma a new field",
//! };
//! ```
//!
//!
//! The following will cause an error because the overriden field's value does not match the original.
//!
//!
//! ```ucg
//! let bad = base{
//! field1 = 300, // Error!!! must be a string.
//! };
//!
//!
//! ```
//!
//!
//! #### Conditional data
//!
//! ucg supports a limited form of conditional data selection of using the select expression. A select expression starts with the `select`
@ -232,7 +232,7 @@
//! All ucg statements must be terminated by a semicolon.
//!
//! * expression statements
//!
//!
//! The simplest and least useful is the expression statement. It is any valid expression followed by a semicolon.
//!
//! ```ucg
@ -246,7 +246,7 @@
//! 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, an `=`, and a valid ucg expression.
//!
@ -255,7 +255,7 @@
//! ```
//!
//! * 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, the keyword `as`, and a name for the imported values.

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,8 @@
//! The tokenization stage of the ucg compiler.
use nom_locate::LocatedSpan;
use nom;
use nom::{alpha, is_alphanumeric, digit, multispace};
use nom::{InputLength, InputIter, Slice};
use nom::{alpha, digit, is_alphanumeric, multispace};
use nom::{InputIter, InputLength, Slice};
use ast::*;
use std;
use std::result::Result;
@ -204,9 +204,11 @@ named!(astok( Span ) -> Token,
fn end_of_input(input: Span) -> nom::IResult<Span, Token> {
match eof!(input,) {
nom::IResult::Done(_, _) => {
return nom::IResult::Done(input,
make_tok!(EOF => input.line as usize,
input.get_column() as usize));
return nom::IResult::Done(
input,
make_tok!(EOF => input.line as usize,
input.get_column() as usize),
);
}
nom::IResult::Incomplete(_) => {
return nom::IResult::Incomplete(nom::Needed::Unknown);
@ -220,22 +222,29 @@ fn end_of_input(input: Span) -> nom::IResult<Span, Token> {
fn comment(input: Span) -> nom::IResult<Span, Token> {
match tag!(input, "//") {
nom::IResult::Done(rest, _) => {
match alt!(rest, take_until_and_consume!("\r\n") | take_until_and_consume!("\n")) {
match alt!(
rest,
take_until_and_consume!("\r\n") | take_until_and_consume!("\n")
) {
nom::IResult::Done(rest, cmt) => {
return nom::IResult::Done(rest,
make_tok!(CMT => cmt.fragment.to_string(),
return nom::IResult::Done(
rest,
make_tok!(CMT => cmt.fragment.to_string(),
input.line as usize,
input.get_column() as usize));
input.get_column() as usize),
);
}
// If we didn't find a new line then we just grab everything.
_ => {
let blen = rest.input_len();
let next = rest.slice(blen..);
let tok = rest.slice(..blen);
return nom::IResult::Done(next,
make_tok!(CMT => tok.fragment.to_string(),
return nom::IResult::Done(
next,
make_tok!(CMT => tok.fragment.to_string(),
input.line as usize, input.get_column() as usize
));
),
);
}
}
}
@ -461,11 +470,13 @@ pub fn pos(i: TokenIter) -> nom::IResult<TokenIter, Position, ParseError> {
let tok = &i[0];
let line = tok.pos.line;
let column = tok.pos.column;
nom::IResult::Done(i.clone(),
Position {
line: line,
column: column,
})
nom::IResult::Done(
i.clone(),
Position {
line: line,
column: column,
},
)
}
/// TokenIter wraps a slice of Tokens and implements the various necessary
@ -528,7 +539,8 @@ impl<'a> InputIter for TokenIter<'a> {
}
fn position<P>(&self, predicate: P) -> Option<usize>
where P: Fn(Self::RawItem) -> bool
where
P: Fn(Self::RawItem) -> bool,
{
for (o, v) in self.iter_indices() {
if predicate(v.clone()) {
@ -580,10 +592,10 @@ mod tokenizer_test {
#[test]
fn test_tokenize_one_of_each() {
// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
// 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
let result = tokenize(LocatedSpan::new("let import macro select as => [ ] { } ; = % / * \
+ - . ( ) , 1 . foo \"bar\" // comment\n ;"));
let result = tokenize(LocatedSpan::new(
"let import macro select as => [ ] { } ; = % / * \
+ - . ( ) , 1 . foo \"bar\" // comment\n ;",
));
assert!(result.is_ok(), format!("result {:?} is not ok", result));
let v = result.unwrap();
for (i, t) in v.iter().enumerate() {
@ -606,40 +618,71 @@ mod tokenizer_test {
fn test_parse_comment() {
assert!(comment(LocatedSpan::new("// comment\n")).is_done());
assert!(comment(LocatedSpan::new("// comment")).is_done());
assert_eq!(comment(LocatedSpan::new("// comment\n")),
nom::IResult::Done(LocatedSpan{fragment: "", offset: 11, line: 2},
Token{
typ: TokenType::COMMENT,
fragment: " comment".to_string(),
pos: Position{line: 1, column: 1},
}));
assert_eq!(
comment(LocatedSpan::new("// comment\n")),
nom::IResult::Done(
LocatedSpan {
fragment: "",
offset: 11,
line: 2,
},
Token {
typ: TokenType::COMMENT,
fragment: " comment".to_string(),
pos: Position { line: 1, column: 1 },
}
)
);
assert!(comment(LocatedSpan::new("// comment\r\n")).is_done());
assert_eq!(comment(LocatedSpan::new("// comment\r\n")),
nom::IResult::Done(LocatedSpan{fragment: "", offset: 12, line: 2},
Token{
assert_eq!(
comment(LocatedSpan::new("// comment\r\n")),
nom::IResult::Done(
LocatedSpan {
fragment: "",
offset: 12,
line: 2,
},
Token {
typ: TokenType::COMMENT,
fragment: " comment".to_string(),
pos: Position{column: 1, line: 1}
}));
pos: Position { column: 1, line: 1 },
}
)
);
assert!(comment(LocatedSpan::new("// comment\r\n ")).is_done());
assert_eq!(comment(LocatedSpan::new("// comment\r\n ")),
nom::IResult::Done(LocatedSpan{fragment: " ", offset: 12, line: 2},
Token{
assert_eq!(
comment(LocatedSpan::new("// comment\r\n ")),
nom::IResult::Done(
LocatedSpan {
fragment: " ",
offset: 12,
line: 2,
},
Token {
typ: TokenType::COMMENT,
fragment: " comment".to_string(),
pos: Position{column: 1, line: 1},
}));
pos: Position { column: 1, line: 1 },
}
)
);
assert!(comment(LocatedSpan::new("// comment")).is_done());
}
#[test]
fn test_match_word() {
let input = vec![Token{
fragment: "foo".to_string(),
typ: TokenType::BAREWORD,
pos: Position{line: 1, column: 1}
}];
let result = word!(TokenIter{source: input.as_slice()}, "foo");
let input = vec![
Token {
fragment: "foo".to_string(),
typ: TokenType::BAREWORD,
pos: Position { line: 1, column: 1 },
},
];
let result = word!(
TokenIter {
source: input.as_slice(),
},
"foo"
);
match result {
nom::IResult::Done(_, tok) => assert_eq!(tok, input[0]),
res => assert!(false, format!("Fail: {:?}", res)),
@ -648,12 +691,19 @@ mod tokenizer_test {
#[test]
fn test_match_word_empty_input() {
let input = vec![Token{
fragment: "".to_string(),
typ: TokenType::END,
pos: Position{line: 1, column: 1},
}];
let result = word!(TokenIter{source: input.as_slice()}, "foo");
let input = vec![
Token {
fragment: "".to_string(),
typ: TokenType::END,
pos: Position { line: 1, column: 1 },
},
];
let result = word!(
TokenIter {
source: input.as_slice(),
},
"foo"
);
match result {
nom::IResult::Done(_, _) => assert!(false, "Should have been an error but was Done"),
nom::IResult::Incomplete(_) => {
@ -667,12 +717,19 @@ mod tokenizer_test {
#[test]
fn test_match_punct() {
let input = vec![Token{
fragment: "!".to_string(),
typ: TokenType::PUNCT,
pos: Position{line: 1, column: 1}
}];
let result = punct!(TokenIter{source: input.as_slice()}, "!");
let input = vec![
Token {
fragment: "!".to_string(),
typ: TokenType::PUNCT,
pos: Position { line: 1, column: 1 },
},
];
let result = punct!(
TokenIter {
source: input.as_slice(),
},
"!"
);
match result {
nom::IResult::Done(_, tok) => assert_eq!(tok, input[0]),
res => assert!(false, format!("Fail: {:?}", res)),
@ -681,12 +738,19 @@ mod tokenizer_test {
#[test]
fn test_match_type() {
let input = vec![Token{
fragment: "foo".to_string(),
typ: TokenType::BAREWORD,
pos: Position{line: 1, column: 1}
}];
let result = match_type!(TokenIter{source: input.as_slice()}, BAREWORD);
let input = vec![
Token {
fragment: "foo".to_string(),
typ: TokenType::BAREWORD,
pos: Position { line: 1, column: 1 },
},
];
let result = match_type!(
TokenIter {
source: input.as_slice(),
},
BAREWORD
);
match result {
nom::IResult::Done(_, tok) => assert_eq!(tok, input[0]),
res => assert!(false, format!("Fail: {:?}", res)),