if expression
This commit is contained in:
parent
dd9a1b8a2e
commit
744ba2fc74
@ -6,7 +6,7 @@ use std::str::FromStr;
|
||||
use nom::IResult;
|
||||
use nom::character::complete::{one_of, space0, alphanumeric0};
|
||||
use nom::bytes::complete::{tag, take, take_while, take_while1, take_until};
|
||||
use nom::combinator::{cut, map, map_res, value, opt, verify};
|
||||
use nom::combinator::{cut, cond, map, map_res, value, opt, verify};
|
||||
use nom::multi::{separated_list, separated_nonempty_list, many1, many0};
|
||||
use nom::error::{context, ParseError, VerboseError};
|
||||
use nom::branch::alt;
|
||||
@ -51,10 +51,15 @@ fn identifier(text: &str) -> ParseResult<Rc<String>> {
|
||||
}
|
||||
|
||||
const OPERATOR_CHARS: &'static str = "~`!@#$%^&*-+=<>?/|";
|
||||
fn parse_binop(text: &str) -> ParseResult<BinOp> {
|
||||
let (text, op): (_, Vec<char>) = context("Binop", many1(one_of(OPERATOR_CHARS)))(text)?;
|
||||
let sigil: String = op.into_iter().collect();
|
||||
Ok((text, BinOp::from_sigil(&sigil)))
|
||||
fn operator(text: &str) -> ParseResult<Vec<char>> {
|
||||
many1(one_of(OPERATOR_CHARS))(text)
|
||||
}
|
||||
|
||||
fn binop(text: &str) -> ParseResult<BinOp> {
|
||||
context("Binop", map(
|
||||
operator,
|
||||
|op| BinOp::from_sigil(&op.into_iter().collect::<String>())
|
||||
))(text)
|
||||
}
|
||||
|
||||
fn bool_literal(text: &str) -> ParseResult<ExpressionKind> {
|
||||
@ -68,7 +73,7 @@ fn bool_literal(text: &str) -> ParseResult<ExpressionKind> {
|
||||
fn number_literal(text: &str) -> ParseResult<ExpressionKind> {
|
||||
let num_lit = many1(alt((
|
||||
map(one_of("1234567890"), |s: char| Some(s)),
|
||||
map(nom::character::complete::char('_'), |_| None)
|
||||
value(None, nom::character::complete::char('_')),
|
||||
)));
|
||||
|
||||
let (text, n) = map_res(num_lit,
|
||||
@ -143,10 +148,10 @@ fn primary_expr(text: &str) -> ParseResult<ExpressionKind> {
|
||||
// primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | lambda_expr | anonymous_struct | list_expr
|
||||
|
||||
alt((
|
||||
if_expr,
|
||||
literal,
|
||||
paren_expr,
|
||||
identifier_expr,
|
||||
//if_expr,
|
||||
))(text)
|
||||
}
|
||||
|
||||
@ -160,19 +165,21 @@ fn invocation_argument(text: &str) -> ParseResult<InvocationArgument> {
|
||||
))(text)
|
||||
}
|
||||
|
||||
/*
|
||||
fn if_expr(text: &str) -> ParseResult<ExpressionKind> {
|
||||
let p = preceded(tag("if"), pair(discriminator, if_expr_body));
|
||||
let p = preceded(tag("if"), pair(ws(discriminator), ws(if_expr_body)));
|
||||
map(p, |(discriminator, body)| {
|
||||
|
||||
let discriminator = discriminator.map(Box::new);
|
||||
let body = Box::new(body);
|
||||
ExpressionKind::IfExpression { discriminator, body }
|
||||
}) (text)
|
||||
|
||||
let expr = IfExpression {
|
||||
discriminator: Option<Box<Expression>>,
|
||||
body: Box<IfExpressionBody>,
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
fn discriminator(text: &str) -> ParseResult<Option<Expression>> {
|
||||
use nom::combinator::verify;
|
||||
cond(text.chars().next().map(|c| c != '{').unwrap_or(true),
|
||||
expression
|
||||
)(text)
|
||||
}
|
||||
|
||||
fn if_expr_body(text: &str) -> ParseResult<IfExpressionBody> {
|
||||
alt((
|
||||
@ -244,7 +251,38 @@ fn pattern_literal(text: &str) -> ParseResult<PatternLiteral> {
|
||||
}
|
||||
|
||||
fn cond_block(text: &str) -> ParseResult<IfExpressionBody> {
|
||||
unimplemented!()
|
||||
use nom::character::complete::char;
|
||||
//TODO maybe change this bit of syntax
|
||||
let comma_or_delimitor = alt((value((), char(',')), statement_sep));
|
||||
let p = delimited(char('{'),
|
||||
separated_nonempty_list(comma_or_delimitor, cond_arm),
|
||||
char('}'));
|
||||
map(p, IfExpressionBody::CondList)(text)
|
||||
}
|
||||
|
||||
fn cond_arm(text: &str) -> ParseResult<ConditionArm> {
|
||||
let variant_1 = map(
|
||||
tuple((condition, guard, tag("then"), expr_or_block)),
|
||||
|(condition, guard, _, body)| ConditionArm { condition, guard, body }
|
||||
);
|
||||
let variant_2 = map(
|
||||
preceded(tag("else"), expr_or_block),
|
||||
|body| ConditionArm { condition: Condition::Else, guard: None, body }
|
||||
);
|
||||
alt((variant_1, variant_2))(text)
|
||||
}
|
||||
|
||||
fn condition(text: &str) -> ParseResult<Condition> {
|
||||
alt((
|
||||
map(preceded(tag("is"), pattern), Condition::Pattern),
|
||||
map(tuple((binop, expression)), |(op, expr)|
|
||||
Condition::TruncatedOp(op, expr)),
|
||||
map(expression, Condition::Expression),
|
||||
))(text)
|
||||
}
|
||||
|
||||
fn guard(text: &str) -> ParseResult<Option<Expression>> {
|
||||
opt(preceded(tag("if"), expression))(text)
|
||||
}
|
||||
|
||||
fn expr_or_block(text: &str) -> ParseResult<Block> {
|
||||
@ -294,7 +332,7 @@ fn precedence_expr(text: &str) -> ParseResult<ExpressionKind> {
|
||||
let (mut outer_rest, mut lhs) = prefix_expr(input)?;
|
||||
loop {
|
||||
let (rest, _) = space0(outer_rest)?;
|
||||
let (rest, maybe_binop) = opt(parse_binop)(rest)?;
|
||||
let (rest, maybe_binop) = opt(binop)(rest)?;
|
||||
let (new_precedence, binop) = match maybe_binop {
|
||||
Some(binop) => (binop.precedence(), binop),
|
||||
None => break,
|
||||
|
Loading…
Reference in New Issue
Block a user