Пример #1
0
        /// <summary>
        /// Parameter ::= Type Identifier.
        /// </summary>
        /// <param name="stop"></param>
        /// <returns></returns>
        private FIELD parseParameter()
        {
            Token token;

            // Parameter ::= Type Identifier.
            FIELD result = null;
            string name = null;
            TYPE parType = parseType();

            if ( parType == null ) errors.issue(null,15); // incorrect type
            token = lexer.get();
            if ( token.code == TokenCode.IDENTIFIER )
            {
                name = token.image;
                lexer.forget();

                result = new FIELD(0,name);
                result.type = parType;
                result.isStatic = false;
            }
            else
            {
                errors.issue(token,11,"identifier");
                lexer.skipUntil(TokenCode.RPAREN);
                result = new FIELD(0,"");
            }
            result.isParameter = true;
            return result;
        }
Пример #2
0
        /// <summary>
        /// FieldDeclaration ::= [Visibility] ["static"] Type Identifier ";".
        ///
        /// MethodDeclaration ::= [Visibility] ["static"] ("void" | Type) Identifier 
        ///                                      "("[Parameter {"," Parameter}] ")" Body.
        ///
        /// Visibility ::= "private" | "public" | "private".
        ///
        /// Parameter ::= Type Identifier.
        ///
        /// Body ::= "{" {LocalDeclaration} {Statement} "}".
        ///
        /// LocalDeclaration ::= Type Identifier ";".
        /// </summary>
        /// <returns></returns>
        private DECLARATION parseMethodOrField()
        {
            int v = 0;
            bool s = false;
            string name = null;

            Token token = lexer.get();

            if ( token.code == TokenCode.RBRACE ) // end of class methods
            {
                lexer.forget();
                return null;
            }

            switch ( token.code )
            {
                case TokenCode.PUBLIC    : v = 0; lexer.forget(); break;
                case TokenCode.PRIVATE   : v = 1; lexer.forget(); break;
                case TokenCode.PROTECTED : v = 2; lexer.forget(); break;
                default: v = 0; break;
            }

            token = lexer.get();
            if ( token.code == TokenCode.STATIC ) { s = true; lexer.forget(); }

            TYPE type = null;

            token = lexer.get();
            if ( token.code == TokenCode.VOID )
                lexer.forget();
            else
                type = parseType();

            token = lexer.get();
            if ( token.code == TokenCode.IDENTIFIER )
            {
                name = token.image;
                lexer.forget();
            }
            else
                errors.issue(token,11,"identifier");

            token = lexer.get();
            if ( token.code == TokenCode.SEMICOLON )
            {
                // End of field declaration
                lexer.forget();
                if ( type == null ) errors.issue(token,14); // void in field declaration
                FIELD field = new FIELD(v,name);
                field.type = type;
                field.isStatic = s;
                return field;
            }
            // Else this is a method declaration.

            METHOD method = new METHOD(v, name);
            method.isStatic = s;
            method.type = type;

            if ( name == "Main" )
            {
                if ( hasMain ) errors.issue(token,32); // multiple Main's
                else hasMain =true;
            }

            // Continue parsing:
            //      "(" [ Parameter {"," Parameter} ] ")" Body

            token = lexer.get();
            if ( token.code != TokenCode.LPAREN )
            {
                errors.issue(token,11,"(");
                lexer.skipUntil(TokenCode.RPAREN);
            }
            else
                lexer.forget();

            int i = 0;
            while ( true ) // parsing method parameters
            {
                token = lexer.get();
                if ( token.code == TokenCode.RPAREN ) { lexer.forget(); break; }

                FIELD parameter = parseParameter();

                string n = parameter.name;
                if ( method.parameters.ContainsKey(n) )
                    errors.issue(token,12,"parameter",n);
                else
                {
                    parameter.number = i;
                    i++;
                    method.parameters.Add(n,parameter);
                }

                token = lexer.get();
                if (token.code == TokenCode.COMMA)
                {
                    lexer.forget();
                    continue;
                }
                else if (token.code != TokenCode.RPAREN)
                {
                    errors.issue(token,16);
                    lexer.skipUntil(TokenCode.RPAREN);
                    lexer.forget();
                    break;
                }
            }

            // Parsing method body:
            //
            // Body ::= "{" {LocalDeclaration} {Statement} "}".

            token = lexer.get();
            if ( token.code == TokenCode.LBRACE ) lexer.forget();
            else                                  lexer.skipUntil(TokenCode.RBRACE);

            int j = 0;
            while ( true )
            {
                token = lexer.get();
                if ( token.code == TokenCode.RBRACE ) { lexer.forget(); break; }

                ENTITY bodyElement = parseBodyElement();
                if ( bodyElement == null ) // and error was detected
                    continue;
                else if ( bodyElement is FIELD )
                {
                    (bodyElement as FIELD).isLocal = true;
                    string n = (bodyElement as FIELD).name;
                    if ( method.locals.ContainsKey(n) )
                        errors.issue(token,12,"local",n);
                    else
                    {
                        (bodyElement as FIELD).number = j;
                        j++;
                        method.locals.Add(n,bodyElement as FIELD);
                    }
                }
                else if ( bodyElement is STATEMENT )
                    method.statements.Add(bodyElement as STATEMENT);
            }
            return method;
        }
Пример #3
0
        /// <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;
            }
        }
 private void generateLocal( ILGenerator il, FIELD field )
 {
     TYPE t = field.type;
     Type type = null;
     if ( t.classRef == null )
     {
         if ( t.isArray ) type = typeof(int[]); else type = typeof(int);
     }
     else
     {
         type = classes[t.className].typeBuilder;
         if ( t.isArray ) type = type.MakeArrayType();
     }
     LocalBuilder local = il.DeclareLocal(type);
     if ( t.classRef == null )
     {
         if ( t.isArray ) il.Emit(OpCodes.Ldnull);
         else             il.Emit(OpCodes.Ldc_I4_0);
     }
     else
         il.Emit(OpCodes.Ldnull);
     il.Emit(OpCodes.Stloc,local);
 }