Exemple #1
0
 // Semantic resolution
 protected override Exp ResolveExpAsRight(ISemanticResolver s)
 {
     // We have a problem. If our arg is a property, then we need to 
     // transform this x++ --> x = x + 1
     // But we can't always transform since we can overload the ++, -- operators.
     // So resolve our arg, see if it's a property, and then transform if it is.
     
     // Since we update the Arg, we must resolve it as a left value
     Exp.ResolveExpAsLeft(ref this.m_exp, s);
     
     // First check if we have an overload
     
     
     // Check if we're a property
     if (m_exp is PropertyExp)
     {
         Exp e = null;
         int iDelta = IsInc ? 1 : -1;
         
         e = new AssignStmtExp(
             m_exp, 
             new BinaryExp(
                 m_exp,
                 new IntExp(iDelta, this.m_filerange),
                 BinaryExp.BinaryOp.cAdd
             )
         );
         
         Exp.ResolveExpAsRight(ref e, s);
         return e;
     }
             
     CalcCLRType(s);
 
     // Ensure type match, unless we have an overload.
     s.EnsureAssignable(Arg, typeof(int));
     
     return this;
 }
Exemple #2
0
    // Do the real work
    protected void ParseStatementOrLocal_Helper(out Statement s, out LocalVarDecl v)
    {   
        s = null;
        v = null;
        
        // For each statement, we know which type based off the first token.
        // Expect for an identifier, in which case it could be a few things.
        Token t = m_lexer.PeekNextToken();
        
        #if false
        // Skip past any ';' (as empty statements)
        while(t.TokenType == Token.Type.cSemi)
        {
            ConsumeNextToken();
            t = m_lexer.PeekNextToken();            
        }
        #endif
                       
        if (IsStartOfExp(t))
        {
            FileRange f = BeginRange();
            
            // This could be either an expression or a type
            Exp e = ParseExp();
            t = m_lexer.PeekNextToken();

            
            // Case 1 - Var declaration:
            // If an identifier follows, then we just read a type and this is
            // a var declaration:
            // Type id ';'
            // Type id '=' exp ';'
            if (t.TokenType == Token.Type.cId)
            {
                TypeSig tSig  = this.ConvertExpToType(e);

                Identifier id = ReadExpectedIdentifier();
                
                v = new LocalVarDecl(id, tSig);
                                
                // Check for optional assignment (if there's an '=' after the name)
                Token t3 = m_lexer.PeekNextToken();
                if (t3.TokenType == Token.Type.cAssign)
                {
                    ConsumeNextToken();                     // '='
                    Exp eRHS = ParseExp();                  // exp                
                    ReadExpectedToken(Token.Type.cSemi);    // ';'
                    
                    SimpleObjExp oleft = new SimpleObjExp(id);
                    StatementExp se = new AssignStmtExp(oleft, eRHS);
                    s = new ExpStatement(se);
                    
                    se.SetLocation(EndRange(f));
                } else {                
                    ReadExpectedToken(Token.Type.cSemi);    // ';'
                }


                
                return;
            } // end decl case

            // Case 2 - label declaration
            else if (t.TokenType == Token.Type.cColon)
            {                
                SimpleObjExp o2 = e as SimpleObjExp;
                if (o2 != null)
                {
                    ConsumeNextToken(); // ':'
                    s = new LabelStatement(o2.Name);
                    return; // skip reading a ';'
                } 
                
                ThrowError(new ParserErrorException(Code.cBadLabelDef, t.Location, 
                    "Bad label definition (labels must be a single identifier)"));                                
            } // end case for label decls
                        
            // Expect a StatementExp
            else if (t.TokenType == Token.Type.cSemi) {
                ReadExpectedToken(Token.Type.cSemi);
                
                // Else we must be a StatementExp
                StatementExp se = e as StatementExp;
                if (se == null)
                    //this.ThrowError_ExpectedStatementExp(e.Location);
                    ThrowError(E_ExpectedStatementExp(e.Location));
                
                se.SetLocation(EndRange(f));
                s = new ExpStatement(se);            
                return;
            }
    
            ThrowError(E_UnexpectedToken(t));
        } // end start of expressions
        
        switch(t.TokenType)
        {
        // Empty statement
        case Token.Type.cSemi:
            ConsumeNextToken();
            s = new EmptyStatement();
            break;

        // Return -> 'return' ';'
        //         | 'return' exp ';'
        case Token.Type.cReturn:
            {
                ConsumeNextToken();
                
                t = m_lexer.PeekNextToken();
                Exp e = null;
                if (t.TokenType != Token.Type.cSemi) 
                {
                    e = ParseExp();                    
                }
                ReadExpectedToken(Token.Type.cSemi);
        
                s = new ReturnStatement(e);                
            }        
            break;
            
        // Note that the semi colons are included inthe stmt            
        // IfSmt -> 'if' '(' exp ')' stmt:then 
        // IfSmt -> 'if' '(' exp ')' stmt:then 'else' stmt:else
        case Token.Type.cIf:
        {
            ConsumeNextToken(); // 'if'
            ReadExpectedToken(Token.Type.cLParen);
            Exp exp = ParseExp();            
            ReadExpectedToken(Token.Type.cRParen);
            
            Statement sThen = ParseStatement();
            Statement sElse = null;
            
            Token t2 = m_lexer.PeekNextToken();
            if (t2.TokenType == Token.Type.cElse) 
            {
                ConsumeNextToken(); // 'else'
                sElse = ParseStatement();                
            }
            
            s = new IfStatement(exp, sThen, sElse);        
        }
            break;
            
        case Token.Type.cSwitch:
            s = ParseSwitchStatement();
            break;            
        
        // Throw an expression
        // ThrowStmt -> 'throw' objexp    
        case Token.Type.cThrow:
        {
            ConsumeNextToken(); // 'throw'
            Exp oe = null;
            if (m_lexer.PeekNextToken().TokenType != Token.Type.cSemi)
            {
                oe = ParseExp();            
            }
            ReadExpectedToken(Token.Type.cSemi);
            
            s = new ThrowStatement(oe);
        }
            break;
        
        // try-catch-finally
        case Token.Type.cTry:
            s = ParseTryCatchFinallyStatement();
            break;
        
        // while loop
        // 'while' '(' exp ')' stmt            
        case Token.Type.cWhile:
        {
            ConsumeNextToken(); // 'while'
            ReadExpectedToken(Token.Type.cLParen);

            Exp e = ParseExp();

            ReadExpectedToken(Token.Type.cRParen);

            Statement body = ParseStatement();

            s = new WhileStatement(e, body);


        }
            break;

        // do loop
        // 'do' stmt 'while' '(' exp ')' ';'
        case Token.Type.cDo:
        {
            ConsumeNextToken(); // 'do'
            Statement body = ParseStatement();
            ReadExpectedToken(Token.Type.cWhile);

            ReadExpectedToken(Token.Type.cLParen);
            Exp e = ParseExp();
            ReadExpectedToken(Token.Type.cRParen);

            ReadExpectedToken(Token.Type.cSemi);

            s = new DoStatement(e, body);

        }
            break;

        // goto
        // 'goto' id:label ';'
        case Token.Type.cGoto:
        {
            ConsumeNextToken();                             // 'goto'
            Identifier id = ReadExpectedIdentifier();       // id:label
            ReadExpectedToken(Token.Type.cSemi);            // ';'

            s = new GotoStatement(id);
        }
            break;

        // break
        // 'break' ';'
        case Token.Type.cBreak:
            ConsumeNextToken();
            ReadExpectedToken(Token.Type.cSemi);
            s = new BreakStatement();
            break;

        // Continue
        // 'continue' ';'
        case Token.Type.cContinue:
            ConsumeNextToken();
            ReadExpectedToken(Token.Type.cSemi);
            s = new ContinueStatement();
            break;
            
        // For-loop            
        case Token.Type.cFor:
            s = ParseForStatement();
            break;

        // For-each
        // -> 'foreach' '(' Type id 'in' exp:collection ')' stmt
        case Token.Type.cForEach:
            s = ParseForeachStatement();
            break;
            
        // BlockStatement - can be nested inside each other
        // start with a  '{', no terminating semicolon
        case Token.Type.cLCurly:
            {
                s = ParseStatementBlock();                
            }
            break;
            
        default:
            ThrowError(E_UnexpectedToken(t)); // unrecognized statement
            break;
        
        } // end switch
        
        // Must have come up with something
        Debug.Assert(s != null || v != null);    
    }
Exemple #3
0
 // Group 0) assignment (=, +=, etc) & conditional ?:
 protected Exp ParseExp_Worker()
 {        
     Exp T = ParseExp1();
     
     Token t = m_lexer.PeekNextToken();
     
     // Assignment
     if (t.TokenType == Token.Type.cAssign)
     {
         ConsumeNextToken();
         Exp E = ParseExp();
         
         AssignStmtExp s = new AssignStmtExp(T, E);
         return s;
     } 
     
     // ?: operator --> E ? E : E
     if (t.TokenType == Token.Type.cQuestion)
     {
         ConsumeNextToken();   
         Exp eTrue = ParseExp();
         ReadExpectedToken(Token.Type.cColon);
         Exp eFalse = ParseExp();
         
         return new IfExp(T, eTrue, eFalse);
     } 
     
     else {            
         // Look for +=,-=,*=,/=,%=
         AST.BinaryExp.BinaryOp op = BinaryExp.BinaryOp.cEqu; // set to dummy
         switch(t.TokenType)
         {
         // Arithmetic
         case Token.Type.cPlusEqual:
             op = BinaryExp.BinaryOp.cAdd;
             break;
         case Token.Type.cMinusEqual:
             op = BinaryExp.BinaryOp.cSub;
             break;
         case Token.Type.cMulEqual:
             op = BinaryExp.BinaryOp.cMul;
             break;
         case Token.Type.cDivEqual:
             op = BinaryExp.BinaryOp.cDiv;
             break;
         case Token.Type.cModEqual:
             op = BinaryExp.BinaryOp.cMod;
             break;          
             
         // Bitwise
         case Token.Type.cBitwiseAndEqual:
             op = BinaryExp.BinaryOp.cBitwiseAnd;
             break;
             
         case Token.Type.cBitwiseOrEqual:
             op = BinaryExp.BinaryOp.cBitwiseOr;
             break;
             
         case Token.Type.cBitwiseXorEqual:
             op = BinaryExp.BinaryOp.cBitwiseXor;
             break;
             
         // Shift
         case Token.Type.cShiftLeftEqual:
             op = BinaryExp.BinaryOp.cShiftLeft;
             break;
             
         case Token.Type.cShiftRightEqual:
             op = BinaryExp.BinaryOp.cShiftRight;
             break;                
         }
         
         if (op != BinaryExp.BinaryOp.cEqu)
         {
             ConsumeNextToken();
             Exp E = ParseExp();                
             //return new OpEqualStmtExp(T, E, op);
             // Transform 'a X= b' -> 'a = (a X b)'
             // This makes things much more consistent.
             AST.AssignStmtExp assign = new AssignStmtExp(
                 T,
                 new BinaryExp(
                     T,
                     E,
                     op)
                 );
             return assign;
         }
     }
     
     Debug.Assert(T != null);
     return T;
 }    
Exemple #4
0
    // Resolve
    protected override Exp ResolveExpAsRight(ISemanticResolver s)
    {
        if (m_symbol != null)
            return this;
            
        // Resolve the type we're allocating        
        m_tFullType.ResolveType(s);
        Debug.Assert(this.ElemType != null);
        
        // Resolve the initializer list        
        if (HasInitializerList) 
        {
            // If we specified a length, it'd better match the intializer list length.
            if (DimensionExpList != null)
            {
                Debug.Assert(this.DimensionExpList.Length == 1, "@todo -multidimensional arrays");
                Exp e = DimensionExpList[0];
                // e must be a compile time constant who's value matches the ArrayInit length
                IntExp eInt = e as IntExp;
                
                if (eInt == null)
                    ThrowError(SymbolError.MustBeCompileTimeConstant(e));
                
                if (eInt.Value != m_ArrayInit.Length)
                    ThrowError(SymbolError.NewArrayBoundsMismatch(this));
            }
        
            m_ArrayInit.Resolve(s, this.ElemType);
            
            // The ability to not specifiy a dimension list is just syntactic sugar.
            // So if we still don't have it, we'd better fill it in based of the array-init list.
            if (DimensionExpList == null)
            {
                m_arExpList = new Exp[] { new IntExp(m_ArrayInit.Length, this.Location) };                
            }        
        }
        
        Debug.Assert(DimensionExpList != null);                
        for(int i = 0; i < this.m_arExpList.Length; i++)
        {
            ResolveExpAsRight(ref m_arExpList[i], s);
        }
        

        m_symbol = new ArrayTypeEntry(m_tFullType, s);
        CalcCLRType(s);
                
        // Transform an initializer list into an CompoundExpression:
        // new T[] { e0, e1, ... en} 
        // <DeclareTemp(x), x = new T[], x[0]=e0, ... x[n]=en, x>
        if (HasInitializerList)
        {
            DeclareLocalStmtExp declare_x = new DeclareLocalStmtExp(this.ArraySymbol); 
                
            LocalExp x = declare_x.GetLocal();
            
            StatementExp [] list = new StatementExp[m_ArrayInit.Length + 2];
            list[0] = declare_x;
            list[1] = new AssignStmtExp(x, this);
            for(int i = 0; i < m_ArrayInit.Length; i++)
                list[i + 2] = new AssignStmtExp(
                    new ArrayAccessExp(
                        x,
                        new IntExp(i, null)
                    ),
                    m_ArrayInit.GetExpAt(i)
                );
            
            // Strip the ArrayInitializer off this node.    
            m_ArrayInit = null;
                            
            StatementExp c = new CompoundStmtExp(list, x);
            
            StatementExp.ResolveExpAsRight(ref c, s);
            
            return c;
        } // end has Initializer
                
        return this;
    }