Exemplo n.º 1
0
        //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);
            }
        }