// TODO Rename this module to func_def for consistency use chumsky::prelude::*; use crate::ast::{Expr, FuncDef, Ident, Space, TablePattern}; use super::basic::{EParser, Error}; fn func_def_anon_no_arg( space: EParser, expr: EParser, ) -> impl Parser { text::keyword("function") .ignore_then(space.clone()) .then_ignore(just('(')) .then(space.clone()) .then_ignore(just(')')) .then(space) .then(expr) .map_with_span(|(((s0, s1), s2), body), span| FuncDef::AnonNoArg { s0, s1, s2, body: Box::new(body), span, }) } fn func_def_anon_arg( space: EParser, ident: EParser, expr: EParser, ) -> impl Parser { text::keyword("function") .ignore_then(space.clone()) .then_ignore(just('(')) .then(space.clone()) .then(ident) .then(space.clone()) .then_ignore(just(')')) .then(space) .then(expr) .map_with_span( |(((((s0, s1), arg), s2), s3), body), span| FuncDef::AnonArg { s0, s1, arg, s2, s3, body: Box::new(body), span, }, ) } fn func_def_anon_destr( space: EParser, table_pattern: EParser, expr: EParser, ) -> impl Parser { text::keyword("function") .ignore_then(space.clone()) .then(table_pattern) .then(space) .then(expr) .map_with_span(|(((s0, pattern), s1), body), span| FuncDef::AnonDestr { s0, pattern, s1, body: Box::new(body), span, }) } fn func_def_named_no_arg( space: EParser, ident: EParser, local: EParser>, expr: EParser, ) -> impl Parser { local .then_ignore(text::keyword("function")) .then(space.clone()) .then(ident) .then(space.clone()) .then_ignore(just('(')) .then(space.clone()) .then_ignore(just(')')) .then(space) .then(expr) .map_with_span( |((((((local, s0), name), s1), s2), s3), body), span| FuncDef::NamedNoArg { local, s0, name, s1, s2, s3, body: Box::new(body), span, }, ) } fn func_def_named_arg( space: EParser, ident: EParser, local: EParser>, expr: EParser, ) -> impl Parser { local .then_ignore(text::keyword("function")) .then(space.clone()) .then(ident.clone()) .then(space.clone()) .then_ignore(just('(')) .then(space.clone()) .then(ident) .then(space.clone()) .then_ignore(just(')')) .then(space) .then(expr) .map_with_span( |((((((((local, s0), name), s1), s2), arg), s3), s4), body), span| FuncDef::NamedArg { local, s0, name, s1, s2, arg, s3, s4, body: Box::new(body), span, }, ) } fn func_def_named_destr( space: EParser, ident: EParser, local: EParser>, table_pattern: EParser, expr: EParser, ) -> impl Parser { local .then_ignore(text::keyword("function")) .then(space.clone()) .then(ident) .then(space.clone()) .then(table_pattern) .then(space) .then(expr) .map_with_span(|((((((local, s0), name), s1), pattern), s2), body), span| { FuncDef::NamedDestr { local, s0, name, s1, pattern, s2, body: Box::new(body), span, } }) } pub fn func_def( space: EParser, ident: EParser, local: EParser>, table_pattern: EParser, expr: EParser, ) -> EParser { let anon_no_arg = func_def_anon_no_arg(space.clone(), expr.clone()); let anon_arg = func_def_anon_arg(space.clone(), ident.clone(), expr.clone()); let anon_destr = func_def_anon_destr(space.clone(), table_pattern.clone(), expr.clone().clone()); let named_no_arg = func_def_named_no_arg( space.clone(), ident.clone(), local.clone(), expr.clone().clone(), ); let named_arg = func_def_named_arg( space.clone(), ident.clone(), local.clone(), expr.clone().clone(), ); let named_destr = func_def_named_destr(space, ident, local, table_pattern, expr); anon_no_arg .or(anon_arg) .or(anon_destr) .or(named_no_arg) .or(named_arg) .or(named_destr) .boxed() }