NovaLang0.2 alpha

Gramática sintática

Esta EBNF transcreve o parser da 0.2.0-alpha. Regras marcadas parcial são reconhecidas pelo front-end, mas não prometem execução. { X } é repetição, [ X ] é opcional e | indica alternativa.

Declarações

program      = { NL }, { declaration, { NL } }, EOF ;
declaration  = [ "pub" ], ( function | variable | struct | enum
             | interface | trait | impl | type_alias | module | import
             | export ) ;
export       = "export", declaration ;
function     = [ "extern" ], [ "async" ], "fn", identifier,
               [ type_params ], parameters, [ "->", type ], block ;
parameters   = "(", [ parameter, { ",", parameter } ], ")" ;
parameter    = [ "mut" ], identifier, [ ":", type ] ;
type_params  = "<", type_param, { ",", type_param }, ">" ;
type_param   = identifier, [ ":", type, { "+", type } ] ;
variable     = ("let" | "const" | "var"), [ "mut" ], identifier,
               [ ":", type ], [ "=", expression ], terminator ;
struct       = "struct", identifier, [ type_params ], "{", { field }, "}" ;
field        = identifier, ":", type, [ "=", expression ],
               ( "," | terminator ) ;
enum         = "enum", identifier, [ type_params ], "{",
               { enum_variant, [ "," ], { NL } }, "}" ;
enum_variant = identifier, [ "(", [ type, { ",", type } ], ")"
               | "{", { identifier, ":", type, terminator }, "}" ] ;
interface    = "interface", identifier, [ type_params ], "{",
               { signature }, "}" ;
trait        = "trait", identifier, [ type_params ], "{",
               { signature }, "}" ;
signature    = [ "async" ], "fn", identifier, [ type_params ],
               parameters, [ "->", type ], terminator ;
impl         = "impl", [ type_params ],
               ( identifier, [ "for", type ] | type ),
               "{", { function | type_alias }, "}" ;
type_alias   = "type", identifier, [ type_params ], "=", type, terminator ;
module       = "mod", identifier, "{", { declaration }, "}" ;
import       = "import", import_item, { ",", import_item }, terminator ;
import_item  = path, [ "::", "*" ], [ "as", identifier ] ;
path         = identifier, { "::", identifier } ;
terminator   = [ ";" ], { NL } ;

priv está reservado; privacidade é implícita sem pub. extern fn ainda exige corpo.

Statements

statement     = block | if_stmt | while_stmt | for_stmt | loop_stmt
              | match_stmt | switch_stmt | try_stmt | throw_stmt
              | defer_stmt | yield_stmt | return_stmt | break_stmt
              | continue_stmt | variable | expression, terminator ;
block         = "{", { NL }, { statement, { NL } }, "}" ;
if_stmt       = "if", expression, block,
                { "elif", expression, block },
                [ "else", (if_stmt | block) ] ;
while_stmt    = "while", expression, block ;
for_stmt      = "for", pattern, "in", expression, block ;
loop_stmt     = "loop", block ;
return_stmt   = "return", [ expression ], terminator ;
break_stmt    = "break", [ identifier ], terminator ;
continue_stmt = "continue", [ identifier ], terminator ;
match_stmt    = "match", expression, match_arms ;
match_arms    = "{", { pattern, [ "if", expression ], "=>",
                (block | expression), [ "," ], { NL } }, "}" ;
switch_stmt   = "switch", expression, "{",                    (* parcial *)
                { "case", expression, ":", block },
                [ "default", ":", block ], "}" ;
try_stmt      = "try", block,                                 (* parcial *)
                { "catch", "(", [ identifier ], ")", block } ;
throw_stmt    = "throw", expression, terminator ;             (* parcial *)
defer_stmt    = "defer", expression, terminator ;             (* parcial *)
yield_stmt    = "yield", [ expression ], terminator ;         (* parcial *)

Rótulos após break/continue são analisados, mas laços rotulados não têm sintaxe correspondente.

Expressões

Da menor para a maior precedência:

NívelOperadoresAssociação
1atribuições =, +=, -=, *=, /=, %=, **=, &=, `=, ^=, <<=, >>=`
2?:direita
3–4`
5–7`, ^, &`
8–9==, !=, <, <=, >, >=esquerda
10–12<<, >>, +, -, *, /, %esquerda
13**direita
14!, not, ~, -, await, ref, ref mut, *direita
15chamada, membro, índice, range, as, isesquerda
expression     = assignment ;
assignment     = conditional, [ assign_op, assignment ] ;
conditional    = logical_or, [ "?", expression, ":", conditional ] ;
logical_or     = logical_and, { ("||" | "or"), logical_and } ;
logical_and    = bit_or, { ("&&" | "and"), bit_or } ;
bit_or         = bit_xor, { "|", bit_xor } ;
bit_xor        = bit_and, { "^", bit_and } ;
bit_and        = equality, { "&", equality } ;
equality       = relational, { ("==" | "!="), relational } ;
relational     = shift, { ("<" | "<=" | ">" | ">="), shift } ;
shift          = additive, { ("<<" | ">>"), additive } ;
additive       = multiplicative, { ("+" | "-"), multiplicative } ;
multiplicative = power, { ("*" | "/" | "%"), power } ;
power          = unary, [ "**", power ] ;
unary          = ("!" | "not" | "~" | "-" | "await" | "ref" [ "mut" ] | "*"),
                 unary | postfix ;
postfix        = primary, { "(", [ expression, { ",", expression } ], ")"
               | ".", identifier | "[", expression, "]"
               | "..", [ postfix ] | "as", type | "is", type } ;
primary        = literal | identifier | "self" | "super"
               | "(", [ expression, { ",", expression } ], ")"
               | "[", [ expression | "...", expression,
                 { ",", expression | "...", expression } ], "]"
               | "{", object_or_block, "}" | lambda | anonymous_fn
               | "match", expression, match_arms ;
lambda         = [ "async" ], "|", [ parameter, { ",", parameter } ], "|",
                 (expression | block) ;
anonymous_fn   = [ "async" ], "fn", parameters, [ "->", type ], block ;

Ranges e sua grafia inclusiva ainda são experimentais. Objetos usam { chave: valor }; a distinção entre objeto e bloco depende dos primeiros tokens.

Patterns e tipos

pattern       = primary_pattern, [ "|", pattern ] ;
primary_pattern = "_" | [ "mut" ], identifier, [ "@", pattern ]
              | literal | "-", integer
              | "(", [ pattern, { ",", pattern } ], ")"
              | "[", [ pattern, { ",", pattern } ],
                [ ",", "...", [ identifier ] ], "]"
              | identifier, "::", identifier, [ pattern ]
              | identifier, "{", { identifier, [ ":", pattern ],
                [ "," ] }, "}" | "...", [ identifier ] ;

type          = nullable_type, { "|", nullable_type } ;
nullable_type = primary_type, [ "?" ] ;
primary_type  = path, [ "<", type, { ",", type }, ">" ],
                [ "[", [ expression ], "]" ]
              | "self"
              | "fn", "(", [ type, { ",", type } ], ")", "->", type
              | "(", ")", "->", type
              | "(", type, "->", type
              | "(", type, ",", type, { ",", type }, ")"
              | "(", type, ")" ;