FEATURE: Allow tuples and lists as the head of a selector.

This commit is contained in:
Jeremy Wall 2018-05-27 14:46:39 -05:00
parent 988698fc01
commit cefb307783
2 changed files with 76 additions and 15 deletions

View File

@ -216,15 +216,25 @@ named!(empty_value<TokenIter, Value, error::Error>,
) )
); );
named!(value<TokenIter, Value, error::Error>, named!(compound_value<TokenIter, Value, error::Error>,
alt!(list_value | tuple)
);
named!(scalar_value<TokenIter, Value, error::Error>,
alt!( alt!(
boolean_value | boolean_value |
empty_value | empty_value |
number | number |
quoted_value | quoted_value
list_value | )
tuple | );
selector_value )
named!(value<TokenIter, Value, error::Error>,
alt!(
selector_value
| compound_value
| scalar_value
)
); );
fn value_to_expression(v: Value) -> ParseResult<Expression> { fn value_to_expression(v: Value) -> ParseResult<Expression> {
@ -382,18 +392,38 @@ named!(grouped_expression<TokenIter, Expression, error::Error>,
); );
fn symbol_or_expression(input: TokenIter) -> NomResult<Expression> { fn symbol_or_expression(input: TokenIter) -> NomResult<Expression> {
let sym = do_parse!(input, sym: symbol >> (sym)); let scalar_head = do_parse!(input, sym: alt!(symbol | compound_value) >> (sym));
match sym { match scalar_head {
IResult::Incomplete(i) => { IResult::Incomplete(i) => IResult::Incomplete(i),
return IResult::Incomplete(i); IResult::Error(_) => grouped_expression(input),
}
IResult::Error(_) => {
// TODO(jwall): Still missing some. But we need to avoid recursion
return grouped_expression(input);
}
IResult::Done(rest, val) => { 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)),
}
} }
} }
} }

View File

@ -362,6 +362,37 @@ fn test_expression_parse() {
[ make_tok!("bar", 1, 5) ] => [ make_tok!("bar", 1, 5) ] =>
1, 1))) 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!( assert_parse!(
expression("1 + 1"), expression("1 + 1"),
Expression::Binary(BinaryOpDef { Expression::Binary(BinaryOpDef {