diff --git a/src/ast/build.rs b/src/ast/build.rs index 3e35eec..faf5ed6 100644 --- a/src/ast/build.rs +++ b/src/ast/build.rs @@ -1,12 +1,15 @@ 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, + AssignStatement, BinaryExpression, BinaryOperator, BlockStatement, CallStatement, + ClassConstructor, ClassConstructorParameter, ClassDeclaration, ClassLevelDeclaration, Closure, + CompilationUnit, Expression, FieldDeclaration, ForStatement, FullyQualifiedName, FunctionBody, + FunctionDefinition, FunctionModifier, FunctionTypeModifier, FunctionTypeUse, GenericArguments, + GenericParameter, GenericParameters, Identifier, IfElseStatement, IfStatement, ImplementsList, + InterfaceDeclaration, InterfaceFunctionDeclaration, InterfaceLevelDeclaration, + InterfaceOperatorFunctionDeclaration, InterfaceOrClassTypeUse, Literal, ModuleDeclaration, + ModuleLevelDeclaration, OperatorFunctionDefinition, Parameter, Parameters, + PlatformFunctionDeclaration, PropertyDeclaration, Reference, References, ReturnStatement, + ReturnType, Statement, TernaryExpression, TupleArguments, TupleTypeUse, TypeUse, + VariableDeclarationStatement, WhileStatement, }; use crate::parser::Rule; use pest::iterators::Pair; @@ -42,6 +45,7 @@ fn build_fqn(fqn_pair: Pair) -> FullyQualifiedName { 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)) } @@ -211,12 +215,23 @@ fn build_function_type_modifier(pair: Pair) -> FunctionTypeModifier { } } -fn build_parameters(pair: Pair) -> Parameters { - todo!() +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(pair: Pair) -> Parameters { - todo!() +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 { @@ -289,7 +304,7 @@ fn build_module_level_declaration(pair: Pair) -> ModuleLevelDeclaration { } Rule::Class => ModuleLevelDeclaration::Class(build_class_declaration(inner_pair)), Rule::FunctionDefinition => { - ModuleLevelDeclaration::Function(build_function_declaration(inner_pair)) + ModuleLevelDeclaration::Function(build_function_definition(inner_pair)) } Rule::PlatformFunction => ModuleLevelDeclaration::PlatformFunction( build_platform_function_declaration(inner_pair), @@ -331,7 +346,7 @@ fn build_class_level_declaration(declaration_pair: Pair) -> ClassLevelDecl } Rule::Class => ClassLevelDeclaration::Class(build_class_declaration(inner_pair)), Rule::FunctionDefinition => { - ClassLevelDeclaration::Function(build_function_declaration(inner_pair)) + ClassLevelDeclaration::Function(build_function_definition(inner_pair)) } Rule::OperatorFunctionDefinition => { ClassLevelDeclaration::OperatorFunction(build_operator_function_declaration(inner_pair)) @@ -454,8 +469,52 @@ fn build_class_declaration(class_pair: Pair) -> ClassDeclaration { } } -fn build_function_declaration(function_definition_pair: Pair) -> FunctionDefinition { - todo!() +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( @@ -510,6 +569,43 @@ fn build_class_constructor(class_constructor_pair: Pair) -> ClassConstruct ) } +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 { @@ -574,3 +670,166 @@ fn build_field_declaration(field_pair: Pair) -> FieldDeclaration { 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 { + todo!() +} + +fn build_assignment_statement(assignment_pair: Pair) -> AssignStatement { + todo!() +} + +fn build_call_statement(call_statement_pair: Pair) -> CallStatement { + todo!() +} + +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 { + let inner_pair = expression_pair.into_inner().next().unwrap(); + match inner_pair.as_rule() { + Rule::TernaryExpression => Expression::Ternary(build_ternary_expression(inner_pair)), + Rule::OrExpression => build_or_expression(inner_pair), + _ => unreachable!(), + } +} + +fn build_ternary_expression(ternary_pair: Pair) -> TernaryExpression { + todo!() +} + +fn build_or_expression(or_expression_pair: Pair) -> Expression { + let mut inner = or_expression_pair.into_inner(); + if inner.len() == 3 { + let left = expect_and_use( + inner.next().unwrap(), + Rule::AndExpression, + build_and_expression, + ); + inner.next().unwrap(); // Or + let right = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression); + Expression::Binary(BinaryExpression { + left: Box::new(left), + operator: BinaryOperator::Or, + right: Box::new(right), + }) + } else { + build_and_expression(inner.next().unwrap()) + } +} + +fn build_and_expression(and_expression_pair: Pair) -> Expression { + todo!() +} + +fn build_equality_expression(equality_pair: Pair) -> Expression { + todo!() +} + +fn build_comparison_expression(comparison_expression_pair: Pair) -> Expression { + todo!() +} + +fn build_shift_expression(shift_expression_pair: Pair) -> Expression { + todo!() +} + +fn build_additive_expression(add_expression_pair: Pair) -> Expression { + todo!() +} + +fn build_multiplicative_expression(multiplicative_expression_pair: Pair) -> Expression { + todo!() +} + +fn build_unary_expression(unary_expression_pair: Pair) -> Expression { + todo!() +} + +fn build_primary_expression(primary_expression_pair: Pair) -> Expression { + let mut inner = primary_expression_pair.into_inner(); + let first_pair = inner.next().unwrap(); + let expression = 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!(), + }; + if let Some(suffix_pair) = inner.next() { + todo!() + } else { + expression + } +} + +fn build_literal(literal_pair: Pair) -> Literal { + todo!() +} + +fn build_closure(closure_pair: Pair) -> Closure { + todo!() +} diff --git a/src/ast/mod.rs b/src/ast/mod.rs index d0c333a..bbef193 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -60,6 +60,7 @@ pub struct FullyQualifiedName(pub Vec); #[derive(Debug)] pub enum TypeUse { + Void, InterfaceOrClass(InterfaceOrClassTypeUse), Tuple(TupleTypeUse), Function(FunctionTypeUse), @@ -189,6 +190,17 @@ pub struct ReturnType { pub references: References, } +impl ReturnType { + pub fn void() -> Self { + ReturnType { + declared_type: Box::new(TypeUse::Void), + references: References::default() + } + } +} + +/* References */ + #[derive(Debug)] pub struct References(pub Vec); @@ -373,14 +385,17 @@ pub struct FieldDeclaration { // Statements #[derive(Debug)] -pub struct BlockStatement(pub Vec); +pub struct BlockStatement { + pub statements: Vec, + pub expression: Option, +} #[derive(Debug)] pub enum Statement { BlockStatement(BlockStatement), VariableDeclarationStatement(VariableDeclarationStatement), AssignStatement(AssignStatement), - CallStatement(CallExpression), + CallStatement(CallStatement), ReturnStatement(ReturnStatement), IfStatement(IfStatement), IfElseStatement(IfElseStatement), @@ -397,7 +412,16 @@ pub struct VariableDeclarationStatement { } #[derive(Debug)] -pub struct AssignStatement(pub AssignmentExpression); +pub struct AssignStatement { + pub lhs: Expression, + pub rhs: Expression, +} + +#[derive(Debug)] +pub struct CallStatement { + pub callee: Expression, + pub arguments: CallArguments +} #[derive(Debug)] pub struct ReturnStatement(pub Option); @@ -439,8 +463,10 @@ pub enum Expression { Ternary(TernaryExpression), Binary(BinaryExpression), Unary(UnaryExpression), - Assignment(Box), Call(CallExpression), + FullyQualifiedName(FullyQualifiedName), + Closure(Closure), + ObjectAccess(ObjectAccess), Literal(Literal), } @@ -465,12 +491,6 @@ pub struct UnaryExpression { pub rhs_operators: Vec, } -#[derive(Debug)] -pub struct AssignmentExpression { - identifier: Identifier, - expression: Expression, -} - #[derive(Debug)] pub struct CallExpression { pub callee: Box, @@ -483,6 +503,26 @@ pub struct CallArguments(pub Vec); #[derive(Debug)] pub struct CallArgument(pub Box); +#[derive(Debug)] +pub struct Closure { + +} + +#[derive(Debug)] +pub struct ObjectAccess { + pub receiver: Box, + pub navigations: ObjectNavigations +} + +#[derive(Debug)] +pub struct ObjectNavigations(pub Vec); + +#[derive(Debug)] +pub enum ObjectNavigation { + Index(Box), + Identifier(Box) +} + #[derive(Debug)] pub enum Literal { IntegerLiteral(i32), diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index ec87955..55a4a39 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -27,6 +27,7 @@ While = { "while" } For = { "for" } In = { "in" } Move = { "move" } +Alias = { "alias" } // Keywords as a rule (for preventing identifiers with keywords, etc.) Keyword = { @@ -58,6 +59,7 @@ Keyword = { | For | In | Move + | Alias } // Symbols @@ -168,7 +170,8 @@ ParenthesesOptionalTypeUseList = { // Parameters = declaration TypeUse = { - InterfaceOrClassTypeUse + Void + | InterfaceOrClassTypeUse | TupleTypeUse | FunctionTypeUse } @@ -433,7 +436,7 @@ FunctionEqualsBody = { } FunctionAliasBody = { - "alias" + Alias ~ Identifier } @@ -504,7 +507,15 @@ AssignmentStatement = { ~ Expression } -CallStatement = { PrimaryExpression } +CallStatement = { + ( + Literal + | FullyQualifiedName + | Closure + | ParenthesizedExpression + ) + ~ ( ObjectAccess? ~ ParenthesesCall )+ +} ReturnStatement = { Return diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 7783166..4d20567 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -8,7 +8,7 @@ pub struct DeimosParser; mod deimos_parser_tests { use crate::parser::{DeimosParser, Rule}; use pest::iterators::Pair; - use pest::{parses_to, Parser}; + use pest::{Parser}; macro_rules! fail_rule { ($pair: expr; $rule:path) => {{