Compare commits

..

3 Commits

Author SHA1 Message Date
Jesse Brault
82af6b4dfb Much work on grammar, AST building and unparsing. 2025-05-13 09:46:24 -05:00
Jesse Brault
e8aff842ed Create and implement AST structs/enums and Unparse traits. 2025-05-11 09:28:42 -05:00
Jesse Brault
1a365481ab Add smoke screen tests for parser; add some function grammar rules. 2025-05-07 15:05:39 -05:00
8 changed files with 2457 additions and 635 deletions

View File

@ -0,0 +1,16 @@
class Counter {
fld count: Int
mut getAndIncrement() -> Int {
let result = count
count++
result
}
}
@Synthetic
class MyClosure(delegate: Counter) : MutClosure(Int, Int) -> Int |delegate| {
mut fn call(x: Int, y: Int) -> Int {
x + y + delegate.getAndIncrement()
}
}

View File

@ -0,0 +1,14 @@
pub type Iterator<T> |backing: &Any| = mut fn () -> Option<&T ref backing>
pub int Iterable<T> {
ref fn iterator() -> Iterator<T>(&self)
}
fn main() {
let nums: List<Int> = [1, 2, 3]
let iterator: Iterator<Int> |backing = nums| = nums.iterator()
let first: &Int ref nums = iterator().unwrap()
let second: &Int ref nums = iterator().unwrap()
let third: &Int ref nums = iterator().unwrap()
println "${*first}, ${*second}, ${*third}"
}

View File

@ -1,374 +1,208 @@
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 crate::ast::{CompilationUnit, DelegateOrIdentifier, Fqn, FunctionModifier, FunctionTypeUse, GenericArgument, GenericArguments, GenericParameter, GenericParameters, Identifier, InputArgument, InputArguments, InterfaceOrClassTypeUse, Reference, References, ReturnType, TupleTypeUse, TypeUse, VoidOrTypeUse};
use crate::parser::Rule;
use pest::iterators::Pair;
use pest::Parser;
fn build_field(field_pair: Pair<Rule>) -> Declaration {
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 {
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_identifier(identifier_pair: Pair<Rule>) -> Identifier {
Identifier {
name: identifier_pair.as_str().to_string(),
}
}
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!(),
}
for identifier_pair in fqn_pair.into_inner() {
identifiers.push(expect_and_use(
identifier_pair,
Rule::Identifier,
build_identifier,
));
}
Fqn { identifiers }
}
fn build_compilation_unit(pair: Pair<Rule>) -> CompilationUnit {
let mut namespace: Option<Fqn> = None;
let mut declarations: Vec<Declaration> = vec![];
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::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!(),
}
}
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));
fn build_interface_or_class_type_use(pair: Pair<Rule>) -> InterfaceOrClassTypeUse {
let mut inner = pair.into_inner();
let fqn = expect_and_use(inner.next().unwrap(), Rule::FullyQualifiedName, build_fqn);
let generics = inner
.next()
.map(|inner_pair| {
expect_and_use(inner_pair, Rule::GenericArguments, build_generic_arguments)
})
.unwrap_or(GenericArguments(vec![]));
InterfaceOrClassTypeUse { fqn, generics }
}
fn build_tuple_type_use(tuple_type_use_pair: Pair<Rule>) -> TupleTypeUse {
TupleTypeUse(
tuple_type_use_pair
.into_inner()
.map(|type_use_pair| expect_and_use(type_use_pair, Rule::TypeUse, build_type_use))
.collect(),
)
}
fn build_function_type_use(function_pair: Pair<Rule>) -> FunctionTypeUse {
let mut function_modifier: Option<FunctionModifier> = None;
let mut generics: Option<GenericParameters> = None;
let mut parameters: Option<TupleTypeUse> = None;
let mut inputs: Option<InputArguments> = None;
let mut return_type: Option<ReturnType> = None;
for inner_pair in function_pair.into_inner() {
match inner_pair.as_rule() {
Rule::FunctionTypeModifier => {
function_modifier = Some(build_function_modifier(inner_pair));
}
Rule::ModuleLevelDeclaration => {
declarations.push(build_module_level_declaration(pair));
Rule::Fn => {}
Rule::GenericParameters => {
generics = Some(build_generic_parameters(inner_pair));
}
Rule::EOI => {} // ignore
Rule::TupleTypeUse => {
parameters = Some(build_tuple_type_use(inner_pair));
}
Rule::FunctionInputArguments => {
inputs = Some(build_function_input_arguments(inner_pair));
}
Rule::ReturnType => {
return_type = Some(build_return_type(inner_pair));
},
_ => unreachable!(),
}
}
CompilationUnit {
namespace,
declarations,
FunctionTypeUse {
function_modifier,
generics: generics.unwrap_or(GenericParameters(vec![])),
parameters: parameters.unwrap(),
inputs: inputs.unwrap_or(InputArguments(vec![])),
return_type: return_type.unwrap(),
}
}
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."),
fn build_generic_arguments(generic_arguments_pair: Pair<Rule>) -> GenericArguments {
let mut generic_arguments: Vec<GenericArgument> = vec![];
for generic_argument_pair in generic_arguments_pair.into_inner() {
generic_arguments.push(expect_and_use(
generic_argument_pair,
Rule::FullyQualifiedName,
build_generic_argument,
));
}
GenericArguments(generic_arguments)
}
fn build_generic_argument(fqn_pair: Pair<Rule>) -> GenericArgument {
GenericArgument {
fqn: build_fqn(fqn_pair),
}
}
fn build_function_modifier(function_modifier_pair: Pair<Rule>) -> FunctionModifier {
let mut inner = function_modifier_pair.into_inner();
if inner.len() == 2 {
FunctionModifier::MutRef
} else {
match inner.next().unwrap().as_rule() {
Rule::Cons => FunctionModifier::Cons,
Rule::Mut => FunctionModifier::Mut,
Rule::Ref => FunctionModifier::Ref,
_ => unreachable!(),
}
}
}
fn build_generic_parameters(generic_parameters_pair: Pair<Rule>) -> GenericParameters {
GenericParameters(
generic_parameters_pair
.into_inner()
.map(|identifier_pair| {
GenericParameter(expect_and_use(
identifier_pair,
Rule::Identifier,
build_identifier,
))
})
.collect(),
)
}
fn build_function_input_arguments(pair: Pair<Rule>) -> InputArguments {
InputArguments(
pair.into_inner()
.map(|function_input_argument_pair| {
let mut inner = function_input_argument_pair.into_inner();
let lhs_pair = inner.next().unwrap();
let lhs = match lhs_pair.as_rule() {
Rule::Delegate => DelegateOrIdentifier::Delegate,
Rule::Identifier => {
DelegateOrIdentifier::Identifier(build_identifier(lhs_pair))
}
_ => unreachable!(),
};
let rhs = build_identifier(inner.next().unwrap());
InputArgument { lhs, rhs }
})
.collect(),
)
}
fn build_return_type(return_type_pair: Pair<Rule>) -> ReturnType {
let mut inner = return_type_pair.into_inner();
let declared_type_pair = inner.next().unwrap();
let declared_type = match declared_type_pair.as_rule() {
Rule::Void => VoidOrTypeUse::Void,
Rule::TypeUse => VoidOrTypeUse::TypeUse(Box::new(
build_type_use(declared_type_pair)
)),
_ => unreachable!(),
};
let references = inner.next().map(|ref_list_pair| {
expect_and_use(ref_list_pair, Rule::RefList, build_references)
}).unwrap_or(References(vec![]));
ReturnType {
declared_type,
references,
}
}
fn build_references(ref_list_pair: Pair<Rule>) -> References {
let mut identifiers: Vec<Identifier> = vec![];
for pair in ref_list_pair.into_inner() {
match pair.as_rule() {
Rule::Ref => {},
Rule::Identifier => {
identifiers.push(build_identifier(pair));
},
_ => unreachable!(),
}
}
References(identifiers.into_iter().map(|identifier| Reference(identifier)).collect())
}

View File

@ -1,256 +1,535 @@
use crate::vm::source_code_location::SourceCodeLocation;
use pest::Parser;
pub mod build;
pub mod unparse;
// Operators
#[derive(Debug)]
pub struct CompilationUnit {
namespace: Option<Fqn>,
declarations: Vec<Declaration>,
pub enum Operator {
Binary(BinaryOperator),
Unary(UnaryOperator),
}
impl CompilationUnit {
pub fn namespace(&self) -> &Option<Fqn> {
&self.namespace
}
#[derive(Debug)]
pub enum BinaryOperator {
Or,
And,
EqualTo,
NotEqualTo,
Greater,
Less,
GreaterEqual,
LessEqual,
Add,
Subtract,
Multiply,
Divide,
Modulo,
LeftShift,
RightShift,
}
pub fn declarations(&self) -> &Vec<Declaration> {
&self.declarations
}
#[derive(Debug)]
pub enum UnaryOperator {
Not,
Negative,
PlusPlus,
MinusMinus,
CallOp,
Spread,
}
// Names
#[derive(Debug, Clone)]
pub struct Identifier {
pub name: String,
}
#[derive(Debug)]
pub struct Fqn {
identifiers: Vec<Identifier>,
pub identifiers: Vec<Identifier>,
}
impl Fqn {
pub fn new(identifiers: Vec<Identifier>) -> Self {
Fqn { identifiers }
}
// Generic parameters
pub fn identifiers(&self) -> &Vec<Identifier> {
&self.identifiers
}
#[derive(Debug)]
pub struct GenericParameters(pub Vec<GenericParameter>);
pub fn push_identifier(&mut self, identifier: Identifier) {
self.identifiers.push(identifier);
}
pub fn pop_identifier(&mut self) {
self.identifiers.pop();
impl GenericParameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub enum Declaration {
Interface {
identifier: Identifier,
is_extern: bool,
is_public: bool,
type_declaration: TypeDeclaration,
},
Implementation {
identifier: Identifier,
is_extern: bool,
is_public: bool,
type_declaration: TypeDeclaration,
impl_ctor: Option<ClassConstructor>,
},
Module {
identifier: Identifier,
is_extern: bool,
is_public: bool,
declarations: Vec<Declaration>,
},
Function(FunctionDeclaration),
Prop(Prop),
Field(Field),
}
pub struct GenericParameter(Identifier);
// Generic arguments
#[derive(Debug)]
pub struct FunctionDeclaration {
source_code_location: SourceCodeLocation,
identifier: Identifier,
is_extern: bool,
is_public: bool,
parameters: Vec<Parameter>,
declared_type: Option<TypeUse>,
block_statement: BlockStatement,
}
pub struct GenericArguments(pub Vec<GenericArgument>);
impl FunctionDeclaration {
pub fn source_code_location(&self) -> &SourceCodeLocation {
&self.source_code_location
impl GenericArguments {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn identifier(&self) -> &Identifier {
&self.identifier
}
pub fn block_statement(&self) -> &BlockStatement {
&self.block_statement
}
}
#[derive(Debug)]
pub struct TypeDeclaration {
generics: Vec<GenericParameter>,
extends: Vec<TypeUse>,
declarations: Vec<Declaration>,
}
impl TypeDeclaration {
pub fn new(
generics: Vec<GenericParameter>,
extends: Vec<TypeUse>,
declarations: Vec<Declaration>,
) -> TypeDeclaration {
TypeDeclaration {
generics,
extends,
declarations,
}
}
}
#[derive(Debug, Clone)]
pub struct Identifier {
name: String,
}
impl Identifier {
pub fn name(&self) -> &str {
&self.name
}
}
#[derive(Debug)]
pub struct GenericParameter {
identifier: Identifier,
bound: Option<GenericBound>,
}
#[derive(Debug)]
pub enum GenericBound {
Extends { fqn: Fqn },
Super { fqn: Fqn },
}
#[derive(Debug)]
pub struct GenericArgument {
fqn: Fqn,
pub fqn: Fqn,
}
// Type-use and components
// #[derive(Debug)]
// pub struct TypeUse {
// pub fqn: Fqn,
// pub arguments: Option<TypeArguments>,
// pub inputs: Option<InputArguments>,
// }
#[derive(Debug)]
pub enum TypeUse {
InterfaceOrClass(InterfaceOrClassTypeUse),
Tuple(TupleTypeUse),
Function(FunctionTypeUse),
}
#[derive(Debug)]
pub struct TypeUse {
fqn: Fqn,
generics: Vec<GenericArgument>,
pub struct InterfaceOrClassTypeUse {
pub fqn: Fqn,
pub generics: GenericArguments,
}
#[derive(Debug)]
pub struct ClassConstructor {
args: Vec<ClassMember>,
pub struct TupleTypeUse(pub Vec<TypeUse>);
#[derive(Debug)]
pub struct FunctionTypeUse {
pub function_modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub parameters: TupleTypeUse,
pub inputs: InputArguments,
pub return_type: ReturnType,
}
impl ClassConstructor {
pub fn new(args: Vec<ClassMember>) -> Self {
ClassConstructor { args }
#[derive(Debug)]
pub enum TypeArguments {
Generics(GenericArguments),
Tuple(TupleArguments),
Function(FunctionTypeArguments),
}
#[derive(Debug)]
pub struct TupleArguments(pub Vec<Fqn>);
impl TupleArguments {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct ClassMember {
is_field: bool,
identifier: Identifier,
type_use: Option<TypeUse>
pub struct FunctionTypeArguments {
pub parameters: TupleParameters,
pub return_type: Box<TypeUse>,
}
impl ClassMember {
pub fn new(is_field: bool, identifier: Identifier, type_use: Option<TypeUse>) -> Self {
ClassMember {
is_field,
identifier,
type_use
}
// Function components
#[derive(Debug)]
pub struct Parameters(pub Vec<Parameter>);
impl Parameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct ImplCtorArg {
is_field: bool,
pub struct Parameter {
identifier: Identifier,
r#type: Option<TypeUse>,
type_use: TypeUse,
}
#[derive(Debug)]
pub struct Prop {
identifier: Identifier,
r#type: TypeUse,
pub struct ReturnType {
pub declared_type: VoidOrTypeUse,
pub references: References,
}
#[derive(Debug)]
pub struct Field {
identifier: Identifier,
r#type: TypeUse,
pub enum VoidOrTypeUse {
Void,
TypeUse(Box<TypeUse>),
}
#[derive(Debug)]
pub struct BlockStatement {
statements: Vec<Statement>,
}
pub struct References(pub Vec<Reference>);
impl BlockStatement {
pub fn statements(&self) -> &Vec<Statement> {
&self.statements
impl References {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct Reference(pub Identifier);
// Inputs
#[derive(Debug)]
pub enum DelegateOrIdentifier {
Delegate,
Identifier(Identifier),
}
#[derive(Debug)]
pub struct InputParameters(pub Vec<DelegateOrIdentifier>);
impl InputParameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct InputArguments(pub Vec<InputArgument>);
impl InputArguments {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct InputArgument {
pub lhs: DelegateOrIdentifier,
pub rhs: Identifier,
}
// Where guards
#[derive(Debug)]
pub struct WhereGuards(pub Vec<WhereGuard>);
impl WhereGuards {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct WhereGuard {
pub identifier: Identifier,
pub implements: ImplementsList,
}
// Implements
#[derive(Debug)]
pub struct ImplementsList(pub Vec<TypeUse>);
impl ImplementsList {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
// Top-level construct
#[derive(Debug)]
pub struct CompilationUnit {
pub namespace: Option<Fqn>,
pub declarations: Vec<ModuleLevelDeclaration>,
}
// Declarations allowed in each level
#[derive(Debug)]
pub enum ModuleLevelDeclaration {
Type(TypeDeclaration),
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(FunctionDeclaration),
PlatformFunction(PlatformFunctionDeclaration),
}
#[derive(Debug)]
pub enum InterfaceLevelDeclaration {
Type(TypeDeclaration),
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(InterfaceFunctionDeclaration),
OperatorFunction(InterfaceOperatorFunctionDeclaration),
}
#[derive(Debug)]
pub enum ClassLevelDeclaration {
Type(TypeDeclaration),
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(FunctionDeclaration),
OperatorFunction(OperatorFunctionDeclaration),
PlatformFunction(PlatformFunctionDeclaration),
Field(FieldDeclaration),
}
// Declarations
#[derive(Debug)]
pub struct TypeDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub parameters: Option<TypeParameters>,
pub where_guards: WhereGuards,
pub rhs: TypeUse,
}
#[derive(Debug)]
pub struct ModuleDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub declarations: Vec<ModuleLevelDeclaration>,
}
#[derive(Debug)]
pub struct InterfaceDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub generics: GenericParameters,
pub inputs: InputParameters,
pub implements: ImplementsList,
pub where_guards: WhereGuards,
pub declarations: Vec<InterfaceLevelDeclaration>,
}
#[derive(Debug)]
pub struct ClassDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub generics: GenericParameters,
pub class_constructor: Option<ClassConstructor>,
pub inputs: InputArguments,
pub implements: ImplementsList,
pub where_guards: WhereGuards,
pub declarations: Vec<ClassLevelDeclaration>,
}
// Function declarations and components
#[derive(Debug)]
pub enum FunctionModifier {
Static,
Cons,
Mut,
Ref,
MutRef,
}
#[derive(Debug)]
pub enum FunctionBody {
EqualsBody(Expression),
BlockBody(BlockStatement),
AliasBody(Identifier),
}
#[derive(Debug)]
pub struct FunctionDeclaration {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: Option<ReturnType>,
pub body: FunctionBody,
}
#[derive(Debug)]
pub struct OperatorFunctionDeclaration {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub operator: Operator,
pub parameters: Parameters,
pub return_type: Option<ReturnType>,
pub body: FunctionBody,
}
#[derive(Debug)]
pub struct PlatformFunctionDeclaration {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: TypeUse,
}
#[derive(Debug)]
pub struct InterfaceFunctionDeclaration {
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: ReturnType,
}
#[derive(Debug)]
pub struct InterfaceOperatorFunctionDeclaration {
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub operator: Operator,
pub parameters: Parameters,
pub return_type: ReturnType,
}
// Type components
#[derive(Debug)]
pub enum TypeParameters {
Generic(GenericParameters),
Tuple(TupleParameters),
Function(FunctionTypeParameters),
}
#[derive(Debug)]
pub struct TupleParameters(pub Vec<Identifier>);
#[derive(Debug)]
pub struct FunctionTypeParameters {
pub parameters: Parameters,
pub return_type: TypeUse,
}
// Class components
#[derive(Debug)]
pub struct ClassConstructor(pub Vec<ClassConstructorParameter>);
#[derive(Debug)]
pub struct ClassConstructorParameter {
pub is_field: bool,
pub identifier: Identifier,
pub declared_type: TypeUse,
}
#[derive(Debug)]
pub struct FieldDeclaration {
pub is_mutable: bool,
pub identifier: Identifier,
pub declared_type: TypeUse,
}
// Statements
#[derive(Debug)]
pub struct BlockStatement(pub Vec<Statement>);
#[derive(Debug)]
pub enum Statement {
BlockStatement(BlockStatement),
CallStatement(CallExpression),
AssignStatement(AssignExpression),
VariableDeclarationStatement(VariableDeclarationStatement),
AssignStatement(AssignStatement),
ReturnStatement(ReturnStatement),
IfStatement(IfStatement),
IfElseStatement(IfElseStatement),
WhileStatement(WhileStatement),
ForStatement(ForStatement),
}
#[derive(Debug)]
pub struct VariableDeclarationStatement {
is_mutable: bool,
identifier: Identifier,
declared_type: Option<TypeUse>,
initializer: Option<Expression>,
}
#[derive(Debug)]
pub struct AssignStatement(pub AssignmentExpression);
#[derive(Debug)]
pub struct ReturnStatement(pub Option<Expression>);
#[derive(Debug)]
pub struct IfStatement {
pub condition: Expression,
pub then_branch: BlockStatement,
}
#[derive(Debug)]
pub struct IfElseStatement {
pub condition: Expression,
pub then_branch: BlockStatement,
pub else_ifs: ElseIfs,
pub else_branch: BlockStatement,
}
#[derive(Debug)]
pub struct ElseIfs(pub Vec<IfStatement>);
#[derive(Debug)]
pub struct WhileStatement {
pub condition: Expression,
pub body: BlockStatement,
}
#[derive(Debug)]
pub struct ForStatement {
pub variable: Identifier,
pub iterator: Expression,
pub body: BlockStatement,
}
// Expressions
#[derive(Debug)]
pub enum Expression {
Binary(BinaryExpression),
Unary(UnaryExpression),
Assignment(Box<AssignmentExpression>),
Call(CallExpression),
Literal(Literal),
}
#[derive(Debug)]
pub struct BinaryExpression {
pub left: Box<Expression>,
pub operator: BinaryOperator,
pub right: Box<Expression>,
}
#[derive(Debug)]
pub struct UnaryExpression {
pub operator: UnaryOperator,
pub expression: Box<Expression>,
}
#[derive(Debug)]
pub struct AssignmentExpression {
identifier: Identifier,
expression: Expression,
}
#[derive(Debug)]
pub struct CallExpression {
receiver: Expression,
actuals_list: Vec<Expression>,
source_code_location: SourceCodeLocation,
}
impl CallExpression {
pub fn receiver(&self) -> &Expression {
&self.receiver
}
pub fn actuals_list(&self) -> &Vec<Expression> {
&self.actuals_list
}
pub fn source_code_location(&self) -> &SourceCodeLocation {
&self.source_code_location
}
pub callee: Box<Expression>,
pub arguments: CallArguments,
}
#[derive(Debug)]
pub struct AssignExpression {
left: LValue,
right: Expression,
}
pub struct CallArguments(pub Vec<CallArgument>);
#[derive(Debug)]
pub enum Expression {
CallExpression(Box<CallExpression>),
AssignExpression(Box<AssignExpression>),
LValue(Box<LValue>),
Literal(Box<Literal>),
}
#[derive(Debug)]
pub enum LValue {
Fqn(Fqn),
}
pub struct CallArgument(pub Box<Expression>);
#[derive(Debug)]
pub enum Literal {
@ -261,9 +540,3 @@ pub enum Literal {
StringLiteral(String),
BooleanLiteral(bool),
}
#[derive(Debug)]
pub struct Parameter {
identifier: Identifier,
declared_type: Option<TypeUse>,
}

1018
src/ast/unparse.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
use crate::ast::{
AssignExpression, BlockStatement, CallExpression, CompilationUnit, Declaration, Expression,
Fqn, FunctionDeclaration, Identifier, LValue, Statement,
AssignExpression, BlockStatement, CallExpression, CompilationUnit, Expression, Fqn,
FunctionDeclaration, Identifier, LValue, ModuleLevelDeclaration, Statement,
};
use crate::object_file::{DvmObjectFile, DvmPath};
use crate::vm::function::DvmFunction;
@ -153,7 +153,7 @@ pub fn convert(file_name: &str, ast: CompilationUnit) -> DvmObjectFile {
for declaration in ast.declarations() {
match declaration {
Declaration::Function(function_declaration) => {
ModuleLevelDeclaration::Function(function_declaration) => {
let function = convert_static_function(&state, &context, function_declaration);
object_file.add_function(function);
}

View File

@ -1,140 +1,780 @@
// Top-level constructs
CompilationUnit = { SOI ~ Namespace? ~ ModuleLevelDeclaration* ~ EOI }
Namespace = { "ns" ~ FullyQualifiedName }
// Keywords
Ns = { "ns" }
TypeKw = { "type" }
Mod = { "mod" }
Int = { "int" }
ClassKw = { "class" }
Platform = { "platform" }
Pub = { "pub" }
Fld = { "fld" }
Impl = { "impl" }
Mut = { "mut" }
Cons = { "cons" }
Static = { "static" }
Ref = { "ref" }
Def = { "def" }
Where = { "where" }
Infer = { "infer" }
Void = { "Void" }
Delegate = { "delegate" }
Let = { "let" }
Fn = { "fn" }
Op = { "op" }
CommonDeclaration = { Interface | Class | Module | Function }
ModuleLevelDeclaration = { Declare? ~ Public? ~ CommonDeclaration }
InterfaceLevelDeclaration = { CommonDeclaration }
ClassLevelDeclaration = { Declare? ~ Public? ~ ( CommonDeclaration | ClassMember ) }
// Module
Module = { "mod" ~ Identifier ~ "{" ~ ModuleLevelDeclaration* ~ "}" }
// Interface
Interface = { "int" ~ Identifier ~ GenericParameters? ~ ExtendsList? ~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )? }
// Class
Class = { "class" ~ Identifier ~ GenericParameters? ~ ClassConstructor? ~ ExtendsList? ~ ( "{" ~ ClassLevelDeclaration* ~ "}" )? }
ClassMember = { Field? ~ Identifier ~ TypeAnnotation? }
// Class Constructor
ClassConstructor = { "(" ~ ClassMemberList? ~ ")" }
ClassMemberList = { ClassMember ~ ( "," ~ ClassMember )* }
// Various Keywords
Declare = { "decl" }
Public = { "pub" }
Field = { "fld" }
Implementation = { "impl" }
Mutable = { "mut" }
// Fqn and identifier
FullyQualifiedName = { Identifier ~ ( "::" ~ Identifier )* }
Identifier = @{ IdentifierStartChar ~ IdentifierChar* }
IdentifierStartChar = { 'a'..'z' | 'A'..'Z' | "_" }
IdentifierChar = { 'a'..'z' | 'A'..'Z' | '0'..'9' | "_" }
// Type constructs
ExtendsList = { ":" ~ TypeUse ~ ( "+" ~ TypeUse )* }
TypeAnnotation = { ":" ~ TypeUse }
TypeUse = { FullyQualifiedName ~ GenericArguments? }
// Generic arguments given to a TypeUse or function calls
GenericArguments = { "<" ~ FullyQualifiedName ~ ( "," ~ FullyQualifiedName )* ~ ">" }
// Generic parameters (for when types are declared)
GenericParameters = { "<" ~ Identifier ~ ( "," ~ Identifier )* ~ ">" }
// Function
Function = { Implementation?
~ "fn"
~ Identifier
~ GenericParameters?
~ "(" ~ Parameters? ~ ")"
~ TypeAnnotation? ~ ( FunctionEqualsBody | BlockStatement )
// Keywords as a rule (for preventing identifiers with keywords, etc.)
Keyword = {
Ns
| TypeKw
| Mod
| Int
| ClassKw
| Platform
| Pub
| Fld
| Impl
| Mut
| Cons
| Static
| Ref
| Def
| Where
| Infer
| Void
| Delegate
| Let
| Fn
| Op
}
Parameters = { Parameter ~ ( "," ~ Parameter )* }
Parameter = { Identifier ~ TypeAnnotation? }
// Symbols
Ellipsis = { "..." }
Underscore = { "_" }
FunctionEqualsBody = { "=" ~ Expression }
// Statements
BlockStatement = { "{" ~ Statement* ~ "}" }
Statement = { VariableDeclaration | CallExpression | AssignmentExpression }
VariableDeclaration = { "let" ~ Mutable? ~ Identifier ~ TypeAnnotation? ~ ( "=" ~ Expression )? }
// Expressions
Expression = { OrExpression }
OrExpression = { AndExpression ~ ( "||" ~ AndExpression )* }
AndExpression = { EqualityExpression ~ ( "&&" ~ EqualityExpression )* }
EqualityExpression = { ComparisonExpression ~ ( ( EqualTo | NotEqualTo ) ~ ComparisonExpression )* }
// Operators
Or = { "||" }
And = { "&&" }
EqualTo = { "==" }
NotEqualTo = { "!=" }
ComparisonExpression = { AdditiveExpression ~ ( ( Greater | Less | GreaterEqual | LessEqual ) ~ AdditiveExpression )* }
Greater = { ">" }
Less = { "<" }
GreaterEqual = { ">=" }
LessEqual = { "<=" }
AdditiveExpression = { MultiplicativeExpression ~ ( ( Add | Subtract ) ~ MultiplicativeExpression )* }
Add = { "+" }
Subtract = { "-" }
MultiplicativeExpression = { UnaryExpression ~ ( ( Multiply | Divide | Modulo ) ~ UnaryExpression )* }
Multiply = { "*" }
Divide = { "/" }
Modulo = { "%" }
UnaryExpression = { ( Not | Negative )* ~ PrimaryExpression ~ ( Call | ( PlusPlus | MinusMinus ) )* }
Not = { "!" }
Negative = { "-" }
PlusPlus = { "++" }
MinusMinus = { "--" }
CallOp = { "()" }
Spread = { Ellipsis }
PrimaryExpression = { Literal | ObjectAccess | ParenthesizedExpression }
ParenthesizedExpression = { "(" ~ Expression ~ ")" }
Operator = {
Or
| And
| EqualTo
| NotEqualTo
| Greater
| Less
| GreaterEqual
| LessEqual
| Add
| Subtract
| Multiply
| Divide
| Modulo
| Not
| Negative
| PlusPlus
| MinusMinus
| CallOp
| Spread
}
// Commonly shared constructs
// Call
CallExpression = { PrimaryExpression ~ Call+ }
Call = { GenericArguments? ~ CallArguments }
ExpressionList = { Expression ~ ( "," ~ Expression )* }
CallArguments = {
( "(" ~ ExpressionList? ~ ")" )
| ExpressionList
FullyQualifiedName = {
Identifier
~ ( "::" ~ Identifier )*
}
Identifier = @{
( Keyword ~ IdentifierChar | !Keyword ~ IdentifierStartChar )
~ IdentifierChar*
}
IdentifierStartChar = {
'a'..'z'
| 'A'..'Z'
| "_"
}
IdentifierChar = {
'a'..'z'
| 'A'..'Z'
| '0'..'9'
| "_"
}
// In general:
// Arguments = usage
// Parameters = declaration
TypeUse = {
InterfaceOrClassTypeUse
| TupleTypeUse
| FunctionTypeUse
}
InterfaceOrClassTypeUse = {
FullyQualifiedName
~ GenericArguments?
}
TupleTypeUse = {
"("
~ (
TypeUse
~ ( "," ~ TypeUse )*
)?
~ ")"
}
FunctionTypeUse = {
FunctionTypeModifier?
~ Fn
~ GenericParameters?
~ TupleTypeUse
~ FunctionInputArguments?
~ ReturnType
}
FunctionTypeModifier = {
Cons
| Mut ~ Ref
| Mut
| Ref
}
GenericArguments = {
"<"
~ FullyQualifiedName
~ ( "," ~ FullyQualifiedName )*
~ ">"
}
InputArguments = {
"|"
~ (
InputArgument
~ ( "," ~ InputArgument )*
)?
~ "|"
}
InputArgument = {
Identifier
~ ( "=" ~ Identifier )
}
RefList = {
Ref
~ Identifier
~ ( "," ~ Identifier )*
}
FunctionInputArguments = {
"|"
~ (
FunctionInputArgument
~ ( "," ~ FunctionInputArgument )*
)?
~ "|"
}
FunctionInputArgument = {
( Delegate | Identifier )
~ ( "=" ~ Identifier )
}
// Generic Parameters
GenericParameters = {
"<"
~ Identifier
~ ( "," ~ Identifier )*
~ ">"
}
InputParameters = {
"|"
~ InputParameter
~ ( "," ~ InputParameter )*
~ "|"
}
InputParameter = {
Identifier
~ ":"
~ TypeUse
}
TupleGenericParameters = {
"("
~ (
Identifier
~ ( "," ~ Identifier )*
)?
~ ")"
}
FunctionGenericParameters = {
TupleGenericParameters
~ FunctionGenericParameterReturnType
}
FunctionGenericParameterReturnType = {
"->"
~ ( Void | Identifier )
~ RefList?
}
FunctionInputParameters = {
"|"
~ FunctionInputParameter
~ ( "," ~ FunctionInputParameter )*
~ "|"
}
FunctionInputParameter = {
( Delegate | Identifier )
~ ":"
~ TypeUse
}
ImplementsList = {
":"
~ TypeUse
~ ( "+" ~ TypeUse )
}
WhereGuards = {
Where
~ WhereGuard
~ ( "," ~ WhereGuard )*
}
WhereGuard = {
Identifier
~ ImplementsList
}
// Top-level constructs
CompilationUnit = {
SOI
~ Namespace?
~ ModuleLevelDeclaration*
~ EOI
}
Namespace = {
Ns
~ FullyQualifiedName
}
// Organizational declarations
ModuleLevelDeclaration = {
Type
| Module
| Interface
| Class
| FunctionDefinition
| PlatformFunction
}
InterfaceLevelDeclaration = {
Type
| Module
| Interface
| Class
| InterfaceFunction
| InterfaceDefaultFunction
| InterfaceOperatorFunction
| InterfaceDefaultOperatorFunction
}
ClassLevelDeclaration = {
Type
| Module
| Interface
| Class
| FunctionDefinition
| OperatorFunctionDefinition
| PlatformFunction
| Field
}
// Main organizational constructs
Type = {
Pub?
~ TypeKw
~ Identifier
~ GenericParameters?
~ TypeWhereGuards?
~ "="
~ TypeUse
}
Module = {
Pub?
~ Mod
~ Identifier
~ "{" ~ ModuleLevelDeclaration* ~ "}"
}
Interface = {
Pub?
~ Int
~ Identifier
~ InterfaceGenericParametersAndInputs?
~ ImplementsList?
~ WhereGuards?
~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )?
}
Class = {
Pub?
~ ClassKw
~ Identifier
~ GenericParameters?
~ ClassConstructor?
~ ImplementsList?
~ InputArguments?
~ WhereGuards?
~ ( "{" ~ ClassLevelDeclaration* ~ "}" )?
}
// Type
TypeWhereGuards = {
Where
~ TypeWhereGuard
~ ( "," ~ TypeWhereGuard )*
}
TypeWhereGuard = {
Identifier
~ ":"
~ TypeTypeUse
~ ( "+" ~ TypeTypeUse )*
}
TypeTypeUse = {
FullyQualifiedName
~ TypeTypeArguments?
}
TypeTypeArguments = {
TypeGenericArguments
| TypeGenericFunctionArguments
| TypeGenericTupleArguments
}
TypeGenericArguments = {
"<"
~ TypeGenericArgument
~ ( "," ~ TypeGenericArgument )*
~ ">"
}
TypeGenericArgument = {
Underscore
| FullyQualifiedName
| ( Infer ~ Identifier )
}
TypeGenericTupleArguments = {
"("
~ (
TypeGenericTupleArgument
~ ( "," ~ TypeGenericTupleArgument )*
)?
~ ")"
}
TypeGenericTupleArgument = {
Underscore
| FullyQualifiedName
| ( Infer ~ Identifier )
| ( Ellipsis ~ Underscore )
| ( Ellipsis ~ Infer ~ Identifier )
}
TypeGenericFunctionArguments = {
TypeGenericTupleArguments
~ TypeGenericArguments?
~ TypeFunctionReturnType
}
TypeFunctionReturnType = {
"->"
~ ( Void | FullyQualifiedName )
~ RefList?
}
// Interface
InterfaceGenericParametersAndInputs = {
GenericParameters ~ InputParameters?
| TupleGenericParameters
| FunctionGenericParameters ~ FunctionInputParameters?
| InputParameters
}
InterfaceFunction = {
(
Static
| Cons
| ( Mut ~ Ref? )
)?
~ Fn
~ GenericParameters?
~ Identifier
~ Parameters
~ ReturnType
~ WhereGuards?
}
InterfaceDefaultFunction = {
Def
~ (
Static
| Cons
| ( Mut ~ Ref? )
)?
~ Fn
~ GenericParameters?
~ Identifier
~ Parameters
~ ReturnType
~ WhereGuards?
~ FunctionBody
}
InterfaceOperatorFunction = {
(
Cons
| ( Mut ~ Ref? )
)?
~ Op
~ Operator
~ Parameters
~ ReturnType
~ RefList?
~ WhereGuards? // TODO: decide if we want this for interface op functions
}
InterfaceDefaultOperatorFunction = {
Def
~ (
Cons
| ( Mut ~ Ref? )
)?
~ Op
~ Operator
~ Parameters
~ ReturnType
~ RefList?
~ WhereGuards?
~ FunctionBody
}
// Class constructs
ClassConstructor = {
"("
~ DataMember
~ ( "," ~ DataMember )*
~ ")"
}
DataMember = {
Property
| Field
}
Property = {
Mut?
~ Identifier
~ ":"
~ TypeUse
}
Field = {
Mut?
~ Fld
~ Identifier
~ ":"
~ TypeUse
}
// Function constructs
FunctionModifier = {
Static
| Cons
| Mut? ~ Ref?
}
FunctionDefinition = {
Pub?
~ FunctionModifier
~ Fn
~ GenericParameters?
~ Identifier
~ Parameters
~ ReturnType?
~ FunctionBody
}
OperatorFunctionDefinition = {
Pub?
~ FunctionModifier
~ Op
~ Operator
~ Parameters
~ ReturnType?
~ FunctionBody
}
PlatformFunction = {
Pub?
~ FunctionModifier
~ Platform
~ Fn
~ GenericParameters
~ Identifier
~ Parameters
~ ReturnType
}
Parameters = {
"("
~ (
Parameter
~ ( "," ~ Parameter )*
)?
~ ")"
}
Parameter = {
Identifier
~ ":"
~ TypeUse
}
ReturnType = {
"->"
~ ( Void | TypeUse )
~ RefList?
}
FunctionBody = {
FunctionEqualsBody
| FunctionBlockBody
| FunctionAliasBody
}
FunctionEqualsBody = {
"="
~ Expression
}
FunctionBlockBody = {
"{"
~ Statement*
~ "}"
}
FunctionAliasBody = {
"alias"
~ Identifier
}
// Statements
BlockStatement = {
"{"
~ Statement*
~ "}"
}
Statement = {
BlockStatement
| VariableDeclaration
| AssignmentExpression
}
VariableDeclaration = {
Let
~ Mut?
~ Identifier
~ ( ":" ~ TypeUse )?
~ ( "=" ~ Expression )?
}
// Expressions
Expression = { OrExpression }
OrExpression = {
AndExpression
~ ( Or ~ Expression )*
}
AndExpression = {
EqualityExpression
~ ( And ~ Expression )*
}
EqualityExpression = {
ComparisonExpression
~ (
( EqualTo | NotEqualTo )
~ Expression
)*
}
ComparisonExpression = {
AdditiveExpression
~ (
( Greater | Less | GreaterEqual | LessEqual )
~ Expression
)*
}
AdditiveExpression = {
MultiplicativeExpression
~ (
( Add | Subtract )
~ Expression
)*
}
MultiplicativeExpression = {
SpreadExpression
~ (
( Multiply | Divide | Modulo )
~ Expression
)*
}
SpreadExpression = {
UnaryExpression
~ Spread
~ Expression
}
UnaryExpression = {
( Not | Negative )*
~ PrimaryExpression
~ ( ( NoParenthesesCall | ParenthesesCall )+ | ( PlusPlus | MinusMinus ) )?
}
PrimaryExpression = {
Literal
| ObjectAccess
| ParenthesizedExpression
}
ParenthesizedExpression = {
"("
~ Expression
~ ")"
}
// Calls
ParenthesesCall = {
TurboFish?
~ "("
~ ExpressionList?
~ ")"
}
NoParenthesesCall = {
TurboFish?
~ ExpressionList
}
TurboFish = {
"::"
~ GenericArguments
}
ExpressionList = {
Expression
~ ( "," ~ Expression )*
}
// Assignment
AssignmentExpression = { ObjectAccess ~ "=" ~ Expression }
AssignmentExpression = {
ObjectAccess
~ "="
~ Expression
}
// Object
ObjectAccess = { FullyQualifiedName ~ ( "." ~ Identifier )* }
ObjectAccess = {
FullyQualifiedName
~ ( "." ~ Identifier )*
}
// Literals
Literal = { NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral }
Literal = {
NumberLiteral
| StringLiteral
| BooleanLiteral
}
NumberLiteral = { LongLiteral | IntLiteral }
NumberLiteral = {
LongLiteral
| IntLiteral
| DoubleLiteral
}
IntLiteral = { NumberBase }
LongLiteral = ${ NumberBase ~ "L" }
NumberBase = { DecimalBase | BinaryBase | HexadecimalBase }
DoubleLiteral = ${ DecimalBase ~ "." ~ Digit+ }
NumberBase = {
DecimalBase
| BinaryBase
| HexadecimalBase
}
DecimalBase = @{ DecimalStartDigit ~ Digit* }
BinaryBase = @{ "0b" ~ Digit* }
DecimalStartDigit = { '1'..'9' }
Digit = { '0'..'9'+ }
HexadecimalBase = @{ "0x" ~ HexadecimalDigit+ }
HexadecimalDigit = { '0'..'9' | 'a'..'f' }
StringLiteral = ${ "\"" ~ StringInner ~ "\"" }
StringInner = @{ StringChar* }
StringChar = {
!( "\"" | "\\" ) ~ ANY
| "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" )
@ -143,6 +783,4 @@ StringChar = {
BooleanLiteral = { "true" | "false" }
NullLiteral = { "null" }
WHITESPACE = _{ " " | "\t" | "\n" | "\r" }

View File

@ -51,7 +51,10 @@ mod deimos_parser_tests {
}
fn parse(rule: Rule, input: &str) -> Pair<Rule> {
let pair = DeimosParser::parse(rule, input).unwrap().next().unwrap();
let pair = DeimosParser::parse(rule, input)
.expect("Parsing failed.")
.next()
.unwrap();
dbg!(&pair);
pair
}
@ -83,7 +86,7 @@ mod deimos_parser_tests {
match_rule!(call; Rule::Call);
});
}
#[test]
fn identifier_call_as_call_expression() {
let pair = parse(Rule::CallExpression, "foo()");
@ -94,4 +97,30 @@ mod deimos_parser_tests {
let call = call_expression_pairs.next().unwrap();
match_rule!(call; Rule::Call);
}
mod smoke_screen_tests {
use crate::parser::deimos_parser_tests::parse;
use crate::parser::Rule;
#[test]
fn simple_interface() {
parse(Rule::CompilationUnit, "pub int Simple { fn foo() -> Void }");
}
#[test]
fn interface_with_op() {
parse(
Rule::CompilationUnit,
"pub int Callable { op () () -> Void }",
);
}
#[test]
fn interface_with_alias() {
parse(
Rule::CompilationUnit,
"pub int Callable {\n fn call() -> Void\n op () () -> Void alias call\n}",
);
}
}
}