diff --git a/src/ast/build.rs b/src/ast/build.rs index faf5ed6..936dd7a 100644 --- a/src/ast/build.rs +++ b/src/ast/build.rs @@ -1,16 +1,4 @@ -use crate::ast::{ - 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::ast::{AssignStatement, BinaryExpression, BinaryOperator, BlockStatement, CallArgument, CallArguments, CallExpression, 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, ObjectAccess, ObjectNavigation, ObjectNavigations, OperatorFunctionDefinition, Parameter, Parameters, PlatformFunctionDeclaration, PropertyDeclaration, Reference, References, ReturnStatement, ReturnType, Statement, SuffixExpression, SuffixUnaryOperator, TernaryExpression, TupleArguments, TupleTypeUse, TurboFish, TypeUse, UnarySuffixExpression, VariableDeclarationStatement, WhileStatement}; use crate::parser::Rule; use pest::iterators::Pair; @@ -749,7 +737,6 @@ 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!(), } } @@ -802,14 +789,93 @@ fn build_multiplicative_expression(multiplicative_expression_pair: Pair) - todo!() } -fn build_unary_expression(unary_expression_pair: Pair) -> Expression { +fn build_prefix_expression(prefix_pair: Pair) -> Expression { todo!() } +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::Suffix(SuffixExpression::ObjectAccess(build_object_access( + result, + suffix_pair, + ))) + } + Rule::ParenthesesCall => { + result = Expression::Suffix(SuffixExpression::Call(build_call_expression( + result, + suffix_pair, + ))) + } + Rule::PlusPlus => { + result = Expression::Suffix(SuffixExpression::Unary(UnarySuffixExpression { + expression: Box::new(result), + operator: SuffixUnaryOperator::PlusPlus, + })) + } + Rule::MinusMinus => { + result = Expression::Suffix(SuffixExpression::Unary(UnarySuffixExpression { + 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 mut inner = primary_expression_pair.into_inner(); - let first_pair = inner.next().unwrap(); - let expression = match first_pair.as_rule() { + 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)), @@ -818,11 +884,24 @@ fn build_primary_expression(primary_expression_pair: Pair) -> Expression { expect_and_use(inner_expression, Rule::Expression, build_expression) } _ => unreachable!(), - }; - if let Some(suffix_pair) = inner.next() { - todo!() - } else { - expression + } +} + +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(), + ), } } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index bbef193..4557caa 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -194,7 +194,7 @@ impl ReturnType { pub fn void() -> Self { ReturnType { declared_type: Box::new(TypeUse::Void), - references: References::default() + references: References::default(), } } } @@ -420,7 +420,7 @@ pub struct AssignStatement { #[derive(Debug)] pub struct CallStatement { pub callee: Expression, - pub arguments: CallArguments + pub arguments: CallArguments, } #[derive(Debug)] @@ -462,12 +462,11 @@ pub struct ForStatement { pub enum Expression { Ternary(TernaryExpression), Binary(BinaryExpression), - Unary(UnaryExpression), - Call(CallExpression), + UnaryPrefix(PrefixExpression), + Suffix(SuffixExpression), + Literal(Literal), FullyQualifiedName(FullyQualifiedName), Closure(Closure), - ObjectAccess(ObjectAccess), - Literal(Literal), } #[derive(Debug)] @@ -485,18 +484,34 @@ pub struct BinaryExpression { } #[derive(Debug)] -pub struct UnaryExpression { - pub lhs_operators: Vec, +pub struct PrefixExpression { + pub operator: PrefixUnaryOperator, pub expression: Box, - pub rhs_operators: Vec, +} + +#[derive(Debug)] +pub enum SuffixExpression { + Call(CallExpression), + ObjectAccess(ObjectAccess), + Unary(UnarySuffixExpression), } #[derive(Debug)] pub struct CallExpression { pub callee: Box, + pub turbo_fish: Option, pub arguments: CallArguments, } +#[derive(Debug)] +pub struct UnarySuffixExpression { + expression: Box, + operator: SuffixUnaryOperator, +} + +#[derive(Debug)] +pub struct TurboFish(pub GenericArguments); + #[derive(Debug)] pub struct CallArguments(pub Vec); @@ -504,14 +519,12 @@ pub struct CallArguments(pub Vec); pub struct CallArgument(pub Box); #[derive(Debug)] -pub struct Closure { - -} +pub struct Closure {} #[derive(Debug)] pub struct ObjectAccess { pub receiver: Box, - pub navigations: ObjectNavigations + pub navigations: ObjectNavigations, } #[derive(Debug)] @@ -520,7 +533,7 @@ pub struct ObjectNavigations(pub Vec); #[derive(Debug)] pub enum ObjectNavigation { Index(Box), - Identifier(Box) + Identifier(Box), } #[derive(Debug)] diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index 55a4a39..998be4a 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -508,13 +508,15 @@ AssignmentStatement = { } CallStatement = { - ( - Literal - | FullyQualifiedName - | Closure - | ParenthesizedExpression - ) - ~ ( ObjectAccess? ~ ParenthesesCall )+ + PrimaryExpression + ~ ObjectAccess? + ~ ParenthesesCall + ~ ( + ObjectAccess + | ParenthesesCall + | PlusPlus + | MinusMinus + )* } ReturnStatement = { @@ -554,16 +556,17 @@ ForStatement = { // Expressions Expression = { - TernaryExpression - | OrExpression + TernaryExpression } TernaryExpression = { - ( OrExpression | ParenthesizedExpression ) - ~ "?" - ~ Expression - ~ ":" - ~ Expression + OrExpression + ~ ( + "?" + ~ Expression + ~ ":" + ~ Expression + )? } OrExpression = { @@ -572,19 +575,14 @@ OrExpression = { } AndExpression = { - EqualityExpression - ~ ( And ~ Expression )? -} - -EqualityExpression = { ComparisonExpression - ~ ( ( EqualTo | NotEqualTo ) ~ Expression )? + ~ ( And ~ Expression )? } ComparisonExpression = { AdditiveExpression ~ ( - ( Greater | Less | GreaterEqual | LessEqual ) + ( Greater | Less | GreaterEqual | LessEqual | EqualTo | NotEqualTo ) ~ Expression )? } @@ -603,14 +601,14 @@ AdditiveExpression = { } MultiplicativeExpression = { - UnaryExpression + PrefixExpression ~ ( ( Multiply | Divide | Modulo ) ~ Expression )? } -UnaryExpression = { +PrefixExpression = { ( Spread | ( Borrow ~ Mut ) @@ -619,18 +617,24 @@ UnaryExpression = { | Not | Negative )* - ~ PrimaryExpression - ~ ( PlusPlus | MinusMinus )* + ~ SuffixExpression +} + +SuffixExpression = { + PrimaryExpression + ~ ( + ObjectAccess + | ParenthesesCall + | PlusPlus + | MinusMinus + )* } PrimaryExpression = { - ( - Literal - | FullyQualifiedName - | Closure - | ParenthesizedExpression - ) - ~ ExpressionSuffix? + Literal + | FullyQualifiedName + | Closure + | ParenthesizedExpression } ParenthesizedExpression = { @@ -639,12 +643,6 @@ ParenthesizedExpression = { ~ ")" } -ExpressionSuffix = { - ObjectAccess - ~ ( ParenthesesCall ~ ObjectAccess? )* - | ( ParenthesesCall ~ ObjectAccess? )+ -} - ObjectAccess = { "." ~ Identifier