if expression
This commit is contained in:
parent
dd9a1b8a2e
commit
744ba2fc74
@ -6,7 +6,7 @@ use std::str::FromStr;
|
|||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
use nom::character::complete::{one_of, space0, alphanumeric0};
|
use nom::character::complete::{one_of, space0, alphanumeric0};
|
||||||
use nom::bytes::complete::{tag, take, take_while, take_while1, take_until};
|
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::multi::{separated_list, separated_nonempty_list, many1, many0};
|
||||||
use nom::error::{context, ParseError, VerboseError};
|
use nom::error::{context, ParseError, VerboseError};
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
@ -51,10 +51,15 @@ fn identifier(text: &str) -> ParseResult<Rc<String>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const OPERATOR_CHARS: &'static str = "~`!@#$%^&*-+=<>?/|";
|
const OPERATOR_CHARS: &'static str = "~`!@#$%^&*-+=<>?/|";
|
||||||
fn parse_binop(text: &str) -> ParseResult<BinOp> {
|
fn operator(text: &str) -> ParseResult<Vec<char>> {
|
||||||
let (text, op): (_, Vec<char>) = context("Binop", many1(one_of(OPERATOR_CHARS)))(text)?;
|
many1(one_of(OPERATOR_CHARS))(text)
|
||||||
let sigil: String = op.into_iter().collect();
|
}
|
||||||
Ok((text, BinOp::from_sigil(&sigil)))
|
|
||||||
|
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> {
|
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> {
|
fn number_literal(text: &str) -> ParseResult<ExpressionKind> {
|
||||||
let num_lit = many1(alt((
|
let num_lit = many1(alt((
|
||||||
map(one_of("1234567890"), |s: char| Some(s)),
|
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,
|
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
|
// primary := literal | paren_expr | if_expr | for_expr | while_expr | identifier_expr | lambda_expr | anonymous_struct | list_expr
|
||||||
|
|
||||||
alt((
|
alt((
|
||||||
|
if_expr,
|
||||||
literal,
|
literal,
|
||||||
paren_expr,
|
paren_expr,
|
||||||
identifier_expr,
|
identifier_expr,
|
||||||
//if_expr,
|
|
||||||
))(text)
|
))(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,19 +165,21 @@ fn invocation_argument(text: &str) -> ParseResult<InvocationArgument> {
|
|||||||
))(text)
|
))(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
fn if_expr(text: &str) -> ParseResult<ExpressionKind> {
|
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)| {
|
map(p, |(discriminator, body)| {
|
||||||
|
let discriminator = discriminator.map(Box::new);
|
||||||
|
let body = Box::new(body);
|
||||||
|
ExpressionKind::IfExpression { discriminator, body }
|
||||||
}) (text)
|
}) (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> {
|
fn if_expr_body(text: &str) -> ParseResult<IfExpressionBody> {
|
||||||
alt((
|
alt((
|
||||||
@ -244,7 +251,38 @@ fn pattern_literal(text: &str) -> ParseResult<PatternLiteral> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn cond_block(text: &str) -> ParseResult<IfExpressionBody> {
|
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> {
|
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)?;
|
let (mut outer_rest, mut lhs) = prefix_expr(input)?;
|
||||||
loop {
|
loop {
|
||||||
let (rest, _) = space0(outer_rest)?;
|
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 {
|
let (new_precedence, binop) = match maybe_binop {
|
||||||
Some(binop) => (binop.precedence(), binop),
|
Some(binop) => (binop.precedence(), binop),
|
||||||
None => break,
|
None => break,
|
||||||
|
Loading…
Reference in New Issue
Block a user