summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-04-29 19:02:34 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-04-29 19:02:34 +0200
commit684a6e62b40389dad5875c86c8d50658d676128d (patch)
treec8665f787b38d56ec797b7f48e840f94f6a68c6e
parent8226a8ec820987c99c24b5f6e76a8b379f9efa0a (diff)
downloadrebel-684a6e62b40389dad5875c86c8d50658d676128d.tar
rebel-684a6e62b40389dad5875c86c8d50658d676128d.zip
rebel-parse: ast: typ: allow to distinguish between free and dynamic array length
-rw-r--r--crates/rebel-parse/src/ast/typ.rs9
-rw-r--r--crates/rebel-parse/src/grammar/recipe.rs18
2 files changed, 21 insertions, 6 deletions
diff --git a/crates/rebel-parse/src/ast/typ.rs b/crates/rebel-parse/src/ast/typ.rs
index 37aa33e..18ea827 100644
--- a/crates/rebel-parse/src/ast/typ.rs
+++ b/crates/rebel-parse/src/ast/typ.rs
@@ -11,10 +11,17 @@ pub enum Type<'a> {
pub enum Literal<'a> {
Unit,
Tuple(Vec<Type<'a>>),
- Array(Box<Type<'a>>, Option<u32>),
+ Array(Box<Type<'a>>, ArrayLen),
Struct(Vec<StructField<'a>>),
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum ArrayLen {
+ Free,
+ Fixed(u32),
+ Dynamic,
+}
+
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructField<'a> {
pub name: &'a str,
diff --git a/crates/rebel-parse/src/grammar/recipe.rs b/crates/rebel-parse/src/grammar/recipe.rs
index 893d4b7..73ddb2e 100644
--- a/crates/rebel-parse/src/grammar/recipe.rs
+++ b/crates/rebel-parse/src/grammar/recipe.rs
@@ -66,16 +66,24 @@ peg::parser! {
/ p('(') elements:(typ() ** p(',')) p(',')? p(')') {
typ::Literal::Tuple(elements)
}
- / p('[') typ:typ() len:tagged(<p(';')>, <number()>)? p(']') { ?
- let len = len
- .map(|n| u32::try_from(n).or(Err("Invalid array length")))
- .transpose()?;
- Ok(typ::Literal::Array(Box::new(typ), len))
+ / p('[') typ:typ() len:array_len() p(']') {
+ typ::Literal::Array(Box::new(typ), len)
}
/ p('{') entries:delimited(<struct_field_typ()>, <p(',')>) p('}') {
typ::Literal::Struct(entries)
}
+ rule array_len() -> typ::ArrayLen
+ = p(';') len:number() { ?
+ Ok(typ::ArrayLen::Fixed(len.try_into().or(Err("Invalid array length"))?))
+ }
+ / p(';') [Token::Ident(name) if *name == "_"] {
+ typ::ArrayLen::Free
+ }
+ / {
+ typ::ArrayLen::Dynamic
+ }
+
rule pat() -> Pat<'a>
= path:path() { Pat::Path(path) }