diff --git a/src/ast/build.rs b/src/ast/build.rs index 5a1c549..08d40c5 100644 --- a/src/ast/build.rs +++ b/src/ast/build.rs @@ -1,6 +1,6 @@ use crate::ast::{ BlockStatement, CompilationUnit, Declaration, Fqn, FunctionDeclaration, GenericArgument, - GenericParameter, Identifier, ImplCtor, ImplCtorArg, Parameter, TypeDeclaration, TypeUse, + GenericParameter, Identifier, ClassConstructor, Parameter, TypeDeclaration, TypeUse, }; use crate::parser::{DeimosParser, Rule}; use crate::vm::source_code_location::SourceCodeLocation; @@ -15,49 +15,6 @@ fn build_prop(prop_pair: Pair) -> Declaration { todo!() } -fn build_impl_ctor_arg(impl_ctor_arg_pair: Pair) -> ImplCtorArg { - let mut is_field = false; - let mut identifier: Option = None; - let mut r#type: Option = None; - - for pair in impl_ctor_arg_pair.into_inner() { - match pair.as_rule() { - Rule::fld => { - is_field = true; - } - Rule::identifier => { - identifier = Some(build_identifier(pair)); - } - Rule::type_use => { - r#type = Some(build_type_use(pair)); - } - _ => panic!("Unexpected rule: {}", pair), - } - } - - ImplCtorArg { - is_field, - identifier: identifier.unwrap(), - r#type, - } -} - -fn build_impl_ctor(impl_ctor_pair: Pair) -> ImplCtor { - let impl_ctor_args_pair = impl_ctor_pair.into_inner().next().unwrap(); - let mut args: Vec = vec![]; - - for pair in impl_ctor_args_pair.into_inner() { - match pair.as_rule() { - Rule::impl_ctor_arg => { - args.push(build_impl_ctor_arg(pair)); - } - _ => panic!("Unexpected rule: {}", pair), - } - } - - ImplCtor { args } -} - fn build_generic_argument(generic_argument_pair: Pair) -> GenericArgument { let fqn_pair = generic_argument_pair.into_inner().next().unwrap(); GenericArgument { @@ -71,7 +28,7 @@ fn build_generic_arguments_declaration( let mut generic_arguments: Vec = vec![]; for pair in generic_arguments_declaration_pair.into_inner() { match pair.as_rule() { - Rule::generic_argument => { + Rule::GenericArguments => { generic_arguments.push(build_generic_argument(pair)); } _ => panic!("Expected only generic_argument rules. Found: {}", pair), @@ -94,10 +51,10 @@ fn build_type_use(type_pair: Pair) -> TypeUse { for pair in type_pair.into_inner() { match pair.as_rule() { - Rule::fqn => { + Rule::FullyQualifiedName => { fqn = Some(build_fqn(pair)); } - Rule::generic_arguments_declaration => { + Rule::GenericArguments => { generic_arguments_declaration = Some(build_generic_arguments_declaration(pair)); } _ => panic!( @@ -119,7 +76,7 @@ fn build_generic_parameters_declaration( let mut parameters: Vec = vec![]; for pair in generic_parameters_declaration_pair.into_inner() { match pair.as_rule() { - Rule::generic_parameter => { + Rule::Identifier => { parameters.push(build_generic_parameter(pair)); } _ => panic!("Expected only generic_parameter rule. Found: {}", pair), @@ -133,7 +90,7 @@ fn build_extends_list(extends_list_pair: Pair) -> Vec { for pair in extends_list_pair.into_inner() { match pair.as_rule() { - Rule::type_use => { + Rule::TypeUse => { extensions.push(build_type_use(pair)); } _ => panic!("Expected only type rule. Found: {}", pair), @@ -151,17 +108,17 @@ fn build_interface(is_extern: bool, is_public: bool, interface_pair: Pair) for pair in interface_pair.into_inner() { match pair.as_rule() { - Rule::identifier => { + Rule::Identifier => { identifier = Some(build_identifier(pair)); } - Rule::generic_parameters_declaration => { + Rule::GenericParameters => { generic_parameters = Some(build_generic_parameters_declaration(pair)); } - Rule::extends_list => { + Rule::ExtendsList => { extends = Some(build_extends_list(pair)); } - Rule::declaration => { - declarations.push(build_declaration(pair)); + Rule::InterfaceLevelDeclaration => { + declarations.push(build_module_level_declaration(pair)); }, _ => panic!( "Expected only identifier, generics_declaration, extends_list, or declaration rules. Found: {}", @@ -182,6 +139,10 @@ fn build_interface(is_extern: bool, is_public: bool, interface_pair: Pair) } } +fn build_class_constructor(class_constructor_pair: Pair) -> ClassConstructor { + todo!() +} + fn build_implementation( is_extern: bool, is_public: bool, @@ -189,26 +150,26 @@ fn build_implementation( ) -> Declaration { let mut identifier: Option = None; let mut generic_parameters: Option> = None; - let mut impl_ctor: Option = None; + let mut impl_ctor: Option = None; let mut extends: Option> = None; let mut declarations: Vec = vec![]; for pair in implementation_pair.into_inner() { match pair.as_rule() { - Rule::identifier => { + Rule::Identifier => { identifier = Some(build_identifier(pair)); } - Rule::generic_parameters_declaration => { + Rule::GenericParameters => { generic_parameters = Some(build_generic_parameters_declaration(pair)); } - Rule::impl_ctor => { - impl_ctor = Some(build_impl_ctor(pair)); + Rule::ClassConstructor => { + impl_ctor = Some(build_class_constructor(pair)); } - Rule::extends_list => { + Rule::ExtendsList => { extends = Some(build_extends_list(pair)); } - Rule::declaration => { - declarations.push(build_declaration(pair)); + Rule::ClassLevelDeclaration => { + declarations.push(build_module_level_declaration(pair)); } _ => panic!("Unexpected rule: {}", pair), } @@ -236,10 +197,10 @@ fn build_parameter(pair: Pair) -> Parameter { let mut declared_type: Option = None; for pair in pair.into_inner() { match pair.as_rule() { - Rule::identifier => { + Rule::Identifier => { identifier = Some(build_identifier(pair)); } - Rule::type_use => { + Rule::TypeAnnotation => { declared_type = Some(build_type_use(pair)); } _ => unreachable!(), @@ -255,7 +216,7 @@ fn build_parameters_list(pair: Pair) -> Vec { let mut parameters: Vec = vec![]; for pair in pair.into_inner() { match pair.as_rule() { - Rule::parameter => { + Rule::Parameter => { parameters.push(build_parameter(pair)); } _ => unreachable!(), @@ -264,7 +225,7 @@ fn build_parameters_list(pair: Pair) -> Vec { parameters } -fn build_function_body(pair: Pair) -> BlockStatement { +fn build_block_statement(pair: Pair) -> BlockStatement { todo!() } @@ -273,6 +234,7 @@ fn build_function_equals_body(pair: Pair) -> BlockStatement { } fn build_function(is_extern: bool, is_public: bool, pair: Pair) -> Declaration { + let mut is_implementation = false; let mut generic_parameters: Option> = None; let mut identifier: Option = None; let mut parameters: Option> = None; @@ -283,22 +245,25 @@ fn build_function(is_extern: bool, is_public: bool, pair: Pair) -> Declara for pair in pair.into_inner() { match pair.as_rule() { - Rule::generic_parameters_declaration => { - generic_parameters = Some(build_generic_parameters_declaration(pair)); + Rule::Implementation => { + is_implementation = true; } - Rule::identifier => { + Rule::Identifier => { identifier = Some(build_identifier(pair)); } - Rule::parameters_list => { + Rule::GenericParameters => { + generic_parameters = Some(build_generic_parameters_declaration(pair)); + } + Rule::Parameters => { parameters = Some(build_parameters_list(pair)); } - Rule::type_use => { + Rule::TypeUse => { return_type = Some(build_type_use(pair)); } - Rule::function_body => { - statement = Some(build_function_body(pair)); + Rule::BlockStatement => { + statement = Some(build_block_statement(pair)); } - Rule::function_equals_body => { + Rule::FunctionEqualsBody => { statement = Some(build_function_equals_body(pair)); } _ => unreachable!(), @@ -320,41 +285,32 @@ fn build_function(is_extern: bool, is_public: bool, pair: Pair) -> Declara }) } -fn build_declaration(declaration_pair: Pair) -> Declaration { +fn build_module_level_declaration(declaration_pair: Pair) -> Declaration { let mut is_extern = false; let mut is_public = false; let mut declaration: Option = None; for pair in declaration_pair.into_inner() { match pair.as_rule() { - Rule::r#extern => { + Rule::Declare => { is_extern = true; } - Rule::r#pub => { + Rule::Public => { is_public = true; } - Rule::interface => { + Rule::Interface => { declaration = Some(build_interface(is_extern, is_public, pair)); } - Rule::implementation => { + Rule::Implementation => { declaration = Some(build_implementation(is_extern, is_public, pair)); } - Rule::module => { + Rule::Module => { declaration = Some(build_module(is_extern, is_public, pair)); } - Rule::function => { + Rule::Function => { declaration = Some(build_function(is_extern, is_public, pair)); } - Rule::prop => { - declaration = Some(build_prop(pair)); - } - Rule::field => { - declaration = Some(build_field(pair)); - } - _ => panic!( - "Expected only interface, implementation, module, or function rules; found {}", - pair - ), + _ => unreachable!(), } } declaration.expect("Expected declaration.") @@ -362,10 +318,10 @@ fn build_declaration(declaration_pair: Pair) -> Declaration { fn build_identifier(pair: Pair) -> Identifier { match pair.as_rule() { - Rule::identifier => Identifier { + Rule::Identifier => Identifier { name: String::from(pair.as_str()), }, - _ => panic!("Expected an identifier."), + _ => unreachable!(), } } @@ -373,10 +329,10 @@ fn build_fqn(fqn_pair: Pair) -> Fqn { let mut identifiers: Vec = vec![]; for pair in fqn_pair.into_inner() { match pair.as_rule() { - Rule::identifier => { + Rule::Identifier => { identifiers.push(build_identifier(pair)); } - _ => panic!("Expected only identifiers."), + _ => unreachable!(), } } Fqn { identifiers } @@ -388,18 +344,15 @@ fn build_compilation_unit(pair: Pair) -> CompilationUnit { for pair in pair.into_inner() { match pair.as_rule() { - Rule::namespace => { + Rule::Namespace => { let fqn_pair = pair.into_inner().next().unwrap(); namespace = Some(build_fqn(fqn_pair)); } - Rule::declaration => { - declarations.push(build_declaration(pair)); + Rule::ModuleLevelDeclaration => { + declarations.push(build_module_level_declaration(pair)); } Rule::EOI => {} // ignore - _ => panic!( - "Expected only namespace, declaration, or EOI rules, found: {}", - pair - ), + _ => unreachable!(), } } @@ -410,12 +363,12 @@ fn build_compilation_unit(pair: Pair) -> CompilationUnit { } pub fn build_ast(src: &str) -> CompilationUnit { - let pair = DeimosParser::parse(Rule::compilation_unit, src) + let pair = DeimosParser::parse(Rule::CompilationUnit, src) .expect("Unsuccessful parse.") .next() - .expect("Expcted compilation_unit."); + .expect("Expected compilation_unit."); match pair.as_rule() { - Rule::compilation_unit => build_compilation_unit(pair), + Rule::CompilationUnit => build_compilation_unit(pair), _ => panic!("Expected compilation_unit rule."), } } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index d8cb65a..4e8565b 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -55,7 +55,7 @@ pub enum Declaration { is_extern: bool, is_public: bool, type_declaration: TypeDeclaration, - impl_ctor: Option, + impl_ctor: Option, }, Module { identifier: Identifier, @@ -149,8 +149,31 @@ pub struct TypeUse { } #[derive(Debug)] -pub struct ImplCtor { - args: Vec, +pub struct ClassConstructor { + args: Vec, +} + +impl ClassConstructor { + pub fn new(args: Vec) -> Self { + ClassConstructor { args } + } +} + +#[derive(Debug)] +pub struct ClassMember { + is_field: bool, + identifier: Identifier, + type_use: Option +} + +impl ClassMember { + pub fn new(is_field: bool, identifier: Identifier, type_use: Option) -> Self { + ClassMember { + is_field, + identifier, + type_use + } + } } #[derive(Debug)] diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index 14c00f6..cf15168 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -1,68 +1,102 @@ -compilation_unit = { SOI ~ namespace? ~ declaration* ~ EOI } -namespace = { "ns" ~ fqn } +// Top-level constructs +CompilationUnit = { SOI ~ Namespace? ~ ModuleLevelDeclaration* ~ EOI } +Namespace = { "ns" ~ FullyQualifiedName } -fqn = { identifier ~ ( "::" ~ identifier )* } -identifier = @{ identifier_start_char ~ identifier_char* } -identifier_start_char = { 'a'..'z' | 'A'..'Z' | "_" } -identifier_char = { 'a'..'z' | 'A'..'Z' | '0'..'9' | "_" } +CommonDeclaration = { Interface | Class | Module | Function } +ModuleLevelDeclaration = { Declare? ~ Public? ~ CommonDeclaration } +InterfaceLevelDeclaration = { CommonDeclaration } +ClassLevelDeclaration = { Declare? ~ Public? ~ ( CommonDeclaration | ClassMember ) } -declaration = { extern? ~ pub? ~ ( interface | implementation | module | function | prop | field ) } -extern = { "extern" } -pub = { "pub" } +// Module +Module = { "mod" ~ Identifier ~ "{" ~ ModuleLevelDeclaration* ~ "}" } -interface = { "int" ~ identifier ~ generic_parameters_declaration? ~ extends_list? ~ ( "{" ~ declaration* ~ "}" )? } -extends_list = { ":" ~ type_use ~ ( "+" ~ type_use )* } +// Interface +Interface = { "int" ~ Identifier ~ GenericParameters? ~ ExtendsList? ~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )? } -implementation = { "impl" ~ identifier ~ generic_parameters_declaration? ~ impl_ctor? ~ extends_list? ~ ( "{" ~ declaration* ~ "}" )? } -impl_ctor = { "(" ~ impl_ctor_args? ~ ")" } -impl_ctor_args = { impl_ctor_arg ~ ( "," ~ impl_ctor_arg )* } -impl_ctor_arg = { fld? ~ identifier ~ ( ":" ~ type_use )? } -fld = { "fld" } +// Class +Class = { "class" ~ Identifier ~ GenericParameters? ~ ClassConstructor? ~ ExtendsList? ~ ( "{" ~ ClassLevelDeclaration* ~ "}" )? } +ClassMember = { Field? ~ Identifier ~ TypeAnnotation? } -module = { "mod" ~ identifier ~ "{" ~ declaration* ~ "}" } +// Class Constructor +ClassConstructor = { "(" ~ ClassMemberList? ~ ")" } +ClassMemberList = { ClassMember ~ ( "," ~ ClassMember )* } -property = { identifier ~ ( ":" ~ type_use )? } +// Various Keywords +Declare = { "decl" } +Public = { "pub" } +Field = { "fld" } +Implementation = { "impl" } +Mutable = { "mut" } -function = { "fn" ~ generic_parameters_declaration? ~ identifier ~ "(" ~ parameters_list? ~ ")" ~ ( ":" ~ type_use )? ~ ( function_body | function_equals_body ) } -function_equals_body = { "=" ~ expression } -function_body = { "{" ~ statement* ~ "}" } +// Fqn and identifier +FullyQualifiedName = { Identifier ~ ( "::" ~ Identifier )* } -type_use = { fqn ~ generic_arguments_declaration? } -generic_parameters_declaration = { "<" ~ generic_parameter ~ ( "," ~ generic_parameter )* ~ ">" } -generic_parameter = { identifier } +Identifier = @{ IdentifierStartChar ~ IdentifierChar* } +IdentifierStartChar = { 'a'..'z' | 'A'..'Z' | "_" } +IdentifierChar = { 'a'..'z' | 'A'..'Z' | '0'..'9' | "_" } -generic_arguments_declaration = { "<" ~ generic_argument ~ ( "," ~ generic_argument )* ~ ">" } -generic_argument = { fqn } +// Type constructs +ExtendsList = { ":" ~ TypeUse ~ ( "+" ~ TypeUse )* } +TypeAnnotation = { ":" ~ TypeUse } +TypeUse = { FullyQualifiedName ~ GenericArguments? } -parameters_list = { parameter ~ ( "," ~ parameter )* } -parameter = { identifier ~ ( ":" ~ "..."? ~ type_use )? } +// Generic arguments given to a TypeUse or function calls +GenericArguments = { "<" ~ FullyQualifiedName ~ ( "," ~ FullyQualifiedName )* ~ ">" } -prop = { identifier ~ ":" ~ type_use } -field = { fld ~ identifier ~ ":" ~ type_use } +// Generic parameters (for when types are declared) +GenericParameters = { "<" ~ Identifier ~ ( "," ~ Identifier )* ~ ">" } -statement = { call_stmt } +// Function +Function = { Implementation? + ~ "fn" + ~ Identifier + ~ GenericParameters? + ~ "(" ~ Parameters? ~ ")" + ~ TypeAnnotation? ~ ( FunctionEqualsBody | BlockStatement ) +} -call_stmt = { call_expr } +Parameters = { Parameter ~ ( "," ~ Parameter )* } +Parameter = { Identifier ~ TypeAnnotation? } -call_expr = { call_expr_with_parens | call_expr_no_parens } -call_expr_with_parens = { fqn ~ "(" ~ call_args? ~ ")" } -call_expr_no_parens = { fqn ~ call_args } -call_args = { call_arg ~ ( "," ~ call_arg )* } -call_arg = { expression } +FunctionEqualsBody = { "=" ~ Expression } -expression = { literal | identifier } +// Statements +BlockStatement = { "{" ~ Statement* ~ "}" } +Statement = { VariableDeclaration | CallExpression | AssignmentExpression } -literal = { number_literal | string_literal } +VariableDeclaration = { "let" ~ Mutable? ~ Identifier ~ TypeAnnotation? ~ ( "=" ~ Expression )? } -number_literal = { int_literal } -int_literal = { '0'..'9'+ } +// Expressions +Expression = { CallExpression | AssignmentExpression | Literal | FullyQualifiedName } +ExpressionList = { Expression ~ ( "," ~ Expression )* } -string_literal = ${ "\"" ~ string_inner ~ "\"" } -string_inner = @{ string_char* } -string_char = { +// Calls +CallExpression = { FullyQualifiedName ~ GenericArguments ~ CallArguments } +CallArguments = { + ( "(" ~ ExpressionList? ~")") + | ExpressionList +} + +// Assignment +AssignmentExpression = { FullyQualifiedName ~ "=" ~ Expression } + +// Literals +Literal = { NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral } + +NumberLiteral = { IntLiteral } +IntLiteral = { '0'..'9'+ } +LongLiteral = { '0'..'9'+ ~ "L" } + +StringLiteral = ${ "\"" ~ StringInner ~ "\"" } +StringInner = @{ StringChar* } +StringChar = { !( "\"" | "\\" ) ~ ANY | "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" ) | "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} ) } +BooleanLiteral = { "true" | "false" } + +NullLiteral = { "null" } + WHITESPACE = _{ " " | "\t" | "\n" | "\r" }