Extended exprs
This commit is contained in:
parent
7a9e43bf8e
commit
b7b4e75f01
@ -176,10 +176,82 @@ fn prefix_expr(input: Span) -> ParseResult<ExpressionKind> {
|
|||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
|
#[derive(Debug)]
|
||||||
context("extended-expr", primary_expr)(input)
|
enum ExtendedPart<'a> {
|
||||||
|
Index(Vec<Expression>),
|
||||||
|
Call(Vec<InvocationArgument>),
|
||||||
|
Accessor(&'a str),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
|
let (s, (primary, parts)) = context("extended-expr",
|
||||||
|
pair(primary_expr, many0(extended_expr_part)))(input)?;
|
||||||
|
|
||||||
|
let mut expression = Expression::new(fresh_id(&s), primary);
|
||||||
|
for part in parts.into_iter() {
|
||||||
|
let kind = match part {
|
||||||
|
ExtendedPart::Index(indexers) => {
|
||||||
|
ExpressionKind::Index { indexee: Box::new(expression), indexers }
|
||||||
|
},
|
||||||
|
ExtendedPart::Call(arguments) => {
|
||||||
|
ExpressionKind::Call { f: Box::new(expression), arguments }
|
||||||
|
}
|
||||||
|
ExtendedPart::Accessor(name) => {
|
||||||
|
let name = rc_string(name);
|
||||||
|
ExpressionKind::Access { name, expr: Box::new(expression) }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expression = Expression::new(fresh_id(&s), kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((s, expression.kind))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extended_expr_part(input: Span) -> ParseResult<ExtendedPart> {
|
||||||
|
fn index_part(input: Span) -> ParseResult<Vec<Expression>> {
|
||||||
|
delimited(
|
||||||
|
tok(char('[')),
|
||||||
|
separated_list1(tok(char(',')), expression),
|
||||||
|
tok(char(']')),
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_part(input: Span) -> ParseResult<Vec<InvocationArgument>> {
|
||||||
|
delimited(
|
||||||
|
tok(char('(')),
|
||||||
|
separated_list0(tok(char(',')), invocation_argument),
|
||||||
|
tok(char(')')),
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn access_part(input: Span) -> ParseResult<&str> {
|
||||||
|
preceded(
|
||||||
|
tok(char('.')),
|
||||||
|
map(identifier, |item| *item.fragment())
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
alt((
|
||||||
|
map(index_part, ExtendedPart::Index),
|
||||||
|
map(call_part, ExtendedPart::Call),
|
||||||
|
map(access_part, ExtendedPart::Accessor)
|
||||||
|
))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO this shouldn't be an expression b/c type annotations disallowed here
|
||||||
|
fn invocation_argument(input: Span) -> ParseResult<InvocationArgument> {
|
||||||
|
alt((
|
||||||
|
map(tok(char('_')), |_| InvocationArgument::Ignored),
|
||||||
|
map(tuple((
|
||||||
|
tok(identifier),
|
||||||
|
tok(char('=')),
|
||||||
|
expression,
|
||||||
|
)), |(name, _, expr)| InvocationArgument::Keyword { name: rc_string(name.fragment()), expr }),
|
||||||
|
map(expression, InvocationArgument::Positional),
|
||||||
|
))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn primary_expr(input: Span) -> ParseResult<ExpressionKind> {
|
fn primary_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||||
context("primary-expr", alt((
|
context("primary-expr", alt((
|
||||||
list_expr, paren_expr,
|
list_expr, paren_expr,
|
||||||
|
@ -222,8 +222,8 @@ fn prefix_exps() {
|
|||||||
assert_expr_comb!("-0.2", prefixop("-", expr(FloatLiteral(0.2))));
|
assert_expr_comb!("-0.2", prefixop("-", expr(FloatLiteral(0.2))));
|
||||||
assert_expr_comb!("!3", prefixop("!", expr(NatLiteral(3))));
|
assert_expr_comb!("!3", prefixop("!", expr(NatLiteral(3))));
|
||||||
assert_expr_comb!("!t", prefixop("!", expr(Value(qn!(t)))));
|
assert_expr_comb!("!t", prefixop("!", expr(Value(qn!(t)))));
|
||||||
assert_expr!("a <- -b", binop("<-", expr(Value(qn!(a))), prefixop("-", expr(Value(qn!(b))))));
|
assert_expr_comb!("a <- -b", binop("<-", expr(Value(qn!(a))), prefixop("-", expr(Value(qn!(b))))));
|
||||||
assert_expr!("a <--b", binop("<--", expr(Value(qn!(a))), expr(Value(qn!(b)))));
|
assert_expr_comb!("a <--b", binop("<--", expr(Value(qn!(a))), expr(Value(qn!(b)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -239,15 +239,15 @@ fn operators() {
|
|||||||
fn accessors() {
|
fn accessors() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
assert_expr!("a.b", expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }));
|
assert_expr_comb!("a.b", expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }));
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"a.b.c",
|
"a.b.c",
|
||||||
expr(Access {
|
expr(Access {
|
||||||
name: rc("c"),
|
name: rc("c"),
|
||||||
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
|
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"a.b.c(3)",
|
"a.b.c(3)",
|
||||||
expr(Call {
|
expr(Call {
|
||||||
f: bx(expr(Access {
|
f: bx(expr(Access {
|
||||||
@ -257,7 +257,7 @@ fn accessors() {
|
|||||||
arguments: vec![InvocationArgument::Positional(expr(NatLiteral(3)))],
|
arguments: vec![InvocationArgument::Positional(expr(NatLiteral(3)))],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"a.b().c",
|
"a.b().c",
|
||||||
expr(Access {
|
expr(Access {
|
||||||
name: rc("c"),
|
name: rc("c"),
|
||||||
@ -296,7 +296,7 @@ fn identifiers() {
|
|||||||
assert_expr_comb!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma))));
|
assert_expr_comb!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma))));
|
||||||
assert_expr_comb!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b)))));
|
assert_expr_comb!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b)))));
|
||||||
assert_expr_comb!("None", expr(Value(qn!(None))));
|
assert_expr_comb!("None", expr(Value(qn!(None))));
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"thing::item::call()",
|
"thing::item::call()",
|
||||||
expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] })
|
expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] })
|
||||||
);
|
);
|
||||||
@ -324,14 +324,14 @@ fn named_struct() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn index() {
|
fn index() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"armok[b,c]",
|
"armok[b,c]",
|
||||||
expr(Index {
|
expr(Index {
|
||||||
indexee: bx(expr(Value(qn!(armok)))),
|
indexee: bx(expr(Value(qn!(armok)))),
|
||||||
indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))]
|
indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"a[b,c][1]",
|
"a[b,c][1]",
|
||||||
expr(Index {
|
expr(Index {
|
||||||
indexee: bx(expr(Index {
|
indexee: bx(expr(Index {
|
||||||
@ -341,7 +341,7 @@ fn index() {
|
|||||||
indexers: vec![expr(NatLiteral(1))]
|
indexers: vec![expr(NatLiteral(1))]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_expr!(
|
assert_expr_comb!(
|
||||||
"perspicacity()[a]",
|
"perspicacity()[a]",
|
||||||
expr(Index {
|
expr(Index {
|
||||||
indexee: bx(expr(Call { f: bx(expr(Value(qn!(perspicacity)))), arguments: vec![] })),
|
indexee: bx(expr(Call { f: bx(expr(Value(qn!(perspicacity)))), arguments: vec![] })),
|
||||||
@ -353,7 +353,7 @@ fn index() {
|
|||||||
let b = expr(Index { indexee: bx(a), indexers: vec![expr(Value(qn!(b)))] });
|
let b = expr(Index { indexee: bx(a), indexers: vec![expr(Value(qn!(b)))] });
|
||||||
let c = expr(Call { f: bx(b), arguments: vec![] });
|
let c = expr(Call { f: bx(b), arguments: vec![] });
|
||||||
let d = expr(Index { indexee: bx(c), indexers: vec![expr(Value(qn!(d)))] });
|
let d = expr(Index { indexee: bx(c), indexers: vec![expr(Value(qn!(d)))] });
|
||||||
assert_expr!("a()[b]()[d]", d);
|
assert_expr_comb!("a()[b]()[d]", d);
|
||||||
|
|
||||||
assert_fail_expr!("a[]", "Empty index expressions are not allowed");
|
assert_fail_expr!("a[]", "Empty index expressions are not allowed");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user