/// <summary>
        /// Type ::= ("int" | Identifier) [ "[" "]" ] .
        /// </summary>
        /// <returns></returns>
        private TYPE parseType()
        {
            TYPE result = new TYPE();

            Token token = lexer.get();
            if ( token.code == TokenCode.INT )
            {
                result.classRef = null;
                result.isArray = false;
                result.className = token.image;
                lexer.forget();
            }
            else if ( token.code == TokenCode.IDENTIFIER )
            {
                result.className = token.image;
                lexer.forget();
            }
            else
                errors.issue(token,13); // type expected

            token = lexer.get();
            if ( token.code == TokenCode.LBRACKET )
            {
                lexer.forget();
                token = lexer.get();
                if ( token.code != TokenCode.RBRACKET ) errors.issue(token,11,"]");
                else                                    lexer.forget();
                result.isArray = true;
            }
            return result;
        }
        /// <summary>
        /// Body ::= "{" {LocalDeclaration} {Statement} "}".
        /// 
        /// Statement ::= Assignment 
        ///             | IfStatement 
        ///             | WhileStatement 
        ///             | ReturnStatement 
        ///             | CallStatement 
        ///             | PrintStatement 
        ///             | Block
        /// </summary>
        /// <returns></returns>
        private ENTITY parseBodyElement()
        {
            Token token = lexer.get();

            switch ( token.code )
            {
                case TokenCode.IF :
                {
                    // IfStatement ::= "if" "(" Relation ")" Statement ["else" Statement].
                    IF ifStmt = new IF();

                    lexer.forget();
                    token = lexer.get();
                    if ( token.code != TokenCode.LPAREN )
                        lexer.skipUntil(TokenCode.RPAREN);
                    else
                    {
                        lexer.forget();
                        ifStmt.relation = parseRelation();
                    }
                    token = lexer.get();
                    if ( token.code == TokenCode.RPAREN ) lexer.forget();
                    else                                  lexer.skipUntil(TokenCode.RPAREN);

                    ifStmt.thenPart = parseBodyElement() as STATEMENT;

                    token = lexer.get();
                    if ( token.code == TokenCode.ELSE )
                    {
                        lexer.forget();
                        ifStmt.elsePart = parseBodyElement() as STATEMENT;
                    }
                    return ifStmt;
                }
                case TokenCode.WHILE:
                {
                    // WhileStatement ::= "while" "(" Relation ")" Statement .
                    WHILE whileStmt = new WHILE();

                    lexer.forget();
                    token = lexer.get();
                    if ( token.code != TokenCode.LPAREN )
                    {
                        errors.issue(token,20);
                        lexer.skipUntil(TokenCode.RPAREN);
                    }
                    else
                    {
                        lexer.forget();
                        whileStmt.relation = parseRelation();
                    }
                    token = lexer.get();
                    if ( token.code == TokenCode.RPAREN ) lexer.forget();
                    else                                  lexer.skipUntil(TokenCode.RPAREN);

                    whileStmt.body = parseBodyElement() as STATEMENT;
                    return whileStmt;
                }
                case TokenCode.RETURN:
                {
                    // ReturnStatement ::= "return" [Expression] ";"
                    RETURN returnStmt = new RETURN();

                    lexer.forget();
                    token = lexer.get();
                    if ( token.code == TokenCode.SEMICOLON )
                        lexer.forget();
                    else
                    {
                        returnStmt.result = parseExpression();
                        token = lexer.get();
                        if ( token.code != TokenCode.SEMICOLON )
                            lexer.skipUntil(TokenCode.SEMICOLON);
                        lexer.forget();
                    }
                    return returnStmt;
                }
                case TokenCode.PRINT:
                {
                    // PrintStatement ::= "print" "(" Expression ")" ";".
                    PRINT print = new PRINT();

                    lexer.forget();
                    token = lexer.get();
                    if ( token.code != TokenCode.LPAREN ) goto Error;
                    lexer.forget();

                    print.value = parseExpression();

                    token = lexer.get();
                    if ( token.code != TokenCode.RPAREN ) goto Error;
                    lexer.forget();

                    token = lexer.get();
                    if ( token.code != TokenCode.SEMICOLON ) goto Error;
                    lexer.forget();

                    return print;
                 Error:
                    errors.issue(token,19);
                    lexer.skipUntil(TokenCode.SEMICOLON);
                    lexer.forget();
                    return null;
                }
                case TokenCode.LBRACE:
                {
                    // Block ::= "{" {Statement} "}".

                    lexer.forget();
                    BLOCK block = new BLOCK();
                    while ( true )
                    {
                        STATEMENT statement = parseBodyElement() as STATEMENT;
                        if ( statement == null ) break;
                        block.statements.Add(statement);
                    }
                    token = lexer.get();
                    if ( token.code != TokenCode.RBRACE ) lexer.skipUntil(TokenCode.RBRACE);
                    lexer.forget();
                    return block;
                }
                case TokenCode.INT:
                {
                    // int x;
                    // int[] x;
                    bool isArray = false;
                    lexer.forget();
                    token = lexer.get();
                    if ( token.code == TokenCode.LBRACKET )
                    {
                        isArray = true;
                        lexer.forget();
                        token = lexer.get();
                        if ( token.code != TokenCode.RBRACKET )
                        {
                            errors.issue(token,17);
                            lexer.skipUntil(TokenCode.SEMICOLON);
                            return null;
                        }
                        else
                            lexer.forget();
                    }
                    string fname = "";
                    token = lexer.get();
                    if ( token.code != TokenCode.IDENTIFIER )
                    {
                        errors.issue(token,17);
                        lexer.skipUntil(TokenCode.SEMICOLON);
                        return null;
                    }
                    else
                    {
                        fname = token.image;
                        lexer.forget();
                    }
                    token = lexer.get();
                    if ( token.code != TokenCode.SEMICOLON ) lexer.skipUntil(TokenCode.SEMICOLON);
                    lexer.forget();

                    TYPE type = new TYPE();
                    type.classRef = null;
                    type.className = "int";
                    type.isArray = isArray;

                    FIELD local = new FIELD(0,fname);
                    local.type = type;
                    local.isLocal = true;
                    return local;
                }
                case TokenCode.IDENTIFIER:
                {
                    // Assignment ::= Identifier ["." Identifier | "[" Expression "]" ] "=" Expression ";"
                    //
                    // CallStatement ::= Identifier ["." Identifier] "(" [Expression {"," Expression}]")" ";".
                    //
                    // LocalDeclaration ::= Type Identifier ";".

                    ENTITY result = null;
                    NAME name = parseName();
                    if ( name == null ) // An error was detected
                    {
                        lexer.skipUntil(TokenCode.SEMICOLON);
                        return null;
                    }
                    // After that goes either assignment of left parenthesis.
                    token = lexer.get();
                    if ( token.code == TokenCode.ASSIGN )
                    {
                        lexer.forget();
                        EXPRESSION rightSide = parseExpression();
                        ASSIGNMENT assignment = new ASSIGNMENT();
                        assignment.name = name;
                        assignment.expression = rightSide;
                        result = assignment;
                    }
                    else if ( token.code == TokenCode.LPAREN )
                    {
                        lexer.forget();
                        CALL call = new CALL();
                        call.name = name;
                        while ( true )
                        {
                            token = lexer.get();
                            if ( token.code == TokenCode.RPAREN ) { lexer.forget(); break; }

                            call.arguments.Add(parseExpression());
                            token = lexer.get();
                            if ( token.code == TokenCode.COMMA )
                            {
                                lexer.forget();
                                continue;
                            }
                            else if ( token.code != TokenCode.RPAREN )
                            {
                                errors.issue(token,18);
                                lexer.skipUntil(TokenCode.SEMICOLON);
                                return null;
                            }
                        }
                        result = call;
                    }
                    else if ( token.code == TokenCode.IDENTIFIER )
                    {
                        // Dont't forget()

                        // A local declaration?
                        // -- Converting NAME to TYPE
                        TYPE type = new TYPE();
                        type.className = name.name;
                        type.isArray = name is ARRAY_ELEM;

                        FIELD local = new FIELD(0,token.image);
                        local.type = type;
                        result = local;

                        lexer.forget();
                    }
                    token = lexer.get();
                    if ( token.code != TokenCode.SEMICOLON )
                    {
                        errors.issue(token,19);
                        lexer.skipUntil(TokenCode.SEMICOLON);
                    }
                    lexer.forget();
                    return result;
                }
                case TokenCode.RBRACE :
                    // End of method body
                    // Don't forget().
                    return null;

                default :
                    errors.issue(token,17);
                    lexer.skipUntil(TokenCode.SEMICOLON);
                    lexer.forget();
                    return null;
            }
        }