Formal Grammar

Compact EBNF-style reference of the NXSL grammar, derived from the parser definition. { x } means zero or more repetitions, [ x ] means optional, | separates alternatives, (empty) denotes an empty production. Terminal symbols are quoted or written in UPPERCASE. Operator precedence and associativity are listed in Operator Precedence.

Script structure
script ::=
  { metadata_statement } script_body

script_body ::=
  module_component { module_component | metadata_statement } |
  expression_statement |
  (empty)

module_component ::=
  const_statement |
  function |
  statement_or_block |
  import_statement

metadata_statement ::=
  "@meta" "(" metadata_value { "," metadata_value } ")"

metadata_value ::=
  IDENTIFIER "=" constant

const_statement ::=
  "const" const_definition { "," const_definition } ";"

const_definition ::=
  IDENTIFIER "=" constant

import_statement ::=
  "import" module_name ";" |
  "import" import_symbol { "," import_symbol } "from" module_name ";"

import_symbol ::=
  IDENTIFIER [ "as" IDENTIFIER ]

module_name ::=
  any_identifier |
  WILDCARD_IDENTIFIER

any_identifier ::=
  IDENTIFIER |
  COMPOUND_IDENTIFIER

function ::=
  "function" function_name "(" [ identifier_list ] ")" block

function_name ::=
  IDENTIFIER |
  COMPOUND_IDENTIFIER

identifier_list ::=
  IDENTIFIER { "," IDENTIFIER }
Statements
block ::=
  "{" { statement_or_block } "}"

statement_or_block ::=
  statement |
  block |
  try_catch_block

try_catch_block ::=
  "try" block "catch" block

statement ::=
  expression_statement ";" |
  builtin_statement |
  ";"

expression_statement ::=
  "with" with_assignment { "," with_assignment } expression |
  expression

with_assignment ::=
  IDENTIFIER [ "(" metadata_value { "," metadata_value } ")" ]
      "=" "{" ( { statement_or_block } | expression ) "}"

builtin_statement ::=
  simple_statement ";" |
  if_statement |
  do_statement |
  while_statement |
  for_statement |
  foreach_statement |
  switch_statement |
  select_statement |
  array_statement |
  global_statement |
  local_statement |
  "break" ";" |
  "continue" ";"

simple_statement ::=
  keyword [ expression ]

keyword ::=
  "abort" |
  "exit" |
  "return"

if_statement ::=
  "if" "(" expression ")" statement_or_block [ "else" statement_or_block ]

while_statement ::=
  "while" "(" expression ")" statement_or_block

do_statement ::=
  "do" statement_or_block "while" "(" expression ")" ";"

for_statement ::=
  "for" "(" expression ";" expression ";" expression ")" statement_or_block

foreach_statement ::=
  ( "foreach" | "for" ) "(" IDENTIFIER ":" expression ")" statement_or_block

switch_statement ::=
  "switch" "(" expression ")" "{" case { case } [ default ] "}"

case ::=
  "case" case_value ":" { statement_or_block } |
  "case" case_value "..." case_value ":" { statement_or_block }

case_value ::=
  constant |
  any_identifier

default ::=
  "default" ":" { statement_or_block }

select_statement ::=
  "select" IDENTIFIER [ "(" expression ")" ] "{" when_clause { when_clause } "}"

when_clause ::=
  "when" expression ":" { statement_or_block }

array_statement ::=
  [ "global" ] "array" identifier_list ";"

global_statement ::=
  "global" global_declaration { "," global_declaration } ";"

global_declaration ::=
  IDENTIFIER [ "(" metadata_value { "," metadata_value } ")" ] [ "=" expression ]

local_statement ::=
  "local" local_declaration { "," local_declaration } ";"

local_declaration ::=
  IDENTIFIER [ "=" expression ]
Expressions
expression ::=
  "(" expression ")" |
  IDENTIFIER "=" expression |
  IDENTIFIER assignment_op expression |
  storage_item "=" expression |
  storage_item assignment_op expression |
  storage_item |
  expression "[" expression "]" "=" expression |
  expression "[" expression "]" assignment_op expression |
  expression "[" expression "]" |
  expression "[" [ expression ] ":" [ expression ] "]" |
  expression "." IDENTIFIER "=" expression |
  expression "." IDENTIFIER |
  expression "?." IDENTIFIER |
  expression "." method_call |
  expression "?." method_call |
  IDENTIFIER "@" expression |
  "-" expression |
  ( "!" | "not" ) expression |
  "~" expression |
  ( "++" | "--" ) IDENTIFIER |
  IDENTIFIER ( "++" | "--" ) |
  ( "++" | "--" ) storage_item |
  storage_item ( "++" | "--" ) |
  ( "++" | "--" ) "(" expression "[" expression "]" ")" |
  expression "[" expression "]" ( "++" | "--" ) |
  expression binary_op expression |
  expression "?" expression ":" expression |
  operand

assignment_op ::=
  "+=" | "-=" | "*=" | "/=" | "\=" | "%=" | "..=" | "&=" | "|=" | "^="

binary_op ::=
  "+" | "-" | "*" | "/" | "\" | "%" | ".." |
  "==" | "!=" | "<" | "<=" | ">" | ">=" |
  "like" | "ilike" | "~=" | "match" | "imatch" | "in" | "has" |
  "&" | "|" | "^" | "<<" | ">>" |
  "&&" | "and" | "||" | "or"

method_call ::=
  function_name "(" [ parameter_list ] ")"

operand ::=
  function_call |
  type_cast |
  array_initializer |
  hash_map_initializer |
  new_expression |
  format_string |
  IDENTIFIER |
  COMPOUND_IDENTIFIER |
  constant

function_call ::=
  [ "@optional" ] ( IDENTIFIER | COMPOUND_IDENTIFIER ) "(" [ parameter_list ] ")"

parameter_list ::=
  parameter { "," parameter }

parameter ::=
  expression |
  IDENTIFIER ":" expression |
  "..." expression

new_expression ::=
  "new" IDENTIFIER [ "(" [ parameter_list ] ")" ]

type_cast ::=
  builtin_type "(" expression ")"

builtin_type ::=
  "boolean" | "int32" | "int64" | "uint32" | "uint64" | "real" | "string"

array_initializer ::=
  "[" [ array_element { "," array_element } ] "]"

array_element ::=
  expression |
  "..." expression

hash_map_initializer ::=
  "%{" [ expression ":" expression { "," expression ":" expression } ] "}"

storage_item ::=
  "#" IDENTIFIER |
  "#" "(" expression ")"

format_string ::=
  'F"' { text | "{" expression "}" } '"'

constant ::=
  STRING | INT32 | UINT32 | INT64 | UINT64 | REAL |
  "true" | "TRUE" | "false" | "FALSE" | "null" | "NULL"
Terminal symbols
IDENTIFIER          ::= [A-Za-z_$][A-Za-z_$0-9]*
COMPOUND_IDENTIFIER ::= IDENTIFIER ( "::" IDENTIFIER )+
WILDCARD_IDENTIFIER ::= IDENTIFIER ( "::" IDENTIFIER )* "::" "*"
INTEGER             ::= [0-9]+ | 0x[0-9A-Fa-f]+
INT32               ::= INTEGER
INT64               ::= INTEGER "L"
UINT32              ::= INTEGER "U"
UINT64              ::= INTEGER ( "UL" | "LU" )
REAL                ::= [0-9]+ "." [0-9]+
STRING              ::= double-quoted ("..."), single-quoted ('...'),
                        or multi-line ("""...""") string literal

Notes:

  • Integer and real literals are unsigned; a leading minus sign is parsed as the unary negation operator.

  • %( …​ ) is a deprecated alternative to the [ …​ ] array initializer; it is accepted with a compilation warning.

  • b@a (production IDENTIFIER "@" expression) is a deprecated alternative to safe attribute access a?.b — the attribute name appears on the left of @; it is accepted with a compilation warning.

  • → is accepted as an alias of . in member access and method call expressions.

  • print and println are ordinary functions, not statement keywords.