//-------------------------------------------------------------------------------------------------
// Grammer for PropC
// Copyright Mike Christle 2016
//-------------------------------------------------------------------------------------------------
// ::=  Is defined by
// |    Or
// []   Optional
// {}   Repeat one or more times
// {}*  Repeat zero or more times
// ()   Group
// ''   Literal symbol
// ABC  Keyword
// ;    Rule terminator
//-------------------------------------------------------------------------------------------------
// <program> ::= { <data-decl-stmt> | <func-decl> }* ;
//
// <func-decl> ::= <return-data-type> <identifier> '(' [ <func-parms> ] ')' <func-body> ;
//
// <func-parms> ::= <data-type> <identifier> { ',' <data-type> <identifier> }* ;
//
// <return-data-type> ::= <data-type> | VOID ;
//
// <func-body> ::= '{' { <data-decl-stmt> }* { <statement> } '}' ;
//
// <data-decl-stmt> ::= <data-type> <data-decl> { ',' <data-decl> }* ';' ;
//
// <data-decl> := <identifier> [ '=' [ '+' | '-' ] <constant> ] ;
//
// <data-type> ::= INT | UINT | REAL ;
//
// <statement> ::= <assignment-stmt>
//               | <function-stmt>
//               | <dot-assign-stmt>
//               | <if-stmt>
//               | <while-stmt>
//               | <do-while-stmt>
//               | <for-stmt>
//               | <switch-stmt>
//               | <break-stmt>
//               | <continue-stmt>
//               | <return-stmt>
//               | <compound-stmt>
//               | <global-array-stmt>
//               | <wait-count-stmt>
//               | <wait-stmt>
//               | <lock-stmt>
//               | <built-in-op-stmt>
//               | <nop-stmt>
//               | ';' ;
//
// <assignment-stmt> ::= <assignment> ';' ;
//
// <assignment> ::= <identifier> <assigmment-op> <expression>
//                | <identifier> '=' [TRUE | FALSE] ;
//
// <assignment-op> ::= '=' | '+=' | '-=' | '*=' | '/=' | '%='
//                   | '|=' | '&=' | '^=' | '&~=' | '<<=' | '>>=' | '<-=' | '->=' ;
//
// <dot-assign-stmt> ::= <identifier> ( '.I' | '.D' | '.S' ) '=' <expression> ';' ;
//
// <global-array-stmt> ::= <global-array> '=' <expression> ';' ;
//
// <global-array> := ( GBYTE | GWORD | GLONG ) '[' <expression> ']' ;
//
// <if-stmt> ::= IF '(' <logical-or-expression> ')' <statement> [ ELSE <statement> ] ;
//
// <while-stmt> ::= WHILE '(' <logical-or-expression> ')' <statement> ;
//
// <do-while-stmt> ::= DO <statement> WHILE '(' <logical-or-expression> ')' ';' ;
//
// <for-stmt> ::= FOR '(' <for-init> [ ';' <logical-or-expression> ';' <for-incr> ] ')' <statement> ;
//
// <for-init> ::= <identifier> '=' <expression> ;
//
// <for-incr> ::= <identifier> <assignment-op> <expression> ;
//
// <switch-stmt> ::= SWITCH '(' <expression> ')' '{' { <case-clause> }* [<default-clause>] '}' ;
//
// <case-clause> ::= CASE <integer-constant> ':' { <statement> }* BREAK ';' ;
//
// <default-clause> ::= DEFAULT ':' { <statement> }* BREAK ';' ;
//
// <break-stmt> ::= BREAK ';' ;
//
// <continue-stmt> ::= CONTINUE ';' ;
//
// <return-stmt> ::= RETURN [<expression>] ';' ;
//
// <function-stmt> ::= <function-call> ';' ;
//
// <function-call> ::= <identifier> '(' [ <expression> { ',' <expression>} }* ] ')' ;
//
// <wait-count-stmt> ::= WAITCNT '(' <identifier> ',' <expression> ')' ';'
//                     | WAITCNT '(' <expression> ')' ';' ;
//
// <wait-stmt> ::= ( WAITPEQ | WAITPNE | WAITVID ) '(' <expression> ',' <expression> ')' ';' ;
//
// <lock-stmt> ::= ( LOCKNEW | LOCKSET | LOCKCLR | LOCKRET ) '(' <IDENTIFIER> ')' ';' ;
//
// <built-in-op-stmt> ::= ( CMPSUB | REV ) '(' <identifier> ',' <expression> ')' ';' ;
//
// <compound-stmt> ::= '{' { <statement> } '}' ;
//
// <nop-stmt> ::= NOP ';' ;
//
// <logical-or-expression> ::= <logical-and-expression>
//                           | <logical-or-expression '||' <logical-and-expression> ;
//
// <logical-and-expression> ::= <relational-expression>
//                            | <logical-and-expression '&&' <relational-expression> ;
//
// <relational-expression> ::= <expression> '==' <expression>
//                           | <expression> '!=' <expression>
//                           | <expression> '<' <expression>
//                           | <expression> '>' <expression>
//                           | <expression> '<=' <expression>
//                           | <expression> '>=' <expression>
//                           | <lock-expression>
//                           | <parity-expression> ;
//
// <lock-expression> ::= ( LOCKSET | LOCKCLR ) '(' <identifier> ')' ( '==' | '!=' } ( TRUE | FALSE ) ;
//
// <parity-expression> ::= <parity-function> ( '==' | '!=' } ( ODD | EVEN ) ;
//
// <expression> ::= <inclusive-or-expression>
//                | <expression> '#>' <inclusive-or-expression>
//                | <expression> '<#' <inclusive-or-expression> ;
//
// <inclusive-or-expression> ::= <exclusive-or-expression>
//                             | <inclusive-or-expression> '|' <exclusive-or-expression> ;
//
// <exclusive-or-expression> ::= <and-expression>
//                             | <exclusive-or-expression> '^' <and-expression> ;
//
// <and-expression> ::= <shift-expression>
//                    | <and-expression> '&' <shift-expression>
//                    | <and-expression> '&~' <shift-expression> ;
//
// <shift-expression> ::= <additive-expression>
//                      | <shift-expression> '<<' <additive-expression>
//                      | <shift-expression> '>>' <additive-expression>
//                      | <shift-expression> '->' <additive-expression>
//                      | <shift-expression> '<-' <additive-expression> ;
//
// <additive-expression> ::= <multiplicative-expression>
//                         | <additive-expression> '+' <multiplicative-expression>
//                         | <additive-expression> '-' <multiplicative-expression> ;
//
// <multiplicative-expression> ::= <unary-expression>
//                               | <multiplicative-expression> '*' <unary-expression>
//                               | <multiplicative-expression> '/' <unary-expression>
//                               | <multiplicative-expression> '%' <unary-expression> ;
//
// <unary-expression> ::= <primary-expression>
//                      | ! <primary-expression>
//                      | ~ <primary-expression>
//                      | - <primary-expression>
//                      | + <primary-expression> ;
//
// <primary-expression> ::= <identifier>
//                        | <function-call>
//                        | <global-array>
//                        | <built-in-function>
//                        | <parity-function>
//                        | <built-in-operation>
//                        | <integer-constant>
//                        | <real-constant>
//                        | '(' <expression> ')' ;
//
// <built-in-function> ::= ( SIN | COS | TAN | ASIN | ACOS | LOG | EXP | SQRT | ISQRT ) '(' <expression> ')' ;
//
// <built-in-operation> ::= ( ABS | ABSN | ITOR | RTOI | CEIL | FLOOR | TRUNC | ROUND | FRACT ) '(' <expression> ')' ;
//
// <parity-function> ::= PARITY '(' <expression> ',' <expression> ')' ;
//
// <identifier> ::= <letter> { <letter> | <digit> | '_' }* ;
//
// <letter> ::= (a-zA-Z) ;
//
// <digit> ::= (0-9) ;
//
// <constant> ::= <integer-constant> | <real-constant> ;
//
// <real-constant> ::= <dec-constant> '.' [ <dec-constant> ] ;
//
// <integer-constant> ::= <dec-constant> | <hex-constant> | <oct-constant> | <bin-constant> ;
//
// <dec-constant> ::= { 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | _ } ;
//
// <hex-constant> ::= '0x' { 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | _ } ;
//
// <oct-constant> ::= '0o' { 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | _ } ;
//
// <bin-constant> ::= '0b' { 0 | 1 | _ } ;
//-------------------------------------------------------------------------------------------------------------------------------------------------
