::= meaning "is defined as"
|   meaning "or"
< > angle brackets used to surround category names.
[]  else
* repetitive items zero or more times
+ repetitive items one or more times
'' keyword
{''-''} set of


<letter> ::= {'A'-'Z'} | {'a'-'z'} | '_'
<digit> ::= {'0'-'9'}
<number> ::= [<digit>]+
<identifier> ::= <letter> [<letter> | <digit>]*

<variable> ::= <identifier>
<constant> ::= <identifier>
<piece> ::= <constant>
<axis> ::= <constant>

<mul-op> ::= '*' | '/'
<add-op> ::= '+' | '-'
<shift-op> ::= '<<' | '>>'
<unary-op> ::= '~' | '!' | '-'
<Relational-op> ::=  | '>' | '>=' | '<' | '<='
<Equality-op>   ::= '==' | '!='

        precedence levels
        1.	- (unary), ! (bitwise not),  ~ (logical not)
        2.	*, /
        3.	+, -
        4       <<, >>
        5.	>, <, >=, <=
        6.      ==, !=,
        7.      &  (Bitwise AND) 
        8.      ^  (Bitwise Exclusive OR)
        9.      |  (Bitwise Inclusive OR) 
        10.     && (Logical AND) 
        11.     ^^ (Logical Exclusive OR) 
        12.     || (Logical Inclusive OR) 



<factor>      	   ::= <identifier> | '(' <expression> ')'	 
<unary-factor> 	   ::= [ <unary-op> ] <factor>
<Mult-Term>        ::= <unary-factor> (<mul-op> <unary_factor>)*	 
<add-term>         ::= <Mult-Term> (<add-op> <Mult-Term>)*
<shift-term>       ::= <add-term>  (<add-term>  <Mult-Term>)*
<Relation-term>    ::= <shift-term> (<Relational-op> <shift-term>)*
<Equality-term>    ::= <Relation-term> (<Equality-op> <Relation-term>)*


// todo : this needs updating to refact that precedence levels now actually work
<expression> ::= <Equality-term> ['||' <Equality-term>] ['^^' <Equality-term>] 
                                 ['&&' <Equality-term>] ['|' <Equality-term>]
                                 ['&' <Equality-term>] ['^' <Equality-term>]


<null> ::= ';'
<Local-Var-list> ::= 'var' <variable> (',' <variable> )* ';'
<if> ::= 'if' '(' <expression> ')' <statement-block> [ 'else' <statement-block>]
<For> ::= 'for' '(' <expression> ',' <expression> ',' <expression> ')' <statement-block>
<while> ::= 'while' '(' <expression> ')' <statement-block>
<do-while> ::= 'do' <statement-block> 'while' '(' <expression> ')'
<return> ::= 'return'
<break> ::= 'break'
<continue> ::= 'continue'

<assignment-type> ::= '+=' | '-=' | '*=' | '/=' | 
                      '&=' | '&&=' | '|=' | '||=' | 
                      '^=' | '^^=' | '<<=' | '>>='

<assignment> ::= <variable> <assignment-type> <expression>

<Get-Unit-Property> ::= 'get' <expression>
<Set-Unit-Property> ::= 'set' <expression> 'to' <expression>
<Sleep> ::= 'sleep' <expression>
<Turn> ::= 'turn' <piece> 'to' <axis> <expression> ( 'speed' <expression> ) | 'now';
<Wait-For-Turn> ::= 'wait-for-turn' <piece> 'around' <axis>
<Move> ::= 'move' <piece> 'to' <axis> <expression> ( 'speed' <expression> ) | 'now';
<Wait-For-Move> ::= 'wait-for-move' <piece> 'along' <axis>

<Spin> ::= 'spin' <piece> 'around' <axis> ( 'speed' <expression> ['accelerate' <expression>] ) | 'now';
<Stop-Spin> ::= 'stop-spin' <piece> 'around' <axis> ['decelerate' <expression>]

<Hide> ::= 'hide' <piece>
<Show> ::= 'show' <piece>
<Cache> ::= 'cache' <piece>
<Dont-Cache> ::= 'dont-cache' <piece>
<shade> ::= 'shade' <piece>
<dont-shade> ::= 'dont-shade' <piece>
<Call-Script> ::= 'call-script' <identifier> '(' <params>  ')'
<Start-Script> ::= 'start-script' <identifier> '(' <params>  ')'
<Signal> ::= 'signal' <expression>
<Set-Signal-Mask> ::= 'set-signal-mask' <expression>
<Explode> ::= 'explode' <piece> 'type' <expression>
<emit-sfx> ::= 'emit-sfx' <piece>
<rand> ::= 'rand' '(' <expression> ',' <expression> ')'
<attach-unit> ::= 'attach-unit'
<drop-unit> ::= 'drop-unit'



<const-var> ::= <variable> '=' <number>
<const-list> ::= 'const' <const-var> (',' <const-var> )* ';'
<localvar-list> ::= 'var' <variable> (',' <variable> )* ';'

<statement> ::= <if> | <while> | <do-while> | <For> | <assignment> |
                <Local-Var-list> |<return> | <break> | <continue> |
                <Get-Unit-Property> | <Set-Unit-Property> | <Sleep>|
                <Wait-For-Turn> | <Wait-For-Move> | <Turn> | <Move> |
                <Spin> | <Stop-Spin> | <Hide> | <Show> | <Cache> | 
                <Dont-Cache> | <Call-Script> | <Start-Script> | <Signal>
                <Set-Signal-Mask> | <Explode> | <emit-sfx> |
                <shade> | <dont-shade> | <rand> | 
                <attach-unit> | <drop-unit> | 
                <const-list> | <localvar-list> |
                <null>

<statements> ::= <statement> ';' ( <statement> ';')+
<statement-block> ::= <statement> [ '{' <statements> '}' ]




<function> ::= <identifier> '(' <params>  ')' <statement-block>
<params> ::= (<identifier> ( ',' <identifier>)+ ) | null


<Global-Var-list> ::= 'static-var' <variable> (',' <variable> )* ';'
<piece-list> ::= 'piece' <piece> (',' <piece> )* ';'

<Global-Declaration> ::= <function> | <Global-Var-list> | <piece-list>
<Global-Declarations> ::= ( <Global-Declaration> )*
