375 lines
12 KiB
Rust
375 lines
12 KiB
Rust
use crate::ast::{
|
|
BlockStatement, CompilationUnit, Declaration, Fqn, FunctionDeclaration, GenericArgument,
|
|
GenericParameter, Identifier, ClassConstructor, Parameter, TypeDeclaration, TypeUse,
|
|
};
|
|
use crate::parser::{DeimosParser, Rule};
|
|
use crate::vm::source_code_location::SourceCodeLocation;
|
|
use pest::iterators::Pair;
|
|
use pest::Parser;
|
|
|
|
fn build_field(field_pair: Pair<Rule>) -> Declaration {
|
|
todo!()
|
|
}
|
|
|
|
fn build_prop(prop_pair: Pair<Rule>) -> Declaration {
|
|
todo!()
|
|
}
|
|
|
|
fn build_generic_argument(generic_argument_pair: Pair<Rule>) -> GenericArgument {
|
|
let fqn_pair = generic_argument_pair.into_inner().next().unwrap();
|
|
GenericArgument {
|
|
fqn: build_fqn(fqn_pair),
|
|
}
|
|
}
|
|
|
|
fn build_generic_arguments_declaration(
|
|
generic_arguments_declaration_pair: Pair<Rule>,
|
|
) -> Vec<GenericArgument> {
|
|
let mut generic_arguments: Vec<GenericArgument> = vec![];
|
|
for pair in generic_arguments_declaration_pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::GenericArguments => {
|
|
generic_arguments.push(build_generic_argument(pair));
|
|
}
|
|
_ => panic!("Expected only generic_argument rules. Found: {}", pair),
|
|
}
|
|
}
|
|
generic_arguments
|
|
}
|
|
|
|
fn build_generic_parameter(generic_parameter_pair: Pair<Rule>) -> GenericParameter {
|
|
let identifier_pair = generic_parameter_pair.into_inner().next().unwrap();
|
|
GenericParameter {
|
|
identifier: build_identifier(identifier_pair),
|
|
bound: None,
|
|
}
|
|
}
|
|
|
|
fn build_type_use(type_pair: Pair<Rule>) -> TypeUse {
|
|
let mut fqn: Option<Fqn> = None;
|
|
let mut generic_arguments_declaration: Option<Vec<GenericArgument>> = None;
|
|
|
|
for pair in type_pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::FullyQualifiedName => {
|
|
fqn = Some(build_fqn(pair));
|
|
}
|
|
Rule::GenericArguments => {
|
|
generic_arguments_declaration = Some(build_generic_arguments_declaration(pair));
|
|
}
|
|
_ => panic!(
|
|
"Expected only fqn or generic_arguments_declaration rules. Found: {}",
|
|
pair
|
|
),
|
|
}
|
|
}
|
|
|
|
TypeUse {
|
|
fqn: fqn.unwrap(),
|
|
generics: generic_arguments_declaration.unwrap_or(vec![]),
|
|
}
|
|
}
|
|
|
|
fn build_generic_parameters_declaration(
|
|
generic_parameters_declaration_pair: Pair<Rule>,
|
|
) -> Vec<GenericParameter> {
|
|
let mut parameters: Vec<GenericParameter> = vec![];
|
|
for pair in generic_parameters_declaration_pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Identifier => {
|
|
parameters.push(build_generic_parameter(pair));
|
|
}
|
|
_ => panic!("Expected only generic_parameter rule. Found: {}", pair),
|
|
}
|
|
}
|
|
parameters
|
|
}
|
|
|
|
fn build_extends_list(extends_list_pair: Pair<Rule>) -> Vec<TypeUse> {
|
|
let mut extensions: Vec<TypeUse> = vec![];
|
|
|
|
for pair in extends_list_pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::TypeUse => {
|
|
extensions.push(build_type_use(pair));
|
|
}
|
|
_ => panic!("Expected only type rule. Found: {}", pair),
|
|
}
|
|
}
|
|
|
|
extensions
|
|
}
|
|
|
|
fn build_interface(is_extern: bool, is_public: bool, interface_pair: Pair<Rule>) -> Declaration {
|
|
let mut identifier: Option<Identifier> = None;
|
|
let mut generic_parameters: Option<Vec<GenericParameter>> = None;
|
|
let mut extends: Option<Vec<TypeUse>> = None;
|
|
let mut declarations: Vec<Declaration> = vec![];
|
|
|
|
for pair in interface_pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Identifier => {
|
|
identifier = Some(build_identifier(pair));
|
|
}
|
|
Rule::GenericParameters => {
|
|
generic_parameters = Some(build_generic_parameters_declaration(pair));
|
|
}
|
|
Rule::ExtendsList => {
|
|
extends = Some(build_extends_list(pair));
|
|
}
|
|
Rule::InterfaceLevelDeclaration => {
|
|
declarations.push(build_module_level_declaration(pair));
|
|
},
|
|
_ => panic!(
|
|
"Expected only identifier, generics_declaration, extends_list, or declaration rules. Found: {}",
|
|
pair
|
|
)
|
|
}
|
|
}
|
|
|
|
Declaration::Interface {
|
|
identifier: identifier.unwrap(),
|
|
is_extern,
|
|
is_public,
|
|
type_declaration: TypeDeclaration::new(
|
|
generic_parameters.unwrap_or(vec![]),
|
|
extends.unwrap_or(vec![]),
|
|
declarations,
|
|
),
|
|
}
|
|
}
|
|
|
|
fn build_class_constructor(class_constructor_pair: Pair<Rule>) -> ClassConstructor {
|
|
todo!()
|
|
}
|
|
|
|
fn build_implementation(
|
|
is_extern: bool,
|
|
is_public: bool,
|
|
implementation_pair: Pair<Rule>,
|
|
) -> Declaration {
|
|
let mut identifier: Option<Identifier> = None;
|
|
let mut generic_parameters: Option<Vec<GenericParameter>> = None;
|
|
let mut impl_ctor: Option<ClassConstructor> = None;
|
|
let mut extends: Option<Vec<TypeUse>> = None;
|
|
let mut declarations: Vec<Declaration> = vec![];
|
|
|
|
for pair in implementation_pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Identifier => {
|
|
identifier = Some(build_identifier(pair));
|
|
}
|
|
Rule::GenericParameters => {
|
|
generic_parameters = Some(build_generic_parameters_declaration(pair));
|
|
}
|
|
Rule::ClassConstructor => {
|
|
impl_ctor = Some(build_class_constructor(pair));
|
|
}
|
|
Rule::ExtendsList => {
|
|
extends = Some(build_extends_list(pair));
|
|
}
|
|
Rule::ClassLevelDeclaration => {
|
|
declarations.push(build_module_level_declaration(pair));
|
|
}
|
|
_ => panic!("Unexpected rule: {}", pair),
|
|
}
|
|
}
|
|
|
|
Declaration::Implementation {
|
|
identifier: identifier.unwrap(),
|
|
is_extern,
|
|
is_public,
|
|
type_declaration: TypeDeclaration::new(
|
|
generic_parameters.unwrap_or(vec![]),
|
|
extends.unwrap_or(vec![]),
|
|
declarations,
|
|
),
|
|
impl_ctor,
|
|
}
|
|
}
|
|
|
|
fn build_module(is_extern: bool, is_public: bool, pair: Pair<Rule>) -> Declaration {
|
|
todo!()
|
|
}
|
|
|
|
fn build_parameter(pair: Pair<Rule>) -> Parameter {
|
|
let mut identifier: Option<Identifier> = None;
|
|
let mut declared_type: Option<TypeUse> = None;
|
|
for pair in pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Identifier => {
|
|
identifier = Some(build_identifier(pair));
|
|
}
|
|
Rule::TypeAnnotation => {
|
|
declared_type = Some(build_type_use(pair));
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
Parameter {
|
|
identifier: identifier.unwrap(),
|
|
declared_type,
|
|
}
|
|
}
|
|
|
|
fn build_parameters_list(pair: Pair<Rule>) -> Vec<Parameter> {
|
|
let mut parameters: Vec<Parameter> = vec![];
|
|
for pair in pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Parameter => {
|
|
parameters.push(build_parameter(pair));
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
parameters
|
|
}
|
|
|
|
fn build_block_statement(pair: Pair<Rule>) -> BlockStatement {
|
|
todo!()
|
|
}
|
|
|
|
fn build_function_equals_body(pair: Pair<Rule>) -> BlockStatement {
|
|
todo!()
|
|
}
|
|
|
|
fn build_function(is_extern: bool, is_public: bool, pair: Pair<Rule>) -> Declaration {
|
|
let mut is_implementation = false;
|
|
let mut generic_parameters: Option<Vec<GenericParameter>> = None;
|
|
let mut identifier: Option<Identifier> = None;
|
|
let mut parameters: Option<Vec<Parameter>> = None;
|
|
let mut return_type: Option<TypeUse> = None;
|
|
let mut statement: Option<BlockStatement> = None;
|
|
|
|
let (line, col) = pair.line_col();
|
|
|
|
for pair in pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Implementation => {
|
|
is_implementation = true;
|
|
}
|
|
Rule::Identifier => {
|
|
identifier = Some(build_identifier(pair));
|
|
}
|
|
Rule::GenericParameters => {
|
|
generic_parameters = Some(build_generic_parameters_declaration(pair));
|
|
}
|
|
Rule::Parameters => {
|
|
parameters = Some(build_parameters_list(pair));
|
|
}
|
|
Rule::TypeUse => {
|
|
return_type = Some(build_type_use(pair));
|
|
}
|
|
Rule::BlockStatement => {
|
|
statement = Some(build_block_statement(pair));
|
|
}
|
|
Rule::FunctionEqualsBody => {
|
|
statement = Some(build_function_equals_body(pair));
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
Declaration::Function(FunctionDeclaration {
|
|
is_extern,
|
|
is_public,
|
|
identifier: identifier.unwrap(),
|
|
parameters: parameters.unwrap(),
|
|
declared_type: return_type,
|
|
block_statement: statement.unwrap(),
|
|
source_code_location: SourceCodeLocation {
|
|
source_file_name: "TODO".to_string(),
|
|
line,
|
|
col,
|
|
},
|
|
})
|
|
}
|
|
|
|
fn build_module_level_declaration(declaration_pair: Pair<Rule>) -> Declaration {
|
|
let mut is_extern = false;
|
|
let mut is_public = false;
|
|
let mut declaration: Option<Declaration> = None;
|
|
|
|
for pair in declaration_pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Declare => {
|
|
is_extern = true;
|
|
}
|
|
Rule::Public => {
|
|
is_public = true;
|
|
}
|
|
Rule::Interface => {
|
|
declaration = Some(build_interface(is_extern, is_public, pair));
|
|
}
|
|
Rule::Implementation => {
|
|
declaration = Some(build_implementation(is_extern, is_public, pair));
|
|
}
|
|
Rule::Module => {
|
|
declaration = Some(build_module(is_extern, is_public, pair));
|
|
}
|
|
Rule::Function => {
|
|
declaration = Some(build_function(is_extern, is_public, pair));
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
declaration.expect("Expected declaration.")
|
|
}
|
|
|
|
fn build_identifier(pair: Pair<Rule>) -> Identifier {
|
|
match pair.as_rule() {
|
|
Rule::Identifier => Identifier {
|
|
name: String::from(pair.as_str()),
|
|
},
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
fn build_fqn(fqn_pair: Pair<Rule>) -> Fqn {
|
|
let mut identifiers: Vec<Identifier> = vec![];
|
|
for pair in fqn_pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Identifier => {
|
|
identifiers.push(build_identifier(pair));
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
Fqn { identifiers }
|
|
}
|
|
|
|
fn build_compilation_unit(pair: Pair<Rule>) -> CompilationUnit {
|
|
let mut namespace: Option<Fqn> = None;
|
|
let mut declarations: Vec<Declaration> = vec![];
|
|
|
|
for pair in pair.into_inner() {
|
|
match pair.as_rule() {
|
|
Rule::Namespace => {
|
|
let fqn_pair = pair.into_inner().next().unwrap();
|
|
namespace = Some(build_fqn(fqn_pair));
|
|
}
|
|
Rule::ModuleLevelDeclaration => {
|
|
declarations.push(build_module_level_declaration(pair));
|
|
}
|
|
Rule::EOI => {} // ignore
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
CompilationUnit {
|
|
namespace,
|
|
declarations,
|
|
}
|
|
}
|
|
|
|
pub fn build_ast(src: &str) -> CompilationUnit {
|
|
let pair = DeimosParser::parse(Rule::CompilationUnit, src)
|
|
.expect("Unsuccessful parse.")
|
|
.next()
|
|
.expect("Expected compilation_unit.");
|
|
match pair.as_rule() {
|
|
Rule::CompilationUnit => build_compilation_unit(pair),
|
|
_ => panic!("Expected compilation_unit rule."),
|
|
}
|
|
}
|