use crate::ast::{ ClassConstructor, ClassConstructorParameter, ClassDeclaration, ClassLevelDeclaration, CompilationUnit, FieldDeclaration, FullyQualifiedName, FunctionDefinition, FunctionTypeModifier, FunctionTypeUse, GenericArguments, GenericParameter, GenericParameters, Identifier, ImplementsList, InterfaceDeclaration, InterfaceFunctionDeclaration, InterfaceLevelDeclaration, InterfaceOperatorFunctionDeclaration, InterfaceOrClassTypeUse, ModuleDeclaration, ModuleLevelDeclaration, OperatorFunctionDefinition, Parameters, PlatformFunctionDeclaration, PropertyDeclaration, Reference, References, ReturnType, TupleArguments, TupleTypeUse, TypeUse, }; use crate::parser::Rule; use pest::iterators::Pair; 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 { Identifier { name: identifier_pair.as_str().to_string(), } } fn build_fqn(fqn_pair: Pair) -> FullyQualifiedName { FullyQualifiedName( fqn_pair .into_inner() .map(|identifier_pair| { expect_and_use(identifier_pair, Rule::Identifier, build_identifier) }) .collect(), ) } 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::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| { GenericParameter(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(pair: Pair) -> Parameters { todo!() } fn build_parameter(pair: Pair) -> Parameters { todo!() } 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| { Reference(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)); } _ => 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_declaration(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_declaration(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_declaration(function_definition_pair: Pair) -> FunctionDefinition { todo!() } 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_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(), } }