roost-lang 2.0.4

Interpreter library for the roost language
Documentation
(*
  -- Grammar for Roost v2 --

  Author: RubixDev
*)

Program      = Statements ;
(* The end of <Statements> is indicated by a following `Eof` or `RBrace` token *)
Statements   = [ Statement , { EOL , Statement } , [ EOL ] ] ;
Block        = BlockExpr | Statement ;

(**************************)
(******* STATEMENTS *******)
(**************************)
Statement    = VarStmt
             | FunctionDecl
             | ClassDecl
             | BreakStmt
             | ContinueStmt
             | ReturnStmt
             | Expression ;
VarStmt      = 'var' , identifier , [ '=' , Expression ] ;
FunctionDecl = 'fun' , identifier , Params , Block ;
ClassDecl    = 'class' , identifier , MemberBlock ;
BreakStmt    = 'break' , [ Expression ] ;
ContinueStmt = 'continue' ;
ReturnStmt   = 'return' , [ Expression ] ;

(*****************************)
(******* CLASS MEMBERS *******)
(*****************************)
Member = [ 'static' ] , ( FunctionDecl | VarStmt ) ;
MemberBlock = '{' , { Member , EOL } , '}' ;

(***************************)
(******* EXPRESSIONS *******)
(***************************)
Expression  = RangeExpr ;
RangeExpr   = OrExpr
            | OrExpr , ( '..' | '..=' ) , OrExpr
            | OrExpr , '..'
            | ( '..' | '..=' ) , OrExpr
            | '..' ;
OrExpr      = AndExpr , { '||' , AndExpr } ;
AndExpr     = BitOrExpr , { '&&' , BitOrExpr } ;
BitOrExpr   = BitXorExpr , { '|' , BitXorExpr } ;
BitXorExpr  = BitAndExpr , { '^' , BitAndExpr } ;
BitAndExpr  = EqExpr , { '&' , EqExpr } ;
EqExpr      = RelExpr , [ ( '==' | '!=' ) , RelExpr ] ;
RelExpr     = ShiftExpr , [ ( '<' | '>' | '<=' | '>=' ) , ShiftExpr ] ;
ShiftExpr   = AddExpr , { ( '<<' | '>>' ) , AddExpr } ;
AddExpr     = MulExpr , { ( '+' | '-' ) , MulExpr } ;
MulExpr     = UnaryExpr , { ( '*' | '/' | '%' | '\' ) , UnaryExpr } ;
UnaryExpr   = ( '+' | '-' | '!' ) , UnaryExpr
            | ExpExpr ;
ExpExpr     = AssignExpr , [ '**' , UnaryExpr ] ;
AssignExpr  = CallExpr , [ ASSIGN_OPERATOR , Expression ] ;
ASSING_OPERATOR = '=' | '*=' | '/=' | '\=' | '%=' | '+=' | '-='
                | '<<=' | '>>=' | '&=' | '^=' | '|=' | '**=' ;
CallExpr    = MemberExpr , [ Args , { CallPart } ] ;
MemberExpr  = Atom , { MemberPart } ;
Atom        = number
            | bool
            | string
            | 'null'
            | identifier
            | '(' , Expression , ')'
            | ListLiteral
            | IfExpr
            | ForExpr
            | WhileExpr
            | LoopExpr
            | FunExpr
            | ClassExpr
            | TryExpr
            | BlockExpr ;
ListLiteral = '[' , [ Expression , { ',' , Expression } , [ ',' ] ] , ']' ;
IfExpr      = 'if' , '(' , Expression , ')' , Block , [ 'else' , Block ] ;
ForExpr     = 'for' , '(' , identifier , 'in' , Expression , ')' , Block ;
WhileExpr   = 'while' , '(' , Expression , ')' , Block ;
LoopExpr    = 'loop' , Block ;
FunExpr     = 'fun' , Params , Block ;
ClassExpr   = 'class' , MemberBlock ;
TryExpr     = 'try' , Block , 'catch' , '(' , identifier , ')' , Block ;
BlockExpr   = '{' , Statements , '}' ;

(*********************)
(******* OTHER *******)
(*********************)
MemberPart = '.' , identifier
           | '[' , Expression , ']' ;
CallPart   = MemberPart | Args ;
Args       = '(' , [ Expression , { ',' , Expression } , [ ',' ] ] , ')' ;
Params     = '(' , [ identifier , { ',' , identifier } , [ ',' ] ] , ')' ;

(**********************************)
(******* NONTERMINAL TOKENS *******)
(**********************************)
number      = DIGIT , { DIGIT | '_' } , [ '.' , DIGIT , { DIGIT | '_' } ]
            | '.' , DIGIT , { DIGIT , | '_' } ;
string      = '"' , { CHAR - ( '"' | '\' ) | escape_seq } , '"'
            | "'" , { CHAR - ( "'" | '\' ) | escape_seq } , "'" ;
escape_seq  = '\' , ( ESCAPE_CHAR
                    | 3 * OCTAL
                    | 'x' , 2 * HEX
                    | 'u' , 4 * HEX
                    | 'U' , 8 * HEX ) ;
bool        = 'true' | 'false' ;
identifier  = ( LETTER , { LETTER | DIGIT } ) - ( bool | 'null' | ? any keyword ? ) ;

(************************************)
(******* TERMINAL SYMBOL SETS *******)
(************************************)
LETTER      = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J'
            | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T'
            | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'
            | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j'
            | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't'
            | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'
            | '_' ;
OCTAL       = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' ;
DIGIT       = OCTAL | '8' | '9' ;
HEX         = DIGIT
            | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
            | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' ;
CHAR        = ? any character included in the Unicode character set ? ;
ESCAPE_CHAR = '\' | "'" | '"' | 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' ;
(*
  <EOL>: End Of Line
  Note: Line break characters (LF) are treated like spaces throughout the
  parsing process but, unlike the other space characters (' ', '\t', and '\r'),
  are accepted in place of semicolons.
*)
EOL         = ';' | ? line feed ? ;