if exprs
This commit is contained in:
parent
ec51659452
commit
721a499384
@ -300,6 +300,16 @@ fn expression_no_struct(input: Span) -> ParseResult<Expression> {
|
||||
})(input)
|
||||
}
|
||||
|
||||
fn expr_or_block(input: Span) -> ParseResult<Block> {
|
||||
let (input, pos) = position(input)?;
|
||||
let id = fresh_id(&input);
|
||||
let location = pos.location_offset().into();
|
||||
alt((
|
||||
block,
|
||||
map(expression, move |expr| Statement { id, location, kind: StatementKind::Expression(expr) }.into()),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn type_anno(input: Span) -> ParseResult<TypeIdentifier> {
|
||||
preceded(tok(char(':')), type_identifier)(input)
|
||||
}
|
||||
@ -444,11 +454,13 @@ fn primary_expr(allow_struct: bool) -> impl FnMut(Span) -> ParseResult<Expressio
|
||||
}
|
||||
|
||||
fn primary_expr_no_struct(input: Span) -> ParseResult<ExpressionKind> {
|
||||
println!("PRIM EXPR: {}", input.fragment());
|
||||
context(
|
||||
"primary-expr-no-struct",
|
||||
alt((
|
||||
while_expr,
|
||||
for_expr,
|
||||
if_expr,
|
||||
list_expr,
|
||||
paren_expr,
|
||||
string_literal,
|
||||
@ -482,10 +494,119 @@ fn while_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||
})(input)
|
||||
}
|
||||
|
||||
fn if_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||
fn else_case(input: Span) -> ParseResult<Option<Block>> {
|
||||
opt(preceded(kw("else"), expr_or_block))(input)
|
||||
}
|
||||
|
||||
fn cond_block(input: Span) -> ParseResult<IfExpressionBody> {
|
||||
map(block_template(cond_arm), IfExpressionBody::CondList)(input)
|
||||
}
|
||||
|
||||
fn cond_arm(input: Span) -> ParseResult<ConditionArm> {
|
||||
let condition = map(preceded(kw("is"), pattern), Condition::Pattern);
|
||||
let condition_guard = opt(preceded(kw("if"), expression));
|
||||
alt((
|
||||
map(preceded(kw("else"), expr_or_block), |body| ConditionArm {
|
||||
condition: Condition::Else,
|
||||
guard: None,
|
||||
body,
|
||||
}),
|
||||
map(
|
||||
tuple((condition, condition_guard, kw("then"), expr_or_block)),
|
||||
|(condition, guard, _, body)| ConditionArm { condition, guard, body },
|
||||
),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn simple_pattern_match(input: Span) -> ParseResult<IfExpressionBody> {
|
||||
map(
|
||||
tuple((preceded(kw("is"), pattern), preceded(kw("then"), pair(expr_or_block, else_case)))),
|
||||
|(pattern, (then_case, else_case))| IfExpressionBody::SimplePatternMatch {
|
||||
pattern,
|
||||
then_case,
|
||||
else_case,
|
||||
},
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn simple_conditional(input: Span) -> ParseResult<IfExpressionBody> {
|
||||
map(preceded(kw("then"), pair(expr_or_block, else_case)), |(then_case, else_case)| {
|
||||
IfExpressionBody::SimpleConditional { then_case, else_case }
|
||||
})(input)
|
||||
}
|
||||
|
||||
fn if_expr_body(input: Span) -> ParseResult<IfExpressionBody> {
|
||||
alt((cond_block, simple_pattern_match, simple_conditional))(input)
|
||||
}
|
||||
|
||||
map(preceded(kw("if"), pair(opt(expression_no_struct), if_expr_body)), |(discriminator, body)| {
|
||||
ExpressionKind::IfExpression { discriminator: discriminator.map(Box::new), body: Box::new(body) }
|
||||
})(input)
|
||||
}
|
||||
|
||||
fn pattern(input: Span) -> ParseResult<Pattern> {
|
||||
alt((
|
||||
map(
|
||||
delimited(tok(char('(')), separated_list1(tok(char(',')), pattern), tok(char(')'))),
|
||||
Pattern::TuplePattern,
|
||||
),
|
||||
simple_pattern,
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn simple_pattern(input: Span) -> ParseResult<Pattern> {
|
||||
fn record_pattern_entry(input: Span) -> ParseResult<(Rc<String>, Pattern)> {
|
||||
let id = fresh_id(&input);
|
||||
alt((
|
||||
map(separated_pair(identifier, tok(char(':')), pattern), |(ident, pat)| {
|
||||
(rc_string(ident.fragment()), pat)
|
||||
}),
|
||||
map(identifier, move |ident| {
|
||||
let qn = QualifiedName { id, components: vec![rc_string(ident.fragment())] };
|
||||
(rc_string(ident.fragment()), Pattern::VarOrName(qn))
|
||||
}),
|
||||
))(input)
|
||||
}
|
||||
|
||||
alt((
|
||||
pattern_literal,
|
||||
map(
|
||||
pair(
|
||||
qualified_identifier,
|
||||
delimited(tok(char('(')), separated_list0(tok(char(',')), pattern), tok(char(')'))),
|
||||
),
|
||||
|(qn, members)| Pattern::TupleStruct(qn, members),
|
||||
),
|
||||
map(
|
||||
pair(
|
||||
qualified_identifier,
|
||||
delimited(
|
||||
tok(char('{')),
|
||||
separated_list0(tok(char(',')), record_pattern_entry),
|
||||
tok(char('}')),
|
||||
),
|
||||
),
|
||||
|(qn, members)| Pattern::Record(qn, members),
|
||||
),
|
||||
map(qualified_identifier, Pattern::VarOrName),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn pattern_literal(input: Span) -> ParseResult<Pattern> {
|
||||
alt((
|
||||
value(Pattern::Ignored, kw("_")),
|
||||
value(Pattern::Literal(PatternLiteral::BoolPattern(true)), kw("true")),
|
||||
value(Pattern::Literal(PatternLiteral::BoolPattern(false)), kw("false")),
|
||||
map(tok(bare_string_literal), |s| Pattern::Literal(PatternLiteral::StringPattern(Rc::new(s)))),
|
||||
map(pair(opt(tok(char('-'))), alt((float_literal, number_literal))), |(sign, num)| {
|
||||
Pattern::Literal(PatternLiteral::NumPattern { neg: sign.is_some(), num })
|
||||
}),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn for_expr(input: Span) -> ParseResult<ExpressionKind> {
|
||||
println!("IN FOR EXPR: {}", input.fragment());
|
||||
fn for_enumerators(input: Span) -> ParseResult<Vec<Enumerator>> {
|
||||
println!("NEUMS: {}", input.fragment());
|
||||
alt((
|
||||
delimited(tok(char('{')), separated_list0(tok(char(',')), enumerator), tok(char('}'))),
|
||||
map(enumerator, |enumerator| vec![enumerator]),
|
||||
@ -543,6 +664,7 @@ fn string_literal(input: Span) -> ParseResult<ExpressionKind> {
|
||||
}
|
||||
|
||||
fn bare_string_literal(input: Span) -> ParseResult<String> {
|
||||
println!("BARE STRING: {}", input.fragment());
|
||||
let string_escape_transforms =
|
||||
alt((value("\\", tag("\\")), value("\"", tag("\"")), value("\n", tag("n")), value("\t", tag("t"))));
|
||||
alt((
|
||||
|
@ -134,7 +134,7 @@ macro_rules! assert_expr {
|
||||
macro_rules! assert_expr_comb {
|
||||
($input:expr, $correct:expr) => {
|
||||
let mut parser = Parser::new();
|
||||
let expr = parser.expression_comb($input);
|
||||
let expr = parser.expression_comb($input.trim_start());
|
||||
if expr.is_err() {
|
||||
println!("Expression parse error: {}", expr.unwrap_err().msg);
|
||||
panic!();
|
||||
@ -1097,7 +1097,7 @@ fn imports() {
|
||||
#[test]
|
||||
fn if_exprs() {
|
||||
use ExpressionKind::*;
|
||||
assert_expr!(
|
||||
assert_expr_comb!(
|
||||
"if a() then { tuah(); }",
|
||||
expr(IfExpression {
|
||||
discriminator: Some(bx(expr(Call { f: bx(expr(Value(qn!(a)))), arguments: vec![] }))),
|
||||
@ -1108,7 +1108,8 @@ fn if_exprs() {
|
||||
})
|
||||
);
|
||||
|
||||
assert_expr!(
|
||||
//TODO add tests for named expressions
|
||||
assert_expr_comb!(
|
||||
"if a then b else c",
|
||||
expr(IfExpression {
|
||||
discriminator: Some(bx(expr(Value(qn!(a))))),
|
||||
@ -1119,9 +1120,8 @@ fn if_exprs() {
|
||||
})
|
||||
);
|
||||
|
||||
assert_expr!(
|
||||
r#"
|
||||
if true then {
|
||||
assert_expr_comb!(
|
||||
r#"if true then {
|
||||
let a = 10
|
||||
b
|
||||
} else {
|
||||
@ -1151,7 +1151,7 @@ fn pattern_matching() {
|
||||
use ExpressionKind::*;
|
||||
|
||||
for item in ["if x is Some(a) then { 4 } else { 9 }", "if x is Some(a) then 4 else 9"] {
|
||||
assert_expr!(
|
||||
assert_expr_comb!(
|
||||
item,
|
||||
expr(IfExpression {
|
||||
discriminator: Some(bx(expr(Value(qn!(x))))),
|
||||
@ -1164,7 +1164,7 @@ fn pattern_matching() {
|
||||
);
|
||||
}
|
||||
|
||||
assert_expr!(
|
||||
assert_expr_comb!(
|
||||
"if x is Something { a, b: x } then { 4 } else { 9 }",
|
||||
expr(IfExpression {
|
||||
discriminator: Some(bx(expr(Value(qn!(x))))),
|
||||
@ -1179,7 +1179,7 @@ fn pattern_matching() {
|
||||
})
|
||||
);
|
||||
|
||||
assert_expr!(
|
||||
assert_expr_comb!(
|
||||
"if x is -1 then 1 else 2",
|
||||
expr(IfExpression {
|
||||
discriminator: Some(bx(expr(Value(qn!(x))))),
|
||||
@ -1191,7 +1191,7 @@ fn pattern_matching() {
|
||||
})
|
||||
);
|
||||
|
||||
assert_expr!(
|
||||
assert_expr_comb!(
|
||||
"if x is true then 1 else 2",
|
||||
expr(IfExpression {
|
||||
discriminator: Some(bx(expr(Value(qn!(x))))),
|
||||
@ -1203,7 +1203,7 @@ fn pattern_matching() {
|
||||
})
|
||||
);
|
||||
|
||||
assert_expr!(
|
||||
assert_expr_comb!(
|
||||
"if x { is 1 then 5; else 20 }",
|
||||
expr(IfExpression {
|
||||
discriminator: Some(bx(expr(Value(qn!(x))))),
|
||||
@ -1225,7 +1225,7 @@ fn pattern_matching() {
|
||||
})
|
||||
);
|
||||
|
||||
assert_expr!(
|
||||
assert_expr_comb!(
|
||||
r#"if x is "gnosticism" then 1 else 2"#,
|
||||
expr(IfExpression {
|
||||
discriminator: Some(bx(expr(Value(qn!(x))))),
|
||||
@ -1237,7 +1237,7 @@ fn pattern_matching() {
|
||||
})
|
||||
);
|
||||
|
||||
assert_expr! {
|
||||
assert_expr_comb! {
|
||||
r#"
|
||||
if (45, "panda", false, 2.2) {
|
||||
is (49, "pablo", _, 28.4) then "no"
|
||||
|
Loading…
Reference in New Issue
Block a user