Removing the Requirement for Braces in Jack's "if" and "while" Statements

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Removing the Requirement for Braces in Jack's "if" and "while" Statements

cadet1620
Administrator
This post was updated on .
It is rather annoying that single statements in the bodies of if and while statements need to be surrounded by {}. This is particularly ugly for "else if" structures.
if (a) {
    do option1();
}
else { 
    if (b) {
        do option2();
    }
    else {
        if (c) {
            do option3();
        }
        else {
            do default();
        }
    }
}
It would be quite nice if this could be written without all the {}.
if (a)
    do option1();
else if (b)
    do option2();
else if (c)
    do option3();
else
    do default();
It is a minor addition to Jack syntax to allow this, and an easy change to the CompilationEngine module to support the new syntax.

Syntax changes

The book's syntax for if and while statements is

ifStatement:  'if ' '(' expression ')' '{' statements '}' ( 'else' '{' statements '}' )?
whileStatement: 'while' '(' expression ')' '{' statements '}'

To support if and while statements without braces, the
  '{' statements '}'
in the if/while syntax needs to also allow a single statement. It changes to
  ( statement | '{' statements '}' )

The syntax will be made a bit cleaner by adding the new construct "block".

ifStatement:  'if ' '(' expression ')' (statement | block) ( 'else' (statement | block) )?
whileStatement: 'while' '(' expression ')' (statement | block)
block: '{' statements '}'

Code changes

Changes to compileWhile() are straightforward.

After compiling the controlling expression and the ')', where you currently check for '{' and then call compileStatements(), you need to insert a check for a keyword token which indicates the beginning of a single statement.

    ...
    compileExpression()
    expect ')'
    write ASM code for loop break
+   if tokenType is KEYWORD
+       compileStatement()
+   else
        expect '{'
        compileStatements()
        expect '}'
+   endif
    ...
Note: expect in this context means consume the next token and throw an error if it was not the correct token.

If you followed the book design, you may need to move single statement compilation from compileStatements() into compileStatement().

Changes to compileIf() are similar to those for compileWhile().

Test Code

/** Test code for "no braces" compiler modification.
 *
 *  Should print "one...two...three...many...many...".
 */

class Main {
    function void main() {
        var int i;
        let i = 1;
        while (i < 6)
            let i = Main.test(i);
        return;
    }

    function int test(int x) {
        if (x > 3)
            do Output.printString("many...");
        else if (x > 2)
            do Output.printString("three...");
        else if (x > 1)
            do Output.printString("two...");
        else
            do Output.printString("one...");
        return x+1;
    }
}