use crate::ast::*; use crate::parser::Rule; use pest::iterators::{Pair, Pairs}; fn expect_and_use(pair: Pair, rule: Rule, f: fn(Pair) -> T) -> T { if pair.as_rule() != rule { panic!("Expected rule {:?} but found {:?}", rule, pair.as_rule()) } f(pair) } pub fn build_ast(compilation_unit_pair: Pair) -> CompilationUnit { build_compilation_unit(compilation_unit_pair) } fn build_identifier(identifier_pair: Pair) -> Identifier { let as_span = identifier_pair.as_span(); Identifier::new( as_span.as_str(), Range { start: as_span.start(), end: as_span.end(), }, ) } fn build_fqn(fqn_pair: Pair) -> FullyQualifiedName { let as_span = fqn_pair.as_span(); FullyQualifiedName::new( fqn_pair .into_inner() .map(|identifier_pair| { expect_and_use(identifier_pair, Rule::Identifier, build_identifier) }) .collect(), Range { start: as_span.start(), end: as_span.end(), }, ) } fn build_type_use(type_use_pair: Pair) -> TypeUse { let inner_pair = type_use_pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::Void => TypeUse::Void, Rule::InterfaceOrClassTypeUse => { TypeUse::InterfaceOrClass(build_interface_or_class_type_use(inner_pair)) } Rule::TupleTypeUse => TypeUse::Tuple(build_tuple_type_use(inner_pair)), Rule::FunctionTypeUse => TypeUse::Function(build_function_type_use(inner_pair)), _ => unreachable!(), } } fn build_interface_or_class_type_use(pair: Pair) -> InterfaceOrClassTypeUse { let mut borrow_count = 0; let mut is_mutable = false; let mut fqn = None; let mut generic_arguments = GenericArguments::default(); for inner_pair in pair.into_inner() { match inner_pair.as_rule() { Rule::Borrow => { borrow_count += 1; } Rule::Mut => { is_mutable = true; } Rule::FullyQualifiedName => { fqn = Some(build_fqn(inner_pair)); } Rule::GenericArguments => { generic_arguments = build_generic_arguments(inner_pair); } _ => unreachable!(), } } InterfaceOrClassTypeUse { borrow_count, is_mutable, fqn: fqn.unwrap(), generics: generic_arguments, } } fn build_tuple_type_use(tuple_type_use_pair: Pair) -> TupleTypeUse { let mut borrow_count = 0; let mut is_mutable = false; let mut arguments = None; for inner_pair in tuple_type_use_pair.into_inner() { match inner_pair.as_rule() { Rule::Borrow => { borrow_count += 1; } Rule::Mut => { is_mutable = true; } Rule::TupleArguments => { arguments = Some(build_tuple_arguments(inner_pair)); } _ => unreachable!(), } } TupleTypeUse { borrow_count, is_mutable, arguments: arguments.unwrap(), } } fn build_function_type_use(function_pair: Pair) -> FunctionTypeUse { let mut borrow_count = 0; let mut function_modifier: Option = None; let mut generics = GenericParameters::default(); let mut parameters: Option = None; let mut return_type: Option = None; for inner_pair in function_pair.into_inner() { match inner_pair.as_rule() { Rule::Borrow => { borrow_count += 1; } Rule::FunctionTypeModifier => { function_modifier = Some(build_function_type_modifier(inner_pair)); } Rule::Fn => {} Rule::GenericParameters => { generics = build_generic_parameters(inner_pair); } Rule::Parameters => { parameters = Some(build_parameters(inner_pair)); } Rule::ReturnType => { return_type = Some(build_return_type(inner_pair)); } _ => unreachable!(), } } FunctionTypeUse { borrow_count, function_modifier, generics, parameters: parameters.unwrap(), return_type: return_type.unwrap(), } } fn build_generic_arguments(generic_arguments_pair: Pair) -> GenericArguments { let type_use_list_pair = generic_arguments_pair.into_inner().next().unwrap(); GenericArguments( type_use_list_pair .into_inner() .map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use)) .collect(), ) } fn build_generic_parameters(generic_parameters_pair: Pair) -> GenericParameters { let identifier_list_pair = generic_parameters_pair.into_inner().next().unwrap(); GenericParameters( identifier_list_pair .into_inner() .map(|identifier_pair| { expect_and_use(identifier_pair, Rule::Identifier, build_identifier) }) .collect(), ) } fn build_tuple_arguments(tuple_arguments_pair: Pair) -> TupleArguments { let parentheses_optional_type_use_list_pair = tuple_arguments_pair.into_inner().next().unwrap(); let type_use_list_pair = parentheses_optional_type_use_list_pair .into_inner() .next() .unwrap(); TupleArguments( type_use_list_pair .into_inner() .map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use)) .collect(), ) } fn build_implements_list(pair: Pair) -> ImplementsList { ImplementsList( pair.into_inner() .map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use)) .collect(), ) } fn build_function_type_modifier(pair: Pair) -> FunctionTypeModifier { let mut inner = pair.into_inner(); if inner.len() == 2 { FunctionTypeModifier::MutRef } else { match inner.next().unwrap().as_rule() { Rule::Cons => FunctionTypeModifier::Cons, Rule::Mut => FunctionTypeModifier::Mut, Rule::Ref => FunctionTypeModifier::Ref, _ => unreachable!(), } } } fn build_parameters(parameters_pair: Pair) -> Parameters { Parameters( parameters_pair .into_inner() .map(|parameter_pair| expect_and_use(parameter_pair, Rule::Parameter, build_parameter)) .collect(), ) } fn build_parameter(parameter_pair: Pair) -> Parameter { let mut inner = parameter_pair.into_inner(); let identifier = expect_and_use(inner.next().unwrap(), Rule::Identifier, build_identifier); let type_use = expect_and_use(inner.next().unwrap(), Rule::TypeUse, build_type_use); Parameter { identifier, type_use, } } fn build_return_type(return_type_pair: Pair) -> ReturnType { let mut inner = return_type_pair.into_inner(); let declared_type = expect_and_use(inner.next().unwrap(), Rule::TypeUse, build_type_use); let references = inner .next() .map(|ref_list_pair| expect_and_use(ref_list_pair, Rule::RefList, build_references)) .unwrap_or_else(References::default); ReturnType { declared_type: Box::new(declared_type), references, } } fn build_references(ref_list_pair: Pair) -> References { let mut inner = ref_list_pair.into_inner(); inner.next().unwrap(); // ref References( inner .map(|identifier_pair| { expect_and_use(identifier_pair, Rule::Identifier, build_identifier) }) .collect(), ) } fn build_compilation_unit(compilation_unit_pair: Pair) -> CompilationUnit { let mut namespace = None; let mut declarations = vec![]; for inner_pair in compilation_unit_pair.into_inner() { match inner_pair.as_rule() { Rule::Namespace => { namespace = Some(build_namespace(inner_pair)); } Rule::ModuleLevelDeclaration => { declarations.push(build_module_level_declaration(inner_pair)); } Rule::EOI => {} _ => unreachable!(), } } CompilationUnit { namespace, declarations, } } fn build_namespace(namespace_pair: Pair) -> FullyQualifiedName { let mut inner = namespace_pair.into_inner(); inner.next(); // ns expect_and_use(inner.next().unwrap(), Rule::FullyQualifiedName, build_fqn) } fn build_module_level_declaration(pair: Pair) -> ModuleLevelDeclaration { let inner_pair = pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::Module => ModuleLevelDeclaration::Module(build_module_declaration(inner_pair)), Rule::Interface => { ModuleLevelDeclaration::Interface(build_interface_declaration(inner_pair)) } Rule::Class => ModuleLevelDeclaration::Class(build_class_declaration(inner_pair)), Rule::FunctionDefinition => { ModuleLevelDeclaration::Function(build_function_definition(inner_pair)) } Rule::PlatformFunction => ModuleLevelDeclaration::PlatformFunction( build_platform_function_declaration(inner_pair), ), _ => unreachable!(), } } fn build_interface_level_declaration(declaration_pair: Pair) -> InterfaceLevelDeclaration { let inner_pair = declaration_pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::Module => InterfaceLevelDeclaration::Module(build_module_declaration(inner_pair)), Rule::Interface => { InterfaceLevelDeclaration::Interface(build_interface_declaration(inner_pair)) } Rule::Class => InterfaceLevelDeclaration::Class(build_class_declaration(inner_pair)), Rule::InterfaceFunction => { InterfaceLevelDeclaration::Function(build_interface_function_declaration(inner_pair)) } Rule::InterfaceDefaultFunction => InterfaceLevelDeclaration::Function( build_default_interface_function_declaration(inner_pair), ), Rule::InterfaceOperatorFunction => InterfaceLevelDeclaration::OperatorFunction( build_interface_operator_function_declaration(inner_pair), ), Rule::InterfaceDefaultOperatorFunction => InterfaceLevelDeclaration::OperatorFunction( build_default_interface_operator_function_declaration(inner_pair), ), _ => unreachable!(), } } fn build_class_level_declaration(declaration_pair: Pair) -> ClassLevelDeclaration { let inner_pair = declaration_pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::Module => ClassLevelDeclaration::Module(build_module_declaration(inner_pair)), Rule::Interface => { ClassLevelDeclaration::Interface(build_interface_declaration(inner_pair)) } Rule::Class => ClassLevelDeclaration::Class(build_class_declaration(inner_pair)), Rule::FunctionDefinition => { ClassLevelDeclaration::Function(build_function_definition(inner_pair)) } Rule::OperatorFunctionDefinition => { ClassLevelDeclaration::OperatorFunction(build_operator_function_declaration(inner_pair)) } Rule::PlatformFunction => { ClassLevelDeclaration::PlatformFunction(build_platform_function_declaration(inner_pair)) } Rule::Property => ClassLevelDeclaration::Property(build_property_declaration(inner_pair)), Rule::Field => ClassLevelDeclaration::Field(build_field_declaration(inner_pair)), _ => unreachable!(), } } fn build_module_declaration(module_pair: Pair) -> ModuleDeclaration { let mut is_public = false; let mut identifier = None; let mut declarations = vec![]; for inner_pair in module_pair.into_inner() { match inner_pair.as_rule() { Rule::Pub => { is_public = true; } Rule::Mod => {} Rule::Identifier => { identifier = Some(build_identifier(inner_pair)); } Rule::ModuleLevelDeclaration => { declarations.push(build_module_level_declaration(inner_pair)); } _ => unreachable!(), } } ModuleDeclaration { is_public, identifier: identifier.unwrap(), declarations, } } fn build_interface_declaration(interface_pair: Pair) -> InterfaceDeclaration { let mut is_public = false; let mut identifier = None; let mut generics = None; let mut implements = None; let mut declarations = vec![]; for inner_pair in interface_pair.into_inner() { match inner_pair.as_rule() { Rule::Pub => { is_public = true; } Rule::Int => {} Rule::Identifier => { identifier = Some(build_identifier(inner_pair)); } Rule::GenericParameters => { generics = Some(build_generic_parameters(inner_pair)); } Rule::ImplementsList => { implements = Some(build_implements_list(inner_pair)); } Rule::InterfaceLevelDeclaration => { declarations.push(build_interface_level_declaration(inner_pair)); } _ => unreachable!(), } } InterfaceDeclaration { is_public, identifier: identifier.unwrap(), generics: generics.unwrap_or_else(GenericParameters::default), implements: implements.unwrap_or_else(ImplementsList::default), declarations, } } fn build_class_declaration(class_pair: Pair) -> ClassDeclaration { let mut is_public = false; let mut identifier = None; let mut generics = None; let mut class_constructor = None; let mut implements = None; let mut declarations = vec![]; for inner_pair in class_pair.into_inner() { match inner_pair.as_rule() { Rule::Pub => { is_public = true; } Rule::ClassKw => {} Rule::Identifier => { identifier = Some(build_identifier(inner_pair)); } Rule::GenericParameters => { generics = Some(build_generic_parameters(inner_pair)); } Rule::ClassConstructor => { class_constructor = Some(build_class_constructor(inner_pair)); } Rule::ImplementsList => { implements = Some(build_implements_list(inner_pair)); } Rule::ClassLevelDeclaration => { declarations.push(build_class_level_declaration(inner_pair)); } _ => unreachable!(), } } ClassDeclaration { is_public, identifier: identifier.unwrap(), generics: generics.unwrap_or_else(GenericParameters::default), class_constructor, implements: implements.unwrap_or_else(ImplementsList::default), declarations, } } fn build_function_definition(function_definition_pair: Pair) -> FunctionDefinition { let mut is_public = false; let mut modifier = None; let mut generics = None; let mut identifier = None; let mut parameters = None; let mut return_type = None; let mut body = None; for inner_pair in function_definition_pair.into_inner() { match inner_pair.as_rule() { Rule::Pub => { is_public = true; } Rule::FunctionModifier => { modifier = Some(build_function_modifier(inner_pair)); } Rule::Fn => {} Rule::GenericParameters => { generics = Some(build_generic_parameters(inner_pair)); } Rule::Identifier => { identifier = Some(build_identifier(inner_pair)); } Rule::Parameters => { parameters = Some(build_parameters(inner_pair)); } Rule::ReturnType => { return_type = Some(build_return_type(inner_pair)); } Rule::FunctionBody => { body = Some(build_function_body(inner_pair)); } _ => unreachable!(), } } FunctionDefinition { is_public, modifier, generics: generics.unwrap_or_else(GenericParameters::default), identifier: identifier.unwrap(), parameters: parameters.unwrap(), return_type: return_type.unwrap_or_else(ReturnType::void), body: body.unwrap(), } } fn build_operator_function_declaration( operator_function_pair: Pair, ) -> OperatorFunctionDefinition { todo!() } fn build_platform_function_declaration( platform_function_pair: Pair, ) -> PlatformFunctionDeclaration { todo!() } fn build_interface_function_declaration( interface_function_pair: Pair, ) -> InterfaceFunctionDeclaration { todo!() } fn build_interface_operator_function_declaration( interface_operator_pair: Pair, ) -> InterfaceOperatorFunctionDeclaration { todo!() } fn build_default_interface_function_declaration( default_interface_function_pair: Pair, ) -> InterfaceFunctionDeclaration { todo!() } fn build_default_interface_operator_function_declaration( default_interface_operator_pair: Pair, ) -> InterfaceOperatorFunctionDeclaration { todo!() } fn build_class_constructor(class_constructor_pair: Pair) -> ClassConstructor { ClassConstructor( class_constructor_pair .into_inner() .map(|data_member_pair| { let inner_pair = data_member_pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::Property => build_property_class_constructor_parameter(inner_pair), Rule::Field => build_field_class_constructor_parameter(inner_pair), _ => unreachable!(), } }) .collect(), ) } fn build_function_modifier(modifier_pair: Pair) -> FunctionModifier { let mut inner = modifier_pair.into_inner(); if inner.len() == 2 { FunctionModifier::MutRef } else { match inner.next().unwrap().as_rule() { Rule::Static => FunctionModifier::Static, Rule::Cons => FunctionModifier::Cons, Rule::Mut => FunctionModifier::Mut, Rule::Ref => FunctionModifier::Ref, _ => unreachable!(), } } } fn build_function_body(body_pair: Pair) -> FunctionBody { let inner_pair = body_pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::FunctionEqualsBody => FunctionBody::Equals(expect_and_use( inner_pair.into_inner().next().unwrap(), Rule::Expression, build_expression, )), Rule::BlockStatement => FunctionBody::Block(build_block_statement(inner_pair)), Rule::FunctionAliasBody => { let mut alias_body_pairs = inner_pair.into_inner(); alias_body_pairs.next().unwrap(); // Alias FunctionBody::Alias(expect_and_use( alias_body_pairs.next().unwrap(), Rule::Identifier, build_identifier, )) } _ => unreachable!(), } } fn build_property_class_constructor_parameter( property_pair: Pair, ) -> ClassConstructorParameter { ClassConstructorParameter::Property(build_property_declaration(property_pair)) } fn build_field_class_constructor_parameter(field_pair: Pair) -> ClassConstructorParameter { ClassConstructorParameter::Field(build_field_declaration(field_pair)) } fn build_property_declaration(property_declaration_pair: Pair) -> PropertyDeclaration { let mut is_mutable = false; let mut identifier = None; let mut declared_type = None; for inner_pair in property_declaration_pair.into_inner() { match inner_pair.as_rule() { Rule::Mut => { is_mutable = true; } Rule::Identifier => { identifier = Some(build_identifier(inner_pair)); } Rule::TypeUse => { declared_type = Some(build_type_use(inner_pair)); } _ => unreachable!(), } } PropertyDeclaration { is_mutable, identifier: identifier.unwrap(), declared_type: declared_type.unwrap(), } } fn build_field_declaration(field_pair: Pair) -> FieldDeclaration { let mut is_mutable = false; let mut identifier = None; let mut declared_type = None; for inner_pair in field_pair.into_inner() { match inner_pair.as_rule() { Rule::Mut => { is_mutable = true; } Rule::Fld => {} Rule::Identifier => { identifier = Some(build_identifier(inner_pair)); } Rule::TypeUse => { declared_type = Some(build_type_use(inner_pair)); } _ => unreachable!(), } } FieldDeclaration { is_mutable, identifier: identifier.unwrap(), declared_type: declared_type.unwrap(), } } fn build_block_statement(block_statement_pair: Pair) -> BlockStatement { let mut statements = vec![]; let mut expression = None; for inner_pair in block_statement_pair.into_inner() { match inner_pair.as_rule() { Rule::Statement => { statements.push(build_statement(inner_pair)); } Rule::Expression => { expression = Some(build_expression(inner_pair)); } _ => unreachable!(), } } BlockStatement { statements, expression, } } fn build_statement(statement_pair: Pair) -> Statement { let first = statement_pair.into_inner().next().unwrap(); match first.as_rule() { Rule::BlockStatement => Statement::BlockStatement(build_block_statement(first)), Rule::VariableDeclaration => { Statement::VariableDeclarationStatement(build_variable_declaration(first)) } Rule::AssignmentStatement => Statement::AssignStatement(build_assignment_statement(first)), Rule::CallStatement => Statement::CallStatement(build_call_statement(first)), Rule::ReturnStatement => Statement::ReturnStatement(build_return_statement(first)), Rule::IfStatement => Statement::IfStatement(build_if_statement(first)), Rule::IfElseStatement => Statement::IfElseStatement(build_if_else_statement(first)), Rule::WhileStatement => Statement::WhileStatement(build_while_statement(first)), Rule::ForStatement => Statement::ForStatement(build_for_statement(first)), _ => unreachable!(), } } fn build_variable_declaration( variable_declaration_pair: Pair, ) -> VariableDeclarationStatement { let mut is_mutable = false; let mut identifier = None; let mut declared_type = None; let mut initializer = None; for inner_pair in variable_declaration_pair.into_inner() { match inner_pair.as_rule() { Rule::Let => {} Rule::Mut => { is_mutable = true; } Rule::Identifier => { identifier = Some(build_identifier(inner_pair)); } Rule::TypeUse => { declared_type = Some(build_type_use(inner_pair)); } Rule::Expression => { initializer = Some(build_expression(inner_pair)); } _ => unreachable!(), } } VariableDeclarationStatement { is_mutable, identifier: identifier.unwrap(), declared_type, initializer, } } fn build_assignment_statement(assignment_pair: Pair) -> AssignStatement { let mut inner = assignment_pair.into_inner(); let lhs = build_expression(inner.next().unwrap()); let rhs = build_expression(inner.next().unwrap()); AssignStatement { lhs, rhs } } fn build_call_statement(call_statement_pair: Pair) -> CallStatement { let mut inner = call_statement_pair.into_inner(); let mut result = expect_and_use( inner.next().unwrap(), Rule::PrimaryExpression, build_primary_expression, ); while let Some(inner_pair) = inner.next() { match inner_pair.as_rule() { Rule::ObjectAccess => { result = Expression::ObjectAccess(build_object_access(result, inner_pair)); } Rule::ParenthesesCall => { result = Expression::Call(build_call_expression(result, inner_pair)); } Rule::PlusPlus => { result = Expression::UnarySuffix(SuffixExpression { expression: Box::new(result), operator: SuffixUnaryOperator::PlusPlus, }); } Rule::MinusMinus => { result = Expression::UnarySuffix(SuffixExpression { expression: Box::new(result), operator: SuffixUnaryOperator::MinusMinus, }); } _ => unreachable!(), } } CallStatement(result) } fn build_return_statement(return_statement_pair: Pair) -> ReturnStatement { todo!() } fn build_if_statement(if_statement_pair: Pair) -> IfStatement { todo!() } fn build_if_else_statement(if_else_statement_pair: Pair) -> IfElseStatement { todo!() } fn build_while_statement(while_statement_pair: Pair) -> WhileStatement { todo!() } fn build_for_statement(for_statement_pair: Pair) -> ForStatement { todo!() } fn build_expression(expression_pair: Pair) -> Expression { expect_and_use( expression_pair.into_inner().next().unwrap(), Rule::TernaryExpression, build_ternary_expression, ) } fn build_ternary_expression(ternary_pair: Pair) -> Expression { let mut inner = ternary_pair.into_inner(); if inner.len() == 3 { let condition = expect_and_use( inner.next().unwrap(), Rule::OrExpression, build_or_expression, ); let true_expression = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression); let false_expression = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression); Expression::Ternary(TernaryExpression { condition: Box::new(condition), true_expression: Box::new(true_expression), false_expression: Box::new(false_expression), }) } else { expect_and_use( inner.next().unwrap(), Rule::OrExpression, build_or_expression, ) } } macro_rules! build_binary_expression { ( $pair:ident, $left_rule:expr, $left_fn:expr, $( $pat:pat => $arm:expr ),* $(,)? ) => {{ let mut inner: Pairs = $pair.into_inner(); if inner.len() == 3 { let left = expect_and_use(inner.next().unwrap(), $left_rule, $left_fn); let op = inner.next().unwrap(); // op let right = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression); Expression::Binary(BinaryExpression { left: Box::new(left), operator: match op.as_rule() { $( $pat => $arm, )* _ => unreachable!(), }, right: Box::new(right), }) } else { expect_and_use(inner.next().unwrap(), $left_rule, $left_fn) } }}; } fn build_or_expression(or_expression_pair: Pair) -> Expression { build_binary_expression!( or_expression_pair, Rule::AndExpression, build_and_expression, Rule::Or => BinaryOperator::Or, ) } fn build_and_expression(and_expression_pair: Pair) -> Expression { build_binary_expression!( and_expression_pair, Rule::ComparisonExpression, build_comparison_expression, Rule::And => BinaryOperator::And, ) } fn build_comparison_expression(comparison_expression_pair: Pair) -> Expression { build_binary_expression!( comparison_expression_pair, Rule::ShiftExpression, build_shift_expression, Rule::Greater => BinaryOperator::Greater, Rule::Less => BinaryOperator::Less, Rule::GreaterEqual => BinaryOperator::GreaterEqual, Rule::LessEqual => BinaryOperator::LessEqual, Rule::EqualTo => BinaryOperator::EqualTo, Rule::NotEqualTo => BinaryOperator::NotEqualTo, ) } fn build_shift_expression(shift_expression_pair: Pair) -> Expression { build_binary_expression!( shift_expression_pair, Rule::AdditiveExpression, build_additive_expression, Rule::LeftShift => BinaryOperator::LeftShift, Rule::RightShift => BinaryOperator::RightShift, ) } fn build_additive_expression(add_expression_pair: Pair) -> Expression { build_binary_expression!( add_expression_pair, Rule::MultiplicativeExpression, build_multiplicative_expression, Rule::Add => BinaryOperator::Add, Rule::Subtract => BinaryOperator::Subtract, ) } fn build_multiplicative_expression(multiplicative_expression_pair: Pair) -> Expression { build_binary_expression!( multiplicative_expression_pair, Rule::PrefixExpression, build_prefix_expression, Rule::Multiply => BinaryOperator::Multiply, Rule::Divide => BinaryOperator::Divide, ) } fn build_prefix_expression(prefix_pair: Pair) -> Expression { let mut inner_rev = prefix_pair.into_inner().rev(); let mut result = expect_and_use( inner_rev.next().unwrap(), Rule::SuffixExpression, build_suffix_expression, ); while let Some(prefix_pair) = inner_rev.next() { match prefix_pair.as_rule() { Rule::Spread => { result = Expression::UnaryPrefix(PrefixExpression { operator: PrefixUnaryOperator::Spread, expression: Box::new(result), }); } Rule::BorrowMut => { result = Expression::UnaryPrefix(PrefixExpression { operator: PrefixUnaryOperator::BorrowMut, expression: Box::new(result), }) } Rule::Borrow => { result = Expression::UnaryPrefix(PrefixExpression { operator: PrefixUnaryOperator::Borrow, expression: Box::new(result), }) } Rule::Mut => { result = Expression::UnaryPrefix(PrefixExpression { operator: PrefixUnaryOperator::Mut, expression: Box::new(result), }) } Rule::Not => { result = Expression::UnaryPrefix(PrefixExpression { operator: PrefixUnaryOperator::Not, expression: Box::new(result), }) } Rule::Negative => { result = Expression::UnaryPrefix(PrefixExpression { operator: PrefixUnaryOperator::Negative, expression: Box::new(result), }) } _ => unreachable!(), } } result } fn build_suffix_expression(suffix_pair: Pair) -> Expression { let mut inner = suffix_pair.into_inner(); let mut result = expect_and_use( inner.next().unwrap(), Rule::PrimaryExpression, build_primary_expression, ); while let Some(suffix_pair) = inner.next() { match suffix_pair.as_rule() { Rule::ObjectAccess => { result = Expression::ObjectAccess(build_object_access(result, suffix_pair)) } Rule::ParenthesesCall => { result = Expression::Call(build_call_expression(result, suffix_pair)) } Rule::PlusPlus => { result = Expression::UnarySuffix(SuffixExpression { expression: Box::new(result), operator: SuffixUnaryOperator::PlusPlus, }) } Rule::MinusMinus => { result = Expression::UnarySuffix(SuffixExpression { expression: Box::new(result), operator: SuffixUnaryOperator::MinusMinus, }) } _ => unreachable!(), } } result } fn build_call_expression(callee: Expression, parentheses_call_pair: Pair) -> CallExpression { let mut turbo_fish = None; let mut arguments = vec![]; for inner_pair in parentheses_call_pair.into_inner() { match inner_pair.as_rule() { Rule::TurboFish => { turbo_fish = Some(build_turbo_fish(inner_pair)); } Rule::ExpressionList => { for expression_pair in inner_pair.into_inner() { arguments.push(expect_and_use( expression_pair, Rule::Expression, build_expression, )); } } Rule::Closure => { arguments.push(Expression::Closure(build_closure(inner_pair))); } _ => unreachable!(), } } CallExpression { callee: Box::new(callee), turbo_fish, arguments: CallArguments( arguments .into_iter() .map(|argument| CallArgument(Box::new(argument))) .collect(), ), } } fn build_turbo_fish(turbo_fish_pair: Pair) -> TurboFish { TurboFish(build_generic_arguments( turbo_fish_pair.into_inner().next().unwrap(), )) } fn build_primary_expression(primary_expression_pair: Pair) -> Expression { let first_pair = primary_expression_pair.into_inner().next().unwrap(); match first_pair.as_rule() { Rule::Literal => Expression::Literal(build_literal(first_pair)), Rule::FullyQualifiedName => Expression::FullyQualifiedName(build_fqn(first_pair)), Rule::Closure => Expression::Closure(build_closure(first_pair)), Rule::ParenthesizedExpression => { let inner_expression = first_pair.into_inner().next().unwrap(); expect_and_use(inner_expression, Rule::Expression, build_expression) } _ => unreachable!(), } } fn build_object_access(receiver: Expression, navigations_pair: Pair) -> ObjectAccess { ObjectAccess { receiver: Box::new(receiver), navigations: ObjectNavigations( navigations_pair .into_inner() .map(|identifier_pair| { ObjectNavigation::Identifier(Box::new(expect_and_use( identifier_pair, Rule::Identifier, build_identifier, ))) }) .collect(), ), } } fn build_closure(closure_pair: Pair) -> Closure { todo!() } fn build_literal(literal_pair: Pair) -> Literal { let inner_pair = literal_pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::NumberLiteral => build_number_literal(inner_pair), Rule::StringLiteral => build_string_literal(inner_pair), Rule::BooleanLiteral => build_boolean_literal(inner_pair), _ => unreachable!(), } } fn build_number_literal(pair: Pair) -> Literal { todo!() } fn build_string_literal(pair: Pair) -> Literal { let inner_pair = pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::SingleQuoteString => build_single_quote_string(inner_pair), Rule::DoubleQuoteString => build_double_quote_string(inner_pair), Rule::BacktickString => build_backtick_string(inner_pair), _ => unreachable!(), } } fn build_boolean_literal(pair: Pair) -> Literal { let inner_pair = pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::True => Literal::Boolean(true), Rule::False => Literal::Boolean(false), _ => unreachable!(), } } fn build_single_quote_string(pair: Pair) -> Literal { let inner_pair = pair.into_inner().next().unwrap(); Literal::String(inner_pair.as_span().as_str().to_string()) } fn build_double_quote_string(pair: Pair) -> Literal { todo!() } fn build_backtick_string(pair: Pair) -> Literal { todo!() }