diff --git a/src/ast/build.rs b/src/ast/build.rs index b030c53..71cad7b 100644 --- a/src/ast/build.rs +++ b/src/ast/build.rs @@ -1,8 +1,8 @@ use crate::ast::{ - CompilationUnit, DelegateOrIdentifier, Fqn, FunctionModifier, FunctionTypeUse, GenericArgument, - GenericArguments, GenericParameter, GenericParameters, Identifier, InputArgument, - InputArguments, InterfaceOrClassTypeUse, Reference, References, ReturnType, TupleTypeUse, - TypeUse, VoidOrTypeUse, + CompilationUnit, DelegateOrIdentifier, FullyQualifiedName, FunctionModifier, FunctionTypeUse, + GenericArgument, GenericArguments, GenericParameter, GenericParameters, Identifier, + InputArgument, InputArguments, InterfaceOrClassTypeUse, Reference, References, ReturnType, + TupleTypeUse, TypeUse, VoidOrTypeUse, }; use crate::parser::Rule; use pest::iterators::Pair; @@ -24,7 +24,7 @@ fn build_identifier(identifier_pair: Pair) -> Identifier { } } -fn build_fqn(fqn_pair: Pair) -> Fqn { +fn build_fqn(fqn_pair: Pair) -> FullyQualifiedName { let mut identifiers: Vec = vec![]; for identifier_pair in fqn_pair.into_inner() { identifiers.push(expect_and_use( @@ -33,7 +33,7 @@ fn build_fqn(fqn_pair: Pair) -> Fqn { build_identifier, )); } - Fqn { identifiers } + FullyQualifiedName { identifiers } } fn build_type_use(type_use_pair: Pair) -> TypeUse { diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 644bf76..2dc7beb 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -8,7 +8,8 @@ pub mod unparse; #[derive(Debug)] pub enum Operator { Binary(BinaryOperator), - Unary(UnaryOperator), + PrefixUnary(PrefixUnaryOperator), + SuffixUnary(SuffixUnaryOperator), } #[derive(Debug)] @@ -31,16 +32,21 @@ pub enum BinaryOperator { } #[derive(Debug)] -pub enum UnaryOperator { +pub enum PrefixUnaryOperator { + Spread, + Borrow, + BorrowMut, Not, Negative, - PlusPlus, - MinusMinus, - CallOp, - Spread, } -// Names +#[derive(Debug)] +pub enum SuffixUnaryOperator { + PlusPlus, + MinusMinus, +} + +/* Names */ #[derive(Debug, Clone)] pub struct Identifier { @@ -48,48 +54,11 @@ pub struct Identifier { } #[derive(Debug)] -pub struct Fqn { +pub struct FullyQualifiedName { pub identifiers: Vec, } -// Generic parameters - -#[derive(Debug)] -pub struct GenericParameters(pub Vec); - -impl GenericParameters { - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -#[derive(Debug)] -pub struct GenericParameter(Identifier); - -// Generic arguments - -#[derive(Debug)] -pub struct GenericArguments(pub Vec); - -impl GenericArguments { - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -#[derive(Debug)] -pub struct GenericArgument { - pub fqn: Fqn, -} - -// Type-use and components - -// #[derive(Debug)] -// pub struct TypeUse { -// pub fqn: Fqn, -// pub arguments: Option, -// pub inputs: Option, -// } +/* Type Use */ #[derive(Debug)] pub enum TypeUse { @@ -100,7 +69,7 @@ pub enum TypeUse { #[derive(Debug)] pub struct InterfaceOrClassTypeUse { - pub fqn: Fqn, + pub fqn: FullyQualifiedName, pub generics: GenericArguments, } @@ -116,26 +85,68 @@ pub struct FunctionTypeUse { pub return_type: ReturnType, } -#[derive(Debug)] -pub enum TypeArguments { - Generics(GenericArguments), - Tuple(TupleArguments), - Function(FunctionTypeArguments), -} +// Generic arguments #[derive(Debug)] -pub struct TupleArguments(pub Vec); +pub struct GenericArguments(pub Vec); -impl TupleArguments { +impl GenericArguments { pub fn is_empty(&self) -> bool { self.0.is_empty() } } #[derive(Debug)] -pub struct FunctionTypeArguments { - pub parameters: TupleParameters, - pub return_type: Box, +pub struct GenericArgument { + pub fqn: FullyQualifiedName, +} + +/* Function Modifier */ + +#[derive(Debug)] +pub enum FunctionModifier { + Static, + Cons, + Mut, + Ref, + MutRef, +} + +/* Generic parameters */ + +#[derive(Debug)] +pub struct GenericParameters(pub Vec); + +impl GenericParameters { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +#[derive(Debug)] +pub struct GenericParameter(Identifier); + +/* Input Arguments */ + +#[derive(Debug)] +pub struct InputArguments(pub Vec); + +impl InputArguments { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +#[derive(Debug)] +pub struct InputArgument { + pub lhs: DelegateOrIdentifier, + pub rhs: Identifier, +} + +#[derive(Debug)] +pub enum DelegateOrIdentifier { + Delegate, + Identifier(Identifier), } // Function components @@ -179,54 +190,13 @@ impl References { #[derive(Debug)] pub struct Reference(pub Identifier); -// Inputs +/* Input Parameters */ #[derive(Debug)] -pub enum DelegateOrIdentifier { - Delegate, - Identifier(Identifier), -} +pub struct InputParameters(pub Vec); #[derive(Debug)] -pub struct InputParameters(pub Vec); - -impl InputParameters { - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -#[derive(Debug)] -pub struct InputArguments(pub Vec); - -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); - -impl WhereGuards { - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -#[derive(Debug)] -pub struct WhereGuard { - pub identifier: Identifier, - pub implements: ImplementsList, -} +pub struct InputParameter(pub TypeUse); // Implements @@ -243,7 +213,7 @@ impl ImplementsList { #[derive(Debug)] pub struct CompilationUnit { - pub namespace: Option, + pub namespace: Option, pub declarations: Vec, } @@ -287,8 +257,8 @@ pub enum ClassLevelDeclaration { pub struct TypeDeclaration { pub is_public: bool, pub identifier: Identifier, - pub parameters: Option, - pub where_guards: WhereGuards, + pub lhs: TypeUse, + pub where_guards: TypeWhereGuards, pub rhs: TypeUse, } @@ -305,8 +275,8 @@ pub struct InterfaceDeclaration { pub identifier: Identifier, pub generics: GenericParameters, pub inputs: InputParameters, + pub return_type: Option, pub implements: ImplementsList, - pub where_guards: WhereGuards, pub declarations: Vec, } @@ -316,30 +286,68 @@ pub struct ClassDeclaration { pub identifier: Identifier, pub generics: GenericParameters, pub class_constructor: Option, - pub inputs: InputArguments, pub implements: ImplementsList, - pub where_guards: WhereGuards, pub declarations: Vec, } +// Type components + +#[derive(Debug)] +pub struct TypeWhereGuards(pub Vec); + +#[derive(Debug)] +pub struct TypeWhereGuard { + pub identifier: Identifier, + pub implements: TypeImplementsList, +} + +#[derive(Debug)] +pub struct TypeImplementsList(pub Vec); + +#[derive(Debug)] +pub struct TypeImplements { + pub fqn: FullyQualifiedName, + pub arguments: TypeImplementsArguments, +} + +#[derive(Debug)] +pub enum TypeImplementsArguments { + Generic(TypeGenericArguments), + Tuple(TypeTupleArguments), + Function(TypeFunctionArguments), +} + +#[derive(Debug)] +pub struct TypeGenericArguments(pub Vec); + +#[derive(Debug)] +pub enum TypeGenericArgument { + Underscore, + FullyQualifiedName(FullyQualifiedName), + Infer(Identifier), +} + +#[derive(Debug)] +pub struct TypeTupleArguments(pub Vec); + +#[derive(Debug)] +pub enum TypeTupleArgument { + Underscore, + FullyQualifiedName(FullyQualifiedName), + Infer(Identifier), + EllipsisUnderscore, + EllipsisInfer(Identifier), +} + +#[derive(Debug)] +pub struct TypeFunctionArguments { + pub generics: GenericArguments, + pub parameters: TypeTupleArguments, + pub return_type: ReturnType, +} + // 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, @@ -390,22 +398,13 @@ pub struct InterfaceOperatorFunctionDeclaration { pub return_type: ReturnType, } -// Type components +// TODO: default interface functions #[derive(Debug)] -pub enum TypeParameters { - Generic(GenericParameters), - Tuple(TupleParameters), - Function(FunctionTypeParameters), -} - -#[derive(Debug)] -pub struct TupleParameters(pub Vec); - -#[derive(Debug)] -pub struct FunctionTypeParameters { - pub parameters: Parameters, - pub return_type: TypeUse, +pub enum FunctionBody { + Equals(Expression), + Block(BlockStatement), + Alias(Identifier), } // Class components @@ -435,9 +434,9 @@ pub struct BlockStatement(pub Vec); #[derive(Debug)] pub enum Statement { BlockStatement(BlockStatement), - CallStatement(CallExpression), VariableDeclarationStatement(VariableDeclarationStatement), AssignStatement(AssignStatement), + CallStatement(CallExpression), ReturnStatement(ReturnStatement), IfStatement(IfStatement), IfElseStatement(IfElseStatement), @@ -462,15 +461,15 @@ pub struct ReturnStatement(pub Option); #[derive(Debug)] pub struct IfStatement { pub condition: Expression, - pub then_branch: BlockStatement, + pub then_block: BlockStatement, } #[derive(Debug)] pub struct IfElseStatement { pub condition: Expression, - pub then_branch: BlockStatement, + pub then_block: BlockStatement, pub else_ifs: ElseIfs, - pub else_branch: BlockStatement, + pub else_block: BlockStatement, } #[derive(Debug)] @@ -493,6 +492,7 @@ pub struct ForStatement { #[derive(Debug)] pub enum Expression { + Ternary(TernaryExpression), Binary(BinaryExpression), Unary(UnaryExpression), Assignment(Box), @@ -500,6 +500,13 @@ pub enum Expression { Literal(Literal), } +#[derive(Debug)] +pub struct TernaryExpression { + pub condition: Box, + pub true_block: Box, + pub false_block: Box, +} + #[derive(Debug)] pub struct BinaryExpression { pub left: Box, @@ -509,8 +516,9 @@ pub struct BinaryExpression { #[derive(Debug)] pub struct UnaryExpression { - pub operator: UnaryOperator, + pub lhs_operators: Vec, pub expression: Box, + pub rhs_operators: Vec, } #[derive(Debug)] diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index 4e4ff73..6f97efa 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -20,6 +20,13 @@ Delegate = { "delegate" } Let = { "let" } Fn = { "fn" } Op = { "op" } +Return = { "return" } +If = { "if" } +Else = { "else" } +While = { "while" } +For = { "for" } +In = { "in" } +Move = { "move" } // Keywords as a rule (for preventing identifiers with keywords, etc.) Keyword = { @@ -44,11 +51,19 @@ Keyword = { | Let | Fn | Op + | Return + | If + | Else + | While + | For + | In + | Move } // Symbols Ellipsis = { "..." } Underscore = { "_" } +Semicolon = { ";" } // Operators Or = { "||" } @@ -70,6 +85,10 @@ PlusPlus = { "++" } MinusMinus = { "--" } CallOp = { "()" } Spread = { Ellipsis } +Borrow = { "&" } +Star = { "*" } +LeftShift = { "<<" } +RightShift = { ">>" } Operator = { Or @@ -91,15 +110,12 @@ Operator = { | MinusMinus | CallOp | Spread + | Borrow + | Star } // Commonly shared constructs -FullyQualifiedName = { - Identifier - ~ ( "::" ~ Identifier )* -} - Identifier = @{ ( Keyword ~ IdentifierChar | !Keyword ~ IdentifierStartChar ) ~ IdentifierChar* @@ -118,14 +134,25 @@ IdentifierChar = { | "_" } +FullyQualifiedName = { + Identifier + ~ ( "::" ~ Identifier )* +} + // In general: // Arguments = usage // Parameters = declaration TypeUse = { - InterfaceOrClassTypeUse - | TupleTypeUse - | FunctionTypeUse + ( + Mut + | ( Borrow ~ Mut? )* + )? + ~ ( + InterfaceOrClassTypeUse + | TupleTypeUse + | FunctionTypeUse + ) } InterfaceOrClassTypeUse = { @@ -151,12 +178,7 @@ FunctionTypeUse = { ~ ReturnType } -FunctionTypeModifier = { - Cons - | Mut ~ Ref - | Mut - | Ref -} +// Generic Arguments GenericArguments = { "<" @@ -165,40 +187,6 @@ GenericArguments = { ~ ">" } -InputArguments = { - "|" - ~ ( - InputArgument - ~ ( "," ~ InputArgument )* - )? - ~ "|" -} - -InputArgument = { - Identifier - ~ ( "=" ~ Identifier ) -} - -RefList = { - Ref - ~ Identifier - ~ ( "," ~ Identifier )* -} - -FunctionInputArguments = { - "|" - ~ ( - FunctionInputArgument - ~ ( "," ~ FunctionInputArgument )* - )? - ~ "|" -} - -FunctionInputArgument = { - ( Delegate | Identifier ) - ~ ( "=" ~ Identifier ) -} - // Generic Parameters GenericParameters = { @@ -208,67 +196,75 @@ GenericParameters = { ~ ">" } -InputParameters = { +// Function Input Arguments + +FunctionInputArguments = { "|" - ~ InputParameter - ~ ( "," ~ InputParameter )* + ~ ( + FunctionInputArgument + ~ ( "," ~ FunctionInputArgument )* + )? ~ "|" } -InputParameter = { - Identifier - ~ ":" - ~ TypeUse +FunctionInputArgument = { + ( Delegate ~ "=" ~ Identifier ) + | Identifier } -TupleGenericParameters = { +// Function type components + +FunctionTypeModifier = { + Cons + | Mut ~ Ref + | Mut + | Ref +} + +Parameters = { "(" ~ ( - Identifier - ~ ( "," ~ Identifier )* + Parameter + ~ ( "," ~ Parameter )* )? ~ ")" } -FunctionGenericParameters = { - TupleGenericParameters - ~ FunctionGenericParameterReturnType -} - -FunctionGenericParameterReturnType = { - "->" - ~ ( Void | Identifier ) - ~ RefList? -} - -FunctionInputParameters = { - "|" - ~ FunctionInputParameter - ~ ( "," ~ FunctionInputParameter )* - ~ "|" -} - -FunctionInputParameter = { - ( Delegate | Identifier ) +Parameter = { + Identifier ~ ":" ~ TypeUse } +ReturnType = { + "->" + ~ ( Void | TypeUse ) + ~ RefList? +} + +RefList = { + Ref + ~ Identifier + ~ ( "," ~ Identifier )* +} + +// Input Parameters + +InputParameters = { + "(" + ~ ( + TypeUse + ~ ( "," ~ TypeUse )* + )? + ~ ")" +} + +// Implements list + ImplementsList = { ":" ~ TypeUse - ~ ( "+" ~ TypeUse ) -} - -WhereGuards = { - Where - ~ WhereGuard - ~ ( "," ~ WhereGuard )* -} - -WhereGuard = { - Identifier - ~ ImplementsList + ~ ( "+" ~ TypeUse )* } // Top-level constructs @@ -324,7 +320,7 @@ Type = { Pub? ~ TypeKw ~ Identifier - ~ GenericParameters? + ~ TypeUse ~ TypeWhereGuards? ~ "=" ~ TypeUse @@ -341,9 +337,10 @@ Interface = { Pub? ~ Int ~ Identifier - ~ InterfaceGenericParametersAndInputs? + ~ GenericParameters? + ~ InputParameters? + ~ ReturnType? ~ ImplementsList? - ~ WhereGuards? ~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )? } @@ -354,8 +351,6 @@ Class = { ~ GenericParameters? ~ ClassConstructor? ~ ImplementsList? - ~ InputArguments? - ~ WhereGuards? ~ ( "{" ~ ClassLevelDeclaration* ~ "}" )? } @@ -370,19 +365,23 @@ TypeWhereGuards = { TypeWhereGuard = { Identifier ~ ":" - ~ TypeTypeUse - ~ ( "+" ~ TypeTypeUse )* + ~ TypeImplementsList } -TypeTypeUse = { +TypeImplementsList = { + TypeImplements + ~ ( "+" ~ TypeImplements )* +} + +TypeImplements = { FullyQualifiedName - ~ TypeTypeArguments? + ~ TypeImplementsArguments? } -TypeTypeArguments = { +TypeImplementsArguments = { TypeGenericArguments - | TypeGenericFunctionArguments - | TypeGenericTupleArguments + | TypeTupleArguments + | TypeFunctionArguments } TypeGenericArguments = { @@ -398,16 +397,16 @@ TypeGenericArgument = { | ( Infer ~ Identifier ) } -TypeGenericTupleArguments = { +TypeTupleArguments = { "(" ~ ( - TypeGenericTupleArgument - ~ ( "," ~ TypeGenericTupleArgument )* + TypeTupleArgument + ~ ( "," ~ TypeTupleArgument )* )? ~ ")" } -TypeGenericTupleArgument = { +TypeTupleArgument = { Underscore | FullyQualifiedName | ( Infer ~ Identifier ) @@ -415,120 +414,13 @@ TypeGenericTupleArgument = { | ( 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 +TypeFunctionArguments = { + TypeGenericArguments? + ~ TypeTupleArguments ~ 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? @@ -562,30 +454,68 @@ PlatformFunction = { ~ ReturnType } -Parameters = { - "(" - ~ ( - Parameter - ~ ( "," ~ Parameter )* +InterfaceFunction = { + ( + Static + | Cons + | ( Mut ~ Ref? ) )? - ~ ")" + ~ Fn + ~ GenericParameters? + ~ Identifier + ~ Parameters + ~ ReturnType } -Parameter = { - Identifier - ~ ":" - ~ TypeUse +InterfaceDefaultFunction = { + Def + ~ ( + Static + | Cons + | ( Mut ~ Ref? ) + )? + ~ Fn + ~ GenericParameters? + ~ Identifier + ~ Parameters + ~ ReturnType + ~ FunctionBody } -ReturnType = { - "->" - ~ ( Void | TypeUse ) +InterfaceOperatorFunction = { + ( + Cons + | ( Mut ~ Ref? ) + )? + ~ Op + ~ Operator + ~ Parameters + ~ ReturnType +} + +InterfaceDefaultOperatorFunction = { + Def + ~ ( + Cons + | ( Mut ~ Ref? ) + )? + ~ Op + ~ Operator + ~ Parameters + ~ ReturnType ~ RefList? + ~ FunctionBody +} + +FunctionModifier = { + Static + | Cons + | Mut? ~ Ref? } FunctionBody = { FunctionEqualsBody - | FunctionBlockBody + | BlockStatement | FunctionAliasBody } @@ -594,29 +524,62 @@ FunctionEqualsBody = { ~ Expression } -FunctionBlockBody = { - "{" - ~ Statement* - ~ "}" -} - FunctionAliasBody = { "alias" ~ Identifier } +// Class constructs + +ClassConstructor = { + "(" + ~ DataMember + ~ ( "," ~ DataMember )* + ~ ")" +} + +DataMember = { + Property + | Field +} + +Property = { + Mut? + ~ Identifier + ~ ":" + ~ TypeUse +} + +Field = { + Mut? + ~ Fld + ~ Identifier + ~ ":" + ~ TypeUse +} + // Statements BlockStatement = { "{" ~ Statement* + ~ Expression? ~ "}" } Statement = { - BlockStatement - | VariableDeclaration - | AssignmentExpression + ( + BlockStatement + | VariableDeclaration + | AssignmentStatement + | CallStatement + | ReturnStatement + | IfStatement + | IfElseStatement + | WhileStatement + | ForStatement + )? + ~ Semicolon } VariableDeclaration = { @@ -627,26 +590,76 @@ VariableDeclaration = { ~ ( "=" ~ Expression )? } +AssignmentStatement = { + Expression + ~ "=" + ~ Expression +} + +CallStatement = { PrimaryExpression } + +ReturnStatement = { + Return + ~ Expression? +} + +IfStatement = { + If + ~ Expression + ~ BlockStatement +} + +IfElseStatement = { + If + ~ Expression + ~ BlockStatement + ~ ( Else ~ IfStatement )* + ~ Else + ~ BlockStatement +} + +WhileStatement = { + While + ~ Expression + ~ BlockStatement +} + +ForStatement = { + For + ~ Expression + ~ In + ~ Expression + ~ BlockStatement +} + // Expressions -Expression = { OrExpression } +Expression = { + TernaryExpression + | OrExpression +} + +TernaryExpression = { + ( OrExpression | ParenthesizedExpression ) + ~ "?" + ~ Expression + ~ ":" + ~ Expression +} OrExpression = { AndExpression - ~ ( Or ~ Expression )* + ~ ( Or ~ Expression )? } AndExpression = { EqualityExpression - ~ ( And ~ Expression )* + ~ ( And ~ Expression )? } EqualityExpression = { ComparisonExpression - ~ ( - ( EqualTo | NotEqualTo ) - ~ Expression - )* + ~ ( ( EqualTo | NotEqualTo ) ~ Expression )? } ComparisonExpression = { @@ -654,7 +667,12 @@ ComparisonExpression = { ~ ( ( Greater | Less | GreaterEqual | LessEqual ) ~ Expression - )* + )? +} + +ShiftExpression = { + AdditiveExpression + ~ ( ( LeftShift | RightShift ) ~ Expression )? } AdditiveExpression = { @@ -662,33 +680,38 @@ AdditiveExpression = { ~ ( ( Add | Subtract ) ~ Expression - )* + )? } MultiplicativeExpression = { - SpreadExpression + UnaryExpression ~ ( ( Multiply | Divide | Modulo ) ~ Expression - )* -} - -SpreadExpression = { - UnaryExpression - ~ Spread - ~ Expression + )? } UnaryExpression = { - ( Not | Negative )* + ( + Spread + | ( Borrow ~ Mut ) + | Borrow + | Mut + | Not + | Negative + )* ~ PrimaryExpression - ~ ( ( NoParenthesesCall | ParenthesesCall )+ | ( PlusPlus | MinusMinus ) )? + ~ ( PlusPlus | MinusMinus )* } PrimaryExpression = { - Literal - | ObjectAccess - | ParenthesizedExpression + ( + Literal + | FullyQualifiedName + | Closure + | ParenthesizedExpression + ) + ~ ExpressionSuffix? } ParenthesizedExpression = { @@ -697,6 +720,18 @@ ParenthesizedExpression = { ~ ")" } +ExpressionSuffix = { + ObjectAccess + ~ ( ParenthesesCall ~ ObjectAccess? )* + | ( ParenthesesCall ~ ObjectAccess? )+ +} + +ObjectAccess = { + "." + ~ Identifier + ~ ( "." ~ Identifier )* +} + // Calls ParenthesesCall = { @@ -704,11 +739,7 @@ ParenthesesCall = { ~ "(" ~ ExpressionList? ~ ")" -} - -NoParenthesesCall = { - TurboFish? - ~ ExpressionList + ~ Closure? } TurboFish = { @@ -721,20 +752,46 @@ ExpressionList = { ~ ( "," ~ Expression )* } -// Assignment -AssignmentExpression = { - ObjectAccess - ~ "=" - ~ Expression +// Closure + +Closure = { + ( Cons | Mut )? + ~ Move? + ~ ClosureCaptures? + ~ "{" + ~ ( ClosureParameters? ~ "->" )? + ~ Statement* + ~ Expression? + ~ "}" } -// Object -ObjectAccess = { - FullyQualifiedName - ~ ( "." ~ Identifier )* +ClosureParameters = { + ClosureParameter + ~ ( "," ~ ClosureParameter )* +} + +ClosureParameter = { + Identifier + ~ ( ":" ~ TypeUse )? +} + +ClosureCaptures = { + "|" + ~ ClosureCapture + ~ ( "," ~ ClosureCapture )* + ~ "|" +} + +ClosureCapture = { + ( + Mut + | ( Borrow ~ Mut? )* + )? + ~ Identifier } // Literals + Literal = { NumberLiteral | StringLiteral @@ -742,9 +799,9 @@ Literal = { } NumberLiteral = { - LongLiteral + DoubleLiteral + | LongLiteral | IntLiteral - | DoubleLiteral } IntLiteral = { NumberBase } @@ -754,18 +811,21 @@ LongLiteral = ${ NumberBase ~ "L" } DoubleLiteral = ${ DecimalBase ~ "." ~ Digit+ } NumberBase = { - DecimalBase - | BinaryBase + BinaryBase | HexadecimalBase + | DecimalBase } -DecimalBase = @{ DecimalStartDigit ~ Digit* } +DecimalBase = @{ + "0" + | DecimalStartDigit ~ Digit* +} -BinaryBase = @{ "0b" ~ Digit* } +BinaryBase = @{ "0b" ~ Digit+ } DecimalStartDigit = { '1'..'9' } -Digit = { '0'..'9'+ } +Digit = @{ '0'..'9'+ } HexadecimalBase = @{ "0x" ~ HexadecimalDigit+ }