Whole lot of added code around if exprs

This commit is contained in:
greg 2020-03-08 05:11:00 -07:00
parent 33d4b28786
commit dd9a1b8a2e

View File

@ -10,7 +10,7 @@ use nom::combinator::{cut, 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;
use nom::sequence::{pair, delimited, preceded}; use nom::sequence::{pair, tuple, delimited, preceded};
use crate::ast::*; use crate::ast::*;
use crate::builtin::Builtin; use crate::builtin::Builtin;
@ -26,6 +26,10 @@ where
delimited(space0, parser, space0) delimited(space0, parser, space0)
} }
fn statement_sep(text: &str) -> ParseResult<()> {
value((), one_of("\n;"))(text)
}
fn single_alphabetic_character(text: &str) -> ParseResult<char> { fn single_alphabetic_character(text: &str) -> ParseResult<char> {
let p = verify(take(1usize), |s: &str| s.chars().nth(0).map(|c| c.is_alphabetic()).unwrap_or(false)); let p = verify(take(1usize), |s: &str| s.chars().nth(0).map(|c| c.is_alphabetic()).unwrap_or(false));
map(p, |s: &str| s.chars().nth(0).unwrap())(text) map(p, |s: &str| s.chars().nth(0).unwrap())(text)
@ -124,18 +128,15 @@ fn prefix_op(text: &str) -> ParseResult<PrefixOp> {
map(p, |sigil| PrefixOp::from_str(&sigil.to_string()).unwrap())(text) map(p, |sigil| PrefixOp::from_str(&sigil.to_string()).unwrap())(text)
} }
fn identifier_expr(text: &str) -> ParseResult<ExpressionKind> { fn qualified_name(text: &str) -> ParseResult<QualifiedName> {
let (text, qualified_identifier) = map( map(
qualified_identifier_list, separated_nonempty_list(tag("::"), identifier),
|components| QualifiedName { id: ItemId::new(0), components } |components| QualifiedName { id: ItemId::new(0), components }
)(text)?; )(text)
//TODO handle struct literals
let exp = Expression::new(ItemId::new(0), ExpressionKind::Value(qualified_identifier));
Ok((text, exp.kind))
} }
fn qualified_identifier_list(text: &str) -> ParseResult<Vec<Rc<String>>> { fn identifier_expr(text: &str) -> ParseResult<ExpressionKind> {
separated_nonempty_list(tag("::"), identifier)(text) map(qualified_name, ExpressionKind::Value)(text)
} }
fn primary_expr(text: &str) -> ParseResult<ExpressionKind> { fn primary_expr(text: &str) -> ParseResult<ExpressionKind> {
@ -173,6 +174,94 @@ fn if_expr(text: &str) -> ParseResult<ExpressionKind> {
} }
*/ */
fn if_expr_body(text: &str) -> ParseResult<IfExpressionBody> {
alt((
preceded(tag("then"), simple_conditional),
preceded(tag("is"), simple_pattern_match),
cond_block,
))(text)
}
fn simple_conditional(text: &str) -> ParseResult<IfExpressionBody> {
map(
pair(expr_or_block, else_case),
|(then_case, else_case)| IfExpressionBody::SimpleConditional { then_case, else_case }
)(text)
}
fn else_case(text: &str) -> ParseResult<Option<Block>> {
opt(preceded(tag("else"), expr_or_block))(text)
}
fn simple_pattern_match(text: &str) -> ParseResult<IfExpressionBody> {
let p = tuple((pattern, tag("then"), expr_or_block, else_case));
map(p, |(pattern, _, then_case, else_case)|
IfExpressionBody::SimplePatternMatch { pattern, then_case, else_case }
)(text)
}
fn pattern(text: &str) -> ParseResult<Pattern> {
use nom::character::complete::char;
let t = delimited(char('('),
separated_nonempty_list(char(','), pattern),
char(')')
);
alt((
map(t, |patterns| Pattern::TuplePattern(patterns)),
simple_pattern,
))(text)
}
fn simple_pattern(text: &str) -> ParseResult<Pattern> {
alt((
value(Pattern::Ignored, tag("_")),
tuple_struct_pattern,
record_pattern,
map(pattern_literal, Pattern::Literal),
map(qualified_name, Pattern::VarOrName),
))(text)
}
fn tuple_struct_pattern(text: &str) -> ParseResult<Pattern> {
unimplemented!()
}
fn record_pattern(text: &str) -> ParseResult<Pattern> {
unimplemented!()
}
fn pattern_literal(text: &str) -> ParseResult<PatternLiteral> {
use PatternLiteral::*;
use nom::character::complete::char;
alt((
value(BoolPattern(true), tag("true")),
value(BoolPattern(false), tag("false")),
map(delimited(char('"'), take_until("\""), char('"')), |s: &str| StringPattern(Rc::new(s.to_string()))),
))(text)
//TODO handle signed_number_literal
}
fn cond_block(text: &str) -> ParseResult<IfExpressionBody> {
unimplemented!()
}
fn expr_or_block(text: &str) -> ParseResult<Block> {
//TODO fix
alt((block, map(expression, |expr| vec![Statement { id: ItemId::new(0), kind: StatementKind::Expression(expr)}])))(text)
}
fn block(text: &str) -> ParseResult<Block> {
use nom::character::complete::char;
//TODO fix this so it can handle nested statements
delimited(char('{'),
separated_nonempty_list(statement_sep,
map(expression, |e| Statement { id: ItemId::new(0), kind: StatementKind::Expression(e) })
),
char('}'))(text)
}
fn call_expr(text: &str) -> ParseResult<ExpressionKind> { fn call_expr(text: &str) -> ParseResult<ExpressionKind> {
use nom::character::complete::char; use nom::character::complete::char;
let parse_call = opt( let parse_call = opt(