//sub-body ::= '{' <local-var-decl>* <statement>* '}' private void ParseSubBody() { Match(new Token(TokenType.Symbol, "{")); ParseLocalVarDecls(); //Notify the code generator -- now _currentSub has full information //about the subroutine's parameters and local variables. switch (_currentSub.Kind) { case SubroutineKind.Constructor: _codeGenerator.ConstructorDeclaration(_currentSub); break; case SubroutineKind.Function: _codeGenerator.FunctionDeclaration(_currentSub); break; case SubroutineKind.Method: _codeGenerator.MethodDeclaration(_currentSub); break; default: ThrowCompilationException("Invalid value for _currentSub.Kind: " + _currentSub.Kind); break; } ParseStatements(); //Make sure the method ends with 'return'. If the method is void, //return an an arbitrary value. This could be left to the CG's //discretion as well. if (!_wasLastStatementReturn) { if (_currentSub.ReturnType == "void") { _codeGenerator.IntConst(0); _codeGenerator.Return(); //NOTE: This is a deviation from the original Jack syntax, //in which all methods must end with a 'return' statement, //even void methods. } else { ThrowCompilationException("Non-void method must return a value"); } } _wasLastStatementReturn = false; _codeGenerator.EndSubroutine(); //This is the last thing we do because it may advance us to the //next line, but we want accurate compilation errors. Match(new Token(TokenType.Symbol, "}")); }