Expressions
This chapter specifies the syntax and semantics.
Notation
Non-terminals are written italic and literal terminals are written in bold style. Numbers in terminals are used as indices. The syntax is defined with the BNF with operator-precedence and expressions are defined with the operator :=. Z represents notation for no-characters.
Ignored characters
Between every expression can be space (vertical,horizontal tabulator and the space character). In case space must be used, it the space expression will be used.
Characters between '//' and end-of-line will be ignored, including '//' and end-ofline. Also characters between '/*' and '*/' will be ignored, including '/*' and '*/'. These ignored characters are called comments. Where a comment started with '//' will be interpreted as an end-of-line/newline and a comment started with '/*' as space.
Library name
The optional first expression of an program is progname. This specifies where all top-level public semantics in the file should be added to. if progname is not used, the program's semantics won't be visible to other files.
Syntax specification
The starting symbol is program. The terminals where defined in the chapter Lexical Elements.
int := Integers
float := Floating-point numbers
num := int | float
str := Strings
char := Characters
literal := num | str | char
id := Identifiers
EOF := No characters available
EOL := line-feed carriage-return | carriage-return line-feed
| carriage-return | line-feed
| Comment starting with //
newline := EOL | EOL newline
idcall := id | id . idcall
idcalls := idcall | ( idcall , idcallm )
idcallm := idcall | idcall , idcallm
program := progname newline program-body | progname EOF
| program-body EOF | EOF
progname := use module id
General program:
program-body := def newline | def EOF | def newline program-body
| use newline | use EOF | use newline program-body
def := func | trait | class | traitimpl | enum | module | vardef | capsdef exprdef := func | trait | class | traitimpl | enum | capsdef
Use:
use := use idcall | use idcall . *
template := { templdecls }
templdecls := templdeclslimit , templlasttype | templatedeclslimit | templlasttype
templdeclslimit := templdecl | templdecl , templdeclslimit
templdecl := id | id : templidcall | id0 : templidcall* := templidcall
templlasttype := id | id : templidcall ... | id0 : templidcall ... := templidcall
templidcalls := templidcall | templidcall , templidcalls | templidcall , newline templidcalls
templidcall := idcall | idcall template
func := func funcdecl newline ; | func funcdecl = expr newline
| func funcdecl newline funcbody ;
| func funcdecl : returntype newline retfuncbody ;
| func funcdecl : newline retfuncbody ;
| funcnb
funcnb := func funcdecl ; | func funcdecl : returntype ;
funcdecl := template funcdeclx | space funcdeclx
funcdeclx := id | id ( funcvars )
funcvars := funcvar | funcvar , funcvars
funcvar := vardecl | vardecl guard
guard := | expr0 | | expr0 = expr1
returntype := templidcall | vardecl
returntypetuple := ( returntuplex )
returntuplex := returntupleunit | returntupleunit , returntuplex
returntupleunit := templidcall | id : templidcall | func | functype
funcbody := stmt | stmt newline funcbody
retfuncbody := funcbody return expr newline
functype := func type | func type : return-type | func type ( funcvars ) | func type ( funcvars ) : return-type
clfunc := func clfuncdecl newline ;
| func clfuncdecl : returntype newline retfuncbody ;
| func clfuncdecl : newline retfuncbody ; | func clfuncdecl = newline expr ;
| func clfuncdecl : returntype = newline expr ;
| clfuncnb
clfuncnb := func clfuncdecl ; | func clfuncdecl ; returntype ;
clfuncdecl := template clfuncdeclx | space clfuncdeclx
clfuncdeclx := id ( funcvars )
lambda := lambda ( vardecl ) newline retfuncbody ;
| lamda ( vardelcs ) newline funcbody ;
| lambda newline retfuncbody ;
| lamda newline funcbody ;
| lambda = expr | lambda ( vardecl ) = expr
trait := trait traitdecl newline traitbody ; | trait traitdecl newline ;
traitdecl := space id | template id | space id : templidcalls | template id : templateidcalls
traitbody := clfuncnb | clfuncnb newline traitbody
class := class classdecl newline classbody ;
| class classdecl classcons newline classbody ;
classdecl := space id | template id
| space id : templidcalls | template id : templidcalls
classcons := ( vardecl )
classbody := classunit | classunit newline classbody
classunit := vardecl | caps vardecl | clfunc | caps clfunc
traitimpl := class space trait traitimpldecl newline traitimplbody ;
traitimpldecl := space idcall : templidcall | template idcall : templidcall
traitimplbody := clfuncnb | clfuncnb newline clfuncnb
enum := enum enumdecl newline enumbody ;
enumdecl := id
enumbody := enumunit | enumunit newline enumbody
enumunit := id | id ( templidcalls )
module := module moduledecl newline program-body
moduledecl := id
General Expression:
expr := exprdef | ( expr ) | biopexpr | unopexpr | fctl | lambda | expr ( expr ) | expr [ expr ] | array | safe | id | literal
stmt := expr | vardecl | vardef | stmt ; stmt
Variable declaration:
vardecl := vardeclunit | vardeclunits
vardeclunits := vardeclunit | vardeclunit , vardeclunits
vardeclunit := id : templidcall | & id : templidcall
| id : functype | & id : functype varids := varid | varid , varids
varid := id
Variable definition:
vardef := vardecl = expr | vardefid := expr | ( vardefids ) := expr
vardefids := vardefid | vardefid , vardefids
vardefid := & id | id
array := arraylit | arraycpy | arrayfor
arraylit := [ expr0 , expr1 ]
arraycpy := [ expr0 ; expr1 ]
arrayempty := [ expr ]
arrayfor := [ for id : expr0 newline retfuncbody ]
caps := # capid newline | # capid newline caps
| #! capsensure newline | #! capsensure newline caps
capid := Unused | Inline | Constant | Internal
capsensure := requires space ensurecond | ensures space ensurecond | ensures space ensurecond0 => ensurecond1
capsdef := caps func | caps class | caps enum | caps vardef
Control-flow expressions:
fctl := cond | loop
cond := if | match | ensure
loop := for | do
If expressions:
if := ifbase else ; | ifbase ;
ifbase := if space expr newline funcbody newline
| if space expr newline funcbody newline loopctl newline
| if space expr newline retfuncbody newline
else := elsebase | else elsebase
elsebase := else space expr newline funcbody newline
| else space expr newline retfuncbody newline
ensure := ensureunit ; | ensureunit else ensure | ensure else newline funcbody ;
ensureunit := ensure ensurecond newline funcbody
ensurecond := idcall ensurecondop expr
ensurecondop := == | != | ~= | > | >= | < | <= | ::
Match expression:
match := matchbase newline matchbody newline ;
matchbase := match expr
matchbody := matchcase | matchcase matchbody
matchcase := matchcasecond => funcbody ; | matchcasesecond => retfuncbody ;
matchcasecond := matchcasecons | matchcasecons expr
matchcasecons := matchcon | matchcon ( matchids )
matchcon := id | num | char | True | False matchids := matchid | matchid , matchids
matchid := _ | id
Loop expressions:
loopctl := break | continue | break int | continue int
for := for newline funcbody ;
| for expr newline funcbody ;| | for expr ; expr newline funcbody ;
| for expr ; expr ; expr newline funcbody ;
do newline funcbody ; for expr
| do expr newline funcbody ; for expr
| do expr ; expr newline funcbody ; for expr
Safe expression:
safe := safe templidcall ( expr )
| safe arraylit
biopexpr := expr0 biop expr1 | expr0 expr1
unopexpr := lunop expr
biop := + | - | * | / | ** | %
| & | | | ^ | << | >>
| == | != | ~= | < | > | <= | >=
| && | || += | -= | *= | /= | *= | %=
| &= | |= | ^= | <<= | >>=
| <>
| = | . | ->\ | , lunop := * | ! | null | + | - | ++ | --