Enough work to hopefully make hello world parse and build AST.

This commit is contained in:
Jesse Brault 2025-05-15 08:13:34 -05:00
parent 63dec99cb5
commit e3dc46e023
3 changed files with 335 additions and 55 deletions

View File

@ -1,6 +1,20 @@
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::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, PrefixExpression, PrefixUnaryOperator, PropertyDeclaration,
Reference, References, ReturnStatement, ReturnType, Statement, SuffixExpression,
SuffixUnaryOperator, TernaryExpression, TupleArguments, TupleTypeUse, TurboFish, TypeUse,
UnarySuffixExpression, VariableDeclarationStatement, WhileStatement,
};
use crate::parser::Rule; use crate::parser::Rule;
use pest::iterators::Pair; use pest::iterators::{Pair, Pairs};
fn expect_and_use<T>(pair: Pair<Rule>, rule: Rule, f: fn(Pair<Rule>) -> T) -> T { fn expect_and_use<T>(pair: Pair<Rule>, rule: Rule, f: fn(Pair<Rule>) -> T) -> T {
if pair.as_rule() != rule { if pair.as_rule() != rule {
@ -702,15 +716,82 @@ fn build_statement(statement_pair: Pair<Rule>) -> Statement {
fn build_variable_declaration( fn build_variable_declaration(
variable_declaration_pair: Pair<Rule>, variable_declaration_pair: Pair<Rule>,
) -> VariableDeclarationStatement { ) -> VariableDeclarationStatement {
todo!() let mut is_mutable = false;
let mut identifier = None;
let mut declared_type = None;
let mut initializer = None;
for inner_pair in variable_declaration_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Let => {}
Rule::Mut => {
is_mutable = true;
}
Rule::Identifier => {
identifier = Some(build_identifier(inner_pair));
}
Rule::TypeUse => {
declared_type = Some(build_type_use(inner_pair));
}
Rule::Expression => {
initializer = Some(build_expression(inner_pair));
}
_ => unreachable!(),
}
}
VariableDeclarationStatement {
is_mutable,
identifier: identifier.unwrap(),
declared_type,
initializer,
}
} }
fn build_assignment_statement(assignment_pair: Pair<Rule>) -> AssignStatement { fn build_assignment_statement(assignment_pair: Pair<Rule>) -> AssignStatement {
todo!() let mut inner = assignment_pair.into_inner();
let lhs = build_expression(inner.next().unwrap());
let rhs = build_expression(inner.next().unwrap());
AssignStatement { lhs, rhs }
} }
fn build_call_statement(call_statement_pair: Pair<Rule>) -> CallStatement { fn build_call_statement(call_statement_pair: Pair<Rule>) -> CallStatement {
todo!() let mut inner = call_statement_pair.into_inner();
let mut result = expect_and_use(
inner.next().unwrap(),
Rule::PrimaryExpression,
build_primary_expression,
);
while let Some(inner_pair) = inner.next() {
match inner_pair.as_rule() {
Rule::ObjectAccess => {
result = Expression::Suffix(SuffixExpression::ObjectAccess(build_object_access(
result, inner_pair,
)));
}
Rule::ParenthesesCall => {
result = Expression::Suffix(SuffixExpression::Call(build_call_expression(
result, inner_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!(),
}
}
CallStatement(result)
} }
fn build_return_statement(return_statement_pair: Pair<Rule>) -> ReturnStatement { fn build_return_statement(return_statement_pair: Pair<Rule>) -> ReturnStatement {
@ -734,63 +815,171 @@ fn build_for_statement(for_statement_pair: Pair<Rule>) -> ForStatement {
} }
fn build_expression(expression_pair: Pair<Rule>) -> Expression { fn build_expression(expression_pair: Pair<Rule>) -> Expression {
let inner_pair = expression_pair.into_inner().next().unwrap(); expect_and_use(
match inner_pair.as_rule() { expression_pair.into_inner().next().unwrap(),
Rule::TernaryExpression => Expression::Ternary(build_ternary_expression(inner_pair)), Rule::TernaryExpression,
_ => unreachable!(), build_ternary_expression,
)
}
fn build_ternary_expression(ternary_pair: Pair<Rule>) -> Expression {
let mut inner = ternary_pair.into_inner();
if inner.len() == 3 {
let condition = expect_and_use(
inner.next().unwrap(),
Rule::OrExpression,
build_or_expression,
);
let true_expression =
expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression);
let false_expression =
expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression);
Expression::Ternary(TernaryExpression {
condition: Box::new(condition),
true_expression: Box::new(true_expression),
false_expression: Box::new(false_expression),
})
} else {
expect_and_use(
inner.next().unwrap(),
Rule::OrExpression,
build_or_expression,
)
} }
} }
fn build_ternary_expression(ternary_pair: Pair<Rule>) -> TernaryExpression { macro_rules! build_binary_expression {
todo!() ( $pair:ident, $left_rule:expr, $left_fn:expr, $( $pat:pat => $arm:expr ),* $(,)? ) => {{
} let mut inner: Pairs<Rule> = $pair.into_inner();
fn build_or_expression(or_expression_pair: Pair<Rule>) -> Expression {
let mut inner = or_expression_pair.into_inner();
if inner.len() == 3 { if inner.len() == 3 {
let left = expect_and_use( let left = expect_and_use(inner.next().unwrap(), $left_rule, $left_fn);
inner.next().unwrap(), let op = inner.next().unwrap(); // op
Rule::AndExpression,
build_and_expression,
);
inner.next().unwrap(); // Or
let right = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression); let right = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression);
Expression::Binary(BinaryExpression { Expression::Binary(BinaryExpression {
left: Box::new(left), left: Box::new(left),
operator: BinaryOperator::Or, operator: match op.as_rule() {
$( $pat => $arm, )*
_ => unreachable!(),
},
right: Box::new(right), right: Box::new(right),
}) })
} else { } else {
build_and_expression(inner.next().unwrap()) $left_fn(inner.next().unwrap())
} }
}};
}
fn build_or_expression(or_expression_pair: Pair<Rule>) -> Expression {
build_binary_expression!(
or_expression_pair,
Rule::AndExpression,
build_and_expression,
Rule::Or => BinaryOperator::Or,
)
} }
fn build_and_expression(and_expression_pair: Pair<Rule>) -> Expression { fn build_and_expression(and_expression_pair: Pair<Rule>) -> Expression {
todo!() build_binary_expression!(
} and_expression_pair,
Rule::ComparisonExpression,
fn build_equality_expression(equality_pair: Pair<Rule>) -> Expression { build_comparison_expression,
todo!() Rule::And => BinaryOperator::And,
)
} }
fn build_comparison_expression(comparison_expression_pair: Pair<Rule>) -> Expression { fn build_comparison_expression(comparison_expression_pair: Pair<Rule>) -> Expression {
todo!() build_binary_expression!(
comparison_expression_pair,
Rule::ShiftExpression,
build_shift_expression,
Rule::Greater => BinaryOperator::Greater,
Rule::Less => BinaryOperator::Less,
Rule::GreaterEqual => BinaryOperator::GreaterEqual,
Rule::LessEqual => BinaryOperator::LessEqual,
Rule::EqualTo => BinaryOperator::EqualTo,
Rule::NotEqualTo => BinaryOperator::NotEqualTo,
)
} }
fn build_shift_expression(shift_expression_pair: Pair<Rule>) -> Expression { fn build_shift_expression(shift_expression_pair: Pair<Rule>) -> Expression {
todo!() build_binary_expression!(
shift_expression_pair,
Rule::AdditiveExpression,
build_additive_expression,
Rule::LeftShift => BinaryOperator::LeftShift,
Rule::RightShift => BinaryOperator::RightShift,
)
} }
fn build_additive_expression(add_expression_pair: Pair<Rule>) -> Expression { fn build_additive_expression(add_expression_pair: Pair<Rule>) -> Expression {
todo!() build_binary_expression!(
add_expression_pair,
Rule::MultiplicativeExpression,
build_multiplicative_expression,
Rule::Add => BinaryOperator::Add,
Rule::Subtract => BinaryOperator::Subtract,
)
} }
fn build_multiplicative_expression(multiplicative_expression_pair: Pair<Rule>) -> Expression { fn build_multiplicative_expression(multiplicative_expression_pair: Pair<Rule>) -> Expression {
todo!() build_binary_expression!(
multiplicative_expression_pair,
Rule::PrefixExpression,
build_prefix_expression,
Rule::Multiply => BinaryOperator::Multiply,
Rule::Divide => BinaryOperator::Divide,
)
} }
fn build_prefix_expression(prefix_pair: Pair<Rule>) -> Expression { fn build_prefix_expression(prefix_pair: Pair<Rule>) -> Expression {
todo!() let mut inner_rev = prefix_pair.into_inner().rev();
let mut result = expect_and_use(
inner_rev.next().unwrap(),
Rule::SuffixExpression,
build_suffix_expression,
);
while let Some(prefix_pair) = inner_rev.next() {
match prefix_pair.as_rule() {
Rule::Spread => {
result = Expression::UnaryPrefix(PrefixExpression {
operator: PrefixUnaryOperator::Spread,
expression: Box::new(result),
});
}
Rule::BorrowMut => {
result = Expression::UnaryPrefix(PrefixExpression {
operator: PrefixUnaryOperator::BorrowMut,
expression: Box::new(result),
})
}
Rule::Borrow => {
result = Expression::UnaryPrefix(PrefixExpression {
operator: PrefixUnaryOperator::Borrow,
expression: Box::new(result),
})
}
Rule::Mut => {
result = Expression::UnaryPrefix(PrefixExpression {
operator: PrefixUnaryOperator::Mut,
expression: Box::new(result),
})
}
Rule::Not => {
result = Expression::UnaryPrefix(PrefixExpression {
operator: PrefixUnaryOperator::Not,
expression: Box::new(result),
})
}
Rule::Negative => {
result = Expression::UnaryPrefix(PrefixExpression {
operator: PrefixUnaryOperator::Negative,
expression: Box::new(result),
})
}
_ => unreachable!(),
}
}
result
} }
fn build_suffix_expression(suffix_pair: Pair<Rule>) -> Expression { fn build_suffix_expression(suffix_pair: Pair<Rule>) -> Expression {
@ -870,7 +1059,9 @@ fn build_call_expression(callee: Expression, parentheses_call_pair: Pair<Rule>)
} }
fn build_turbo_fish(turbo_fish_pair: Pair<Rule>) -> TurboFish { fn build_turbo_fish(turbo_fish_pair: Pair<Rule>) -> TurboFish {
TurboFish(build_generic_arguments(turbo_fish_pair.into_inner().next().unwrap())) 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 {
@ -905,10 +1096,52 @@ fn build_object_access(receiver: Expression, navigations_pair: Pair<Rule>) -> Ob
} }
} }
fn build_literal(literal_pair: Pair<Rule>) -> Literal {
todo!()
}
fn build_closure(closure_pair: Pair<Rule>) -> Closure { fn build_closure(closure_pair: Pair<Rule>) -> Closure {
todo!() todo!()
} }
fn build_literal(literal_pair: Pair<Rule>) -> Literal {
let inner_pair = literal_pair.into_inner().next().unwrap();
match inner_pair.as_rule() {
Rule::NumberLiteral => build_number_literal(inner_pair),
Rule::StringLiteral => build_string_literal(inner_pair),
Rule::BooleanLiteral => build_boolean_literal(inner_pair),
_ => unreachable!(),
}
}
fn build_number_literal(pair: Pair<Rule>) -> Literal {
todo!()
}
fn build_string_literal(pair: Pair<Rule>) -> Literal {
let inner_pair = pair.into_inner().next().unwrap();
match inner_pair.as_rule() {
Rule::SingleQuoteString => build_single_quote_string(inner_pair),
Rule::DoubleQuoteString => build_double_quote_string(inner_pair),
Rule::BacktickString => build_backtick_string(inner_pair),
_ => unreachable!(),
}
}
fn build_boolean_literal(pair: Pair<Rule>) -> Literal {
let inner_pair = pair.into_inner().next().unwrap();
match inner_pair.as_rule() {
Rule::True => Literal::BooleanLiteral(true),
Rule::False => Literal::BooleanLiteral(false),
_ => unreachable!(),
}
}
fn build_single_quote_string(pair: Pair<Rule>) -> Literal {
let inner_pair = pair.into_inner().next().unwrap();
Literal::StringLiteral(inner_pair.to_string())
}
fn build_double_quote_string(pair: Pair<Rule>) -> Literal {
todo!()
}
fn build_backtick_string(pair: Pair<Rule>) -> Literal {
todo!()
}

View File

@ -34,8 +34,9 @@ pub enum BinaryOperator {
#[derive(Debug)] #[derive(Debug)]
pub enum PrefixUnaryOperator { pub enum PrefixUnaryOperator {
Spread, Spread,
Borrow,
BorrowMut, BorrowMut,
Borrow,
Mut,
Not, Not,
Negative, Negative,
} }
@ -418,10 +419,7 @@ pub struct AssignStatement {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct CallStatement { pub struct CallStatement(pub Expression);
pub callee: Expression,
pub arguments: CallArguments,
}
#[derive(Debug)] #[derive(Debug)]
pub struct ReturnStatement(pub Option<Expression>); pub struct ReturnStatement(pub Option<Expression>);
@ -472,8 +470,8 @@ pub enum Expression {
#[derive(Debug)] #[derive(Debug)]
pub struct TernaryExpression { pub struct TernaryExpression {
pub condition: Box<Expression>, pub condition: Box<Expression>,
pub true_block: Box<Expression>, pub true_expression: Box<Expression>,
pub false_block: Box<Expression>, pub false_expression: Box<Expression>,
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -28,6 +28,8 @@ For = { "for" }
In = { "in" } In = { "in" }
Move = { "move" } Move = { "move" }
Alias = { "alias" } Alias = { "alias" }
True = { "true" }
False = { "false" }
// Keywords as a rule (for preventing identifiers with keywords, etc.) // Keywords as a rule (for preventing identifiers with keywords, etc.)
Keyword = { Keyword = {
@ -60,6 +62,8 @@ Keyword = {
| In | In
| Move | Move
| Alias | Alias
| True
| False
} }
// Symbols // Symbols
@ -611,7 +615,7 @@ MultiplicativeExpression = {
PrefixExpression = { PrefixExpression = {
( (
Spread Spread
| ( Borrow ~ Mut ) | BorrowMut
| Borrow | Borrow
| Mut | Mut
| Not | Not
@ -620,6 +624,10 @@ PrefixExpression = {
~ SuffixExpression ~ SuffixExpression
} }
BorrowMut = {
Borrow ~ Mut
}
SuffixExpression = { SuffixExpression = {
PrimaryExpression PrimaryExpression
~ ( ~ (
@ -748,16 +756,57 @@ HexadecimalBase = @{ "0x" ~ HexadecimalDigit+ }
HexadecimalDigit = { '0'..'9' | 'a'..'f' } HexadecimalDigit = { '0'..'9' | 'a'..'f' }
StringLiteral = ${ "\"" ~ StringInner ~ "\"" } StringLiteral = {
SingleQuoteString
| DoubleQuoteString
| BacktickString
}
SingleQuoteString = ${ "'" ~ StringInner ~ "'" }
DoubleQuoteString = {
"\""
~ ( DStringInner? ~ DStringExpression )*
~ DStringInner?
~ "\""
}
StringInner = @{ StringChar* } StringInner = @{ StringChar* }
StringChar = { StringChar = {
!( "\"" | "\\" ) ~ ANY !( "\"" | "\\" ) ~ ANY
| "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" ) | "\\" ~ ( "'" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" )
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} ) | "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
} }
BooleanLiteral = { "true" | "false" } DStringInner = @{ DStringChar+ }
DStringChar = {
!( "\"" | "\\" ) ~ ANY
| "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" )
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
}
DStringExpression = {
"$"
~ BlockStatement
}
BacktickString = {
"`"
~ ( DStringInner? ~ DStringExpression )*
~ DStringInner?
~ "`"
}
BacktickInner = @{ BacktickStringChar+ }
BacktickStringChar = {
!( "\"" | "\\" ) ~ ANY
| "\\" ~ ( "`" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" )
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
}
BooleanLiteral = { True | False }
WHITESPACE = _{ " " | "\t" | "\n" | "\r" } WHITESPACE = _{ " " | "\t" | "\n" | "\r" }