Appendix A
The Full Grammar
This appendix collects the complete context-free grammar of Nex in one place,
with the expression grammar given in its layered form so that operator
precedence and associativity (Section 2.6 ) are expressed directly by the
productions rather than assumed.
A.1 Programs, Modules, and Declarations
program ::= topitem *
topitem ::= import | intern | classdec | uniondec | fundec | funsig | tydec | stmt
import ::= import id (. id )* ⟨from string ⟩
intern ::= intern id (/ id )* ⟨as id ⟩
qid ::= id (/ id )* — class name, bare or qualified (Section 3.6.1 )
tydec ::= declare type id = ty ⟨where id : exp ⟩
fundec ::= function id ⟨gen ⟩ ( ⟨params ⟩ ) ⟨: ty ⟩ ⟨note ⟩ ⟨require ⟩ do block ⟨ensure ⟩ ⟨rescue ⟩ end
funsig ::= declare function id ⟨gen ⟩ ( ⟨params ⟩ ) ⟨: ty ⟩ ⟨note ⟩
A.2 Classes
classdec ::= ⟨sealed ⟩ ⟨deferred ⟩ class id ⟨gen ⟩ ⟨note ⟩ ⟨inherit ⟩ classbody ⟨invariant ⟩ end
inherit ::= inherit parent (, parent )*
parent ::= qid ⟨tyargs ⟩
classbody ::= (featuresec | createsec )*
uniondec ::= ⟨enum ⟩ union id ⟨gen ⟩ ⟨note ⟩ variant + end
variant ::= id ⟨( params ) ⟩
featuresec ::= ⟨private ⟩ feature member +
createsec ::= create constructor +
member ::= field | constant | method
field ::= ⟨once ⟩ id : ty ⟨note ⟩
constant ::= id ⟨: ty ⟩ = exp ⟨note ⟩
method ::= id ⟨( ⟨params ⟩ ) ⟩ ⟨: ty ⟩ ⟨alias ⟩ ⟨note ⟩ ⟨require ⟩ do block ⟨ensure ⟩ ⟨rescue ⟩ end
| id ( ⟨params ⟩ ) ⟨: ty ⟩ ⟨alias ⟩ ⟨note ⟩ ⟨deferred ⟩
alias ::= alias opsym
opsym ::= "+" | "-" | "*" | "/" | "%" | "^"
constructor ::= id ⟨( ⟨params ⟩ ) ⟩ ⟨require ⟩ do block ⟨ensure ⟩ ⟨rescue ⟩ end
invariant ::= invariant assertion +
params ::= param (, param )*
param ::= id (, id )* ⟨: ty ⟩
require ::= require assertion +
ensure ::= ensure assertion +
rescue ::= rescue block
assertion ::= id : exp
note ::= note string
A.3 Types and Generics
gen ::= [ genparam (, genparam )* ]
genparam ::= ⟨? ⟩ id ⟨-> id ⟩
tyargs ::= [ ty (, ty )* ]
ty ::= Integer | Real | Char | Boolean | String
| ? ty | funty | qid ⟨tyargs ⟩
funty ::= Function ⟨( ⟨funtyparams ⟩ ) ⟨: ty ⟩⟩
funtyparams ::= funtyparam (, funtyparam )*
funtyparam ::= id : ty | ty
A.4 Statements
block ::= stmt *
stmt ::= id := exp | exp . id := exp
| let id ⟨: ty ⟩ := exp
| if exp then block (elseif exp then block )* ⟨else block ⟩ end
| from block ⟨invariant ⟩ ⟨variant ⟩ until exp do block end
| repeat exp do block end
| across exp as id do block end
| case exp of caseclause + ⟨else stmt ⟩ end
| match exp of matchclause + ⟨else block ⟩ end
| select selectclause + ⟨timeout ⟩ ⟨else block ⟩ end
| do block ⟨rescue ⟩ end | with string do block end
| raise exp | retry | assert (assertion + | exp ) | exp
caseclause ::= scon (, scon )* then stmt
matchclause ::= pattern ⟨as id ⟩ ⟨if exp ⟩ then stmt
pattern ::= _ | qid ⟨tyargs ⟩ ⟨( fieldpat (, fieldpat )* ) ⟩
fieldpat ::= _ | id | id : id | scon | pattern
selectclause ::= when exp ⟨as id ⟩ then block
timeout ::= timeout exp then block
invariant ::= invariant assertion +
variant ::= variant exp
A.5 Expressions (Layered)
The following layering expresses the precedence and associativity of
Section 2.6 : each level refers to the next more tightly binding one, with the
binary operators of a level left-associative, ^ included
(Section 2.6 ).
exp ::= orexp
orexp ::= andexp (or andexp )*
andexp ::= eqexp (and eqexp )*
eqexp ::= relexp ((= | /= | == | != ) relexp )*
relexp ::= addexp ((< | <= | > | >= ) addexp )*
addexp ::= mulexp ((+ | - ) mulexp )*
mulexp ::= unexp ((* | / | % | ^ ) unexp )*
unexp ::= - unexp | not unexp | ? postexp as id | postexp
postexp ::= primary postfix *
postfix ::= ⟨? ⟩ . id ⟨( ⟨args ⟩ ) ⟩ | ( ⟨args ⟩ )
primary ::= scon | id | this | super | result | ( exp )
| createexp | whenexp | fnexp | spawnexp | convexp
| old primary | arraylit | maplit | setlit
createexp ::= create qid ⟨tyargs ⟩ ⟨. id ⟨( ⟨args ⟩ ) ⟩⟩
whenexp ::= when exp then exp else exp end
fnexp ::= fn ⟨gen ⟩ ( ⟨params ⟩ ) ⟨: ty ⟩ do block end
spawnexp ::= spawn do block end
convexp ::= convert exp to id : ty
args ::= exp (, exp )*
arraylit ::= [ ⟨exp (, exp )* ⟩ ]
maplit ::= { } | { exp : exp (, exp : exp )* }
setlit ::= #{ ⟨exp (, exp )* ⟩ }
A.6 Lexical Grammar
id ::= (letter | _ ) (letter | _ | digit )*
scon ::= int | byte | int16 | int32 | real | char | string | true | false | nil
int ::= digit + | 0b bit + | 0o odigit + | 0x hdigit +
byte ::= int u8
int16 ::= int i16
int32 ::= int i32
real ::= ⟨digit + ⟩ . digit + ⟨exp ⟩
char ::= # (char≠digit,ws | named | digit + )
named ::= nul | space | newline | tab | return
string ::= " … " | ' … '
comment ::= -- … end-of-line
A digit separator _ may occur between two digits of any numeric
literal. A byte , int16 or int32 is an
int with a suffix, forming a single token; its range is checked
(Section 2.2 ), and a leading - is absorbed into an
int16 or int32 . The reserved words of Section 2.1 are excluded from
id by the longest-match rule of Section 2.5 .