diff --git a/parser/src/error.rs b/parser/src/error.rs index 5157482..a5d50dc 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -1,16 +1,19 @@ use crate::Rule; -pub type ParseResult<'a, T, ET = T> = Result>; +pub type AstResult<'a, T, ET = T> = Result>; #[derive(Debug, Clone)] pub enum ParseError<'a, T> { PreAst(pest::error::Error), - Ast { - span: pest::Span<'a>, - error_code: ErrorCode, - error_message: String, - recovered: Option, - }, + Ast(AstError<'a, T>), +} + +#[derive(Debug, Clone)] +pub struct AstError<'a, T> { + span: pest::Span<'a>, + error_code: ErrorCode, + error_message: String, + recovered: Option, } #[derive(Debug, Clone)] @@ -18,37 +21,35 @@ pub enum ErrorCode { InvalidStatement = 200, } -impl<'a, F> ParseError<'a, F> { - pub fn get(self) -> ParseError<'a, T> { - match self { - Self::Ast { - span, - error_code, - error_message, - .. - } => ParseError::Ast { - span, - error_code, - error_message, - recovered: None, - }, - Self::PreAst(pest_err) => ParseError::PreAst(pest_err), - } - } -} - impl From> for ParseError<'_, T> { fn from(value: pest::error::Error) -> Self { Self::PreAst(value) } } +impl<'a, T> From> for ParseError<'a, T> { + fn from(value: AstError<'a, T>) -> Self { + Self::Ast(value) + } +} + +impl<'a, F> AstError<'a, F> { + pub fn get(self) -> AstError<'a, T> { + AstError { + span: self.span, + error_code: self.error_code, + error_message: self.error_message, + recovered: None, + } + } +} + pub trait GetParseError<'a, F> { - fn get(self) -> ParseResult<'a, F, T>; + fn get(self) -> AstResult<'a, F, T>; } -impl<'a, F> GetParseError<'a, F> for ParseResult<'a, F> { - fn get(self) -> ParseResult<'a, F, T> { +impl<'a, F> GetParseError<'a, F> for AstResult<'a, F> { + fn get(self) -> AstResult<'a, F, T> { match self { Ok(v) => Ok(v), Err(e) => Err(e.get()), @@ -56,11 +57,40 @@ impl<'a, F> GetParseError<'a, F> for ParseResult<'a, F> { } } -impl<'a, F> GetParseError<'a, Option> for Result, ParseError<'a, F>> { - fn get(self) -> ParseResult<'a, Option, T> { +impl<'a, F> GetParseError<'a, Option> for Result, AstError<'a, F>> { + fn get(self) -> AstResult<'a, Option, T> { match self { Ok(v) => Ok(v), Err(e) => Err(e.get()), } } } + +pub fn collect_recovered<'a, T, ET>( + pairs: impl Iterator>, +) -> AstResult<'a, Vec, Vec> +where + T: TryFrom, Error = AstError<'a, ET>>, +{ + let mut items = Vec::new(); + let mut last_error: Option> = None; + + for pair in pairs { + match T::try_from(pair) { + Ok(item) => items.push(item), + Err(e) => { + last_error = Some(e); + } + } + } + + match last_error { + Some(ast_err) => Err(AstError { + span: ast_err.span, + error_code: ast_err.error_code, + error_message: ast_err.error_message, + recovered: None, + }), + None => Ok(items), + } +} diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 86e8ea7..5ab2bbf 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -7,13 +7,13 @@ pub mod parser; use ast::*; -use crate::error::{GetParseError, ParseResult}; +use crate::error::{GetParseError, ParseError}; #[derive(Parser)] #[grammar = "./src/grammar.pest"] pub struct MistParser; -pub fn parse<'a>(source: &'a str) -> ParseResult<'a, Vec> { +pub fn parse<'a>(source: &'a str) -> Result, ParseError<'a, Vec>> { let mut pairs = MistParser::parse(Rule::program, source)?; let mut statements = vec![]; diff --git a/parser/src/parser/common/decl.rs b/parser/src/parser/common/decl.rs index 5e4038d..d9a3dc5 100644 --- a/parser/src/parser/common/decl.rs +++ b/parser/src/parser/common/decl.rs @@ -1,12 +1,12 @@ use crate::{ Rule, ast::*, - error::{GetParseError, ParseError}, + error::{AstError, GetParseError}, parser::listen_rule, }; impl<'a> TryFrom> for VarDeclStmt { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -26,7 +26,7 @@ impl<'a> TryFrom> for VarDeclStmt { } impl<'a> TryFrom> for FieldDeclStmt { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -46,7 +46,7 @@ impl<'a> TryFrom> for FieldDeclStmt { } impl<'a> TryFrom> for VarDecl { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -82,7 +82,7 @@ impl<'a> TryFrom> for VarDecl { } impl<'a> TryFrom> for FieldDecl { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 342e2a4..0d25e58 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -1,11 +1,11 @@ use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{AstError, AstResult}, }; impl<'a> TryFrom> for Expression { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -19,7 +19,7 @@ impl<'a> TryFrom> for Expression { p.into_inner() .into_iter() .map(Prefix::try_from) - .collect::, _>>() + .collect::, _>>() }) .transpose()? .unwrap_or_default(); @@ -32,7 +32,7 @@ impl<'a> TryFrom> for Expression { prefixes, postfixes: inner .map(|p| Postfix::try_from(p)) - .collect::>>()?, + .collect::>>()?, }) } else { Ok(exp) @@ -47,7 +47,7 @@ impl<'a> TryFrom> for Expression { } impl<'a> TryFrom> for Prefix { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { Ok(match pair.as_rule() { @@ -63,7 +63,7 @@ impl<'a> TryFrom> for Prefix { } impl<'a> TryFrom> for Postfix { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -74,7 +74,7 @@ impl<'a> TryFrom> for Postfix { Rule::field_px => Postfix::FieldAccess(Identifier::try_from(inner.next().unwrap())?), - Rule::call_px => Postfix::Call(inner.map(Expression::try_from).collect:: Postfix::Call(inner.map(Expression::try_from).collect::, _, @@ -89,7 +89,7 @@ impl<'a> TryFrom> for Postfix { Expression::try_from(pi.next().unwrap())?, )) }) - .collect::>>()?, + .collect::>>()?, ), Rule::index_px => Postfix::Index(Expression::try_from(inner.next().unwrap())?), diff --git a/parser/src/parser/common/mod.rs b/parser/src/parser/common/mod.rs index 0dc5dfd..9f3cbb4 100644 --- a/parser/src/parser/common/mod.rs +++ b/parser/src/parser/common/mod.rs @@ -6,12 +6,12 @@ pub mod types; use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{AstError, AstResult}, parser::consume_rule, }; impl<'a> TryFrom> for Identifier { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { Ok(Identifier(pair.as_str().to_string())) @@ -19,14 +19,14 @@ impl<'a> TryFrom> for Identifier { } impl<'a> TryFrom> for Path { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { Rule::static_path => Ok(Path( pair.into_inner() .map(Identifier::try_from) - .collect::>>()?, + .collect::>>()?, )), _ => unimplemented!("{pair:#?}"), } @@ -34,7 +34,7 @@ impl<'a> TryFrom> for Path { } impl<'a> TryFrom> for Literal { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -50,7 +50,7 @@ impl<'a> TryFrom> for Literal { Rule::tuple => Literal::Tuple( inner .map(Expression::try_from) - .collect::>>()?, + .collect::>>()?, ), _ => unimplemented!("{rule:#?}"), }) @@ -58,7 +58,7 @@ impl<'a> TryFrom> for Literal { } impl<'a> TryFrom> for Pattern { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -68,21 +68,21 @@ impl<'a> TryFrom> for Pattern { Rule::tuple_pattern => Pattern::Tuple( inner .map(Identifier::try_from) - .collect::>>()?, + .collect::>>()?, ), Rule::named_tuple_pattern => Pattern::NamedTuple( Path::try_from(inner.next().unwrap())?, inner .map(Identifier::try_from) - .collect::>>()?, + .collect::>>()?, ), Rule::struct_pattern => Pattern::Struct( Path::try_from(inner.next().unwrap())?, inner .map(Identifier::try_from) - .collect::>>()?, + .collect::>>()?, ), Rule::literal => Pattern::Literal(Literal::try_from(pair)?), @@ -97,11 +97,11 @@ impl<'a> TryFrom> for Pattern { } impl<'a> TryFrom<&mut pest::iterators::Pairs<'a, Rule>> for Visibility { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pairs: &mut pest::iterators::Pairs<'a, Rule>) -> Result { Ok(consume_rule(pairs, Rule::visibility) - .map(|pair| -> Result> { + .map(|pair| -> Result> { if let Some(path) = pair.into_inner().next() { Ok(Visibility::PublicTarget(Path::try_from(path)?)) } else { diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs index a95d7e1..d30c5d2 100644 --- a/parser/src/parser/common/statement.rs +++ b/parser/src/parser/common/statement.rs @@ -1,12 +1,12 @@ use crate::{ Rule, ast::*, - error::{ErrorCode, ParseError, ParseResult}, + error::{ErrorCode, AstError, AstResult}, parser::listen_rule, }; impl<'a> TryFrom> for Block { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let statements = pair @@ -18,14 +18,14 @@ impl<'a> TryFrom> for Block { vec![Statement::try_from(pair)] } }) - .collect::>>()?; + .collect::>>()?; Ok(Block(statements)) } } impl<'a> TryFrom> for Statement { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -58,7 +58,7 @@ impl<'a> TryFrom> for Statement { .unwrap() .into_inner() .map(StatementBranch::try_from) - .collect::>>()?, + .collect::>>()?, else_branch: inner .next() .map(Statement::try_from) @@ -98,11 +98,11 @@ impl<'a> TryFrom> for Statement { Block::try_from(match_inner.next().unwrap())?, )) }) - .collect::>>()?, + .collect::>>()?, ), Rule::unexpected_statement => { - return Err(ParseError::Ast { + return Err(AstError::Ast { span: pair.as_span(), error_code: ErrorCode::InvalidStatement, error_message: "Invalid Statement".to_string(), @@ -115,7 +115,7 @@ impl<'a> TryFrom> for Statement { } impl<'a> TryFrom> for StatementBranch { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); diff --git a/parser/src/parser/common/types.rs b/parser/src/parser/common/types.rs index 912f8ae..89493f3 100644 --- a/parser/src/parser/common/types.rs +++ b/parser/src/parser/common/types.rs @@ -1,12 +1,12 @@ use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{AstError, AstResult}, parser::{consume_rule, listen_rule}, }; impl<'a> TryFrom> for TypePostfix { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -39,7 +39,7 @@ impl<'a> TryFrom> for TypePostfix { } impl<'a> TryFrom> for TypeExprKind { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -49,13 +49,13 @@ impl<'a> TryFrom> for TypeExprKind { Rule::tuple_type => Ok(TypeExprKind::Tuple( inner .map(TypeExpr::try_from) - .collect::>()?, + .collect::>()?, )), Rule::path_type => { let path = Path::try_from(inner.next().unwrap())?; let params = inner .map(TypeExpr::try_from) - .collect::>>()?; + .collect::>>()?; if params.len() == 0 { Ok(TypeExprKind::Path(path)) @@ -69,7 +69,7 @@ impl<'a> TryFrom> for TypeExprKind { } impl<'a> TryFrom> for TypeExpr { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -80,7 +80,7 @@ impl<'a> TryFrom> for TypeExpr { TypeExprKind::try_from(inner.next().unwrap())?, inner .map(TypePostfix::try_from) - .collect::>()?, + .collect::>()?, )), Rule::type_expr_param => Self::try_from(inner.next().unwrap()), Rule::lifetime => Ok(TypeExpr( @@ -93,7 +93,7 @@ impl<'a> TryFrom> for TypeExpr { } impl<'a> TryFrom> for Generics { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -102,7 +102,7 @@ impl<'a> TryFrom> for Generics { match rule { Rule::generics => Ok(Generics( inner - .map(|pair| -> ParseResult<'a, Generic> { + .map(|pair| -> AstResult<'a, Generic> { let mut inner = pair.into_inner(); Ok( if let Some(pair) = consume_rule(&mut inner, Rule::lifetime) { @@ -114,12 +114,12 @@ impl<'a> TryFrom> for Generics { Identifier::try_from(inner.next().unwrap())?, inner .map(TypeExpr::try_from) - .collect::>>()?, + .collect::>>()?, ) }, ) }) - .collect::>>()?, + .collect::>>()?, )), _ => unimplemented!("{rule:#?}"), } diff --git a/parser/src/parser/items/attribute.rs b/parser/src/parser/items/attribute.rs index 44bf9f3..b75a864 100644 --- a/parser/src/parser/items/attribute.rs +++ b/parser/src/parser/items/attribute.rs @@ -1,11 +1,11 @@ use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{AstError, AstResult}, }; impl<'a> TryFrom> for Attribute { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { match pair.as_rule() { @@ -41,7 +41,7 @@ impl<'a> TryFrom> for Attribute { let items = next .into_inner() .map(Attribute::try_from) - .collect::, _>>()?; + .collect::, _>>()?; Ok(Attribute::List { path, items }) } diff --git a/parser/src/parser/items/class.rs b/parser/src/parser/items/class.rs index 5517ec0..09b13e8 100644 --- a/parser/src/parser/items/class.rs +++ b/parser/src/parser/items/class.rs @@ -1,7 +1,7 @@ -use crate::{Rule, ast::*, error::ParseError, parser::consume_rule}; +use crate::{Rule, ast::*, error::AstError, parser::consume_rule}; impl<'a> TryFrom> for ClassConstructor { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); @@ -28,7 +28,7 @@ impl<'a> TryFrom> for ClassConstructor { } impl<'a> TryFrom> for ClassItem { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); diff --git a/parser/src/parser/items/enums.rs b/parser/src/parser/items/enums.rs index 70e0d8a..2b4dc89 100644 --- a/parser/src/parser/items/enums.rs +++ b/parser/src/parser/items/enums.rs @@ -1,11 +1,11 @@ use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{AstError, AstResult}, }; impl<'a> TryFrom> for EnumItem { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -23,7 +23,7 @@ impl<'a> TryFrom> for EnumItem { .unwrap() .into_inner() .map(TypeExpr::try_from) - .collect::>>()?, + .collect::>>()?, )), Rule::enum_struct => Ok(EnumItem::Struct( @@ -33,7 +33,7 @@ impl<'a> TryFrom> for EnumItem { .map(|pair| { pair.into_inner() .map(FieldDecl::try_from) - .collect::>>() + .collect::>>() }) .transpose()? .unwrap_or_default(), diff --git a/parser/src/parser/items/function.rs b/parser/src/parser/items/function.rs index c4d25cf..fde3a29 100644 --- a/parser/src/parser/items/function.rs +++ b/parser/src/parser/items/function.rs @@ -1,12 +1,12 @@ use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{AstError, AstResult}, parser::{consume_rule, listen_rule}, }; impl<'a> TryFrom> for FunctionDecl { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); @@ -47,7 +47,7 @@ impl<'a> TryFrom> for FunctionDecl { let params = consume_rule(&mut inner, Rule::param_list) .map({ let self_param = self_param.clone(); - |params_pair| -> ParseResult<'a, ParamList> { + |params_pair| -> AstResult<'a, ParamList> { let mut params = ParamList::try_from(params_pair)?; if let Some(x) = self_param { params.0.insert(0, x); @@ -72,13 +72,13 @@ impl<'a> TryFrom> for FunctionDecl { } impl<'a> TryFrom> for ParamList { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { Ok(ParamList( pair.into_inner() .map(VarDecl::try_from) - .collect::>>()?, + .collect::>>()?, )) } } diff --git a/parser/src/parser/items/impl_decl.rs b/parser/src/parser/items/impl_decl.rs index 6f66f9f..7d4fab2 100644 --- a/parser/src/parser/items/impl_decl.rs +++ b/parser/src/parser/items/impl_decl.rs @@ -1,12 +1,12 @@ use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{AstError, AstResult}, parser::consume_rule, }; impl<'a> TryFrom> for ImplDecl { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -22,7 +22,7 @@ impl<'a> TryFrom> for ImplDecl { target: TypeExpr::try_from(inner.next().unwrap())?, methods: inner .map(FunctionDecl::try_from) - .collect::>>()?, + .collect::>>()?, }), Rule::impl_decl => Ok(ImplDecl { @@ -34,7 +34,7 @@ impl<'a> TryFrom> for ImplDecl { target: TypeExpr::try_from(inner.next().unwrap())?, methods: inner .map(FunctionDecl::try_from) - .collect::>>()?, + .collect::>>()?, }), _ => unimplemented!("{rule:#?}"), diff --git a/parser/src/parser/items/mod.rs b/parser/src/parser/items/mod.rs index e098145..7e97ab0 100644 --- a/parser/src/parser/items/mod.rs +++ b/parser/src/parser/items/mod.rs @@ -7,12 +7,12 @@ pub mod impl_decl; use crate::{ Rule, ast::*, - error::{ParseError, ParseResult}, + error::{AstError, AstResult}, parser::consume_rule, }; impl<'a> TryFrom> for TopLevel { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let mut inner = pair.into_inner(); @@ -22,7 +22,7 @@ impl<'a> TryFrom> for TopLevel { .unwrap() .into_inner() .map(Attribute::try_from) - .collect::>>()?; + .collect::>>()?; Ok(TopLevel( inner @@ -35,7 +35,7 @@ impl<'a> TryFrom> for TopLevel { } impl<'a> TryFrom> for TopLevelKind { - type Error = ParseError<'a, Self>; + type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); @@ -61,7 +61,7 @@ impl<'a> TryFrom> for TopLevelKind { .map(|pair| { pair.into_inner() .map(FieldDecl::try_from) - .collect::>>() + .collect::>>() }) .transpose()? .unwrap_or_default(), @@ -79,12 +79,12 @@ impl<'a> TryFrom> for TopLevelKind { .unwrap() .into_inner() .map(FieldDeclStmt::try_from) - .collect::>>()?, + .collect::>>()?, constructor: ClassConstructor::try_from(inner.next().unwrap())?, items: inner .into_iter() .map(ClassItem::try_from) - .collect::>>()?, + .collect::>>()?, }, Rule::enum_decl => TopLevelKind::EnumDecl { @@ -96,7 +96,7 @@ impl<'a> TryFrom> for TopLevelKind { .unwrap_or_default(), fields: inner .map(EnumItem::try_from) - .collect::>>()?, + .collect::>>()?, }, Rule::mod_package => TopLevelKind::Mod( @@ -119,13 +119,13 @@ impl<'a> TryFrom> for TopLevelKind { .map(|pair| { pair.into_inner() .map(TypeExpr::try_from) - .collect::>>() + .collect::>>() }) .transpose()? .unwrap_or_default(), items: inner .map(FunctionDecl::try_from) - .collect::>>()?, + .collect::>>()?, }, _ => unimplemented!("{rule:#?}"),