//term ::= <int-const> | <str-const> | <keyword-const> | <var-name> | // <var-name> '[' <expression> ']' | <sub-call> | '(' expression ')' | // ('-' | '!') <term> private void ParseTerm() { if (LookAheadToken.Type == TokenType.IntConst) { Token intConst = NextToken(); _codeGenerator.IntConst(int.Parse(intConst.Value)); } else if (LookAheadToken.Type == TokenType.StrConst) { Token strConst = NextToken(); _codeGenerator.StrConst(strConst.Value); } else if (IsNextTokenKeywordConst()) { Token keywordConst = NextToken(); switch (keywordConst.Value) { case "true": _codeGenerator.True(); break; case "false": _codeGenerator.False(); break; case "null": _codeGenerator.Null(); break; case "this": if (_currentSub.Kind != SubroutineKind.Method && _currentSub.Kind != SubroutineKind.Constructor) { ThrowCompilationException("'this' can be used only in a method or a constructor"); } _codeGenerator.This(); break; default: ThrowCompilationException("Unexpected keyword constant '" + keywordConst.Value + "'"); break; } } else if (LookAheadToken.Type == TokenType.Ident) { //This is either a variable name, an array access, or a //subroutine call. To know which it's going to be, we need //the token after the variable name. Token varName = NextToken(); if (LookAheadToken.Value == ".") { ParseSubCall(varName); } else { //Now is the time to verify that we have a valid variable: Symbol symbol = GetClosestSymbol(varName.Value); if (symbol == null) { ThrowCompilationException("Undefined identifier '" + varName.Value + "'"); } bool withArrayIndex = false; if (LookAheadToken.Value == "[") { withArrayIndex = true; VerifyArrayAccessAllowed(varName); Match(new Token(TokenType.Symbol, "[")); ParseExpression(); Match(new Token(TokenType.Symbol, "]")); } _codeGenerator.VariableRead(varName, withArrayIndex); } } else if (LookAheadToken.Value == "(") { Match(new Token(TokenType.Symbol, "(")); ParseExpression(); Match(new Token(TokenType.Symbol, ")")); } else if (IsNextTokenUnaryOp()) { Token unaryOp = NextToken(); ParseTerm(); switch (unaryOp.Value) { case "-": _codeGenerator.Negate(); break; case "!": _codeGenerator.Not(); break; default: ThrowCompilationException("Unexpected unary operator: " + unaryOp.Value); break; } } else { ThrowCompilationException("Expected a term, got: " + LookAheadToken.Value); } }