From a028960a43a7c3ec00e7510560f5d9222942d53b Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Fri, 28 Dec 2018 19:02:37 -0600 Subject: [PATCH] REFACTOR/FEATURE: Treat selectors as an operator. --- src/ast/mod.rs | 168 +---- src/ast/test.rs | 16 +- src/build/mod.rs | 200 +++-- src/build/test.rs | 32 +- src/parse/mod.rs | 210 +----- src/parse/precedence.rs | 57 +- src/parse/test.rs | 1547 --------------------------------------- 7 files changed, 212 insertions(+), 2018 deletions(-) delete mode 100644 src/parse/test.rs diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 3083be6..1eec9ab 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -185,158 +185,11 @@ macro_rules! make_expr { }; } -/// Helper macro for making selectors. -/// -/// ``` -/// make_selector!(Token::new("tpl", 1, 1), Token::new("fld", 1, 4)); -/// -/// make_selector!(Token::new("tpl", 1, 1), vec![Token::new("fld", 1, 4)], => 1, 1); -/// -/// make_selector!(foo", ["bar"]); -/// -/// make_selector!(foo", ["bar"] => 1, 0); -/// ``` -#[allow(unused_macros)] -macro_rules! make_selector { - ( $h:expr, $i:expr) => { - SelectorDef::new( - SelectorList{head: Box::new($h), tail: None}, - $i) - }; - - ( $h: expr, $list:expr, $i:expr) => { - SelectorDef::new( - SelectorList{head: Box::new($h), tail: Some($list)}, - $i) - }; - - // Tokens - ( $h:expr => [ $( $item:expr ),* ], $i:expr ) => { - { - make_selector!($h => [ $( $item, )* ] => $i) - } - }; - - ( $h:expr => [ $( $item:expr ),* ] => $i:expr ) => { - { - let mut list: Vec = Vec::new(); - - $( - list.push($item); - )* - - make_selector!($h, list, $i) - } - }; - - // Strings not tokens - ( $h:expr => $( $item:expr ),* ) => { - { - - let mut col = 1; - let mut list: Vec = Vec::new(); - - $( - list.push(make_tok!($item, Position::new(1, col, col))); - col += $item.len() + 1; - )* - - // Shut up the lint about unused code; - assert!(col != 0); - - make_selector!($h, list, Position::new(1, 1, 1)) - } - - }; - - ( $h:expr => $( $item:expr ),* => $l:expr, $c:expr ) => { - { - let mut col = $c; - let mut list: Vec = Vec::new(); - - $( - list.push(make_tok!($item, Position::new($l, col, col))); - col += $item.len() + 1; - )* - - // Shut up the linter about unused code; - assert!(col != 0); - - make_selector!($h, list, Position::new($l, $c, $c)) - } - }; -} - -/// An Expression with a series of symbols specifying the key -/// with which to descend into the result of the expression. -/// -/// The expression must evaluate to either a tuple or an array. The token must -/// evaluate to either a bareword Symbol or an Int. -/// -/// ```ucg -/// let foo = { bar = "a thing" }; -/// let thing = foo.bar; -/// -/// let arr = ["one", "two"]; -/// let first = arr.0; -/// -/// let berry = {best = "strawberry", unique = "acai"}.best; -/// let third = ["uno", "dos", "tres"].1; -/// ''' -#[derive(PartialEq, Clone)] -pub struct SelectorList { - pub head: Box, - // TODO This should now work more like a binary operator. Perhaps move into the precendence parser code? - pub tail: Option>, -} - -impl SelectorList { - /// Returns a stringified version of a SelectorList. - pub fn to_string(&self) -> String { - "TODO".to_string() - } -} - -impl fmt::Debug for SelectorList { - fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { - write!(w, "Selector({})", self) - } -} - -impl fmt::Display for SelectorList { - fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { - write!(w, "{}", self.head)?; - if let Some(ref tok_vec) = self.tail { - for t in tok_vec.iter() { - write!(w, ".{}", t.fragment)?; - } - } - return Ok(()); - } -} - /// 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)] -pub struct SelectorDef { - pub pos: Position, - pub sel: SelectorList, -} - -impl SelectorDef { - /// Constructs a new SelectorDef. - pub fn new>(sel: SelectorList, p: P) -> Self { - SelectorDef { - pos: p.into(), - sel: sel, - } - } -} - /// Represents a Value in the UCG parsed AST. #[derive(Debug, PartialEq, Clone)] pub enum Value { @@ -350,7 +203,6 @@ pub enum Value { // Complex Values Tuple(PositionedItem), List(ListDef), - Selector(SelectorDef), } impl Value { @@ -365,7 +217,6 @@ impl Value { &Value::Symbol(_) => "Symbol".to_string(), &Value::Tuple(_) => "Tuple".to_string(), &Value::List(_) => "List".to_string(), - &Value::Selector(_) => "Selector".to_string(), } } @@ -396,7 +247,6 @@ impl Value { &Value::Symbol(ref s) => format!("{}", s.val), &Value::Tuple(ref fs) => format!("{}", Self::fields_to_string(&fs.val)), &Value::List(ref def) => format!("[{}]", Self::elems_to_string(&def.elems)), - &Value::Selector(ref v) => v.sel.to_string(), } } @@ -411,7 +261,6 @@ impl Value { &Value::Symbol(ref s) => &s.pos, &Value::Tuple(ref fs) => &fs.pos, &Value::List(ref def) => &def.pos, - &Value::Selector(ref v) => &v.pos, } } @@ -427,8 +276,7 @@ impl Value { &Value::Str(_), &Value::Symbol(_), &Value::Tuple(_), - &Value::List(_), - &Value::Selector(_) + &Value::List(_) ) } } @@ -437,7 +285,7 @@ impl Value { /// defined. #[derive(PartialEq, Debug, Clone)] pub struct CallDef { - pub macroref: SelectorDef, + pub macroref: Value, pub arglist: Vec, pub pos: Position, } @@ -552,8 +400,6 @@ impl MacroDef { if !self.symbol_is_in_args(&name.val) { bad_symbols.insert(name.val.clone()); } - } else if let &Value::Selector(ref sel_node) = val { - stack.push(&sel_node.sel.head); } else if let &Value::Tuple(ref tuple_node) = val { let fields = &tuple_node.val; for &(_, ref expr) in fields.iter() { @@ -637,6 +483,7 @@ impl MacroDef { /// UCG expression. #[derive(Debug, PartialEq, Clone)] pub enum BinaryExprType { + // Math Add, Sub, Mul, @@ -648,7 +495,8 @@ pub enum BinaryExprType { NotEqual, GTEqual, LTEqual, - // TODO DOT Selector operator + // Selector operator + DOT, } /// Represents an expression with a left and a right side. @@ -663,7 +511,7 @@ pub struct BinaryOpDef { /// Encodes a tuple Copy expression in the UCG AST. #[derive(Debug, PartialEq, Clone)] pub struct CopyDef { - pub selector: SelectorDef, + pub selector: Value, pub fields: FieldList, pub pos: Position, } @@ -694,8 +542,8 @@ pub enum ListOpType { #[derive(Debug, PartialEq, Clone)] pub struct ListOpDef { pub typ: ListOpType, - pub mac: SelectorDef, - pub field: String, + pub mac: PositionedItem, + pub field: PositionedItem, pub target: Box, pub pos: Position, } diff --git a/src/ast/test.rs b/src/ast/test.rs index d97060b..e16bee6 100644 --- a/src/ast/test.rs +++ b/src/ast/test.rs @@ -72,10 +72,10 @@ pub fn test_macro_validation_selector_happy_path() { make_tok!("f1", Position::new(1, 1, 0)), Expression::Binary(BinaryOpDef { kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Selector(make_selector!( - make_expr!("foo", Position::new(1, 1, 0)) => [ - make_tok!("quux", Position::new(1, 1, 0)) ] - => Position::new(1, 1, 0))))), + left: Box::new(Expression::Simple(Value::Symbol(PositionedItem::new( + "foo".to_string(), + Position::new(1, 1, 0), + )))), right: Box::new(Expression::Simple(Value::Int(value_node!( 1, Position::new(1, 1, 0) @@ -96,10 +96,10 @@ pub fn test_macro_validation_selector_fail() { make_tok!("f1", Position::new(1, 1, 0)), Expression::Binary(BinaryOpDef { kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Selector( - make_selector!(make_expr!("bar", Position::new(1, 1, 0)) => [ - make_tok!("quux", Position::new(1, 1, 0)) ] => Position::new(1, 1, 0)), - ))), + left: Box::new(Expression::Simple(Value::Symbol(PositionedItem::new( + "bar".to_string(), + Position::new(1, 1, 0), + )))), right: Box::new(Expression::Simple(Value::Int(value_node!( 1, Position::new(1, 1, 0) diff --git a/src/build/mod.rs b/src/build/mod.rs index c18cd8f..59d3a95 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -15,7 +15,7 @@ //! The build stage of the ucg compiler. use std::cell::RefCell; use std::collections::hash_map::Entry; -use std::collections::{HashMap, VecDeque}; +use std::collections::HashMap; use std::env; use std::error::Error; use std::fs::File; @@ -239,9 +239,6 @@ impl<'a> FileBuilder<'a> { } &Value::List(ref def) => self.eval_list(def, scope), &Value::Tuple(ref tuple) => self.eval_tuple(&tuple.val, scope), - &Value::Selector(ref selector_list_node) => { - self.lookup_selector(&selector_list_node.sel, scope) - } } } @@ -476,131 +473,86 @@ impl<'a> FileBuilder<'a> { fn lookup_in_env( &self, - search: &Token, - stack: &mut VecDeque>, + pos: &Position, + field: &Rc, fs: &Vec<(String, String)>, - ) -> Result<(), Box> { + ) -> Result, Box> { + let field = if let &Val::Str(ref name) = field.as_ref() { + name + } else { + return Err(Box::new(error::BuildError::new( + format!("Invalid type {} for field lookup in env", field), + error::ErrorType::TypeFail, + pos.clone(), + ))); + }; for &(ref name, ref val) in fs.iter() { - if &search.fragment == name { - stack.push_back(Rc::new(Val::Str(val.clone()))); - return Ok(()); + if field == name { + return Ok(Rc::new(Val::Str(val.clone()))); } else if !self.strict { - stack.push_back(Rc::new(Val::Empty)); - return Ok(()); + return Ok(Rc::new(Val::Empty)); } } return Err(Box::new(error::BuildError::new( - format!("Environment Variable {} not set", search.fragment), + format!("Environment Variable {} not set", field), error::ErrorType::NoSuchSymbol, - search.pos.clone(), + pos.clone(), ))); } + // TODO: Do as part of a binary operator selector lookup. fn lookup_in_tuple( &self, - stack: &mut VecDeque>, - sl: &SelectorList, - next: (&Position, &str), + pos: &Position, + field: &Val, fs: &Vec<(PositionedItem, Rc)>, - ) -> Result<(), Box> { - if let Some(vv) = Self::find_in_fieldlist(next.1, fs) { - stack.push_back(vv.clone()); + ) -> Result, Box> { + let field = if let &Val::Str(ref name) = field { + name } else { return Err(Box::new(error::BuildError::new( - format!( - "Unable to \ - match element {} in selector \ - path [{}]", - next.1, sl, - ), - error::ErrorType::NoSuchSymbol, - next.0.clone(), + format!("Invalid type {} for field lookup in tuple", field), + error::ErrorType::TypeFail, + pos.clone(), ))); + }; + if let Some(vv) = Self::find_in_fieldlist(&field, fs) { + Ok(vv) + } else { + Err(Box::new(error::BuildError::new( + format!("Unable to {} match element in tuple.", field,), + error::ErrorType::NoSuchSymbol, + pos.clone(), + ))) } - Ok(()) } + // TODO: Do as part of a binary operator selector lookup. fn lookup_in_list( &self, - stack: &mut VecDeque>, - sl: &SelectorList, - next: (&Position, &str), + pos: &Position, + field: &Rc, elems: &Vec>, - ) -> Result<(), Box> { - let idx = next.1.parse::()?; - if idx < elems.len() { - stack.push_back(elems[idx].clone()); - } else { - return Err(Box::new(error::BuildError::new( - format!( - "Unable to \ - match element {} in selector \ - path [{}]", - next.1, sl, - ), - error::ErrorType::NoSuchSymbol, - next.0.clone(), - ))); - } - Ok(()) - } - - fn lookup_selector(&mut self, sl: &SelectorList, scope: &Scope) -> Result, Box> { - let first = self.eval_expr(&sl.head, scope)?; - // First we ensure that the result is a tuple or a list. - let mut stack = VecDeque::new(); - match first.as_ref() { - &Val::Tuple(_) => { - stack.push_back(first.clone()); - } - &Val::List(_) => { - stack.push_back(first.clone()); - } - &Val::Env(_) => { - stack.push_back(first.clone()); - } + ) -> Result, Box> { + let idx = match field.as_ref() { + &Val::Int(i) => i as usize, + &Val::Str(ref s) => s.parse::()?, _ => { - // noop - } - } - - if let &Some(ref tail) = &sl.tail { - if tail.len() == 0 { - return Ok(first); - } - let mut it = tail.iter().peekable(); - loop { - let vref = stack.pop_front().unwrap(); - if it.peek().is_none() { - return Ok(vref.clone()); - } - // This unwrap is safe because we already checked for - // None above. - let next = it.next().unwrap(); - match vref.as_ref() { - &Val::Tuple(ref fs) => { - self.lookup_in_tuple(&mut stack, sl, (&next.pos, &next.fragment), fs)?; - continue; - } - &Val::Env(ref fs) => { - self.lookup_in_env(&next, &mut stack, fs)?; - continue; - } - &Val::List(ref elems) => { - self.lookup_in_list(&mut stack, sl, (&next.pos, &next.fragment), elems)?; - continue; - } - _ => { - return Err(Box::new(error::BuildError::new( - format!("{} is not a Tuple or List", vref), - error::ErrorType::TypeFail, - next.pos.clone(), - ))); - } - } + return Err(Box::new(error::BuildError::new( + format!("Invalid idx type {} for list lookup", field), + error::ErrorType::TypeFail, + pos.clone(), + ))) } + }; + if idx < elems.len() { + Ok(elems[idx].clone()) } else { - return Ok(first); + Err(Box::new(error::BuildError::new( + format!("idx {} out of bounds in list", idx), + error::ErrorType::NoSuchSymbol, + pos.clone(), + ))) } } @@ -857,21 +809,44 @@ impl<'a> FileBuilder<'a> { ))) } + fn do_dot_lookup( + &mut self, + pos: &Position, + left: Rc, + right: Rc, + scope: &Scope, + ) -> Result, Box> { + match left.as_ref() { + &Val::Tuple(ref fs) => self.lookup_in_tuple(pos, &right, fs), + &Val::List(ref fs) => self.lookup_in_list(pos, &right, fs), + &Val::Env(ref fs) => self.lookup_in_env(pos, &right, fs), + _ => Err(Box::new(error::BuildError::new( + "Invalid type left operand for dot lookup", + error::ErrorType::TypeFail, + pos.clone(), + ))), + } + } + fn eval_binary(&mut self, def: &BinaryOpDef, scope: &Scope) -> Result, Box> { let kind = &def.kind; let left = self.eval_expr(&def.left, scope)?; let right = self.eval_expr(&def.right, scope)?; match kind { + // Handle math and concatenation operators here &BinaryExprType::Add => self.add_vals(&def.pos, left, right), &BinaryExprType::Sub => self.subtract_vals(&def.pos, left, right), &BinaryExprType::Mul => self.multiply_vals(&def.pos, left, right), &BinaryExprType::Div => self.divide_vals(&def.pos, left, right), + // Handle Comparison operators here &BinaryExprType::Equal => self.do_deep_equal(&def.pos, left, right), &BinaryExprType::GT => self.do_gt(&def.pos, left, right), &BinaryExprType::LT => self.do_lt(&def.pos, left, right), &BinaryExprType::GTEqual => self.do_gtequal(&def.pos, left, right), &BinaryExprType::LTEqual => self.do_ltequal(&def.pos, left, right), &BinaryExprType::NotEqual => self.do_not_deep_equal(&def.pos, left, right), + // TODO Handle the whole selector lookup logic here. + &BinaryExprType::DOT => self.do_dot_lookup(&def.pos, left, right, scope), } } @@ -960,7 +935,7 @@ impl<'a> FileBuilder<'a> { } fn eval_copy(&mut self, def: &CopyDef, scope: &Scope) -> Result, Box> { - let v = self.lookup_selector(&def.selector.sel, scope)?; + let v = self.eval_value(&def.selector, scope)?; if let &Val::Tuple(ref src_fields) = v.as_ref() { let mut child_scope = scope.spawn_child(); child_scope.set_curr_val(v.clone()); @@ -1011,14 +986,14 @@ impl<'a> FileBuilder<'a> { mod_def.arg_tuple ), error::ErrorType::TypeFail, - def.selector.pos.clone(), + def.selector.pos().clone(), ))); } } Err(Box::new(error::BuildError::new( format!("Expected Tuple or Module got {}", v), error::ErrorType::TypeFail, - def.selector.pos.clone(), + def.selector.pos().clone(), ))) } @@ -1035,9 +1010,8 @@ impl<'a> FileBuilder<'a> { } fn eval_call(&mut self, def: &CallDef, scope: &Scope) -> Result, Box> { - let sel = &def.macroref; let args = &def.arglist; - let v = self.lookup_selector(&sel.sel, scope)?; + let v = self.eval_value(&def.macroref, scope)?; if let &Val::Macro(ref m) = v.deref() { // Congratulations this is actually a macro. let mut argvals: Vec> = Vec::new(); @@ -1145,13 +1119,13 @@ impl<'a> FileBuilder<'a> { ))); } }; - let mac = &def.mac; - if let &Val::Macro(ref macdef) = self.lookup_selector(&mac.sel, scope)?.as_ref() { + let mac_sym = Value::Symbol(def.mac.clone()); + if let &Val::Macro(ref macdef) = self.eval_value(&mac_sym, &self.scope)?.as_ref() { let mut out = Vec::new(); for item in l.iter() { let argvals = vec![item.clone()]; let fields = macdef.eval(self.file.clone(), self, argvals)?; - if let Some(v) = Self::find_in_fieldlist(&def.field, &fields) { + if let Some(v) = Self::find_in_fieldlist(&def.field.val, &fields) { match def.typ { ListOpType::Map => { out.push(v.clone()); @@ -1172,7 +1146,7 @@ impl<'a> FileBuilder<'a> { return Ok(Rc::new(Val::List(out))); } return Err(Box::new(error::BuildError::new( - format!("Expected macro but got {:?}", mac), + format!("Expected macro but got {:?}", def.mac), error::ErrorType::TypeFail, def.pos.clone(), ))); diff --git a/src/build/test.rs b/src/build/test.rs index c3915ca..604e68d 100644 --- a/src/build/test.rs +++ b/src/build/test.rs @@ -157,10 +157,10 @@ fn test_expr_copy_no_such_tuple() { test_expr_to_val( vec![( Expression::Copy(CopyDef { - selector: make_selector!( - make_expr!("tpl1", Position::new(1, 1, 1)), - Position::new(1, 1, 1) - ), + selector: Value::Symbol(PositionedItem::new( + "tpl1".to_string(), + Position::new(1, 1, 1), + )), fields: Vec::new(), pos: Position::new(1, 0, 0), }), @@ -183,10 +183,10 @@ fn test_expr_copy_not_a_tuple() { test_expr_to_val( vec![( Expression::Copy(CopyDef { - selector: make_selector!( - make_expr!("tpl1", Position::new(1, 1, 1)), - Position::new(1, 1, 1) - ), + selector: Value::Symbol(PositionedItem::new( + "tpl1".to_string(), + Position::new(1, 1, 1), + )), fields: Vec::new(), pos: Position::new(1, 0, 0), }), @@ -212,10 +212,10 @@ fn test_expr_copy_field_type_error() { test_expr_to_val( vec![( Expression::Copy(CopyDef { - selector: make_selector!( - make_expr!("tpl1", Position::new(1, 1, 1)), - Position::new(1, 1, 1) - ), + selector: Value::Symbol(PositionedItem::new( + "tpl1".to_string(), + Position::new(1, 1, 1), + )), fields: vec![( make_tok!("fld1", Position::new(1, 1, 1)), Expression::Simple(Value::Str(value_node!( @@ -261,10 +261,10 @@ fn test_macro_hermetic() { test_expr_to_val( vec![( Expression::Call(CallDef { - macroref: make_selector!( - make_expr!("tstmac", Position::new(1, 1, 1)), - Position::new(1, 1, 1) - ), + macroref: Value::Symbol(PositionedItem::new( + "tstmac".to_string(), + Position::new(1, 1, 1), + )), arglist: vec![Expression::Simple(Value::Str(value_node!( "bar".to_string(), Position::new(1, 1, 1) diff --git a/src/parse/mod.rs b/src/parse/mod.rs index d0b0662..7d4b57d 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -279,7 +279,7 @@ make_fn!( either!( // TODO This should move to op_expression instead of a value now. // We probably still need a bareword parser though? - trace_parse!(selector_value), + trace_parse!(symbol), trace_parse!(compound_value), trace_parse!(boolean_value), trace_parse!(empty_value), @@ -318,107 +318,14 @@ make_fn!( ) ); -fn symbol_or_expression(input: SliceIter) -> ParseResult { - let _i = input.clone(); - let scalar_head = do_each!(input, - sym => either!(symbol, compound_value), - (sym) - ); - - match scalar_head { - Result::Incomplete(offset) => Result::Incomplete(offset), - Result::Fail(_) => grouped_expression(_i), - Result::Abort(e) => Result::Abort(e), - Result::Complete(rest, val) => { - let res = peek!(rest.clone(), punct!(".")); - match val { - Value::Tuple(_) => { - if res.is_complete() { - Result::Complete(rest, Expression::Simple(val)) - } else { - return Result::Fail(Error::new( - "Expected (.) but no dot found".to_string(), - Box::new(rest.clone()), - )); - } - } - Value::List(_) => { - if res.is_complete() { - Result::Complete(rest, Expression::Simple(val)) - } else { - return Result::Fail(Error::new( - "Expected (.) but no dot found".to_string(), - Box::new(rest.clone()), - )); - } - } - _ => Result::Complete(rest, Expression::Simple(val)), - } - } - } -} - -fn selector_list(input: SliceIter) -> ParseResult { - let (rest, head) = match symbol_or_expression(input) { - Result::Complete(rest, val) => (rest, val), - Result::Fail(e) => { - return Result::Fail(e); - } - Result::Incomplete(i) => { - return Result::Incomplete(i); - } - Result::Abort(e) => return Result::Abort(e), - }; - - let (rest, is_dot) = match punct!(rest, ".") { - Result::Complete(rest, tok) => (rest, Some(tok)), - Result::Incomplete(i) => { - return Result::Incomplete(i); - } - Result::Fail(_) => (rest, None), - Result::Abort(e) => return Result::Abort(e), - }; - - let (rest, list) = if is_dot.is_some() { - let (rest, list) = match separated!( - rest, - punct!("."), - either!(match_type!(BAREWORD), match_type!(DIGIT), match_type!(STR)) - ) { - Result::Complete(rest, val) => (rest, val), - Result::Incomplete(i) => return Result::Incomplete(i), - Result::Fail(e) => return Result::Fail(e), - Result::Abort(e) => return Result::Abort(e), - }; - - if list.is_empty() { - return Result::Fail(Error::new( - "(.) with no selector fields after".to_string(), - Box::new(rest.clone()), - )); - } else { - (rest, Some(list)) - } - } else { - (rest, None) - }; - - let sel_list = SelectorList { - head: Box::new(head), - tail: list, - }; - - return Result::Complete(rest, sel_list); -} - -fn tuple_to_copy(def: SelectorDef, fields: Option) -> Expression { - let pos = def.pos.clone(); +fn tuple_to_copy(sym: Value, fields: Option) -> Expression { + let pos = sym.pos().clone(); let fields = match fields { Some(fields) => fields, None => Vec::new(), }; Expression::Copy(CopyDef { - selector: def, + selector: sym, fields: fields, pos: pos, }) @@ -427,14 +334,13 @@ fn tuple_to_copy(def: SelectorDef, fields: Option) -> Expression { make_fn!( copy_expression, Expression>, do_each!( - pos => pos, // TODO This should become just a bareword symbol now - selector => trace_parse!(selector_list), + sym => trace_parse!(symbol), _ => punct!("{"), fields => optional!(trace_parse!(field_list)), _ => optional!(punct!(",")), // noms opt! macro does not preserve error types properly but this one does. _ => punct!("}"), - (tuple_to_copy(SelectorDef::new(selector, pos), fields)) + (tuple_to_copy(sym, fields)) ) ); @@ -610,9 +516,9 @@ fn tuple_to_call<'a>( val: Value, exprs: Option>, ) -> ConvertResult<'a, Expression> { - if let Value::Selector(def) = val { + if let Value::Symbol(_) = val { Ok(Expression::Call(CallDef { - macroref: def, + macroref: val, arglist: exprs.unwrap_or_else(|| Vec::new()), pos: (&input).into(), })) @@ -624,22 +530,10 @@ fn tuple_to_call<'a>( } } -fn vec_to_selector_value(pos: Position, list: SelectorList) -> Value { - Value::Selector(SelectorDef::new(list, pos)) -} - -make_fn!( - selector_value, Value>, - do_each!( - sl => trace_parse!(selector_list), - (vec_to_selector_value(sl.head.pos().clone(), sl)) - ) -); - fn call_expression(input: SliceIter) -> Result, Expression> { let parsed = do_each!(input.clone(), // TODO This should become just a bareword symbol now - callee_name => trace_parse!(selector_value), + callee_name => trace_parse!(symbol), _ => punct!("("), args => optional!(separated!(punct!(","), trace_parse!(expression))), _ => punct!(")"), @@ -664,59 +558,34 @@ fn tuple_to_list_op<'a>( input: &'a SliceIter, kind: ListOpType, macroname: Value, + outfield: Value, list: Expression, ) -> ConvertResult<'a, Expression> { - if let Value::Selector(mut def) = macroname { - // First of all we need to assert that this is a selector of at least - // two sections. - let fieldname: String = match &mut def.sel.tail { - &mut None => { - if ENABLE_TRACE { - eprintln!( - "tuple_to_list_op had error {}", - "Missing a result field for the macro" - ); - } - return Err(Error::new( - format!("Missing a result field for the macro"), - Box::new(input.clone()), - )); - } - &mut Some(ref mut tl) => { - if tl.len() < 1 { - if ENABLE_TRACE { - eprintln!( - "tuple_to_list_op had error {}", - "Missing a result field for the macro" - ); - } - return Err(Error::new( - format!("Missing a result field for the macro"), - Box::new(input.clone()), - )); - } - let fname = tl.pop(); - fname.unwrap().fragment - } - }; - return Ok(Expression::ListOp(ListOpDef { - typ: kind, - mac: def, - field: fieldname, - target: Box::new(list), - pos: input.into(), - })); - } - if ENABLE_TRACE { - eprintln!( - "tuple_to_list_op had error {}", - format!("Expected a selector but got {}", macroname.type_name()) - ); - } - return Err(Error::new( - format!("Expected a selector but got {}", macroname.type_name()), - Box::new(input.clone()), - )); + let macroname = match macroname { + Value::Symbol(sym) => sym, + _ => { + return Err(Error::new( + format!("Expected a macro name but got {}", macroname.type_name()), + Box::new(input.clone()), + )) + } + }; + let outfield = match outfield { + Value::Symbol(sym) => sym, + _ => { + return Err(Error::new( + format!("Expected a field name but got {}", outfield.type_name()), + Box::new(input.clone()), + )) + } + }; + return Ok(Expression::ListOp(ListOpDef { + typ: kind, + mac: macroname, + field: outfield, + target: Box::new(list), + pos: input.into(), + })); } make_fn!( @@ -728,9 +597,11 @@ make_fn!( do_each!(_ => word!("filter"), (ListOpType::Filter)) ), // TODO This should become just a bareword symbol now - macroname => trace_parse!(selector_value), + macroname => trace_parse!(symbol), + _ => punct!("."), + outfield => trace_parse!(symbol), list => trace_parse!(non_op_expression), - (tuple_to_list_op(&input, optype, macroname, list).unwrap()) + (tuple_to_list_op(&input, optype, macroname, outfield, list).unwrap()) ) ); @@ -916,6 +787,3 @@ pub fn parse<'a>(input: OffsetStrIter<'a>) -> std::result::Result } pub mod precedence; - -#[cfg(test)] -mod test; diff --git a/src/parse/precedence.rs b/src/parse/precedence.rs index 236b545..b3048aa 100644 --- a/src/parse/precedence.rs +++ b/src/parse/precedence.rs @@ -27,6 +27,13 @@ pub enum Element { Op(BinaryExprType), } +make_fn!( + dot_op_type, Element>, + do_each!( + _ => punct!("."), + (Element::Op(BinaryExprType::DOT))) +); + make_fn!( math_op_type, Element>, either!( @@ -66,6 +73,34 @@ fn parse_expression(i: SliceIter) -> Result, Express )); } +fn parse_dot_operator(i: SliceIter) -> Result, BinaryExprType> { + let mut i_ = i.clone(); + if eoi(i_.clone()).is_complete() { + return Result::Fail(Error::new( + format!("Expected Expression found End Of Input"), + Box::new(i_), + )); + } + let el = i_.next(); + if let Some(&Element::Op(ref op)) = el { + match op { + &BinaryExprType::DOT => { + return Result::Complete(i_.clone(), op.clone()); + } + _other => { + // noop + } + }; + } + return Result::Fail(Error::new( + format!( + "Error while parsing Binary Expression Unexpected Operator {:?}", + el + ), + Box::new(i_), + )); +} + fn parse_sum_operator(i: SliceIter) -> Result, BinaryExprType> { let mut i_ = i.clone(); if eoi(i_.clone()).is_complete() { @@ -182,6 +217,7 @@ make_fn!( parse_sum_operator, either!( trace_parse!(product_expression), + trace_parse!(dot_expression), trace_parse!(parse_expression) ) ) @@ -189,7 +225,10 @@ make_fn!( make_fn!( product_expression, Expression>, - do_binary_expr!(parse_product_operator, trace_parse!(parse_expression)) + do_binary_expr!( + parse_product_operator, + either!(trace_parse!(dot_expression), trace_parse!(parse_expression)) + ) ); make_fn!( @@ -247,7 +286,17 @@ fn parse_compare_operator(i: SliceIter) -> Result, B make_fn!( binary_expression, Expression>, - either!(compare_expression, math_expression, parse_expression) + either!( + compare_expression, + math_expression, + dot_expression, + parse_expression + ) +); + +make_fn!( + dot_expression, Expression>, + do_binary_expr!(parse_dot_operator, trace_parse!(parse_expression)) ); make_fn!( @@ -256,6 +305,7 @@ make_fn!( parse_compare_operator, either!( trace_parse!(math_expression), + trace_parse!(dot_expression), trace_parse!(parse_expression) ) ) @@ -290,7 +340,8 @@ fn parse_operand_list<'a>(i: SliceIter<'a, Token>) -> ParseResult<'a, Vec { if firstrun { // If we don't find an operator in our first diff --git a/src/parse/test.rs b/src/parse/test.rs deleted file mode 100644 index dbbed3e..0000000 --- a/src/parse/test.rs +++ /dev/null @@ -1,1547 +0,0 @@ -// Copyright 2017 Jeremy Wall -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// 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 super::*; -use crate::tokenizer::tokenize; - -use abortable_parser::{Result, SliceIter}; - -use crate::iter::OffsetStrIter; - -macro_rules! assert_parse { - ($parsemac:ident($i:expr), $out:expr) => { - assert_parse!($i, $parsemac, $out) - }; - ($i:expr, $f:expr, $out:expr) => {{ - let input = OffsetStrIter::new($i); - match tokenize(input.clone()) { - Err(e) => assert!(false, format!("Tokenizer Error: {:?}", e)), - Ok(val) => match $f(SliceIter::new(val.as_slice())) { - Result::Complete(_, result) => assert_eq!(result, $out), - other => assert!(false, format!("Expected Done got {:?}", other)), - }, - } - };}; -} - -macro_rules! assert_fail { - ($parsemac:ident($i:expr)) => { - assert_fail!($i, $parsemac) - }; - ($i:expr, $f:expr) => {{ - let input = OffsetStrIter::new($i); - match tokenize(input.clone()) { - Err(_) => assert!(true), - Ok(val) => { - let result = $f(SliceIter::new(val.as_slice())); - assert!(result.is_fail(), format!("Not an abort: {:?}", result)) - } - } - }}; -} - -macro_rules! assert_abort { - ($parsemac:ident($i:expr)) => { - assert_abort!($i, $parsemac) - }; - ($i:expr, $f:expr) => {{ - let input = OffsetStrIter::new($i); - match tokenize(input.clone()) { - Err(_) => assert!(true), - Ok(val) => { - let result = $f(SliceIter::new(val.as_slice())); - assert!(result.is_abort(), format!("Not a fail: {:?}", result)) - } - } - }}; -} - -#[test] -fn test_null_parsing() { - assert_parse!(empty_value("NULL "), Value::Empty(Position::new(1, 1, 0))); - assert_parse!(value("NULL "), Value::Empty(Position::new(1, 1, 0))); - assert_parse!( - simple_expression("NULL "), - Expression::Simple(Value::Empty(Position::new(1, 1, 0))) - ); - assert_parse!( - expression("NULL,"), - Expression::Simple(Value::Empty(Position::new(1, 1, 0))) - ); -} - -#[test] -fn test_boolean_parsing() { - assert_parse!( - boolean_value("true"), - Value::Boolean(PositionedItem::new(true, Position::new(1, 1, 0))) - ); - assert_parse!( - boolean_value("false"), - Value::Boolean(PositionedItem::new(false, Position::new(1, 1, 0))) - ); - assert_fail!(boolean_value("truth")); -} - -#[test] -fn test_symbol_parsing() { - assert_parse!( - symbol("foo"), - Value::Symbol(value_node!("foo".to_string(), Position::new(1, 1, 0))) - ); - assert_parse!( - symbol("foo-bar"), - Value::Symbol(value_node!("foo-bar".to_string(), Position::new(1, 1, 0))) - ); - assert_parse!( - symbol("foo_bar"), - Value::Symbol(value_node!("foo_bar".to_string(), Position::new(1, 1, 0))) - ); -} - -#[test] -fn test_selector_parsing() { - assert_fail!(selector_value("foo.")); - assert_parse!( - selector_value("foo.bar "), - Value::Selector( - make_selector!(make_expr!("foo".to_string(), Position::new(1, 1, 0)) => [ - make_tok!("bar", Position::new(1, 5, 4))] => - Position::new(1, 1, 0)) - ) - ); - assert_parse!( - selector_value("foo.0 "), - Value::Selector( - make_selector!(make_expr!("foo".to_string(), Position::new(1, 1, 0)) => [ - make_tok!(DIGIT => "0", Position::new(1, 5, 4))] => - Position::new(1, 1, 0)) - ) - ); - assert_parse!( - selector_value("foo.bar;"), - Value::Selector(make_selector!(make_expr!("foo", Position::new(1, 1, 0)) => - [ - make_tok!("bar", Position::new(1, 5, 4)) - ] => - Position::new(1, 1, 0))) - ); - assert_parse!( - selector_value("({foo=1}).foo "), - Value::Selector( - make_selector!(Expression::Grouped(Box::new(Expression::Simple( - Value::Tuple(value_node!( - vec![(make_tok!("foo", Position::new(1, 3, 2)), Expression::Simple(Value::Int(PositionedItem::new(1, Position::new(1, 7, 6)))))], - Position::new(1, 3, 3))) - ))) => [ make_tok!("foo", Position::new(1, 11, 10)) ] => Position::new(1, 2, 1)) - ) - ); -} - -#[test] -fn test_statement_parse() { - let stmt = "import \"foo\" as foo;"; - assert_parse!( - statement(stmt), - Statement::Import(ImportDef { - path: make_tok!(QUOT => "foo", Position::new(1, 8, 7)), - name: make_tok!("foo", Position::new(1, 17, 16)), - }) - ); - - assert_abort!(import_statement("import \"foo\"")); - - assert_parse!( - statement("let foo = 1.0 ;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Simple(Value::Float(value_node!(1.0, Position::new(1, 11, 10)))), - }) - ); - - assert_parse!( - statement("let foo = 1 + 1 * 2;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 11, 10) - )))), - right: Box::new(Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Mul, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 15, 14) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 2, - Position::new(1, 19, 18) - )))), - pos: Position::new(1, 15, 14), - })), - pos: Position::new(1, 11, 10), - }), - }) - ); - - assert_parse!( - statement("let foo = (1 + 1) * 2;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Mul, - left: Box::new(Expression::Grouped(Box::new(Expression::Binary( - BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 12, 11) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 16, 15) - )))), - pos: Position::new(1, 12, 11), - }, - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 2, - Position::new(1, 21, 20) - )))), - pos: Position::new(1, 12, 11), - }), - }) - ); - - assert_parse!( - statement("let foo = 1 * 1 + 2;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Mul, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 11, 10) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 15, 14) - )))), - pos: Position::new(1, 11, 10), - })), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 2, - Position::new(1, 19, 18) - )))), - pos: Position::new(1, 11, 10), - }), - }) - ); - - assert_parse!( - statement("// comment\nlet foo = 1.0 ;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(2, 5, 15)), - value: Expression::Simple(Value::Float(value_node!(1.0, Position::new(2, 11, 21)))), - }) - ); - - assert_parse!( - statement("1.0;"), - Statement::Expression(Expression::Simple(Value::Float(value_node!( - 1.0, - Position::new(1, 1, 0) - )))) - ); -} - -#[test] -fn test_import_statement_parse() { - assert_abort!(import_statement("import")); - assert_abort!(import_statement("import \"foo\"")); - assert_abort!(import_statement("import \"foo\" as")); - assert_abort!(import_statement("import \"foo\" as foo")); - - let import_stmt = "import \"foo\" as foo;"; - assert_parse!( - import_statement(import_stmt), - Statement::Import(ImportDef { - path: make_tok!(QUOT => "foo", Position::new(1, 8, 7)), - name: make_tok!("foo", Position::new(1, 17, 16)), - }) - ); -} - -#[test] -fn test_let_statement_parse() { - assert_fail!(let_statement("foo")); - assert_abort!(let_statement("let \"foo\"")); - assert_abort!(let_statement("let 1")); - assert_abort!(let_statement("let")); - assert_abort!(let_statement("let foo")); - assert_abort!(let_statement("let foo =")); - assert_abort!(let_statement("let foo = ")); - assert_abort!(let_statement("let foo = 1")); - - assert_parse!( - let_statement("let foo = 1.0 ;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Simple(Value::Float(value_node!(1.0, Position::new(1, 11, 10)))), - }) - ); - - assert_parse!( - let_statement("let foo = // comment\n1.0 ;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Simple(Value::Float(value_node!(1.0, Position::new(2, 1, 22)))), - }) - ); - - assert_parse!( - let_statement("let foo = 1.0 // comment\n;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Simple(Value::Float(value_node!(1.0, Position::new(1, 11, 10)))), - }) - ); - - assert_parse!( - let_statement("let foo= 1.0;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Simple(Value::Float(value_node!(1.0, Position::new(1, 10, 9)))), - }) - ); - - assert_parse!( - let_statement("let foo =1.0;"), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 5, 4)), - value: Expression::Simple(Value::Float(value_node!(1.0, Position::new(1, 10, 9)))), - }) - ); -} - -#[test] -fn test_out_statement_parse() { - assert_abort!(out_statement("out")); - assert_abort!(out_statement("out json")); - assert_abort!(out_statement("out json foo")); - assert_parse!( - out_statement("out json 1.0;"), - Statement::Output( - Token { - pos: Position { - line: 1, - column: 5, - offset: 4 - }, - fragment: "json".to_string(), - typ: TokenType::BAREWORD - }, - Expression::Simple(Value::Float(value_node!(1.0, Position::new(1, 10, 9)))) - ) - ); -} - -#[test] -fn test_assert_statement_parse() { - assert_fail!(out_statement("assert")); - assert_fail!(out_statement("assert |")); - assert_fail!(out_statement("assert |foo")); - assert_parse!( - assert_statement("assert |foo|;"), - Statement::Assert(Token { - pos: Position { - line: 1, - column: 8, - offset: 7 - }, - fragment: "foo".to_string(), - typ: TokenType::PIPEQUOTE - }) - ); -} -#[test] -fn test_expression_statement_parse() { - assert_fail!(expression_statement("foo")); - assert_parse!( - expression_statement("1.0;"), - Statement::Expression(Expression::Simple(Value::Float(value_node!( - 1.0, - Position::new(1, 1, 0) - )))) - ); - assert_parse!( - expression_statement("1.0 ;"), - Statement::Expression(Expression::Simple(Value::Float(value_node!( - 1.0, - Position::new(1, 1, 0) - )))) - ); - assert_parse!( - expression_statement(" 1.0;"), - Statement::Expression(Expression::Simple(Value::Float(value_node!( - 1.0, - Position::new(1, 2, 1) - )))) - ); - assert_parse!( - expression_statement("foo;"), - Statement::Expression(Expression::Simple(Value::Selector(make_selector!( - make_expr!("foo", Position::new(1, 1, 0)), - Position::new(1, 1, 0) - )))) - ); - assert_parse!( - expression_statement("foo ;"), - Statement::Expression(Expression::Simple(Value::Selector(make_selector!( - make_expr!("foo", Position::new(1, 2, 1)), - Position::new(1, 1, 0) - )))) - ); - assert_parse!( - expression_statement(" foo;"), - Statement::Expression(Expression::Simple(Value::Selector(make_selector!( - make_expr!("foo", Position::new(1, 2, 1)), - Position::new(1, 2, 1) - )))) - ); - assert_parse!( - expression_statement("\"foo\";"), - Statement::Expression(Expression::Simple(Value::Str(value_node!( - "foo".to_string(), - Position::new(1, 1, 0) - )))) - ); - assert_parse!( - expression_statement("\"foo\" ;"), - Statement::Expression(Expression::Simple(Value::Str(value_node!( - "foo".to_string(), - Position::new(1, 1, 0) - )))) - ); - assert_parse!( - expression_statement(" \"foo\";"), - Statement::Expression(Expression::Simple(Value::Str(value_node!( - "foo".to_string(), - Position::new(1, 2, 1) - )))) - ); -} - -#[test] -fn test_expression_parse() { - assert_parse!( - expression("NULL "), - Expression::Simple(Value::Empty(Position::new(1, 1, 0))) - ); - assert_parse!( - expression("\"foo\""), - Expression::Simple(Value::Str(value_node!( - "foo".to_string(), - Position::new(1, 1, 0) - ))) - ); - assert_parse!( - expression("1"), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 1, 0)))) - ); - assert_parse!( - expression("foo "), - Expression::Simple(Value::Selector(make_selector!( - make_expr!("foo", Position::new(1, 1, 0)), - Position::new(1, 1, 0) - ))) - ); - assert_parse!( - expression("foo.bar "), - Expression::Simple(Value::Selector( - make_selector!(make_expr!("foo", Position::new(1, 1, 0)) => - [ make_tok!("bar", Position::new(1, 5, 4)) ] => - Position::new(1, 1, 0)) - )) - ); - assert_parse!( - expression("{foo=1}.foo "), - Expression::Simple(Value::Selector( - make_selector!(Expression::Simple(Value::Tuple( - value_node!(vec![ - ( - make_tok!("foo", Position::new(1, 2, 1)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 6, 5)))), - ), - ], - Position::new(1, 1, 0)), - )) => - [ make_tok!("foo", Position::new(1, 9, 8)) ] => - Position::new(1, 1, 0)) - )) - ); - assert_parse!( - expression("[1, 2].1 "), - Expression::Simple(Value::Selector( - make_selector!(Expression::Simple(Value::List( - ListDef{ - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 2, 1)))), - Expression::Simple(Value::Int(value_node!(2, Position::new(1, 5, 4)))), - ], - pos: Position::new(1, 1, 0), - })) => - [ make_tok!(DIGIT => "1", Position::new(1, 8, 7)) ] => - Position::new(1, 1, 0)) - )) - ); - assert_parse!( - expression("1 + 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 5, 4) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1 - 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Sub, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 5, 4) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1 / 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Div, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 5, 4) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("(1 / 1)"), - Expression::Grouped(Box::new(Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Div, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 2, 1) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 6, 5) - )))), - pos: Position::new(1, 2, 1), - }))) - ); - assert_parse!( - expression("1 / 1 + 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Div, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 5, 4) - )))), - pos: Position::new(1, 1, 0), - })), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 9, 8) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("(1 + 1) * 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Mul, - left: Box::new(Expression::Grouped(Box::new(Expression::Binary( - BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 2, 1) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 6, 5) - )))), - pos: Position::new(1, 2, 1), - } - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 11, 10) - )))), - pos: Position::new(1, 2, 1), - }) - ); - assert_parse!( - expression("1 > 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::GT, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 5, 4) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1 < 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::LT, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 5, 4) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1 <= 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::LTEqual, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 5, 4) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1 >= 1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::GTEqual, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 5, 4) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1+1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 3, 2) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1-1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Sub, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 3, 2) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1*1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Mul, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 3, 2) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("1/1"), - Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Div, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 1, 0) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 3, 2) - )))), - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("macro (arg1, arg2) => { foo = arg1 }"), - Expression::Macro(MacroDef { - argdefs: vec![ - value_node!("arg1".to_string(), Position::new(1, 8, 7)), - value_node!("arg2".to_string(), Position::new(1, 14, 13)), - ], - fields: vec![( - make_tok!("foo", Position::new(1, 25, 24)), - Expression::Simple(Value::Selector(make_selector!( - make_expr!("arg1", Position::new(1, 31, 30)), - Position::new(1, 31, 30) - ))), - )], - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("select foo, 1, { foo = 2 }"), - Expression::Select(SelectDef { - val: Box::new(Expression::Simple(Value::Selector(make_selector!( - make_expr!("foo", Position::new(1, 8, 7)), - Position::new(1, 8, 7) - )))), - default: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 13, 12) - )))), - tuple: vec![( - make_tok!("foo", Position::new(1, 18, 17)), - Expression::Simple(Value::Int(value_node!(2, Position::new(1, 24, 23)))), - )], - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("foo.bar (1, \"foo\")"), - Expression::Call(CallDef { - macroref: make_selector!(make_expr!("foo", Position::new(1, 1, 0)) => - [ make_tok!("bar", Position::new(1, 5, 4)) ] => - Position::new(1, 1, 0)), - arglist: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 10, 9)))), - Expression::Simple(Value::Str(value_node!( - "foo".to_string(), - Position::new(1, 13, 12) - ))), - ], - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - expression("(1 + 1)"), - Expression::Grouped(Box::new(Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 2, 1) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 6, 5) - )))), - pos: Position::new(1, 2, 1), - }))) - ); - assert_parse!( - expression("[1, 1]"), - Expression::Simple(Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 2, 1)))), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 5, 4)))), - ], - pos: Position::new(1, 1, 0), - })) - ); -} - -#[test] -fn test_format_parse() { - assert_fail!(format_expression("\"foo")); - assert_fail!(format_expression("\"foo\"")); - assert_fail!(format_expression("\"foo\" %")); - assert_fail!(format_expression("\"foo\" % (, 2")); - - assert_parse!( - format_expression("\"foo @ @\" % (1, 2)"), - Expression::Format(FormatDef { - template: "foo @ @".to_string(), - args: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 14, 13)))), - Expression::Simple(Value::Int(value_node!(2, Position::new(1, 17, 16)))), - ], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - format_expression("\"foo @ @\"%(1, 2)"), - Expression::Format(FormatDef { - template: "foo @ @".to_string(), - args: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 12, 11)))), - Expression::Simple(Value::Int(value_node!(2, Position::new(1, 15, 14)))), - ], - pos: Position::new(1, 1, 0), - }) - ); -} - -#[test] -fn test_call_parse() { - assert_fail!(call_expression("foo")); - assert_fail!(call_expression("foo (")); - assert_fail!(call_expression("foo (1")); - assert_fail!(call_expression("foo (1,")); - assert_fail!(call_expression("foo (1,2")); - - assert_parse!( - call_expression("foo (1, \"foo\")"), - Expression::Call(CallDef { - macroref: make_selector!( - make_expr!("foo", Position::new(1, 1, 0)), - Position::new(1, 1, 0) - ), - arglist: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 6, 5)))), - Expression::Simple(Value::Str(value_node!( - "foo".to_string(), - Position::new(1, 9, 8) - ))), - ], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - call_expression("foo.bar (1, \"foo\")"), - Expression::Call(CallDef { - macroref: make_selector!(make_expr!("foo", Position::new(1, 1, 0)) => [ make_tok!("bar", Position::new(1, 5, 4)) ] => Position::new(1, 1, 0)), - arglist: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 10, 9)))), - Expression::Simple(Value::Str(value_node!( - "foo".to_string(), - Position::new(1, 13, 12) - ))), - ], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - call_expression("foo ()"), - Expression::Call(CallDef { - macroref: make_selector!( - make_expr!("foo", Position::new(1, 1, 0)), - Position::new(1, 1, 0) - ), - arglist: Vec::new(), - pos: Position::new(1, 1, 0), - }) - ); -} - -#[test] -fn test_select_parse() { - assert_fail!(select_expression("select")); - assert_fail!(select_expression("select foo")); - assert_fail!(select_expression("select foo, 1")); - assert_fail!(select_expression("select foo, 1, {")); - - assert_parse!( - select_expression("select foo, 1, { foo = 2 }"), - Expression::Select(SelectDef { - val: Box::new(Expression::Simple(Value::Selector(make_selector!( - make_expr!("foo", Position::new(1, 8, 7)), - Position::new(1, 8, 7) - )))), - default: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 13, 12) - )))), - tuple: vec![( - make_tok!("foo", Position::new(1, 18, 17)), - Expression::Simple(Value::Int(value_node!(2, Position::new(1, 24, 23)))), - )], - pos: Position::new(1, 1, 0), - }) - ); -} - -#[test] -fn test_module_expression_parsing() { - assert_fail!(module_expression("foo")); - assert_fail!(module_expression("module")); - assert_fail!(module_expression("module(")); - assert_fail!(module_expression("module[")); - assert_fail!(module_expression("module {")); - assert_fail!(module_expression("module {}")); - assert_fail!(module_expression("module {} =>")); - assert_fail!(module_expression("module {} => {")); - - assert_parse!( - module_expression("module {} => {}"), - Expression::Module(ModuleDef { - pos: Position::new(1, 1, 0), - arg_set: Vec::new(), - arg_tuple: None, - statements: Vec::new(), - }) - ); -} - -#[test] -fn test_macro_expression_parsing() { - assert_fail!(macro_expression("foo")); - assert_fail!(macro_expression("macro \"foo\"")); - assert_fail!(macro_expression("macro 1")); - assert_fail!(macro_expression("macro")); - assert_fail!(macro_expression("macro (")); - assert_fail!(macro_expression("macro (arg")); - assert_fail!(macro_expression("macro (arg, arg2")); - assert_fail!(macro_expression("macro (arg1, arg2) =>")); - assert_fail!(macro_expression("macro (arg1, arg2) => {")); - assert_fail!(macro_expression("macro (arg1, arg2) => { foo")); - assert_fail!(macro_expression("macro (arg1, arg2) => { foo =")); - - assert_parse!( - macro_expression("macro () => {foo=1,bar=2}"), - Expression::Macro(MacroDef { - argdefs: Vec::new(), - fields: vec![ - ( - make_tok!("foo", Position::new(1, 14, 13)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 18, 17)))), - ), - ( - make_tok!("bar", Position::new(1, 20, 19)), - Expression::Simple(Value::Int(value_node!(2, Position::new(1, 24, 23)))), - ), - ], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - macro_expression("macro (arg1, arg2) => {foo=1,bar=2}"), - Expression::Macro(MacroDef { - argdefs: vec![ - value_node!("arg1".to_string(), Position::new(1, 8, 7)), - value_node!("arg2".to_string(), Position::new(1, 14, 13)), - ], - fields: vec![ - ( - make_tok!("foo", Position::new(1, 24, 23)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 28, 27)))), - ), - ( - make_tok!("bar", Position::new(1, 30, 29)), - Expression::Simple(Value::Int(value_node!(2, Position::new(1, 34, 33)))), - ), - ], - pos: Position::new(1, 1, 0), - }) - ); -} - -#[test] -fn test_copy_parse() { - assert_fail!(copy_expression("{}")); - assert_fail!(copy_expression("foo")); - assert_fail!(copy_expression("foo{")); - - assert_parse!( - copy_expression("foo{}"), - Expression::Copy(CopyDef { - selector: make_selector!( - make_expr!("foo", Position::new(1, 1, 0)), - Position::new(1, 1, 0) - ), - fields: Vec::new(), - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - copy_expression("foo{bar=1}"), - Expression::Copy(CopyDef { - selector: make_selector!( - make_expr!("foo", Position::new(1, 1, 0)), - Position::new(1, 1, 0) - ), - fields: vec![( - make_tok!("bar", Position::new(1, 5, 4)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - )], - pos: Position::new(1, 1, 0), - }) - ); - assert_parse!( - copy_expression("foo{bar=1,}"), - Expression::Copy(CopyDef { - selector: make_selector!( - make_expr!("foo", Position::new(1, 1, 0)), - Position::new(1, 1, 0) - ), - fields: vec![( - make_tok!("bar", Position::new(1, 5, 4)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - )], - pos: Position::new(1, 1, 0), - }) - ); -} - -#[test] -fn test_grouped_expression_parse() { - assert_fail!(grouped_expression("foo")); - assert_fail!(grouped_expression("(foo")); - assert_parse!( - grouped_expression("(foo)"), - Expression::Grouped(Box::new(Expression::Simple(Value::Selector( - make_selector!( - make_expr!("foo", Position::new(1, 2, 1)), - Position::new(1, 2, 1) - ) - )))) - ); - assert_parse!( - grouped_expression("(1 + 1)"), - Expression::Grouped(Box::new(Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 2, 1) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 6, 5) - )))), - pos: Position::new(1, 2, 1), - }))) - ); -} - -#[test] -fn test_list_value_parse() { - assert_fail!(list_value("foo")); - assert_fail!(list_value("[foo")); - assert_fail!(list_value("// commen\n[foo")); - - assert_parse!( - list_value("[foo]"), - Value::List(ListDef { - elems: vec![Expression::Simple(Value::Selector(make_selector!( - make_expr!("foo", Position::new(1, 2, 1)), - Position::new(1, 2, 1) - )))], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - list_value("[1, 1]"), - Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 2, 1)))), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 5, 4)))), - ], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - list_value("[1, 1,]"), - Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 2, 1)))), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 5, 4)))), - ], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - list_value("// comment\n[1, 1]"), - Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 2, 12)))), - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 5, 14)))), - ], - pos: Position::new(2, 1, 11), - }) - ); - - assert_parse!( - list_value("[// comment\n1, 1]"), - Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 2, 12)))), - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 5, 15)))), - ], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - list_value("[1, // comment\n1]"), - Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 2, 1)))), - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 1, 14)))), - ], - pos: Position::new(1, 1, 0), - }) - ); - - assert_parse!( - list_value("[1, 1 // comment\n]"), - Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 2, 1)))), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 5, 4)))), - ], - pos: Position::new(1, 1, 0), - }) - ); -} - -#[test] -fn test_tuple_parse() { - assert_fail!(tuple("{")); - assert_fail!(tuple("{ foo")); - assert_fail!(tuple("{ foo =")); - assert_fail!(tuple("{ foo = 1")); - assert_fail!(tuple("{ foo = 1,")); - assert_fail!(tuple("{ foo = 1, bar =")); - assert_fail!(tuple("// comment\n{ foo = 1, bar =")); - - assert_parse!( - tuple("{ }"), - Value::Tuple(value_node!(vec![], Position::new(1, 1, 0))) - ); - - assert_parse!( - tuple("{ foo = 1 }"), - Value::Tuple(value_node!( - vec![( - make_tok!("foo", Position::new(1, 3, 2)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - )], - Position::new(1, 1, 0) - )) - ); - - assert_parse!( - tuple("// comment\n{ foo = 1 }"), - Value::Tuple(value_node!( - vec![( - make_tok!("foo", Position::new(2, 3, 13)), - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 9, 19)))), - )], - Position::new(1, 1, 0) - )) - ); - - assert_parse!( - tuple("{// comment\n foo = 1 }"), - Value::Tuple(value_node!( - vec![( - make_tok!("foo", Position::new(2, 2, 13)), - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 8, 19)))), - )], - Position::new(1, 1, 0) - )) - ); - - assert_parse!( - tuple("{ foo = 1// comment\n }"), - Value::Tuple(value_node!( - vec![( - make_tok!("foo", Position::new(1, 3, 2)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - )], - Position::new(1, 1, 0) - )) - ); - - assert_parse!( - tuple("{ foo = 1, bar = \"1\" }"), - Value::Tuple(value_node!( - vec![ - ( - make_tok!("foo", Position::new(1, 3, 2)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - ), - ( - make_tok!("bar", Position::new(1, 12, 11)), - Expression::Simple(Value::Str(value_node!( - "1".to_string(), - Position::new(1, 18, 17) - ))), - ), - ], - Position::new(1, 1, 0) - )) - ); - assert_parse!( - tuple("{ foo = 1, // comment\nbar = \"1\" }"), - Value::Tuple(value_node!( - vec![ - ( - make_tok!("foo", Position::new(1, 3, 2)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - ), - ( - make_tok!("bar", Position::new(2, 1, 22)), - Expression::Simple(Value::Str(value_node!( - "1".to_string(), - Position::new(2, 7, 28) - ))), - ), - ], - Position::new(1, 1, 0) - )) - ); - assert_parse!( - tuple("{ foo = 1, bar = {} }"), - Value::Tuple(value_node!( - vec![ - ( - make_tok!("foo", Position::new(1, 3, 2)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - ), - ( - make_tok!("bar", Position::new(1, 12, 11)), - Expression::Simple(Value::Tuple(value_node!( - Vec::new(), - Position::new(1, 17, 16) - ))), - ), - ], - Position::new(1, 1, 0) - )) - ); - assert_parse!( - tuple("{ foo = 1, bar = {}, }"), - Value::Tuple(value_node!( - vec![ - ( - make_tok!("foo", Position::new(1, 3, 2)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - ), - ( - make_tok!("bar", Position::new(1, 12, 11)), - Expression::Simple(Value::Tuple(value_node!( - Vec::new(), - Position::new(1, 17, 16) - ))), - ), - ], - Position::new(1, 1, 0) - )) - ); - - assert_parse!( - expression("{ foo = 1, lst = [1, 2, 3], }"), - Expression::Simple(Value::Tuple(value_node!( - vec![ - ( - make_tok!("foo", Position::new(1, 3, 2)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 9, 8)))), - ), - ( - make_tok!("lst", Position::new(1, 12, 11)), - Expression::Simple(Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 19, 18) - ))), - Expression::Simple(Value::Int(value_node!( - 2, - Position::new(1, 22, 21) - ))), - Expression::Simple(Value::Int(value_node!( - 3, - Position::new(1, 25, 24) - ))), - ], - pos: Position { - line: 1, - column: 18, - offset: 17, - }, - })), - ), - ], - Position::new(1, 1, 0) - ))) - ); -} - -#[test] -fn test_field_list_parse() { - let mut f_list = "foo = 1, quux = 2;"; - assert_parse!( - field_list(f_list), - vec![ - ( - make_tok!("foo", Position::new(1, 1, 0)), - make_expr!(1 => int, Position::new(1, 7, 6)) - ), - ( - make_tok!("quux", Position::new(1, 10, 9)), - make_expr!(2 => int, Position::new(1, 17, 16)) - ), - ] - ); - - f_list = "foo = 1, // comment\nquux = 2;"; - assert_parse!( - field_list(f_list), - vec![ - ( - make_tok!("foo", Position::new(1, 1, 0)), - make_expr!(1 => int, Position::new(1, 7, 6)) - ), - ( - make_tok!("quux", Position::new(2, 1, 20)), - make_expr!(2 => int, Position::new(2, 8, 27)) - ), - ] - ); - - f_list = "foo = 1,\n// comment\nquux = 2;"; - assert_parse!( - field_list(f_list), - vec![ - ( - make_tok!("foo", Position::new(1, 1, 0)), - make_expr!(1 => int, Position::new(1, 7, 6)) - ), - ( - make_tok!("quux", Position::new(3, 1, 20)), - make_expr!(2 => int, Position::new(3, 8, 28)) - ), - ] - ); - f_list = "foo = 1,\nquux = [1, 2],"; - assert_parse!( - field_list(f_list), - vec![ - ( - make_tok!("foo", Position::new(1, 1, 0)), - make_expr!(1 => int, Position::new(1, 7, 6)) - ), - ( - make_tok!("quux", Position::new(2, 1, 9)), - Expression::Simple(Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 9, 17)))), - Expression::Simple(Value::Int(value_node!(2, Position::new(2, 12, 20)))), - ], - pos: Position::new(2, 8, 16), - })), - ), - ] - ); -} - -#[test] -fn test_field_value_parse() { - assert_fail!(field_value("foo")); - assert_fail!(field_value("// comment\nfoo")); - assert_fail!(field_value("foo =")); - - assert_parse!( - field_value("foo = 1"), - ( - make_tok!("foo", Position::new(1, 1, 0)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 7, 6)))) - ) - ); - assert_parse!( - field_value("foo = 1 // foo comment\n"), - ( - make_tok!("foo", Position::new(1, 1, 0)), - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 7, 6)))) - ) - ); - assert_parse!( - field_value("foo // foo comment\n = 1"), - ( - make_tok!("foo", Position::new(1, 1, 0)), - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 4, 4)))) - ) - ); - assert_parse!( - field_value("// foo comment\nfoo = 1"), - ( - make_tok!("foo", Position::new(2, 1, 15)), - Expression::Simple(Value::Int(value_node!(1, Position::new(2, 7, 21)))) - ) - ); - assert_parse!( - field_value("foo = \"1\""), - ( - make_tok!("foo", Position::new(1, 1, 0)), - Expression::Simple(Value::Str(value_node!( - "1".to_string(), - Position::new(1, 7, 6) - ))) - ) - ); - assert_parse!( - field_value("foo = bar "), - ( - make_tok!("foo", Position::new(1, 1, 0)), - Expression::Simple(Value::Selector(make_selector!( - make_expr!("bar", Position::new(1, 7, 6)), - Position::new(1, 7, 6) - ))) - ) - ); - assert_parse!( - field_value("foo = bar.baz "), - ( - make_tok!("foo", Position::new(1, 1, 0)), - Expression::Simple(Value::Selector( - make_selector!(make_expr!("bar", Position::new(1, 7, 6)) => [ make_tok!("baz", Position::new(1, 11, 10)) ] => Position::new(1, 7, 6)), - )) - ) - ); - assert_parse!( - field_value("foo = [1,2], "), - ( - make_tok!("foo", Position::new(1, 1, 0)), - Expression::Simple(Value::List(ListDef { - elems: vec![ - Expression::Simple(Value::Int(value_node!(1, Position::new(1, 8, 7)))), - Expression::Simple(Value::Int(value_node!(2, Position::new(1, 10, 9)))), - ], - pos: Position::new(1, 7, 6), - })) - ) - ); -} - -#[test] -fn test_number_parsing() { - assert_fail!(number(".")); - assert_fail!(number(". ")); - assert_parse!( - number("1.0"), - Value::Float(value_node!(1.0, Position::new(1, 1, 0))) - ); - assert_parse!( - number("1."), - Value::Float(value_node!(1.0, Position::new(1, 1, 0))) - ); - assert_parse!( - number("1"), - Value::Int(value_node!(1, Position::new(1, 1, 0))) - ); - assert_parse!( - number(".1"), - Value::Float(value_node!(0.1, Position::new(1, 1, 0))) - ); -} - -#[test] -fn test_parse() { - let bad_input = OffsetStrIter::new("import mylib as lib;"); - let bad_result = parse(bad_input); - assert!(bad_result.is_err()); - - // Valid parsing tree - let input = OffsetStrIter::new("import \"mylib\" as lib;let foo = 1;1+1;"); - let result = parse(input); - assert!(result.is_ok(), format!("Expected Ok, Got {:?}", result)); - let tpl = result.unwrap(); - assert_eq!( - tpl, - vec![ - Statement::Import(ImportDef { - path: make_tok!(QUOT => "mylib", Position::new(1, 8, 7)), - name: make_tok!("lib", Position::new(1, 19, 18)), - }), - Statement::Let(LetDef { - name: make_tok!("foo", Position::new(1, 27, 26)), - value: Expression::Simple(Value::Int(value_node!(1, Position::new(1, 33, 32)))), - }), - Statement::Expression(Expression::Binary(BinaryOpDef { - kind: BinaryExprType::Add, - left: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 35, 34) - )))), - right: Box::new(Expression::Simple(Value::Int(value_node!( - 1, - Position::new(1, 37, 36) - )))), - pos: Position::new(1, 35, 34), - })), - ] - ); -}