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::{
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<Rule>) -> 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<Rule>) -
todo!()
}
fn build_unary_expression(unary_expression_pair: Pair<Rule>) -> Expression {
fn build_prefix_expression(prefix_pair: Pair<Rule>) -> Expression {
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 {
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<Rule>) -> 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<Rule>) -> 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(),
),
}
}

View File

@ -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<PrefixUnaryOperator>,
pub struct PrefixExpression {
pub operator: PrefixUnaryOperator,
pub expression: Box<Expression>,
pub rhs_operators: Vec<SuffixUnaryOperator>,
}
#[derive(Debug)]
pub enum SuffixExpression {
Call(CallExpression),
ObjectAccess(ObjectAccess),
Unary(UnarySuffixExpression),
}
#[derive(Debug)]
pub struct CallExpression {
pub callee: Box<Expression>,
pub turbo_fish: Option<TurboFish>,
pub arguments: CallArguments,
}
#[derive(Debug)]
pub struct UnarySuffixExpression {
expression: Box<Expression>,
operator: SuffixUnaryOperator,
}
#[derive(Debug)]
pub struct TurboFish(pub GenericArguments);
#[derive(Debug)]
pub struct CallArguments(pub Vec<CallArgument>);
@ -504,14 +519,12 @@ pub struct CallArguments(pub Vec<CallArgument>);
pub struct CallArgument(pub Box<Expression>);
#[derive(Debug)]
pub struct Closure {
}
pub struct Closure {}
#[derive(Debug)]
pub struct ObjectAccess {
pub receiver: Box<Expression>,
pub navigations: ObjectNavigations
pub navigations: ObjectNavigations,
}
#[derive(Debug)]
@ -520,7 +533,7 @@ pub struct ObjectNavigations(pub Vec<ObjectNavigation>);
#[derive(Debug)]
pub enum ObjectNavigation {
Index(Box<Expression>),
Identifier(Box<Identifier>)
Identifier(Box<Identifier>),
}
#[derive(Debug)]

View File

@ -508,13 +508,15 @@ AssignmentStatement = {
}
CallStatement = {
(
Literal
| FullyQualifiedName
| Closure
| ParenthesizedExpression
)
~ ( ObjectAccess? ~ ParenthesesCall )+
PrimaryExpression
~ ObjectAccess?
~ ParenthesesCall
~ (
ObjectAccess
| ParenthesesCall
| PlusPlus
| MinusMinus
)*
}
ReturnStatement = {
@ -555,15 +557,16 @@ ForStatement = {
Expression = {
TernaryExpression
| OrExpression
}
TernaryExpression = {
( OrExpression | ParenthesizedExpression )
~ "?"
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?
}
ParenthesizedExpression = {
@ -639,12 +643,6 @@ ParenthesizedExpression = {
~ ")"
}
ExpressionSuffix = {
ObjectAccess
~ ( ParenthesesCall ~ ObjectAccess? )*
| ( ParenthesesCall ~ ObjectAccess? )+
}
ObjectAccess = {
"."
~ Identifier