summaryrefslogtreecommitdiffstats
path: root/crates/rebel-parse
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-05-01 00:51:26 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-05-01 10:42:48 +0200
commitd267148ba107e8f7e622e1722c03c80abb51a65f (patch)
treee37c61e7c867d3b8a58b1a2a29361442bc513b27 /crates/rebel-parse
parent23f2fb9ddca6801388b3e4debb66d1db673ec38c (diff)
downloadrebel-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.rs19
-rw-r--r--crates/rebel-parse/src/ast/mod.rs16
-rw-r--r--crates/rebel-parse/src/ast/pat.rs15
-rw-r--r--crates/rebel-parse/src/grammar/recipe.rs24
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() {