From 205e2d9fd34ac1d6870978848ff6692ff00e9c26 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 16:48:31 +0200 Subject: [PATCH] generics parsing and AST --- parser/src/ast.rs | 4 ++++ parser/src/grammar.pest | 8 +++++++- parser/src/lib.rs | 42 +++++++++++++++++++++++++++++------------ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index dc77c0e..8b29051 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -81,6 +81,7 @@ pub enum TopLevelKind { }, StructDecl { visibility: Visibility, + generics: Generics, name: Identifier, fields: FieldList, }, @@ -94,6 +95,9 @@ pub enum TopLevelKind { }, } +#[derive(Debug, Clone, Serialize)] +pub struct Generics(pub Vec<(Identifier, Vec)>); + #[derive(Debug, Clone, Serialize)] pub enum Pattern { NamedTuple(Path, Vec), diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 3b7eb05..5d8b892 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -52,6 +52,12 @@ export = { "public" } mutable = { "mut" } var = { "var" } +// ====================================================== +// GENERICS +// ====================================================== +generic = { identifier ~ (":" ~ static_path ~ ("+" ~ static_path)*)? } +generics = { "<" ~ (generic ~ ("," ~ generic)*)? ~ ">" } + // ====================================================== // TYPES // ====================================================== @@ -168,7 +174,7 @@ mod_package = { // ====================================================== struct_decl = { - export? ~ "struct" ~ identifier ~ "{" ~ field_list? ~ "}" + export? ~ "struct" ~ identifier ~ generics? ~ "{" ~ field_list? ~ "}" } // ====================================================== diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 2128993..79886ac 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -223,6 +223,28 @@ impl From> for ClassConstructor { } } +impl From> for Generics { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + let inner = pair.clone().into_inner(); + + match rule { + Rule::generics => Generics( + inner + .map(|pair| { + let mut inner = pair.into_inner(); + ( + Identifier::from(inner.next().unwrap()), + inner.map(Path::from).collect(), + ) + }) + .collect(), + ), + _ => unimplemented!("{rule:#?}"), + } + } +} + impl From> for TopLevelKind { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); @@ -233,18 +255,14 @@ impl From> for TopLevelKind { Rule::function_decl => TopLevelKind::FunctionDecl(FunctionDecl::from(pair)), - Rule::struct_decl => { - let visibility = Visibility::from(&mut inner); - let name = Identifier::from(inner.next().unwrap()); - let fields_pair = inner.next().unwrap(); - let fields = FieldList::from(fields_pair); - - TopLevelKind::StructDecl { - visibility, - name, - fields, - } - } + Rule::struct_decl => TopLevelKind::StructDecl { + visibility: Visibility::from(&mut inner), + name: Identifier::from(inner.next().unwrap()), + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or(Generics(Vec::new())), + fields: FieldList::from(inner.next().unwrap()), + }, Rule::class_decl => TopLevelKind::ClassDecl { visibility: Visibility::from(&mut inner),