From 78cac259f2cc90374d606993c06b84dc0e3a942a Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 14 May 2026 21:52:56 +0200 Subject: [PATCH] Decl, Expr, and statement --- parser/src/lib.rs | 434 +------------------------- parser/src/parser/common/decl.rs | 100 ++++++ parser/src/parser/common/expr.rs | 165 ++++++++++ parser/src/parser/common/mod.rs | 3 + parser/src/parser/common/statement.rs | 131 ++++++++ parser/src/parser/common/types.rs | 34 ++ parser/src/parser/items/function.rs | 12 + 7 files changed, 446 insertions(+), 433 deletions(-) create mode 100644 parser/src/parser/common/decl.rs create mode 100644 parser/src/parser/common/expr.rs create mode 100644 parser/src/parser/common/statement.rs diff --git a/parser/src/lib.rs b/parser/src/lib.rs index ee0a859..9b99918 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -7,9 +7,7 @@ pub mod parser; use ast::*; -use crate::error::{ErrorCode, ParseError, ParseResult}; - -use crate::parser::{consume_rule, listen_rule}; +use crate::error::ParseResult; #[derive(Parser)] #[grammar = "./src/grammar.pest"] @@ -28,433 +26,3 @@ pub fn parse<'a>(source: &'a str) -> ParseResult<'a, Vec> { Ok(statements) } - -impl<'a> TryFrom> for ParamList { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - Ok(ParamList( - pair.into_inner() - .map(VarDecl::try_from) - .collect::>>()?, - )) - } -} - -impl<'a> TryFrom> for StatementBranch { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let mut inner = pair.into_inner(); - - let condition = Expression::try_from(inner.next().unwrap())?; - let body = Statement::try_from(inner.next().unwrap())?; - - Ok(StatementBranch { - condition, - body: Box::new(body), - }) - } -} - -impl<'a> TryFrom> for Generics { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let rule = pair.as_rule(); - let inner = pair.clone().into_inner(); - - match rule { - Rule::generics => Ok(Generics( - inner - .map(|pair| -> ParseResult<'a, Generic> { - let mut inner = pair.into_inner(); - Ok( - if let Some(pair) = consume_rule(&mut inner, Rule::lifetime) { - Generic::Lifetime(Identifier::try_from( - pair.into_inner().next().unwrap(), - )?) - } else { - Generic::Type( - Identifier::try_from(inner.next().unwrap())?, - inner - .map(TypeExpr::try_from) - .collect::>>()?, - ) - }, - ) - }) - .collect::>>()?, - )), - _ => unimplemented!("{rule:#?}"), - } - } -} - -impl<'a> TryFrom> for Block { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let statements = pair - .into_inner() - .flat_map(|pair| { - if pair.as_rule() == Rule::statement_list { - pair.into_inner().map(Statement::try_from).collect() - } else { - vec![Statement::try_from(pair)] - } - }) - .collect::>>()?; - - Ok(Block(statements)) - } -} - -impl<'a> TryFrom> for Statement { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let rule = pair.as_rule(); - let mut inner = pair.clone().into_inner(); - - Ok(match rule { - Rule::statement => Statement::try_from(inner.next().unwrap())?, - - Rule::expr_stmt => Statement::Expression(Expression::try_from(inner.next().unwrap())?), - - Rule::block => Statement::Block(Block::try_from(inner.next().unwrap())?), - - Rule::var_decl_statement => Statement::VarDecl(VarDeclStmt::try_from(pair)?), - - Rule::return_stmt => { - Statement::Return(inner.next().map(Expression::try_from).transpose()?) - } - - Rule::break_stmt => Statement::Break, - - Rule::continue_stmt => Statement::Continue, - - Rule::if_stmt => { - let mut inner = inner.skip(2); - - Statement::If { - initial: StatementBranch::try_from(pair)?, - else_if: inner - .next() - .unwrap() - .into_inner() - .map(StatementBranch::try_from) - .collect::>>()?, - else_branch: inner - .next() - .map(Statement::try_from) - .transpose()? - .map(Box::new), - } - } - - Rule::while_stmt => Statement::While(pair.try_into()?), - - Rule::c_for_stmt => Statement::CStyleFor { - init: Box::new(Statement::try_from(inner.next().unwrap())?), - condition: inner.next().unwrap().try_into()?, - update: Box::new(Statement::try_from(inner.next().unwrap())?), - body: Box::new(Statement::try_from(inner.next().unwrap())?), - }, - - Rule::for_stmt => Statement::For { - mutable: listen_rule(&mut inner, Rule::mutable), - pattern: Pattern::try_from(inner.next().unwrap())?, - iterator: inner.next().unwrap().try_into()?, - body: Box::new(Statement::try_from(inner.next().unwrap())?), - }, - - Rule::assign_statement => Statement::VarAssign(VarAssignStmt { - target: Expression::try_from(inner.next().unwrap())?, - value: Expression::try_from(inner.next().unwrap())?, - }), - - Rule::match_stmt => Statement::Match( - Expression::try_from(inner.next().unwrap())?, - inner - .map(|match_itms| { - let mut match_inner = match_itms.into_inner(); - Ok(( - Pattern::try_from(match_inner.next().unwrap())?, - Block::try_from(match_inner.next().unwrap())?, - )) - }) - .collect::>>()?, - ), - - Rule::unexpected_statement => { - return Err(ParseError::Ast { - span: pair.as_span(), - error_code: ErrorCode::InvalidStatement, - error_message: "Invalid Statement".to_string(), - }); - } - - _ => unimplemented!("{rule:#?}"), - }) - } -} - -impl<'a> TryFrom> for Expression { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let rule = pair.as_rule(); - let mut inner = pair.clone().into_inner(); - - match rule { - Rule::expr => { - let prefixes: Vec = inner - .next() - .map(|p| { - p.into_inner() - .into_iter() - .map(Prefix::try_from) - .collect::>>() - }) - .transpose()? - .unwrap_or_default(); - - let exp = Expression::try_from(inner.next().unwrap())?; - - if inner.len() > 0 || prefixes.len() > 0 { - Ok(Expression::Fix { - initial: Box::new(exp), - prefixes, - postfixes: inner - .map(|p| Postfix::try_from(p)) - .collect::>>()?, - }) - } else { - Ok(exp) - } - } - Rule::primary => Expression::try_from(inner.next().unwrap()), - Rule::static_path => Ok(Expression::Path(Path::try_from(pair)?)), - Rule::literal => Ok(Expression::Literal(Literal::try_from(pair)?)), - _ => unimplemented!("{rule:#?}"), - } - } -} - -impl<'a> TryFrom> for Prefix { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - Ok(match pair.as_rule() { - Rule::prefix => Self::try_from(pair.into_inner().next().unwrap())?, - Rule::deref_px => Self::Deref, - Rule::mut_ref_px => Self::RefMut, - Rule::ref_px => Self::Ref, - Rule::new_px => Self::New, - Rule::not_px => Self::Not, - _ => unimplemented!("{pair:#?}"), - }) - } -} - -impl<'a> TryFrom> for Postfix { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let rule = pair.as_rule(); - let mut inner = pair.into_inner(); - - Ok(match rule { - Rule::postfix => Postfix::try_from(inner.next().unwrap())?, - - Rule::field_px => Postfix::FieldAccess(Identifier::try_from(inner.next().unwrap())?), - - Rule::call_px => Postfix::Call( - inner - .map(Expression::try_from) - .collect::>>()?, - ), - - Rule::struct_px => Postfix::StructCall( - inner - .map(|p| { - let mut pi = p.into_inner(); - Ok(( - Identifier::try_from(pi.next().unwrap())?, - Expression::try_from(pi.next().unwrap())?, - )) - }) - .collect::>>()?, - ), - - Rule::index_px => Postfix::Index(Expression::try_from(inner.next().unwrap())?), - - Rule::binary_px => { - let op_pair = inner.next().unwrap(); - let op = match op_pair.as_str() { - "+" => BinaryOp::Plus, - "-" => BinaryOp::Minus, - "*" => BinaryOp::Multiply, - "/" => BinaryOp::Divide, - "%" => BinaryOp::Modulo, - "==" => BinaryOp::Equal, - "!=" => BinaryOp::NotEqual, - "<" => BinaryOp::LessThan, - ">" => BinaryOp::GreaterThan, - "<=" => BinaryOp::LessThanOrEqual, - ">=" => BinaryOp::GreaterThanOrEqual, - "&&" => BinaryOp::And, - "||" => BinaryOp::Or, - - _ => { - unimplemented!("Binary operator not implemented yet: {}", op_pair.as_str()) - } - }; - Postfix::Binary(op, Expression::try_from(inner.next().unwrap())?) - } - - Rule::macro_call_px => Postfix::MacroCall(inner.as_str().to_string()), - - _ => unimplemented!("{rule:#?}"), - }) - } -} - -impl<'a> TryFrom> for VarDeclStmt { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - match pair.as_rule() { - Rule::var_decl_statement => { - let mut inner = pair.into_inner(); - - let decl = VarDecl::try_from(inner.next().unwrap())?; - - let init = inner.next().map(Expression::try_from).transpose()?; - - Ok(VarDeclStmt { decl, init }) - } - - _ => unimplemented!(), - } - } -} - -impl<'a> TryFrom> for FieldDeclStmt { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - match pair.as_rule() { - Rule::class_field => { - let mut inner = pair.into_inner(); - - let decl = FieldDecl::try_from(inner.next().unwrap())?; - - let init = inner.next().map(Expression::try_from).transpose()?; - - Ok(FieldDeclStmt { decl, init }) - } - - _ => unimplemented!(), - } - } -} - -impl<'a> TryFrom> for Pattern { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let rule = pair.as_rule(); - let mut inner = pair.clone().into_inner(); - - Ok(match rule { - Rule::tuple_pattern => Pattern::Tuple( - inner - .map(Identifier::try_from) - .collect::>>()?, - ), - - Rule::named_tuple_pattern => Pattern::NamedTuple( - Path::try_from(inner.next().unwrap())?, - inner - .map(Identifier::try_from) - .collect::>>()?, - ), - - Rule::struct_pattern => Pattern::Struct( - Path::try_from(inner.next().unwrap())?, - inner - .map(Identifier::try_from) - .collect::>>()?, - ), - - Rule::literal => Pattern::Literal(Literal::try_from(pair)?), - - Rule::identifier => Pattern::Id(Identifier::try_from(pair)?), - - Rule::static_path => Pattern::Path(Path::try_from(pair)?), - - _ => unimplemented!("{rule:?}"), - }) - } -} - -impl<'a> TryFrom> for VarDecl { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - match pair.as_rule() { - Rule::var_decl => { - let mut inner = pair.into_inner(); - - let type_ = inner - .next() - .and_then(|pair| { - if pair.as_str().trim() == "var" { - None - } else { - Some(TypeExpr::try_from(pair)) - } - }) - .transpose()?; - - let mutable = listen_rule(&mut inner, Rule::mutable); - - let name = Pattern::try_from(inner.next().unwrap())?; - - Ok(VarDecl { - mutable, - name, - type_, - }) - } - - _ => unimplemented!("{:?}", pair.as_rule()), - } - } -} - -impl<'a> TryFrom> for FieldDecl { - type Error = ParseError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - match pair.as_rule() { - Rule::field => { - let mut inner = pair.into_inner(); - - let visibility = Visibility::try_from(&mut inner)?; - let type_ = TypeExpr::try_from(inner.next().unwrap())?; - let name = Identifier::try_from(inner.next().unwrap())?; - - Ok(FieldDecl { - visibility, - type_, - name, - }) - } - - _ => unimplemented!("{:?}", pair.as_rule()), - } - } -} diff --git a/parser/src/parser/common/decl.rs b/parser/src/parser/common/decl.rs new file mode 100644 index 0000000..9ffafdb --- /dev/null +++ b/parser/src/parser/common/decl.rs @@ -0,0 +1,100 @@ +use crate::{Rule, ast::*, error::ParseError, parser::listen_rule}; + +impl<'a> TryFrom> for VarDeclStmt { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + match pair.as_rule() { + Rule::var_decl_statement => { + let mut inner = pair.into_inner(); + + let decl = VarDecl::try_from(inner.next().unwrap())?; + + let init = inner.next().map(Expression::try_from).transpose()?; + + Ok(VarDeclStmt { decl, init }) + } + + _ => unimplemented!(), + } + } +} + +impl<'a> TryFrom> for FieldDeclStmt { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + match pair.as_rule() { + Rule::class_field => { + let mut inner = pair.into_inner(); + + let decl = FieldDecl::try_from(inner.next().unwrap())?; + + let init = inner.next().map(Expression::try_from).transpose()?; + + Ok(FieldDeclStmt { decl, init }) + } + + _ => unimplemented!(), + } + } +} + +impl<'a> TryFrom> for VarDecl { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + match pair.as_rule() { + Rule::var_decl => { + let mut inner = pair.into_inner(); + + let type_ = inner + .next() + .and_then(|pair| { + if pair.as_str().trim() == "var" { + None + } else { + Some(TypeExpr::try_from(pair)) + } + }) + .transpose()?; + + let mutable = listen_rule(&mut inner, Rule::mutable); + + let name = Pattern::try_from(inner.next().unwrap())?; + + Ok(VarDecl { + mutable, + name, + type_, + }) + } + + _ => unimplemented!("{:?}", pair.as_rule()), + } + } +} + +impl<'a> TryFrom> for FieldDecl { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + match pair.as_rule() { + Rule::field => { + let mut inner = pair.into_inner(); + + let visibility = Visibility::try_from(&mut inner)?; + let type_ = TypeExpr::try_from(inner.next().unwrap())?; + let name = Identifier::try_from(inner.next().unwrap())?; + + Ok(FieldDecl { + visibility, + type_, + name, + }) + } + + _ => unimplemented!("{:?}", pair.as_rule()), + } + } +} diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs new file mode 100644 index 0000000..0ff9be8 --- /dev/null +++ b/parser/src/parser/common/expr.rs @@ -0,0 +1,165 @@ +use crate::{ + Rule, + ast::*, + error::{ParseError, ParseResult}, +}; + +impl<'a> TryFrom> for Expression { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let rule = pair.as_rule(); + let mut inner = pair.clone().into_inner(); + + match rule { + Rule::expr => { + let prefixes: Vec = inner + .next() + .map(|p| { + p.into_inner() + .into_iter() + .map(Prefix::try_from) + .collect::>>() + }) + .transpose()? + .unwrap_or_default(); + + let exp = Expression::try_from(inner.next().unwrap())?; + + if inner.len() > 0 || prefixes.len() > 0 { + Ok(Expression::Fix { + initial: Box::new(exp), + prefixes, + postfixes: inner + .map(|p| Postfix::try_from(p)) + .collect::>>()?, + }) + } else { + Ok(exp) + } + } + Rule::primary => Expression::try_from(inner.next().unwrap()), + Rule::static_path => Ok(Expression::Path(Path::try_from(pair)?)), + Rule::literal => Ok(Expression::Literal(Literal::try_from(pair)?)), + _ => unimplemented!("{rule:#?}"), + } + } +} + +impl<'a> TryFrom> for Prefix { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + Ok(match pair.as_rule() { + Rule::prefix => Self::try_from(pair.into_inner().next().unwrap())?, + Rule::deref_px => Self::Deref, + Rule::mut_ref_px => Self::RefMut, + Rule::ref_px => Self::Ref, + Rule::new_px => Self::New, + Rule::not_px => Self::Not, + _ => unimplemented!("{pair:#?}"), + }) + } +} + +impl<'a> TryFrom> for Postfix { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let rule = pair.as_rule(); + let mut inner = pair.into_inner(); + + Ok(match rule { + Rule::postfix => Postfix::try_from(inner.next().unwrap())?, + + Rule::field_px => Postfix::FieldAccess(Identifier::try_from(inner.next().unwrap())?), + + Rule::call_px => Postfix::Call( + inner + .map(Expression::try_from) + .collect::>>()?, + ), + + Rule::struct_px => Postfix::StructCall( + inner + .map(|p| { + let mut pi = p.into_inner(); + Ok(( + Identifier::try_from(pi.next().unwrap())?, + Expression::try_from(pi.next().unwrap())?, + )) + }) + .collect::>>()?, + ), + + Rule::index_px => Postfix::Index(Expression::try_from(inner.next().unwrap())?), + + Rule::binary_px => { + let op_pair = inner.next().unwrap(); + let op = match op_pair.as_str() { + "+" => BinaryOp::Plus, + "-" => BinaryOp::Minus, + "*" => BinaryOp::Multiply, + "/" => BinaryOp::Divide, + "%" => BinaryOp::Modulo, + "==" => BinaryOp::Equal, + "!=" => BinaryOp::NotEqual, + "<" => BinaryOp::LessThan, + ">" => BinaryOp::GreaterThan, + "<=" => BinaryOp::LessThanOrEqual, + ">=" => BinaryOp::GreaterThanOrEqual, + "&&" => BinaryOp::And, + "||" => BinaryOp::Or, + + _ => { + unimplemented!("Binary operator not implemented yet: {}", op_pair.as_str()) + } + }; + Postfix::Binary(op, Expression::try_from(inner.next().unwrap())?) + } + + Rule::macro_call_px => Postfix::MacroCall(inner.as_str().to_string()), + + _ => unimplemented!("{rule:#?}"), + }) + } +} + +impl<'a> TryFrom> for Pattern { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let rule = pair.as_rule(); + let mut inner = pair.clone().into_inner(); + + Ok(match rule { + Rule::tuple_pattern => Pattern::Tuple( + inner + .map(Identifier::try_from) + .collect::>>()?, + ), + + Rule::named_tuple_pattern => Pattern::NamedTuple( + Path::try_from(inner.next().unwrap())?, + inner + .map(Identifier::try_from) + .collect::>>()?, + ), + + Rule::struct_pattern => Pattern::Struct( + Path::try_from(inner.next().unwrap())?, + inner + .map(Identifier::try_from) + .collect::>>()?, + ), + + Rule::literal => Pattern::Literal(Literal::try_from(pair)?), + + Rule::identifier => Pattern::Id(Identifier::try_from(pair)?), + + Rule::static_path => Pattern::Path(Path::try_from(pair)?), + + _ => unimplemented!("{rule:?}"), + }) + } +} diff --git a/parser/src/parser/common/mod.rs b/parser/src/parser/common/mod.rs index a6acde1..1f1169f 100644 --- a/parser/src/parser/common/mod.rs +++ b/parser/src/parser/common/mod.rs @@ -1,3 +1,6 @@ +pub mod decl; +pub mod expr; +pub mod statement; pub mod types; use crate::{ diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs new file mode 100644 index 0000000..f78065d --- /dev/null +++ b/parser/src/parser/common/statement.rs @@ -0,0 +1,131 @@ +use crate::{ + Rule, + ast::*, + error::{ErrorCode, ParseError, ParseResult}, + parser::listen_rule, +}; + +impl<'a> TryFrom> for Block { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let statements = pair + .into_inner() + .flat_map(|pair| { + if pair.as_rule() == Rule::statement_list { + pair.into_inner().map(Statement::try_from).collect() + } else { + vec![Statement::try_from(pair)] + } + }) + .collect::>>()?; + + Ok(Block(statements)) + } +} + +impl<'a> TryFrom> for Statement { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let rule = pair.as_rule(); + let mut inner = pair.clone().into_inner(); + + Ok(match rule { + Rule::statement => Statement::try_from(inner.next().unwrap())?, + + Rule::expr_stmt => Statement::Expression(Expression::try_from(inner.next().unwrap())?), + + Rule::block => Statement::Block(Block::try_from(inner.next().unwrap())?), + + Rule::var_decl_statement => Statement::VarDecl(VarDeclStmt::try_from(pair)?), + + Rule::return_stmt => { + Statement::Return(inner.next().map(Expression::try_from).transpose()?) + } + + Rule::break_stmt => Statement::Break, + + Rule::continue_stmt => Statement::Continue, + + Rule::if_stmt => { + let mut inner = inner.skip(2); + + Statement::If { + initial: StatementBranch::try_from(pair)?, + else_if: inner + .next() + .unwrap() + .into_inner() + .map(StatementBranch::try_from) + .collect::>>()?, + else_branch: inner + .next() + .map(Statement::try_from) + .transpose()? + .map(Box::new), + } + } + + Rule::while_stmt => Statement::While(pair.try_into()?), + + Rule::c_for_stmt => Statement::CStyleFor { + init: Box::new(Statement::try_from(inner.next().unwrap())?), + condition: inner.next().unwrap().try_into()?, + update: Box::new(Statement::try_from(inner.next().unwrap())?), + body: Box::new(Statement::try_from(inner.next().unwrap())?), + }, + + Rule::for_stmt => Statement::For { + mutable: listen_rule(&mut inner, Rule::mutable), + pattern: Pattern::try_from(inner.next().unwrap())?, + iterator: inner.next().unwrap().try_into()?, + body: Box::new(Statement::try_from(inner.next().unwrap())?), + }, + + Rule::assign_statement => Statement::VarAssign(VarAssignStmt { + target: Expression::try_from(inner.next().unwrap())?, + value: Expression::try_from(inner.next().unwrap())?, + }), + + Rule::match_stmt => Statement::Match( + Expression::try_from(inner.next().unwrap())?, + inner + .map(|match_itms| { + let mut match_inner = match_itms.into_inner(); + Ok(( + Pattern::try_from(match_inner.next().unwrap())?, + Block::try_from(match_inner.next().unwrap())?, + )) + }) + .collect::>>()?, + ), + + Rule::unexpected_statement => { + return Err(ParseError::Ast { + span: pair.as_span(), + error_code: ErrorCode::InvalidStatement, + error_message: "Invalid Statement".to_string(), + }); + } + + _ => unimplemented!("{rule:#?}"), + }) + } +} + +impl<'a> TryFrom> for StatementBranch { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let mut inner = pair.into_inner(); + + let condition = Expression::try_from(inner.next().unwrap())?; + let body = Statement::try_from(inner.next().unwrap())?; + + Ok(StatementBranch { + condition, + body: Box::new(body), + }) + } +} diff --git a/parser/src/parser/common/types.rs b/parser/src/parser/common/types.rs index 08050b9..f5dc265 100644 --- a/parser/src/parser/common/types.rs +++ b/parser/src/parser/common/types.rs @@ -91,3 +91,37 @@ impl<'a> TryFrom> for TypeExpr { } } } + +impl<'a> TryFrom> for Generics { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let rule = pair.as_rule(); + let inner = pair.clone().into_inner(); + + match rule { + Rule::generics => Ok(Generics( + inner + .map(|pair| -> ParseResult<'a, Generic> { + let mut inner = pair.into_inner(); + Ok( + if let Some(pair) = consume_rule(&mut inner, Rule::lifetime) { + Generic::Lifetime(Identifier::try_from( + pair.into_inner().next().unwrap(), + )?) + } else { + Generic::Type( + Identifier::try_from(inner.next().unwrap())?, + inner + .map(TypeExpr::try_from) + .collect::>>()?, + ) + }, + ) + }) + .collect::>>()?, + )), + _ => unimplemented!("{rule:#?}"), + } + } +} diff --git a/parser/src/parser/items/function.rs b/parser/src/parser/items/function.rs index 4de9d45..07520ad 100644 --- a/parser/src/parser/items/function.rs +++ b/parser/src/parser/items/function.rs @@ -70,3 +70,15 @@ impl<'a> TryFrom> for FunctionDecl { }) } } + +impl<'a> TryFrom> for ParamList { + type Error = ParseError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + Ok(ParamList( + pair.into_inner() + .map(VarDecl::try_from) + .collect::>>()?, + )) + } +}