(* Grammar definition in EBNF format. *) Program = {Statement} EOF; (* Statement *) Statement = ExpressionStatement | ReturnStatement | BreakStatement | ContinueExpression | PrintStatement; ExpressionStatement = Expression ";"; ReturnStatement = "return" Expression ";"; BreakStatement = "break" [Expression] ";"; ContinueStatement = "continue" ";"; (* NOTE: Hard-coded PrintStatement until Rabbithole has an standard library *) PrintStatement = "print" Expression ";"; (* Expression *) Expression = AssignmentExpression; (* Expressions affected by precedence*) (* NOTE: Only allow IDENTIFIERs and their fields as the LValue for now. *) AssignmentExpression = IDENTIFIER {"." IDENTIFIER} ("=" | ":=") AssignmentExpression | EqualityExpression; EqualityExpression = ComparisonExpression { ("==" | "!=") ComparisonExpression }; ComparisonExpression = TermExpression { ("<" | "<=" | ">" | ">=") TermExpression }; TermExpression = FactorExpression { ("+" | "-") FactorExpression }; FactorExpression = UnaryExpression { ("*" | "/") UnaryExpression }; UnaryExpression = ( "-" | "!" ) UnaryExpression | PostfixExpression ; PostfixExpression = UnitExpression { ( "(" [FnCallArguments] ")" | "[" Expression "]" | "." IDENTIFIER ) }; (* Unaffected Expressions *) UnitExpression = FLOAT | INT | STR | TRUE | FALSE | GroupExpression | BlockExpression | FnExpression | TypeExpression | FormExpression | IfExpression; GroupExpression = "(" Expression ")"; BlockExpression = Block; FnExpression = "fn" FnHeader Block; TypeExpression = "type" TypeBlock; (* NOTE: Will associated functions clash with fields? *) FormExpression = "form" TypeBlock; IfExpression = "if" Expression Block { "elif" Expression Block } [ "else" Block ]; LoopExpression = "loop" ["if" Expression] Block; (* Parts *) FnHeader = (FnParameters) ["->" Type]; FnParameters = ("self" | FnParameter) { "," FnParameter}; FnCallArguments = Expression { "," Expression }; (* Utils *) Block = "{" { Statement } [Expression] "}"; TypeBlock = "{" [ TypedIdentifier ] { "," TypedIdentifier } "}"; TypedIdentifier = IDENTIFIER [":" Type]; (* NOTE: Type doesn't include anything other than simple named types for now. *) Type = IDENTIFIER;