use crate::ast::{ ClassConstructor, ClassConstructorParameter, ClassDeclaration, ClassLevelDeclaration, CompilationUnit, DelegateOrIdentifier, FieldDeclaration, FullyQualifiedName, FunctionDeclaration, FunctionModifier, FunctionTypeParameters, FunctionTypeUse, GenericArgument, GenericArguments, GenericParameter, GenericParameters, Identifier, ImplementsList, InputArgument, InputArguments, InputParameter, InputParameters, InterfaceDeclaration, InterfaceFunctionDeclaration, InterfaceLevelDeclaration, InterfaceOperatorFunctionDeclaration, InterfaceOrClassTypeUse, ModuleDeclaration, ModuleLevelDeclaration, OperatorFunctionDeclaration, PlatformFunctionDeclaration, PropertyDeclaration, Reference, References, ReturnType, TupleTypeUse, TypeDeclaration, TypeFunctionArguments, TypeGenericArgument, TypeGenericArguments, TypeImplements, TypeImplementsArguments, TypeImplementsList, TypeTupleArgument, TypeTupleArguments, TypeUse, TypeWhereGuard, TypeWhereGuards, VoidOrTypeUse, }; 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 { let mut identifiers: Vec = vec![]; for identifier_pair in fqn_pair.into_inner() { identifiers.push(expect_and_use( identifier_pair, Rule::Identifier, build_identifier, )); } FullyQualifiedName { identifiers } } fn build_type_use(type_use_pair: Pair) -> TypeUse { let mut borrow_count = 0; let mut result = None; for inner_pair in type_use_pair.into_inner() { match inner_pair.as_rule() { Rule::Borrow => { borrow_count += 1; } Rule::InterfaceOrClassTypeUse => { result = Some(TypeUse::InterfaceOrClass( build_interface_or_class_type_use(borrow_count, inner_pair), )); } Rule::TupleTypeUse => { result = Some(TypeUse::Tuple(build_tuple_type_use( borrow_count, inner_pair, ))); } Rule::FunctionTypeUse => { result = Some(TypeUse::Function(build_function_type_use( borrow_count, inner_pair, ))); } _ => unreachable!(), } } result.unwrap() } fn build_interface_or_class_type_use( borrow_count: usize, pair: Pair, ) -> InterfaceOrClassTypeUse { let mut is_mut = false; let mut fqn = None; let mut generic_arguments = GenericArguments(vec![]); for inner_pair in pair.into_inner() { match inner_pair.as_rule() { Rule::Mut => { is_mut = true; } Rule::FullyQualifiedName => { fqn = Some(build_fqn(inner_pair)); } Rule::GenericArguments => { generic_arguments = build_generic_arguments(inner_pair); } _ => unreachable!(), } } InterfaceOrClassTypeUse { borrow_count, is_mut, fqn: fqn.unwrap(), generics: generic_arguments, } } fn build_tuple_type_use(borrow_count: usize, tuple_type_use_pair: Pair) -> TupleTypeUse { let mut is_mut = false; let mut type_uses = vec![]; for inner_pair in tuple_type_use_pair.into_inner() { match inner_pair.as_rule() { Rule::Mut => { is_mut = true; } Rule::TypeUse => { type_uses.push(build_type_use(inner_pair)); } _ => unreachable!(), } } TupleTypeUse { borrow_count, is_mut, type_uses, } } fn build_function_type_use(borrow_count: usize, function_pair: Pair) -> FunctionTypeUse { let mut function_modifier: Option = None; let mut generics: GenericParameters = GenericParameters(vec![]); let mut parameters: Option = None; let mut inputs: InputArguments = InputArguments(vec![]); let mut return_type: Option = None; for inner_pair in function_pair.into_inner() { match inner_pair.as_rule() { Rule::FunctionTypeModifier => { function_modifier = Some(build_function_type_modifier(inner_pair)); } Rule::Fn => {} Rule::GenericParameters => { generics = build_generic_parameters(inner_pair); } Rule::FunctionTypeParameters => { parameters = Some(build_function_type_parameters(inner_pair)); } Rule::FunctionInputArguments => { inputs = build_function_input_arguments(inner_pair); } Rule::ReturnType => { return_type = Some(build_return_type(inner_pair)); } _ => unreachable!(), } } FunctionTypeUse { borrow_count, function_modifier, generics, parameters: parameters.unwrap(), inputs, return_type: return_type.unwrap(), } } fn build_generic_arguments(generic_arguments_pair: Pair) -> GenericArguments { let mut generic_arguments: Vec = vec![]; for generic_argument_pair in generic_arguments_pair.into_inner() { generic_arguments.push(expect_and_use( generic_argument_pair, Rule::FullyQualifiedName, build_generic_argument, )); } GenericArguments(generic_arguments) } fn build_generic_argument(fqn_pair: Pair) -> GenericArgument { GenericArgument { fqn: build_fqn(fqn_pair), } } fn build_generic_parameters(generic_parameters_pair: Pair) -> GenericParameters { GenericParameters( generic_parameters_pair .into_inner() .map(|identifier_pair| { GenericParameter(expect_and_use( identifier_pair, Rule::Identifier, build_identifier, )) }) .collect(), ) } fn build_function_type_parameters( function_type_parameters_pair: Pair, ) -> FunctionTypeParameters { FunctionTypeParameters( function_type_parameters_pair .into_inner() .map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use)) .collect(), ) } fn build_function_input_arguments(pair: Pair) -> InputArguments { InputArguments( pair.into_inner() .map(|function_input_argument_pair| { let mut inner = function_input_argument_pair.into_inner(); let lhs_pair = inner.next().unwrap(); let lhs = match lhs_pair.as_rule() { Rule::Delegate => DelegateOrIdentifier::Delegate, Rule::Identifier => { DelegateOrIdentifier::Identifier(build_identifier(lhs_pair)) } _ => unreachable!(), }; let rhs = build_identifier(inner.next().unwrap()); InputArgument { lhs, rhs } }) .collect(), ) } fn build_function_type_modifier(function_type_modifier_pair: Pair) -> FunctionModifier { let mut inner = function_type_modifier_pair.into_inner(); if inner.len() == 2 { FunctionModifier::MutRef } else { match inner.next().unwrap().as_rule() { Rule::Cons => FunctionModifier::Cons, Rule::Mut => FunctionModifier::Mut, Rule::Ref => FunctionModifier::Ref, _ => unreachable!(), } } } fn build_return_type(return_type_pair: Pair) -> ReturnType { let mut inner = return_type_pair.into_inner(); let declared_type_pair = inner.next().unwrap(); let declared_type = match declared_type_pair.as_rule() { Rule::Void => VoidOrTypeUse::Void, Rule::TypeUse => VoidOrTypeUse::TypeUse(Box::new(build_type_use(declared_type_pair))), _ => unreachable!(), }; let references = inner .next() .map(|ref_list_pair| expect_and_use(ref_list_pair, Rule::RefList, build_references)) .unwrap_or(References(vec![])); ReturnType { declared_type, references, } } fn build_references(ref_list_pair: Pair) -> References { let mut identifiers: Vec = vec![]; for pair in ref_list_pair.into_inner() { match pair.as_rule() { Rule::Ref => {} Rule::Identifier => { identifiers.push(build_identifier(pair)); } _ => unreachable!(), } } References( identifiers .into_iter() .map(|identifier| Reference(identifier)) .collect(), ) } fn build_input_parameters(pair: Pair) -> InputParameters { InputParameters( pair.into_inner() .map(|type_use_pair| { InputParameter(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_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 build_fqn(inner.next().unwrap()) } fn build_module_level_declaration(pair: Pair) -> ModuleLevelDeclaration { let inner_pair = pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::Type => ModuleLevelDeclaration::Type(build_type_declaration(inner_pair)), 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::Type => InterfaceLevelDeclaration::Type(build_type_declaration(inner_pair)), 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::Type => ClassLevelDeclaration::Type(build_type_declaration(inner_pair)), 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 = GenericParameters(vec![]); let mut inputs = InputParameters(vec![]); let mut return_type = None; let mut implements = ImplementsList(vec![]); 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 = build_generic_parameters(inner_pair); } Rule::InputParameters => { inputs = build_input_parameters(inner_pair); } Rule::ReturnType => { return_type = Some(build_return_type(inner_pair)); } Rule::ImplementsList => { implements = build_implements_list(inner_pair); } Rule::InterfaceLevelDeclaration => { declarations.push(build_interface_level_declaration(inner_pair)); } _ => unreachable!(), } } InterfaceDeclaration { is_public, identifier: identifier.unwrap(), generics, inputs, return_type, implements, declarations, } } fn build_class_declaration(class_pair: Pair) -> ClassDeclaration { let mut is_public = false; let mut identifier = None; let mut generics = GenericParameters(vec![]); let mut class_constructor = None; let mut implements = ImplementsList(vec![]); 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 = build_generic_parameters(inner_pair); } Rule::ClassConstructor => { class_constructor = Some(build_class_constructor(inner_pair)); } Rule::ImplementsList => { implements = build_implements_list(inner_pair); } Rule::ClassLevelDeclaration => { declarations.push(build_class_level_declaration(inner_pair)); } _ => unreachable!(), } } ClassDeclaration { is_public, identifier: identifier.unwrap(), generics, class_constructor, implements, declarations, } } fn build_type_declaration(type_pair: Pair) -> TypeDeclaration { let mut is_public = false; let mut identifier = None; let mut lhs = None; let mut where_guards = TypeWhereGuards(vec![]); let mut rhs = None; for inner_pair in type_pair.into_inner() { match inner_pair.as_rule() { Rule::Pub => is_public = true, Rule::TypeKw => {} Rule::Identifier => { identifier = Some(build_identifier(inner_pair)); } Rule::TypeUse => { if lhs.is_none() { lhs = Some(build_type_use(inner_pair)); } else { rhs = Some(build_type_use(inner_pair)); } } Rule::TypeWhereGuards => { where_guards = build_type_where_guards(inner_pair); } _ => unreachable!(), } } TypeDeclaration { is_public, identifier: identifier.unwrap(), lhs: lhs.unwrap(), where_guards, rhs: rhs.unwrap(), } } fn build_type_where_guards(type_where_guards_pair: Pair) -> TypeWhereGuards { let mut inner = type_where_guards_pair.into_inner(); inner.next(); // where TypeWhereGuards( inner .map(|type_where_guard_pair| { expect_and_use( type_where_guard_pair, Rule::TypeWhereGuard, build_type_where_guard, ) }) .collect(), ) } fn build_type_where_guard(type_where_guard_pair: Pair) -> TypeWhereGuard { let mut inner = type_where_guard_pair.into_inner(); let identifier = expect_and_use(inner.next().unwrap(), Rule::Identifier, build_identifier); let implements = expect_and_use( inner.next().unwrap(), Rule::TypeImplementsList, build_type_implements_list, ); TypeWhereGuard { identifier, implements, } } fn build_type_implements_list(type_implements_list_pair: Pair) -> TypeImplementsList { TypeImplementsList( type_implements_list_pair .into_inner() .map(|type_implements_pair| { expect_and_use( type_implements_pair, Rule::TypeImplements, build_type_implements, ) }) .collect(), ) } fn build_type_implements(type_implements_pair: Pair) -> TypeImplements { let mut inner = type_implements_pair.into_inner(); let fqn = expect_and_use(inner.next().unwrap(), Rule::FullyQualifiedName, build_fqn); let arguments = expect_and_use( inner.next().unwrap(), Rule::TypeImplementsArguments, build_type_implements_arguments, ); TypeImplements { fqn, arguments } } fn build_type_implements_arguments( type_implements_arguments_pair: Pair, ) -> TypeImplementsArguments { let inner_pair = type_implements_arguments_pair.into_inner().next().unwrap(); match inner_pair.as_rule() { Rule::TypeGenericArguments => { TypeImplementsArguments::Generic(build_type_generic_arguments(inner_pair)) } Rule::TypeTupleArguments => { TypeImplementsArguments::Tuple(build_type_tuple_arguments(inner_pair)) } Rule::TypeFunctionArguments => { TypeImplementsArguments::Function(build_type_function_arguments(inner_pair)) } _ => unreachable!(), } } fn build_type_generic_arguments(type_generic_arguments_pair: Pair) -> TypeGenericArguments { TypeGenericArguments( type_generic_arguments_pair .into_inner() .map(|type_generic_argument_pair| { expect_and_use( type_generic_argument_pair, Rule::TypeGenericArgument, build_type_generic_argument, ) }) .collect(), ) } fn build_type_generic_argument(type_generic_argument_pair: Pair) -> TypeGenericArgument { let mut inner = type_generic_argument_pair.into_inner(); if inner.len() == 2 { inner.next(); // infer TypeGenericArgument::Infer(expect_and_use( inner.next().unwrap(), Rule::Identifier, build_identifier, )) } else { let inner_pair = inner.next().unwrap(); match inner_pair.as_rule() { Rule::Underscore => TypeGenericArgument::Underscore, Rule::FullyQualifiedName => { TypeGenericArgument::FullyQualifiedName(build_fqn(inner_pair)) } _ => unreachable!(), } } } fn build_type_tuple_arguments(type_tuple_arguments_pair: Pair) -> TypeTupleArguments { TypeTupleArguments( type_tuple_arguments_pair .into_inner() .map(|type_tuple_argument_pair| { expect_and_use( type_tuple_argument_pair, Rule::TypeTupleArgument, build_type_tuple_argument, ) }) .collect(), ) } fn build_type_tuple_argument(type_tuple_argument_pair: Pair) -> TypeTupleArgument { let mut inner = type_tuple_argument_pair.into_inner(); let first = inner.next().unwrap(); match first.as_rule() { Rule::Underscore => TypeTupleArgument::Underscore, Rule::FullyQualifiedName => TypeTupleArgument::FullyQualifiedName(build_fqn(first)), Rule::Infer => { let second = inner.next().unwrap(); TypeTupleArgument::Infer(expect_and_use(second, Rule::Identifier, build_identifier)) } Rule::Ellipsis => { let second = inner.next().unwrap(); match second.as_rule() { Rule::Underscore => TypeTupleArgument::EllipsisUnderscore, Rule::Infer => TypeTupleArgument::EllipsisInfer(expect_and_use( inner.next().unwrap(), Rule::Identifier, build_identifier, )), _ => unreachable!(), } } _ => unreachable!(), } } fn build_type_function_arguments( type_function_arguments_pair: Pair, ) -> TypeFunctionArguments { let mut generics = TypeGenericArguments(vec![]); let mut parameters = None; let mut return_type = None; for inner_pair in type_function_arguments_pair.into_inner() { match inner_pair.as_rule() { Rule::TypeGenericArguments => { generics = build_type_generic_arguments(inner_pair); } Rule::TypeTupleArguments => { parameters = Some(build_type_tuple_arguments(inner_pair)); } Rule::ReturnType => { return_type = Some(build_return_type(inner_pair)); } _ => unreachable!(), } } TypeFunctionArguments { generics, parameters: parameters.unwrap(), return_type: return_type.unwrap(), } } fn build_function_declaration(function_definition_pair: Pair) -> FunctionDeclaration { todo!() } fn build_operator_function_declaration( operator_function_pair: Pair, ) -> OperatorFunctionDeclaration { 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(), } }