Add expression rules and basic left-recursive AST-expression building.

This commit is contained in:
Jesse Brault 2025-05-14 20:07:44 -05:00
parent 487d0383c5
commit 63dec99cb5
3 changed files with 165 additions and 75 deletions

View File

@ -1,16 +1,4 @@
use crate::ast::{ 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};
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 crate::parser::Rule;
use pest::iterators::Pair; use pest::iterators::Pair;
@ -749,7 +737,6 @@ fn build_expression(expression_pair: Pair<Rule>) -> Expression {
let inner_pair = expression_pair.into_inner().next().unwrap(); let inner_pair = expression_pair.into_inner().next().unwrap();
match inner_pair.as_rule() { match inner_pair.as_rule() {
Rule::TernaryExpression => Expression::Ternary(build_ternary_expression(inner_pair)), Rule::TernaryExpression => Expression::Ternary(build_ternary_expression(inner_pair)),
Rule::OrExpression => build_or_expression(inner_pair),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -802,14 +789,93 @@ fn build_multiplicative_expression(multiplicative_expression_pair: Pair<Rule>) -
todo!() todo!()
} }
fn build_unary_expression(unary_expression_pair: Pair<Rule>) -> Expression { fn build_prefix_expression(prefix_pair: Pair<Rule>) -> Expression {
todo!() todo!()
} }
fn build_suffix_expression(suffix_pair: Pair<Rule>) -> 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<Rule>) -> 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<Rule>) -> TurboFish {
TurboFish(build_generic_arguments(turbo_fish_pair.into_inner().next().unwrap()))
}
fn build_primary_expression(primary_expression_pair: Pair<Rule>) -> Expression { fn build_primary_expression(primary_expression_pair: Pair<Rule>) -> Expression {
let mut inner = primary_expression_pair.into_inner(); let first_pair = primary_expression_pair.into_inner().next().unwrap();
let first_pair = inner.next().unwrap(); match first_pair.as_rule() {
let expression = match first_pair.as_rule() {
Rule::Literal => Expression::Literal(build_literal(first_pair)), Rule::Literal => Expression::Literal(build_literal(first_pair)),
Rule::FullyQualifiedName => Expression::FullyQualifiedName(build_fqn(first_pair)), Rule::FullyQualifiedName => Expression::FullyQualifiedName(build_fqn(first_pair)),
Rule::Closure => Expression::Closure(build_closure(first_pair)), Rule::Closure => Expression::Closure(build_closure(first_pair)),
@ -818,11 +884,24 @@ fn build_primary_expression(primary_expression_pair: Pair<Rule>) -> Expression {
expect_and_use(inner_expression, Rule::Expression, build_expression) expect_and_use(inner_expression, Rule::Expression, build_expression)
} }
_ => unreachable!(), _ => unreachable!(),
}; }
if let Some(suffix_pair) = inner.next() { }
todo!()
} else { fn build_object_access(receiver: Expression, navigations_pair: Pair<Rule>) -> ObjectAccess {
expression 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(),
),
} }
} }

View File

@ -194,7 +194,7 @@ impl ReturnType {
pub fn void() -> Self { pub fn void() -> Self {
ReturnType { ReturnType {
declared_type: Box::new(TypeUse::Void), declared_type: Box::new(TypeUse::Void),
references: References::default() references: References::default(),
} }
} }
} }
@ -420,7 +420,7 @@ pub struct AssignStatement {
#[derive(Debug)] #[derive(Debug)]
pub struct CallStatement { pub struct CallStatement {
pub callee: Expression, pub callee: Expression,
pub arguments: CallArguments pub arguments: CallArguments,
} }
#[derive(Debug)] #[derive(Debug)]
@ -462,12 +462,11 @@ pub struct ForStatement {
pub enum Expression { pub enum Expression {
Ternary(TernaryExpression), Ternary(TernaryExpression),
Binary(BinaryExpression), Binary(BinaryExpression),
Unary(UnaryExpression), UnaryPrefix(PrefixExpression),
Call(CallExpression), Suffix(SuffixExpression),
Literal(Literal),
FullyQualifiedName(FullyQualifiedName), FullyQualifiedName(FullyQualifiedName),
Closure(Closure), Closure(Closure),
ObjectAccess(ObjectAccess),
Literal(Literal),
} }
#[derive(Debug)] #[derive(Debug)]
@ -485,18 +484,34 @@ pub struct BinaryExpression {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct UnaryExpression { pub struct PrefixExpression {
pub lhs_operators: Vec<PrefixUnaryOperator>, pub operator: PrefixUnaryOperator,
pub expression: Box<Expression>, pub expression: Box<Expression>,
pub rhs_operators: Vec<SuffixUnaryOperator>, }
#[derive(Debug)]
pub enum SuffixExpression {
Call(CallExpression),
ObjectAccess(ObjectAccess),
Unary(UnarySuffixExpression),
} }
#[derive(Debug)] #[derive(Debug)]
pub struct CallExpression { pub struct CallExpression {
pub callee: Box<Expression>, pub callee: Box<Expression>,
pub turbo_fish: Option<TurboFish>,
pub arguments: CallArguments, pub arguments: CallArguments,
} }
#[derive(Debug)]
pub struct UnarySuffixExpression {
expression: Box<Expression>,
operator: SuffixUnaryOperator,
}
#[derive(Debug)]
pub struct TurboFish(pub GenericArguments);
#[derive(Debug)] #[derive(Debug)]
pub struct CallArguments(pub Vec<CallArgument>); pub struct CallArguments(pub Vec<CallArgument>);
@ -504,14 +519,12 @@ pub struct CallArguments(pub Vec<CallArgument>);
pub struct CallArgument(pub Box<Expression>); pub struct CallArgument(pub Box<Expression>);
#[derive(Debug)] #[derive(Debug)]
pub struct Closure { pub struct Closure {}
}
#[derive(Debug)] #[derive(Debug)]
pub struct ObjectAccess { pub struct ObjectAccess {
pub receiver: Box<Expression>, pub receiver: Box<Expression>,
pub navigations: ObjectNavigations pub navigations: ObjectNavigations,
} }
#[derive(Debug)] #[derive(Debug)]
@ -520,7 +533,7 @@ pub struct ObjectNavigations(pub Vec<ObjectNavigation>);
#[derive(Debug)] #[derive(Debug)]
pub enum ObjectNavigation { pub enum ObjectNavigation {
Index(Box<Expression>), Index(Box<Expression>),
Identifier(Box<Identifier>) Identifier(Box<Identifier>),
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -508,13 +508,15 @@ AssignmentStatement = {
} }
CallStatement = { CallStatement = {
( PrimaryExpression
Literal ~ ObjectAccess?
| FullyQualifiedName ~ ParenthesesCall
| Closure ~ (
| ParenthesizedExpression ObjectAccess
) | ParenthesesCall
~ ( ObjectAccess? ~ ParenthesesCall )+ | PlusPlus
| MinusMinus
)*
} }
ReturnStatement = { ReturnStatement = {
@ -554,16 +556,17 @@ ForStatement = {
// Expressions // Expressions
Expression = { Expression = {
TernaryExpression TernaryExpression
| OrExpression
} }
TernaryExpression = { TernaryExpression = {
( OrExpression | ParenthesizedExpression ) OrExpression
~ "?" ~ (
~ Expression "?"
~ ":" ~ Expression
~ Expression ~ ":"
~ Expression
)?
} }
OrExpression = { OrExpression = {
@ -572,19 +575,14 @@ OrExpression = {
} }
AndExpression = { AndExpression = {
EqualityExpression
~ ( And ~ Expression )?
}
EqualityExpression = {
ComparisonExpression ComparisonExpression
~ ( ( EqualTo | NotEqualTo ) ~ Expression )? ~ ( And ~ Expression )?
} }
ComparisonExpression = { ComparisonExpression = {
AdditiveExpression AdditiveExpression
~ ( ~ (
( Greater | Less | GreaterEqual | LessEqual ) ( Greater | Less | GreaterEqual | LessEqual | EqualTo | NotEqualTo )
~ Expression ~ Expression
)? )?
} }
@ -603,14 +601,14 @@ AdditiveExpression = {
} }
MultiplicativeExpression = { MultiplicativeExpression = {
UnaryExpression PrefixExpression
~ ( ~ (
( Multiply | Divide | Modulo ) ( Multiply | Divide | Modulo )
~ Expression ~ Expression
)? )?
} }
UnaryExpression = { PrefixExpression = {
( (
Spread Spread
| ( Borrow ~ Mut ) | ( Borrow ~ Mut )
@ -619,18 +617,24 @@ UnaryExpression = {
| Not | Not
| Negative | Negative
)* )*
~ PrimaryExpression ~ SuffixExpression
~ ( PlusPlus | MinusMinus )* }
SuffixExpression = {
PrimaryExpression
~ (
ObjectAccess
| ParenthesesCall
| PlusPlus
| MinusMinus
)*
} }
PrimaryExpression = { PrimaryExpression = {
( Literal
Literal | FullyQualifiedName
| FullyQualifiedName | Closure
| Closure | ParenthesizedExpression
| ParenthesizedExpression
)
~ ExpressionSuffix?
} }
ParenthesizedExpression = { ParenthesizedExpression = {
@ -639,12 +643,6 @@ ParenthesizedExpression = {
~ ")" ~ ")"
} }
ExpressionSuffix = {
ObjectAccess
~ ( ParenthesesCall ~ ObjectAccess? )*
| ( ParenthesesCall ~ ObjectAccess? )+
}
ObjectAccess = { ObjectAccess = {
"." "."
~ Identifier ~ Identifier