//! Corresponds to `ast::var`. use chumsky::prelude::*; use crate::ast::{Expr, Ident, Space, Var}; use super::basic::{EParser, Error}; fn var_access(space: EParser, expr: EParser) -> impl Parser { just('[') .ignore_then(space.clone()) .then(expr) .then(space) .then_ignore(just(']')) .map_with_span(|((s0, index), s1), span| Var::Access { s0, index: Box::new(index), s1, span, }) } fn var_assign( space: EParser, local: EParser>, expr: EParser, ) -> impl Parser { local .then_ignore(just('[')) .then(space.clone()) .then(expr.clone()) .then(space.clone()) .then_ignore(just(']')) .then(space.clone()) .then_ignore(just('=')) .then(space) .then(expr) .map_with_span( |((((((local, s0), index), s1), s2), s3), value), span| Var::Assign { local, s0, index: Box::new(index), s1, s2, s3, value: Box::new(value), span, }, ) } fn var_assign_ident( space: EParser, ident: EParser, local: EParser>, expr: EParser, ) -> impl Parser { local .then(ident) .then(space.clone()) .then_ignore(just('=')) .then(space) .then(expr) .map_with_span( |((((local, name), s0), s1), value), span| Var::AssignIdent { local, name, s0, s1, value: Box::new(value), span, }, ) } pub fn var( space: EParser, ident: EParser, local: EParser>, expr: EParser, ) -> EParser { let access = var_access(space.clone(), expr.clone()); let assign = var_assign(space.clone(), local.clone(), expr.clone()); let access_ident = ident.clone().map(Var::AccessIdent); let assign_ident = var_assign_ident(space, ident, local, expr); assign.or(access).or(assign_ident).or(access_ident).boxed() }