deimos-lang/src/ast/build.rs

1127 lines
36 KiB
Rust

use crate::ast::*;
use crate::parser::Rule;
use pest::iterators::{Pair, Pairs};
fn expect_and_use<T>(pair: Pair<Rule>, rule: Rule, f: fn(Pair<Rule>) -> T) -> T {
if pair.as_rule() != rule {
panic!("Expected rule {:?} but found {:?}", rule, pair.as_rule())
}
f(pair)
}
pub fn build_ast(compilation_unit_pair: Pair<Rule>) -> CompilationUnit {
build_compilation_unit(compilation_unit_pair)
}
fn build_identifier(identifier_pair: Pair<Rule>) -> Identifier {
let as_span = identifier_pair.as_span();
Identifier::new(
as_span.as_str(),
Range {
start: as_span.start(),
end: as_span.end(),
},
)
}
fn build_fqn(fqn_pair: Pair<Rule>) -> FullyQualifiedName {
let as_span = fqn_pair.as_span();
FullyQualifiedName::new(
fqn_pair
.into_inner()
.map(|identifier_pair| {
expect_and_use(identifier_pair, Rule::Identifier, build_identifier)
})
.collect(),
Range {
start: as_span.start(),
end: as_span.end(),
},
)
}
fn build_type_use(type_use_pair: Pair<Rule>) -> 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))
}
Rule::TupleTypeUse => TypeUse::Tuple(build_tuple_type_use(inner_pair)),
Rule::FunctionTypeUse => TypeUse::Function(build_function_type_use(inner_pair)),
_ => unreachable!(),
}
}
fn build_interface_or_class_type_use(pair: Pair<Rule>) -> InterfaceOrClassTypeUse {
let mut borrow_count = 0;
let mut is_mutable = false;
let mut fqn = None;
let mut generic_arguments = GenericArguments::default();
for inner_pair in pair.into_inner() {
match inner_pair.as_rule() {
Rule::Borrow => {
borrow_count += 1;
}
Rule::Mut => {
is_mutable = true;
}
Rule::FullyQualifiedName => {
fqn = Some(build_fqn(inner_pair));
}
Rule::GenericArguments => {
generic_arguments = build_generic_arguments(inner_pair);
}
_ => unreachable!(),
}
}
InterfaceOrClassTypeUse {
borrow_count,
is_mutable,
fqn: fqn.unwrap(),
generics: generic_arguments,
}
}
fn build_tuple_type_use(tuple_type_use_pair: Pair<Rule>) -> TupleTypeUse {
let mut borrow_count = 0;
let mut is_mutable = false;
let mut arguments = None;
for inner_pair in tuple_type_use_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Borrow => {
borrow_count += 1;
}
Rule::Mut => {
is_mutable = true;
}
Rule::TupleArguments => {
arguments = Some(build_tuple_arguments(inner_pair));
}
_ => unreachable!(),
}
}
TupleTypeUse {
borrow_count,
is_mutable,
arguments: arguments.unwrap(),
}
}
fn build_function_type_use(function_pair: Pair<Rule>) -> FunctionTypeUse {
let mut borrow_count = 0;
let mut function_modifier: Option<FunctionTypeModifier> = None;
let mut generics = GenericParameters::default();
let mut parameters: Option<Parameters> = None;
let mut return_type: Option<ReturnType> = None;
for inner_pair in function_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Borrow => {
borrow_count += 1;
}
Rule::FunctionTypeModifier => {
function_modifier = Some(build_function_type_modifier(inner_pair));
}
Rule::Fn => {}
Rule::GenericParameters => {
generics = build_generic_parameters(inner_pair);
}
Rule::Parameters => {
parameters = Some(build_parameters(inner_pair));
}
Rule::ReturnType => {
return_type = Some(build_return_type(inner_pair));
}
_ => unreachable!(),
}
}
FunctionTypeUse {
borrow_count,
function_modifier,
generics,
parameters: parameters.unwrap(),
return_type: return_type.unwrap(),
}
}
fn build_generic_arguments(generic_arguments_pair: Pair<Rule>) -> GenericArguments {
let type_use_list_pair = generic_arguments_pair.into_inner().next().unwrap();
GenericArguments(
type_use_list_pair
.into_inner()
.map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use))
.collect(),
)
}
fn build_generic_parameters(generic_parameters_pair: Pair<Rule>) -> GenericParameters {
let identifier_list_pair = generic_parameters_pair.into_inner().next().unwrap();
GenericParameters(
identifier_list_pair
.into_inner()
.map(|identifier_pair| {
expect_and_use(identifier_pair, Rule::Identifier, build_identifier)
})
.collect(),
)
}
fn build_tuple_arguments(tuple_arguments_pair: Pair<Rule>) -> TupleArguments {
let parentheses_optional_type_use_list_pair = tuple_arguments_pair.into_inner().next().unwrap();
let type_use_list_pair = parentheses_optional_type_use_list_pair
.into_inner()
.next()
.unwrap();
TupleArguments(
type_use_list_pair
.into_inner()
.map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use))
.collect(),
)
}
fn build_implements_list(pair: Pair<Rule>) -> ImplementsList {
ImplementsList(
pair.into_inner()
.map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use))
.collect(),
)
}
fn build_function_type_modifier(pair: Pair<Rule>) -> FunctionTypeModifier {
let mut inner = pair.into_inner();
if inner.len() == 2 {
FunctionTypeModifier::MutRef
} else {
match inner.next().unwrap().as_rule() {
Rule::Cons => FunctionTypeModifier::Cons,
Rule::Mut => FunctionTypeModifier::Mut,
Rule::Ref => FunctionTypeModifier::Ref,
_ => unreachable!(),
}
}
}
fn build_parameters(parameters_pair: Pair<Rule>) -> Parameters {
Parameters(
parameters_pair
.into_inner()
.map(|parameter_pair| expect_and_use(parameter_pair, Rule::Parameter, build_parameter))
.collect(),
)
}
fn build_parameter(parameter_pair: Pair<Rule>) -> 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<Rule>) -> ReturnType {
let mut inner = return_type_pair.into_inner();
let declared_type = expect_and_use(inner.next().unwrap(), Rule::TypeUse, build_type_use);
let references = inner
.next()
.map(|ref_list_pair| expect_and_use(ref_list_pair, Rule::RefList, build_references))
.unwrap_or_else(References::default);
ReturnType {
declared_type: Box::new(declared_type),
references,
}
}
fn build_references(ref_list_pair: Pair<Rule>) -> References {
let mut inner = ref_list_pair.into_inner();
inner.next().unwrap(); // ref
References(
inner
.map(|identifier_pair| {
expect_and_use(identifier_pair, Rule::Identifier, build_identifier)
})
.collect(),
)
}
fn build_compilation_unit(compilation_unit_pair: Pair<Rule>) -> CompilationUnit {
let mut namespace = None;
let mut declarations = vec![];
for inner_pair in compilation_unit_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Namespace => {
namespace = Some(build_namespace(inner_pair));
}
Rule::ModuleLevelDeclaration => {
declarations.push(build_module_level_declaration(inner_pair));
}
Rule::EOI => {}
_ => unreachable!(),
}
}
CompilationUnit {
namespace,
declarations,
}
}
fn build_namespace(namespace_pair: Pair<Rule>) -> FullyQualifiedName {
let mut inner = namespace_pair.into_inner();
inner.next(); // ns
expect_and_use(inner.next().unwrap(), Rule::FullyQualifiedName, build_fqn)
}
fn build_module_level_declaration(pair: Pair<Rule>) -> ModuleLevelDeclaration {
let inner_pair = pair.into_inner().next().unwrap();
match inner_pair.as_rule() {
Rule::Module => ModuleLevelDeclaration::Module(build_module_declaration(inner_pair)),
Rule::Interface => {
ModuleLevelDeclaration::Interface(build_interface_declaration(inner_pair))
}
Rule::Class => ModuleLevelDeclaration::Class(build_class_declaration(inner_pair)),
Rule::FunctionDefinition => {
ModuleLevelDeclaration::Function(build_function_definition(inner_pair))
}
Rule::PlatformFunction => ModuleLevelDeclaration::PlatformFunction(
build_platform_function_declaration(inner_pair),
),
_ => unreachable!(),
}
}
fn build_interface_level_declaration(declaration_pair: Pair<Rule>) -> InterfaceLevelDeclaration {
let inner_pair = declaration_pair.into_inner().next().unwrap();
match inner_pair.as_rule() {
Rule::Module => InterfaceLevelDeclaration::Module(build_module_declaration(inner_pair)),
Rule::Interface => {
InterfaceLevelDeclaration::Interface(build_interface_declaration(inner_pair))
}
Rule::Class => InterfaceLevelDeclaration::Class(build_class_declaration(inner_pair)),
Rule::InterfaceFunction => {
InterfaceLevelDeclaration::Function(build_interface_function_declaration(inner_pair))
}
Rule::InterfaceDefaultFunction => InterfaceLevelDeclaration::Function(
build_default_interface_function_declaration(inner_pair),
),
Rule::InterfaceOperatorFunction => InterfaceLevelDeclaration::OperatorFunction(
build_interface_operator_function_declaration(inner_pair),
),
Rule::InterfaceDefaultOperatorFunction => InterfaceLevelDeclaration::OperatorFunction(
build_default_interface_operator_function_declaration(inner_pair),
),
_ => unreachable!(),
}
}
fn build_class_level_declaration(declaration_pair: Pair<Rule>) -> ClassLevelDeclaration {
let inner_pair = declaration_pair.into_inner().next().unwrap();
match inner_pair.as_rule() {
Rule::Module => ClassLevelDeclaration::Module(build_module_declaration(inner_pair)),
Rule::Interface => {
ClassLevelDeclaration::Interface(build_interface_declaration(inner_pair))
}
Rule::Class => ClassLevelDeclaration::Class(build_class_declaration(inner_pair)),
Rule::FunctionDefinition => {
ClassLevelDeclaration::Function(build_function_definition(inner_pair))
}
Rule::OperatorFunctionDefinition => {
ClassLevelDeclaration::OperatorFunction(build_operator_function_declaration(inner_pair))
}
Rule::PlatformFunction => {
ClassLevelDeclaration::PlatformFunction(build_platform_function_declaration(inner_pair))
}
Rule::Property => ClassLevelDeclaration::Property(build_property_declaration(inner_pair)),
Rule::Field => ClassLevelDeclaration::Field(build_field_declaration(inner_pair)),
_ => unreachable!(),
}
}
fn build_module_declaration(module_pair: Pair<Rule>) -> ModuleDeclaration {
let mut is_public = false;
let mut identifier = None;
let mut declarations = vec![];
for inner_pair in module_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Pub => {
is_public = true;
}
Rule::Mod => {}
Rule::Identifier => {
identifier = Some(build_identifier(inner_pair));
}
Rule::ModuleLevelDeclaration => {
declarations.push(build_module_level_declaration(inner_pair));
}
_ => unreachable!(),
}
}
ModuleDeclaration {
is_public,
identifier: identifier.unwrap(),
declarations,
}
}
fn build_interface_declaration(interface_pair: Pair<Rule>) -> InterfaceDeclaration {
let mut is_public = false;
let mut identifier = None;
let mut generics = None;
let mut implements = None;
let mut declarations = vec![];
for inner_pair in interface_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Pub => {
is_public = true;
}
Rule::Int => {}
Rule::Identifier => {
identifier = Some(build_identifier(inner_pair));
}
Rule::GenericParameters => {
generics = Some(build_generic_parameters(inner_pair));
}
Rule::ImplementsList => {
implements = Some(build_implements_list(inner_pair));
}
Rule::InterfaceLevelDeclaration => {
declarations.push(build_interface_level_declaration(inner_pair));
}
_ => unreachable!(),
}
}
InterfaceDeclaration {
is_public,
identifier: identifier.unwrap(),
generics: generics.unwrap_or_else(GenericParameters::default),
implements: implements.unwrap_or_else(ImplementsList::default),
declarations,
}
}
fn build_class_declaration(class_pair: Pair<Rule>) -> ClassDeclaration {
let mut is_public = false;
let mut identifier = None;
let mut generics = None;
let mut class_constructor = None;
let mut implements = None;
let mut declarations = vec![];
for inner_pair in class_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Pub => {
is_public = true;
}
Rule::ClassKw => {}
Rule::Identifier => {
identifier = Some(build_identifier(inner_pair));
}
Rule::GenericParameters => {
generics = Some(build_generic_parameters(inner_pair));
}
Rule::ClassConstructor => {
class_constructor = Some(build_class_constructor(inner_pair));
}
Rule::ImplementsList => {
implements = Some(build_implements_list(inner_pair));
}
Rule::ClassLevelDeclaration => {
declarations.push(build_class_level_declaration(inner_pair));
}
_ => unreachable!(),
}
}
ClassDeclaration {
is_public,
identifier: identifier.unwrap(),
generics: generics.unwrap_or_else(GenericParameters::default),
class_constructor,
implements: implements.unwrap_or_else(ImplementsList::default),
declarations,
}
}
fn build_function_definition(function_definition_pair: Pair<Rule>) -> 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(
operator_function_pair: Pair<Rule>,
) -> OperatorFunctionDefinition {
todo!()
}
fn build_platform_function_declaration(
platform_function_pair: Pair<Rule>,
) -> PlatformFunctionDeclaration {
todo!()
}
fn build_interface_function_declaration(
interface_function_pair: Pair<Rule>,
) -> InterfaceFunctionDeclaration {
todo!()
}
fn build_interface_operator_function_declaration(
interface_operator_pair: Pair<Rule>,
) -> InterfaceOperatorFunctionDeclaration {
todo!()
}
fn build_default_interface_function_declaration(
default_interface_function_pair: Pair<Rule>,
) -> InterfaceFunctionDeclaration {
todo!()
}
fn build_default_interface_operator_function_declaration(
default_interface_operator_pair: Pair<Rule>,
) -> InterfaceOperatorFunctionDeclaration {
todo!()
}
fn build_class_constructor(class_constructor_pair: Pair<Rule>) -> ClassConstructor {
ClassConstructor(
class_constructor_pair
.into_inner()
.map(|data_member_pair| {
let inner_pair = data_member_pair.into_inner().next().unwrap();
match inner_pair.as_rule() {
Rule::Property => build_property_class_constructor_parameter(inner_pair),
Rule::Field => build_field_class_constructor_parameter(inner_pair),
_ => unreachable!(),
}
})
.collect(),
)
}
fn build_function_modifier(modifier_pair: Pair<Rule>) -> 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<Rule>) -> 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<Rule>,
) -> ClassConstructorParameter {
ClassConstructorParameter::Property(build_property_declaration(property_pair))
}
fn build_field_class_constructor_parameter(field_pair: Pair<Rule>) -> ClassConstructorParameter {
ClassConstructorParameter::Field(build_field_declaration(field_pair))
}
fn build_property_declaration(property_declaration_pair: Pair<Rule>) -> PropertyDeclaration {
let mut is_mutable = false;
let mut identifier = None;
let mut declared_type = None;
for inner_pair in property_declaration_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Mut => {
is_mutable = true;
}
Rule::Identifier => {
identifier = Some(build_identifier(inner_pair));
}
Rule::TypeUse => {
declared_type = Some(build_type_use(inner_pair));
}
_ => unreachable!(),
}
}
PropertyDeclaration {
is_mutable,
identifier: identifier.unwrap(),
declared_type: declared_type.unwrap(),
}
}
fn build_field_declaration(field_pair: Pair<Rule>) -> FieldDeclaration {
let mut is_mutable = false;
let mut identifier = None;
let mut declared_type = None;
for inner_pair in field_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Mut => {
is_mutable = true;
}
Rule::Fld => {}
Rule::Identifier => {
identifier = Some(build_identifier(inner_pair));
}
Rule::TypeUse => {
declared_type = Some(build_type_use(inner_pair));
}
_ => unreachable!(),
}
}
FieldDeclaration {
is_mutable,
identifier: identifier.unwrap(),
declared_type: declared_type.unwrap(),
}
}
fn build_block_statement(block_statement_pair: Pair<Rule>) -> 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<Rule>) -> 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<Rule>,
) -> VariableDeclarationStatement {
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 {
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 {
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::ObjectAccess(build_object_access(result, inner_pair));
}
Rule::ParenthesesCall => {
result = Expression::Call(build_call_expression(result, inner_pair));
}
Rule::PlusPlus => {
result = Expression::UnarySuffix(SuffixExpression {
expression: Box::new(result),
operator: SuffixUnaryOperator::PlusPlus,
});
}
Rule::MinusMinus => {
result = Expression::UnarySuffix(SuffixExpression {
expression: Box::new(result),
operator: SuffixUnaryOperator::MinusMinus,
});
}
_ => unreachable!(),
}
}
CallStatement(result)
}
fn build_return_statement(return_statement_pair: Pair<Rule>) -> ReturnStatement {
todo!()
}
fn build_if_statement(if_statement_pair: Pair<Rule>) -> IfStatement {
todo!()
}
fn build_if_else_statement(if_else_statement_pair: Pair<Rule>) -> IfElseStatement {
todo!()
}
fn build_while_statement(while_statement_pair: Pair<Rule>) -> WhileStatement {
todo!()
}
fn build_for_statement(for_statement_pair: Pair<Rule>) -> ForStatement {
todo!()
}
fn build_expression(expression_pair: Pair<Rule>) -> Expression {
expect_and_use(
expression_pair.into_inner().next().unwrap(),
Rule::TernaryExpression,
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,
)
}
}
macro_rules! build_binary_expression {
( $pair:ident, $left_rule:expr, $left_fn:expr, $( $pat:pat => $arm:expr ),* $(,)? ) => {{
let mut inner: Pairs<Rule> = $pair.into_inner();
if inner.len() == 3 {
let left = expect_and_use(inner.next().unwrap(), $left_rule, $left_fn);
let op = inner.next().unwrap(); // op
let right = expect_and_use(inner.next().unwrap(), Rule::Expression, build_expression);
Expression::Binary(BinaryExpression {
left: Box::new(left),
operator: match op.as_rule() {
$( $pat => $arm, )*
_ => unreachable!(),
},
right: Box::new(right),
})
} else {
expect_and_use(inner.next().unwrap(), $left_rule, $left_fn)
}
}};
}
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 {
build_binary_expression!(
and_expression_pair,
Rule::ComparisonExpression,
build_comparison_expression,
Rule::And => BinaryOperator::And,
)
}
fn build_comparison_expression(comparison_expression_pair: Pair<Rule>) -> Expression {
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 {
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 {
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 {
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 {
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 {
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::ObjectAccess(build_object_access(result, suffix_pair))
}
Rule::ParenthesesCall => {
result = Expression::Call(build_call_expression(result, suffix_pair))
}
Rule::PlusPlus => {
result = Expression::UnarySuffix(SuffixExpression {
expression: Box::new(result),
operator: SuffixUnaryOperator::PlusPlus,
})
}
Rule::MinusMinus => {
result = Expression::UnarySuffix(SuffixExpression {
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 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)),
Rule::ParenthesizedExpression => {
let inner_expression = first_pair.into_inner().next().unwrap();
expect_and_use(inner_expression, Rule::Expression, build_expression)
}
_ => unreachable!(),
}
}
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(),
),
}
}
fn build_closure(closure_pair: Pair<Rule>) -> Closure {
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::Boolean(true),
Rule::False => Literal::Boolean(false),
_ => unreachable!(),
}
}
fn build_single_quote_string(pair: Pair<Rule>) -> Literal {
let inner_pair = pair.into_inner().next().unwrap();
Literal::String(inner_pair.as_span().as_str().to_string())
}
fn build_double_quote_string(pair: Pair<Rule>) -> Literal {
todo!()
}
fn build_backtick_string(pair: Pair<Rule>) -> Literal {
todo!()
}