(machine code and abstract syntax tree can be found at the end)
GRAMMAR:
Program ::== Statement $
Statement ::== print ( Expr )
::== Id = Expr
::== VarDecl
::== if BoolExpr Statement
::== while BoolExpr Statement
::== { StatementList }
StatementList ::== Statement StatementList
::== ?
Expr ::== IntExpr
::== CharExpr
::== BoolExpr
::== Id
IntExpr ::== digit op Expr
::== digit
CharExpr ::== " CharList "
CharList ::== Char CharList
::== Space CharList
::== ?
BoolExpr ::== ( digit boolOp Expr )
::== ( boolInstance boolOp Expr )
::== boolInstance
VarDecl ::== Type Id
Type ::== int | char | bool
Id ::== Char
Char ::== a | b | c ... z
Space ::== the space character
digit ::== 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0
op ::== + | -
boolInstance ::== true | false
boolOp ::== == | !=
NOTES:
Comments: All comments must be preceded by and followed by the # symbol. Other than this requirement they can appear anywhere in the source code, even bisecting tokens.
Booleans: Except for `true` or `false` on their own, boolean expressions must be surrounded by parentheses, even if these would already be there in a print statement. For example: print(1!=2) returns an error. print ((1!=2)) is correct.
In boolean expressions, the integer 1 evaluates to true, 0 evaluates to false, and all other integers do not evaluate to a boolean value when compared to a boolean (hence ((2 == false) || (2 == true)) returns false). Integers can, however, be compared to each other.
Strings cannot be used in boolean expressions - this will return an error.
In the machine code our compiler generates, printing booleans will print 1 if true, 0 if false.
Integers are allocated one byte so an integer can be from 0-255. Integers must be positive.
Strings (CharLists) can be of any length, except that the entire program must be 128 bytes or less.