#[macro_use]
use crate::*;
#[cfg(not(feature = "no-std"))] use core::fmt;
#[cfg(feature = "no-std")] use alloc::fmt;
#[cfg(feature = "no-std")] use alloc::string::String;
#[cfg(feature = "no-std")] use alloc::vec::Vec;
use nom::{
IResult,
branch::alt,
sequence::tuple as nom_tuple,
combinator::{opt, eof},
multi::{many1, many_till, many0, separated_list1,separated_list0},
Err,
Err::Failure
};
pub fn function_define(input: ParseString) -> ParseResult<FunctionDefine> {
let ((input, name)) = identifier(input)?;
let ((input, _)) = left_parenthesis(input)?;
let ((input, input_args)) = separated_list0(list_separator, function_arg)(input)?;
let ((input, _)) = right_parenthesis(input)?;
let ((input, _)) = whitespace0(input)?;
match function_define_match_arms(input.clone(), name.clone(), input_args.clone()) {
Ok((input, fxn_def)) => Ok((input, fxn_def)),
Err(_) => function_define_statements(input, name, input_args),
}
}
fn function_define_statements(
input: ParseString,
name: Identifier,
input_args: Vec<FunctionArgument>,
) -> ParseResult<FunctionDefine> {
let ((input, _)) = equal(input)?;
let ((input, _)) = whitespace0(input)?;
let ((input, output)) = alt((function_out_args,function_out_arg))(input)?;
let ((input, _)) = define_operator(input)?;
let ((input, statements)) = separated_list1(alt((whitespace1,statement_separator)), statement)(input)?;
let ((input, _)) = period(input)?;
Ok((input,FunctionDefine{name,input: input_args,output,statements,match_arms: vec![]}))
}
fn function_define_match_arms(
input: ParseString,
name: Identifier,
input_args: Vec<FunctionArgument>,
) -> ParseResult<FunctionDefine> {
let (input, _) = output_operator(input)?;
let (input, _) = whitespace0(input)?;
let (input, output_kind) = kind_annotation(input)?;
let output_src_range = output_kind
.tokens()
.first()
.map(|token| token.src_range.clone())
.unwrap_or_default();
let output = vec![FunctionArgument {
name: Identifier {
name: Token::new(TokenKind::Identifier, output_src_range, vec!['_']),
},
kind: output_kind,
}];
let (input, _) = many1(alt((whitespace1, statement_separator)))(input)?;
let (input, match_arms) = many1(function_match_arm)(input)?;
let (input, _) = opt(period)(input)?;
Ok((input, FunctionDefine {
name,
input: input_args,
output,
statements: vec![],
match_arms,
}))
}
fn function_match_arm(input: ParseString) -> ParseResult<FunctionMatchArm> {
let (input, _) = whitespace0(input)?;
let (input, _) = alt((box_t_left, box_bl, bar))(input)?;
let (input, _) = whitespace0(input)?;
if let Ok((input, pattern)) = crate::patterns::pattern(input.clone()) {
if let Ok((input, _)) = whitespace0(input) {
if let Ok((input, _)) = output_operator(input) {
let (input, _) = whitespace0(input)?;
let (input, expr) = expression(input)?;
let (input, _) = opt(alt((whitespace1, statement_separator)))(input)?;
return Ok((input, FunctionMatchArm {
pattern,
expression: expr,
}));
}
}
}
let (input, expr) = expression(input)?;
let (input, _) = opt(alt((whitespace1, statement_separator)))(input)?;
Ok((input, FunctionMatchArm {
pattern: Pattern::Wildcard,
expression: expr,
}))
}
pub fn function_out_args(input: ParseString) -> ParseResult<Vec<FunctionArgument>> {
let ((input, _)) = left_parenthesis(input)?;
let ((input, args)) = separated_list1(list_separator,function_arg)(input)?;
let ((input, _)) = right_parenthesis(input)?;
Ok((input, args))
}
pub fn function_out_arg(input: ParseString) -> ParseResult<Vec<FunctionArgument>> {
let ((input, arg)) = function_arg(input)?;
Ok((input, vec![arg]))
}
pub fn function_arg(input: ParseString) -> ParseResult<FunctionArgument> {
let ((input, name)) = identifier(input)?;
let ((input, kind)) = kind_annotation(input)?;
Ok((input, FunctionArgument{ name, kind }))
}
pub fn argument_list(input: ParseString) -> ParseResult<ArgumentList> {
let (input, _) = left_parenthesis(input)?;
let (input, args) = separated_list0(list_separator, alt((call_arg_with_binding,call_arg)))(input)?;
let (input, _) = right_parenthesis(input)?;
Ok((input, args))
}
pub fn function_call(input: ParseString) -> ParseResult<FunctionCall> {
let (input, name) = identifier(input)?;
let (input, args) = argument_list(input)?;
Ok((input, FunctionCall{name,args} ))
}
pub fn call_arg_with_binding(input: ParseString) -> ParseResult<(Option<Identifier>,Expression)> {
let (input, arg_name) = identifier(input)?;
let (input, _) = whitespace0(input)?;
let (input, _) = colon(input)?;
let (input, _) = whitespace0(input)?;
let (input, expr) = expression(input)?;
Ok((input, (Some(arg_name), expr)))
}
pub fn call_arg(input: ParseString) -> ParseResult<(Option<Identifier>,Expression)> {
let (input, expr) = expression(input)?;
Ok((input, (None, expr)))
}