Program ::= Statement+ Statement ::= (AssignmentStatement | ImportDeclaration | ExternDeclaration | CastStatement | SizeOfStatement | FunctionCallStatement | IfStatement | WhileStatement | ReturnStatement | "break" | "continue") SEMICOLON AssignmentStatement ::= ("let")? ("*")? Expression EQUALS Expression ImportDeclaration ::= "import" STRING ExternDeclaration ::= "extern" IDENTIFIER EQUALS Type FunctionCallStatement ::= (IDENTIFIER | FunctionDefinition) LPAREN FunctionArguments? RPAREN IfStatement ::= "if" Expression LBRACE Statement* RBRACE -- TODO: Should function definitions be allowed? WhileStatement ::= "while" Expression LBRACE Statement* RBRACE ReturnStatement ::= RETURN (Expression)? FunctionArguments ::= Expression ("," Expression)* Expression ::= EqualityExpression | AdditiveExpression CastStatement ::= "cast" LPAREN TYPE "," Expression RPAREN SizeOfStatement ::= "sizeof" LPAREN TYPE RPAREN EqualityExpression ::= AdditiveExpression ("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression AdditiveExpression ::= MultiplicativeExpression (("+" | "-") MultiplicativeExpression)* MultiplicativeExpression ::= UnaryExpression (("*" | "/" | "%") UnaryExpression)* UnaryExpression ::= ("!" | "-" | "*") UnaryExpression | PostfixExpression PostfixExpression ::= PrimaryExpression (FieldAccess | FunctionCallStatement | CastStatement | SizeOfStatement)* PrimaryExpression ::= NULL | NUMBER | BOOLEAN | CHAR | STRING | IDENTIFIER | FunctionDefinition | StructDefinition | StructInstantiation | FieldAccess | LPAREN Expression RPAREN FunctionDefinition ::= LPAREN FunctionParameters? RPAREN ARROW IDENTIFIER LBRACE Statement* ReturnStatement SEMICOLON RBRACE FunctionParameters ::= IDENTIFIER ":" Type ("," IDENTIFIER ":" Type)* Type ::= IDENTIFIER | FunctionType FunctionType ::= LPAREN (Type ("," Type)*)? RPAREN ARROW Type ParameterTypes ::= Type ("," Type)* StructDefinition ::= "struct" LBRACE (StructField ("," StructField)*)? RBRACE StructField ::= IDENTIFIER ":" Type StructInstantiation ::= IDENTIFIER LBRACE RBRACE FieldAccess ::= Expression DOT IDENTIFIER