Parse named function definitions

This commit is contained in:
Joscha 2022-11-19 19:24:23 +01:00
parent ff3edf17e5
commit 0099277644
3 changed files with 95 additions and 9 deletions

View file

@ -55,3 +55,7 @@ pub fn ident() -> BoxedParser<'static, char, Ident, Error> {
}) })
.boxed() .boxed()
} }
pub fn local() -> BoxedParser<'static, char, Option<Space>, Error> {
text::keyword("local").ignore_then(space()).or_not().boxed()
}

View file

@ -2,7 +2,7 @@ use chumsky::prelude::*;
use crate::ast::{Expr, FuncDef}; use crate::ast::{Expr, FuncDef};
use super::basic::{ident, space, Error}; use super::basic::{ident, local, space, Error};
use super::table_destr::table_pattern; use super::table_destr::table_pattern;
fn func_def_anon_no_arg( fn func_def_anon_no_arg(
@ -66,11 +66,97 @@ fn func_def_anon_destr(
}) })
} }
fn func_def_named_no_arg(
expr: impl Parser<char, Expr, Error = Error>,
) -> impl Parser<char, FuncDef, Error = Error> {
local()
.then_ignore(text::keyword("function"))
.then(space())
.then(ident())
.then(space())
.then_ignore(just('('))
.then(space())
.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(
expr: impl Parser<char, Expr, Error = Error>,
) -> impl Parser<char, FuncDef, Error = Error> {
local()
.then_ignore(text::keyword("function"))
.then(space())
.then(ident())
.then(space())
.then_ignore(just('('))
.then(space())
.then(ident())
.then(space())
.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(
expr: impl Parser<char, Expr, Error = Error>,
) -> impl Parser<char, FuncDef, Error = Error> {
local()
.then_ignore(text::keyword("function"))
.then(space())
.then(ident())
.then(space())
.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( pub fn func_def(
expr: impl Parser<char, Expr, Error = Error> + Clone + 'static, expr: impl Parser<char, Expr, Error = Error> + Clone + 'static,
) -> BoxedParser<'static, char, FuncDef, Error> { ) -> BoxedParser<'static, char, FuncDef, Error> {
func_def_anon_no_arg(expr.clone()) func_def_anon_no_arg(expr.clone())
.or(func_def_anon_arg(expr.clone())) .or(func_def_anon_arg(expr.clone()))
.or(func_def_anon_destr(expr)) .or(func_def_anon_destr(expr.clone()))
.or(func_def_named_no_arg(expr.clone()))
.or(func_def_named_arg(expr.clone()))
.or(func_def_named_destr(expr))
.boxed() .boxed()
} }

View file

@ -4,7 +4,7 @@ use chumsky::prelude::*;
use crate::ast::{Expr, Var}; use crate::ast::{Expr, Var};
use super::basic::{ident, space, Error}; use super::basic::{ident, local, space, Error};
fn var_access( fn var_access(
expr: impl Parser<char, Expr, Error = Error> + Clone, expr: impl Parser<char, Expr, Error = Error> + Clone,
@ -25,9 +25,7 @@ fn var_access(
fn var_assign( fn var_assign(
expr: impl Parser<char, Expr, Error = Error> + Clone, expr: impl Parser<char, Expr, Error = Error> + Clone,
) -> impl Parser<char, Var, Error = Error> + Clone { ) -> impl Parser<char, Var, Error = Error> + Clone {
let local = text::keyword("local").ignore_then(space()).or_not(); local()
local
.then_ignore(just('[')) .then_ignore(just('['))
.then(space()) .then(space())
.then(expr.clone()) .then(expr.clone())
@ -54,9 +52,7 @@ fn var_assign(
fn var_assign_ident( fn var_assign_ident(
expr: impl Parser<char, Expr, Error = Error> + Clone, expr: impl Parser<char, Expr, Error = Error> + Clone,
) -> impl Parser<char, Var, Error = Error> + Clone { ) -> impl Parser<char, Var, Error = Error> + Clone {
let local = text::keyword("local").ignore_then(space()).or_not(); local()
local
.then(ident()) .then(ident())
.then(space()) .then(space())
.then_ignore(just('=')) .then_ignore(just('='))