. . . a kick-ass parser for a mediocre 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.