From 73e32252c417717b2387ddbc235c00f09e0f7e34 Mon Sep 17 00:00:00 2001 From: Joscha Date: Fri, 18 Nov 2022 21:40:27 +0100 Subject: [PATCH] Parse table destructuring --- src/parser.rs | 1 + src/parser/expr.rs | 8 +++-- src/parser/table_destr.rs | 67 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/parser/table_destr.rs diff --git a/src/parser.rs b/src/parser.rs index 6f00075..3d81aa9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3,6 +3,7 @@ mod expr; mod lit; mod suffix; mod table_constr; +mod table_destr; mod var; use chumsky::prelude::*; diff --git a/src/parser/expr.rs b/src/parser/expr.rs index 0c0af2e..ab54245 100644 --- a/src/parser/expr.rs +++ b/src/parser/expr.rs @@ -8,6 +8,7 @@ use super::basic::{space, Error}; use super::lit::lit; use super::suffix::suffixed; use super::table_constr::table_constr; +use super::table_destr::table_destr; use super::var::var; fn atom_paren( @@ -30,11 +31,12 @@ fn atom( expr: impl Parser + Clone, ) -> impl Parser { let lit = lit(expr.clone()).map(Expr::Lit); - let paren = atom_paren(expr.clone()); + let var = var(expr.clone()).map(Expr::Var); let table_constr = table_constr(expr.clone()).map(Expr::TableConstr); - let var = var(expr).map(Expr::Var); + let table_destr = table_destr(expr.clone()).map(Expr::TableDestr); + let paren = atom_paren(expr); - lit.or(paren).or(table_constr).or(var) + lit.or(paren).or(table_destr).or(table_constr).or(var) } pub fn expr( diff --git a/src/parser/table_destr.rs b/src/parser/table_destr.rs new file mode 100644 index 0000000..29a8389 --- /dev/null +++ b/src/parser/table_destr.rs @@ -0,0 +1,67 @@ +//! Corresponds to `ast::table_constr`. + +use chumsky::prelude::*; + +use crate::ast::{Expr, TableDestr, TablePattern, TablePatternElem}; + +use super::basic::{ident, space, Error}; + +pub fn table_pattern_elem() -> impl Parser { + let positional = ident().map(TablePatternElem::Positional); + + let named = ident() + .then(space()) + .then_ignore(just(':')) + .then(space()) + .then(ident()) + .map_with_span(|(((name, s0), s1), ident), span| TablePatternElem::Named { + name, + s0, + s1, + ident, + span, + }); + + named.or(positional) +} + +pub fn table_pattern() -> impl Parser { + let elem = space() + .then(table_pattern_elem()) + .then(space()) + .map(|((s0, elem), s1)| (s0, elem, s1)); + + let trailing_comma = just(",").ignore_then(space()).or_not(); + + let elems = elem.separated_by(just(",")).then(trailing_comma); + + just("{") + .ignore_then(elems) + .then_ignore(just("}")) + .map_with_span(|(elems, trailing_comma), span| TablePattern { + elems, + trailing_comma, + span, + }) +} + +pub fn table_destr( + expr: impl Parser, +) -> impl Parser { + let local = text::keyword("local").ignore_then(space()).or_not(); + + local + .then(table_pattern()) + .then(space()) + .then_ignore(just('=')) + .then(space()) + .then(expr) + .map_with_span(|((((local, pattern), s0), s1), value), span| TableDestr { + local, + pattern, + s0, + s1, + value: Box::new(value), + span, + }) +}