use crate::ast::{ BlockStatement, CompilationUnit, Declaration, Fqn, FunctionDeclaration, GenericArgument, GenericParameter, Identifier, ClassConstructor, Parameter, TypeDeclaration, TypeUse, }; use crate::parser::{DeimosParser, Rule}; use crate::vm::source_code_location::SourceCodeLocation; use pest::iterators::Pair; use pest::Parser; fn build_field(field_pair: Pair) -> Declaration { todo!() } fn build_prop(prop_pair: Pair) -> Declaration { todo!() } fn build_generic_argument(generic_argument_pair: Pair) -> GenericArgument { let fqn_pair = generic_argument_pair.into_inner().next().unwrap(); GenericArgument { fqn: build_fqn(fqn_pair), } } fn build_generic_arguments_declaration( generic_arguments_declaration_pair: Pair, ) -> Vec { let mut generic_arguments: Vec = vec![]; for pair in generic_arguments_declaration_pair.into_inner() { match pair.as_rule() { Rule::GenericArguments => { generic_arguments.push(build_generic_argument(pair)); } _ => panic!("Expected only generic_argument rules. Found: {}", pair), } } generic_arguments } fn build_generic_parameter(generic_parameter_pair: Pair) -> GenericParameter { let identifier_pair = generic_parameter_pair.into_inner().next().unwrap(); GenericParameter { identifier: build_identifier(identifier_pair), bound: None, } } fn build_type_use(type_pair: Pair) -> TypeUse { let mut fqn: Option = None; let mut generic_arguments_declaration: Option> = None; for pair in type_pair.into_inner() { match pair.as_rule() { Rule::FullyQualifiedName => { fqn = Some(build_fqn(pair)); } Rule::GenericArguments => { generic_arguments_declaration = Some(build_generic_arguments_declaration(pair)); } _ => panic!( "Expected only fqn or generic_arguments_declaration rules. Found: {}", pair ), } } TypeUse { fqn: fqn.unwrap(), generics: generic_arguments_declaration.unwrap_or(vec![]), } } fn build_generic_parameters_declaration( generic_parameters_declaration_pair: Pair, ) -> Vec { let mut parameters: Vec = vec![]; for pair in generic_parameters_declaration_pair.into_inner() { match pair.as_rule() { Rule::Identifier => { parameters.push(build_generic_parameter(pair)); } _ => panic!("Expected only generic_parameter rule. Found: {}", pair), } } parameters } fn build_extends_list(extends_list_pair: Pair) -> Vec { let mut extensions: Vec = vec![]; for pair in extends_list_pair.into_inner() { match pair.as_rule() { Rule::TypeUse => { extensions.push(build_type_use(pair)); } _ => panic!("Expected only type rule. Found: {}", pair), } } extensions } fn build_interface(is_extern: bool, is_public: bool, interface_pair: Pair) -> Declaration { let mut identifier: Option = None; let mut generic_parameters: Option> = None; let mut extends: Option> = None; let mut declarations: Vec = vec![]; for pair in interface_pair.into_inner() { match pair.as_rule() { Rule::Identifier => { identifier = Some(build_identifier(pair)); } Rule::GenericParameters => { generic_parameters = Some(build_generic_parameters_declaration(pair)); } Rule::ExtendsList => { extends = Some(build_extends_list(pair)); } Rule::InterfaceLevelDeclaration => { declarations.push(build_module_level_declaration(pair)); }, _ => panic!( "Expected only identifier, generics_declaration, extends_list, or declaration rules. Found: {}", pair ) } } Declaration::Interface { identifier: identifier.unwrap(), is_extern, is_public, type_declaration: TypeDeclaration::new( generic_parameters.unwrap_or(vec![]), extends.unwrap_or(vec![]), declarations, ), } } fn build_class_constructor(class_constructor_pair: Pair) -> ClassConstructor { todo!() } fn build_implementation( is_extern: bool, is_public: bool, implementation_pair: Pair, ) -> Declaration { let mut identifier: Option = None; let mut generic_parameters: Option> = None; let mut impl_ctor: Option = None; let mut extends: Option> = None; let mut declarations: Vec = vec![]; for pair in implementation_pair.into_inner() { match pair.as_rule() { Rule::Identifier => { identifier = Some(build_identifier(pair)); } Rule::GenericParameters => { generic_parameters = Some(build_generic_parameters_declaration(pair)); } Rule::ClassConstructor => { impl_ctor = Some(build_class_constructor(pair)); } Rule::ExtendsList => { extends = Some(build_extends_list(pair)); } Rule::ClassLevelDeclaration => { declarations.push(build_module_level_declaration(pair)); } _ => panic!("Unexpected rule: {}", pair), } } Declaration::Implementation { identifier: identifier.unwrap(), is_extern, is_public, type_declaration: TypeDeclaration::new( generic_parameters.unwrap_or(vec![]), extends.unwrap_or(vec![]), declarations, ), impl_ctor, } } fn build_module(is_extern: bool, is_public: bool, pair: Pair) -> Declaration { todo!() } fn build_parameter(pair: Pair) -> Parameter { let mut identifier: Option = None; let mut declared_type: Option = None; for pair in pair.into_inner() { match pair.as_rule() { Rule::Identifier => { identifier = Some(build_identifier(pair)); } Rule::TypeAnnotation => { declared_type = Some(build_type_use(pair)); } _ => unreachable!(), } } Parameter { identifier: identifier.unwrap(), declared_type, } } fn build_parameters_list(pair: Pair) -> Vec { let mut parameters: Vec = vec![]; for pair in pair.into_inner() { match pair.as_rule() { Rule::Parameter => { parameters.push(build_parameter(pair)); } _ => unreachable!(), } } parameters } fn build_block_statement(pair: Pair) -> BlockStatement { todo!() } fn build_function_equals_body(pair: Pair) -> BlockStatement { todo!() } fn build_function(is_extern: bool, is_public: bool, pair: Pair) -> Declaration { let mut is_implementation = false; let mut generic_parameters: Option> = None; let mut identifier: Option = None; let mut parameters: Option> = None; let mut return_type: Option = None; let mut statement: Option = None; let (line, col) = pair.line_col(); for pair in pair.into_inner() { match pair.as_rule() { Rule::Implementation => { is_implementation = true; } Rule::Identifier => { identifier = Some(build_identifier(pair)); } Rule::GenericParameters => { generic_parameters = Some(build_generic_parameters_declaration(pair)); } Rule::Parameters => { parameters = Some(build_parameters_list(pair)); } Rule::TypeUse => { return_type = Some(build_type_use(pair)); } Rule::BlockStatement => { statement = Some(build_block_statement(pair)); } Rule::FunctionEqualsBody => { statement = Some(build_function_equals_body(pair)); } _ => unreachable!(), } } Declaration::Function(FunctionDeclaration { is_extern, is_public, identifier: identifier.unwrap(), parameters: parameters.unwrap(), declared_type: return_type, block_statement: statement.unwrap(), source_code_location: SourceCodeLocation { source_file_name: "TODO".to_string(), line, col, }, }) } fn build_module_level_declaration(declaration_pair: Pair) -> Declaration { let mut is_extern = false; let mut is_public = false; let mut declaration: Option = None; for pair in declaration_pair.into_inner() { match pair.as_rule() { Rule::Declare => { is_extern = true; } Rule::Public => { is_public = true; } Rule::Interface => { declaration = Some(build_interface(is_extern, is_public, pair)); } Rule::Implementation => { declaration = Some(build_implementation(is_extern, is_public, pair)); } Rule::Module => { declaration = Some(build_module(is_extern, is_public, pair)); } Rule::Function => { declaration = Some(build_function(is_extern, is_public, pair)); } _ => unreachable!(), } } declaration.expect("Expected declaration.") } fn build_identifier(pair: Pair) -> Identifier { match pair.as_rule() { Rule::Identifier => Identifier { name: String::from(pair.as_str()), }, _ => unreachable!(), } } fn build_fqn(fqn_pair: Pair) -> Fqn { let mut identifiers: Vec = vec![]; for pair in fqn_pair.into_inner() { match pair.as_rule() { Rule::Identifier => { identifiers.push(build_identifier(pair)); } _ => unreachable!(), } } Fqn { identifiers } } fn build_compilation_unit(pair: Pair) -> CompilationUnit { let mut namespace: Option = None; let mut declarations: Vec = vec![]; for pair in pair.into_inner() { match pair.as_rule() { Rule::Namespace => { let fqn_pair = pair.into_inner().next().unwrap(); namespace = Some(build_fqn(fqn_pair)); } Rule::ModuleLevelDeclaration => { declarations.push(build_module_level_declaration(pair)); } Rule::EOI => {} // ignore _ => unreachable!(), } } CompilationUnit { namespace, declarations, } } pub fn build_ast(src: &str) -> CompilationUnit { let pair = DeimosParser::parse(Rule::CompilationUnit, src) .expect("Unsuccessful parse.") .next() .expect("Expected compilation_unit."); match pair.as_rule() { Rule::CompilationUnit => build_compilation_unit(pair), _ => panic!("Expected compilation_unit rule."), } }