diff --git a/src/parse/mod.rs b/src/parse/mod.rs index e8b5d0d..4263469 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -216,15 +216,25 @@ named!(empty_value, ) ); -named!(value, +named!(compound_value, + alt!(list_value | tuple) +); + +named!(scalar_value, alt!( boolean_value | empty_value | number | - quoted_value | - list_value | - tuple | - selector_value ) + quoted_value + ) +); + +named!(value, + alt!( + selector_value + | compound_value + | scalar_value + ) ); fn value_to_expression(v: Value) -> ParseResult { @@ -382,18 +392,38 @@ named!(grouped_expression, ); fn symbol_or_expression(input: TokenIter) -> NomResult { - let sym = do_parse!(input, sym: symbol >> (sym)); + let scalar_head = do_parse!(input, sym: alt!(symbol | compound_value) >> (sym)); - match sym { - IResult::Incomplete(i) => { - return IResult::Incomplete(i); - } - IResult::Error(_) => { - // TODO(jwall): Still missing some. But we need to avoid recursion - return grouped_expression(input); - } + match scalar_head { + IResult::Incomplete(i) => IResult::Incomplete(i), + IResult::Error(_) => grouped_expression(input), IResult::Done(rest, val) => { - return IResult::Done(rest, Expression::Simple(val)); + let res = peek!(rest.clone(), punct!(".")); + match val { + Value::Tuple(_) => { + if res.is_done() { + IResult::Done(rest, Expression::Simple(val)) + } else { + return IResult::Error(nom::ErrorKind::Custom(error::Error::new( + "Expected (.) but no dot found".to_string(), + error::ErrorType::IncompleteParsing, + val.pos().clone(), + ))); + } + } + Value::List(_) => { + if res.is_done() { + IResult::Done(rest, Expression::Simple(val)) + } else { + return IResult::Error(nom::ErrorKind::Custom(error::Error::new( + "Expected (.) but no dot found".to_string(), + error::ErrorType::IncompleteParsing, + val.pos().clone(), + ))); + } + } + _ => IResult::Done(rest, Expression::Simple(val)), + } } } } diff --git a/src/parse/test.rs b/src/parse/test.rs index 84797a3..b5be55c 100644 --- a/src/parse/test.rs +++ b/src/parse/test.rs @@ -362,6 +362,37 @@ fn test_expression_parse() { [ make_tok!("bar", 1, 5) ] => 1, 1))) ); + assert_parse!( + expression("{foo=1}.foo "), + Expression::Simple(Value::Selector( + make_selector!(Expression::Simple(Value::Tuple( + value_node!(vec![ + ( + make_tok!("foo", 1, 2), + Expression::Simple(Value::Int(value_node!(1, 1, 6))), + ), + ], + 1, 1), + )) => + [ make_tok!("foo", 1, 9) ] => + 1, 1) + )) + ); + 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, 1, 2))), + Expression::Simple(Value::Int(value_node!(2, 1, 5))), + ], + pos: Position::new(1, 1), + })) => + [ make_tok!(DIGIT => "1", 1, 8) ] => + 1, 1) + )) + ); assert_parse!( expression("1 + 1"), Expression::Binary(BinaryOpDef {