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.1Programs, Modules, and Declarations

program::=topitem*
topitem::=import | intern | classdec | fundec | funsig | tydec | stmt
import::=import id (. id)*from string
intern::=intern id (/ id)*as id
tydec::=declare type id = ty
fundec::=function idgen(params): ty⟩ ⟨note⟩ ⟨requiredo blockensure⟩ ⟨rescueend
funsig::=declare function idgen(params): ty⟩ ⟨note

A.2Classes

classdec::=sealed⟩ ⟨deferredclass idgen⟩ ⟨note⟩ ⟨inheritclassbodyinvariantend
inherit::=inherit parent (, parent)*
parent::=idtyargs
classbody::=(featuresec | createsec)*
featuresec::=privatefeature member+
createsec::=create constructor+
member::=field | method
field::=onceid : ty:= exp⟩ ⟨note| id := expnote
method::=id(params)⟩ ⟨: ty⟩ ⟨note⟩ ⟨requiredo blockensure⟩ ⟨rescueend
|id (params): ty⟩ ⟨note⟩ ⟨deferred
constructor::=id(params)⟩ ⟨requiredo blockensure⟩ ⟨rescueend
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.3Types and Generics

gen::=[ genparam (, genparam)* ]
genparam::=?id-> id
tyargs::=[ ty (, ty)* ]
ty::=Integer | Integer64 | Real | Decimal | Char | Boolean | String
|? ty | funty | idtyargs
funty::=Function(funtyparams): ty⟩⟩
funtyparams::=funtyparam (, funtyparam)*
funtyparam::=id : ty | ty

A.4Statements

block::=stmt*
stmt::=id := exp | exp . id := exp
|let id: ty:= exp
|if exp then block (elseif exp then block)*else blockend
|from blockinvariant⟩ ⟨variantuntil exp do block end
|repeat exp do block end
|across exp as id do block end
|case exp of caseclause+else stmtend
|match exp of matchclause+else blockend
|select selectclause+timeout⟩ ⟨else blockend
|do blockrescueend | with string do block end
|raise exp | retry | exp
caseclause::=scon (, scon)* then stmt
matchclause::=when idtyargsas id then block
selectclause::=when expas idthen block
timeout::=timeout exp then block
invariant::=invariant assertion+
variant::=variant exp

A.5Expressions (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 except ^.

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
postexp::=primary postfix*
postfix::=?. id(args)| (args)
primary::=scon | id | this | result | ( exp )
|createexp | whenexp | fnexp | spawnexp | convexp
|old primary | arraylit | maplit | setlit
createexp::=create idtyargs⟩ ⟨. id(args)⟩⟩
whenexp::=when exp then exp else exp end
fnexp::=fngen(params): tydo 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.6Lexical Grammar

id::=(letter | _) (letter | _ | digit)*
scon::=int | real | char | string | true | false | nil
int::=digit+ | 0b bit+ | 0o odigit+ | 0x hdigit+
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. The reserved words of Section 2.1 are excluded from id by the longest-match rule of Section 2.5.