Grammar
File = "package" ident ";" { Import ";" } { TopDecl ";" } .
Import = "import" ( string | "(" { string ";" } ")" ) .
TopDecl = ConstDecl | TypeDecl | EnumDecl | FuncDecl | ScriptDecl .
ConstDecl = "const" ident [ Type ] "=" Expr .
TypeDecl = "type" ident "struct" "{" { ident Type ";" } "}" .
EnumDecl = "enum" ident "{" { ident ";" } "}" .
FuncDecl = { Attr } "func" ident "(" [ Params ] ")" [ Type | "coroutine" ] Block .
Params = ident Type { "," ident Type } .
ScriptDecl = { Attr } "script" ident "{" { ScriptMember ";" } "}" .
ScriptMember= { Attr } "var" ident Type [ "=" Expr ] | FuncDecl | SignalDecl .
SignalDecl = "signal" ident "(" [ Params ] ")" .
Attr = "@" ident [ "(" [ AttrArg { "," AttrArg } ] ")" ] .
AttrArg = [ ident "=" ] ( Literal | "-" Literal ) .
Type = ident [ "." ident ] [ "<" Type { "," Type } ">" ] | "[" "]" Type .
Block = "{" { Stmt ";" } "}" .
Stmt = "var" ident Type [ "=" Expr ]
| ident ":=" Expr
| LValue ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" ) Expr
| LValue ( "++" | "--" )
| Expr | If | For | Switch
| "return" [ Expr ] | "break" | "continue" | Block
| "yield" [ YieldArg ] .
YieldArg = "wait" "(" Expr ")" | "frames" "(" Expr ")" | "fixed" "(" Expr ")" | Expr .
If = "if" Expr Block [ "else" ( If | Block ) ] .
For = "for" [ Expr | [ Simple ] ";" [ Expr ] ";" [ Simple ] ] Block .
Switch = "switch" Expr "{" { ( "case" Expr { "," Expr } | "default" ) ":" { Stmt ";" } } "}" .
Expr = Unary { BinOp Unary } .
Unary = [ "-" | "!" ] Primary | "start" ident "(" [ Expr { "," Expr } ] ")" .
Primary = Operand { "." ident | "[" Expr "]" | [ "<" Type ">" ] "(" [ Expr { "," Expr } ] ")" } .
Operand = Literal | ident | "(" Expr ")" | Type "{" [ Elems ] "}" .
Precedence, high to low: unary - !; * / %; + -; == != < <= > >=; &&; ||. Type arguments in a call (Get<T>()) are accepted by the parser anywhere, but only intrinsics may use them (§9).
Composite literals are not allowed directly in the head of if, for or switch; parenthesize them (if x == (Stats{}) {).