diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-05-01 00:51:26 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-05-01 10:42:48 +0200 |
commit | d267148ba107e8f7e622e1722c03c80abb51a65f (patch) | |
tree | e37c61e7c867d3b8a58b1a2a29361442bc513b27 /crates/rebel-parse | |
parent | 23f2fb9ddca6801388b3e4debb66d1db673ec38c (diff) | |
download | rebel-d267148ba107e8f7e622e1722c03c80abb51a65f.tar rebel-d267148ba107e8f7e622e1722c03c80abb51a65f.zip |
rebel-parse: handle more pattern types
Add support for parsing parentheses, field access and index operations
in patterns, and distinguish let and destructuring pattern.
Diffstat (limited to 'crates/rebel-parse')
-rw-r--r-- | crates/rebel-parse/src/ast/expr.rs | 19 | ||||
-rw-r--r-- | crates/rebel-parse/src/ast/mod.rs | 16 | ||||
-rw-r--r-- | crates/rebel-parse/src/ast/pat.rs | 15 | ||||
-rw-r--r-- | crates/rebel-parse/src/grammar/recipe.rs | 24 |
4 files changed, 60 insertions, 14 deletions
diff --git a/crates/rebel-parse/src/ast/expr.rs b/crates/rebel-parse/src/ast/expr.rs index 4e386e7..fda37e8 100644 --- a/crates/rebel-parse/src/ast/expr.rs +++ b/crates/rebel-parse/src/ast/expr.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use super::{Ident, Path, ValidationError}; +use super::{DestrPat, Ident, Path, ValidationError}; use crate::token; pub use token::StrKind; @@ -142,6 +142,23 @@ impl<'a> Expr<'a> { } } +impl<'a> From<&DestrPat<'a>> for Expr<'a> { + fn from(value: &DestrPat<'a>) -> Self { + match value { + DestrPat::Index { pat, index } => Expr::Index { + expr: Box::new(pat.as_ref().into()), + index: index.clone(), + }, + DestrPat::Field { pat, field } => Expr::Field { + expr: Box::new(pat.as_ref().into()), + field: *field, + }, + DestrPat::Paren(pat) => Expr::Paren(Box::new(pat.as_ref().into())), + DestrPat::Path(path) => Expr::Path(path.clone()), + } + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub enum Literal<'a> { Unit, diff --git a/crates/rebel-parse/src/ast/mod.rs b/crates/rebel-parse/src/ast/mod.rs index eb6a7bd..1afa9a1 100644 --- a/crates/rebel-parse/src/ast/mod.rs +++ b/crates/rebel-parse/src/ast/mod.rs @@ -2,10 +2,12 @@ pub mod expr; pub mod pat; pub mod typ; -use expr::*; -use pat::Pat; +use expr::Expr; +use pat::DestrPat; use typ::Type; +use self::pat::Pat; + pub type Recipe<'a> = Vec<RecipeStmt<'a>>; #[derive(Debug, Clone, PartialEq, Eq)] @@ -58,7 +60,7 @@ pub enum BlockStmt<'a> { expr: Option<Box<Expr<'a>>>, }, Assign { - dest: Box<Pat<'a>>, + dest: Box<DestrPat<'a>>, expr: Box<Expr<'a>>, }, Expr { @@ -76,16 +78,14 @@ impl<'a> BlockStmt<'a> { } pub(crate) fn assign( - dest: Pat<'a>, - op: Option<OpBinary>, + dest: DestrPat<'a>, + op: Option<expr::OpBinary>, swapped: bool, expr: Expr<'a>, ) -> Self { let expr = match op { Some(op) => { - let dest_expr = match &dest { - Pat::Path(path) => Expr::Path(path.clone()), - }; + let dest_expr = Expr::from(&dest); if swapped { Expr::binary(expr, op, dest_expr) } else { diff --git a/crates/rebel-parse/src/ast/pat.rs b/crates/rebel-parse/src/ast/pat.rs index a376956..d1baf68 100644 --- a/crates/rebel-parse/src/ast/pat.rs +++ b/crates/rebel-parse/src/ast/pat.rs @@ -2,5 +2,20 @@ use super::*; #[derive(Debug, Clone, PartialEq, Eq)] pub enum Pat<'a> { + Paren(Box<Pat<'a>>), + Ident(Ident<'a>), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum DestrPat<'a> { + Index { + pat: Box<DestrPat<'a>>, + index: Box<Expr<'a>>, + }, + Field { + pat: Box<DestrPat<'a>>, + field: Ident<'a>, + }, + Paren(Box<DestrPat<'a>>), Path(Path<'a>), } diff --git a/crates/rebel-parse/src/grammar/recipe.rs b/crates/rebel-parse/src/grammar/recipe.rs index 68429cb..8903eec 100644 --- a/crates/rebel-parse/src/grammar/recipe.rs +++ b/crates/rebel-parse/src/grammar/recipe.rs @@ -2,7 +2,7 @@ use crate::{ ast::{ self, expr::{self, Expr}, - pat::Pat, + pat::{DestrPat, Pat}, typ::{self, Type}, }, token::*, @@ -40,10 +40,10 @@ peg::parser! { / [Token::Keyword(Keyword::Let)] dest:typed_pat() { ast::BlockStmt::let_assign(dest, None) } - / dest:pat() op:assign_op() expr:expr() { + / dest:destr_pat() op:assign_op() expr:expr() { ast::BlockStmt::assign(dest, op, false, expr) } - / dest:pat() p2('=', '+') expr:expr() { + / dest:destr_pat() p2('=', '+') expr:expr() { ast::BlockStmt::assign(dest, Some(Add), true, expr) } / expr:expr() { @@ -79,8 +79,22 @@ peg::parser! { typ::Literal::Struct(entries) } - pub rule pat() -> Pat<'a> - = path:path() { Pat::Path(path) } + pub rule pat() -> ast::pat::Pat<'a> + = p('(') pat:pat() p(')') { Pat::Paren(Box::new(pat)) } + / ident:ident() { Pat::Ident(ident) } + + pub rule destr_pat() -> DestrPat<'a> = precedence! { + pat:@ p('[') index:expr() p(']') { + DestrPat::Index { pat: Box::new(pat), index: Box::new(index) } + } + -- + pat:@ p('.') field:field() { + DestrPat::Field { pat: Box::new(pat), field } + } + -- + p('(') pat:destr_pat() p(')') { DestrPat::Paren(Box::new(pat)) } + path:path() { DestrPat::Path(path) } + } rule struct_field_typ() -> typ::StructField<'a> = field:field() p(':') typ:typ() { |