Update grammar.

This commit is contained in:
Jesse Brault 2025-04-16 09:12:48 -05:00
parent aa3f4b3a8b
commit 815168603c
3 changed files with 162 additions and 152 deletions

View File

@ -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<Rule>) -> Declaration {
todo!()
}
fn build_impl_ctor_arg(impl_ctor_arg_pair: Pair<Rule>) -> ImplCtorArg {
let mut is_field = false;
let mut identifier: Option<Identifier> = None;
let mut r#type: Option<TypeUse> = 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<Rule>) -> ImplCtor {
let impl_ctor_args_pair = impl_ctor_pair.into_inner().next().unwrap();
let mut args: Vec<ImplCtorArg> = 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<Rule>) -> 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<GenericArgument> = 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<Rule>) -> 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<GenericParameter> = 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<Rule>) -> Vec<TypeUse> {
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<Rule>)
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<Rule>)
}
}
fn build_class_constructor(class_constructor_pair: Pair<Rule>) -> ClassConstructor {
todo!()
}
fn build_implementation(
is_extern: bool,
is_public: bool,
@ -189,26 +150,26 @@ fn build_implementation(
) -> Declaration {
let mut identifier: Option<Identifier> = None;
let mut generic_parameters: Option<Vec<GenericParameter>> = None;
let mut impl_ctor: Option<ImplCtor> = 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 => {
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<Rule>) -> Parameter {
let mut declared_type: Option<TypeUse> = 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<Rule>) -> Vec<Parameter> {
let mut parameters: Vec<Parameter> = 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<Rule>) -> Vec<Parameter> {
parameters
}
fn build_function_body(pair: Pair<Rule>) -> BlockStatement {
fn build_block_statement(pair: Pair<Rule>) -> BlockStatement {
todo!()
}
@ -273,6 +234,7 @@ fn build_function_equals_body(pair: Pair<Rule>) -> BlockStatement {
}
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;
@ -283,22 +245,25 @@ fn build_function(is_extern: bool, is_public: bool, pair: Pair<Rule>) -> 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<Rule>) -> Declara
})
}
fn build_declaration(declaration_pair: Pair<Rule>) -> Declaration {
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::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<Rule>) -> Declaration {
fn build_identifier(pair: Pair<Rule>) -> 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<Rule>) -> Fqn {
let mut identifiers: Vec<Identifier> = 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<Rule>) -> 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<Rule>) -> 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."),
}
}

View File

@ -55,7 +55,7 @@ pub enum Declaration {
is_extern: bool,
is_public: bool,
type_declaration: TypeDeclaration,
impl_ctor: Option<ImplCtor>,
impl_ctor: Option<ClassConstructor>,
},
Module {
identifier: Identifier,
@ -149,8 +149,31 @@ pub struct TypeUse {
}
#[derive(Debug)]
pub struct ImplCtor {
args: Vec<ImplCtorArg>,
pub struct ClassConstructor {
args: Vec<ClassMember>,
}
impl ClassConstructor {
pub fn new(args: Vec<ClassMember>) -> Self {
ClassConstructor { args }
}
}
#[derive(Debug)]
pub struct ClassMember {
is_field: bool,
identifier: Identifier,
type_use: Option<TypeUse>
}
impl ClassMember {
pub fn new(is_field: bool, identifier: Identifier, type_use: Option<TypeUse>) -> Self {
ClassMember {
is_field,
identifier,
type_use
}
}
}
#[derive(Debug)]

View File

@ -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" }