Esempio n. 1
0
		private void ParseExpressionSegment()
		{
			#region Chart
			// arraycre		new			: type : [{
			// literal		(lit)
			// simpleName	ident
			// parenExpr	LParen		: expr
			// memAccess	pexpr		: Dot
			//				pdefType	: Dot
			// invoke		pexpr		: LParen
			// elemAccess	noArrCreExpr: LBracket
			// thisAccess	this
			// baseAccess	base		: Dot
			//				base		: LBracket
			// postInc		pexpr		: ++
			// postDec		pexpr		: --
			// objCre		new			: type : LParen
			// delgCre		new			: delgType : LParen
			// typeof		typeof		: LParen
			// checked		checked		: LParen
			// unchecked	unchecked	: LParen
			#endregion
			ExpressionNode tempNode = null;
			TokenID startToken = curtok.ID;
			switch (curtok.ID)
			{
				#region Literals
				case TokenID.NullLiteral:
                    exprStack.Push(new NullPrimitive(curtok));
					Advance();
					break;

				case TokenID.TrueLiteral:
                    exprStack.Push(new BooleanPrimitive(true, curtok));
					Advance();
					ParseContinuingPrimary();
					break;

				case TokenID.FalseLiteral:
                    exprStack.Push(new BooleanPrimitive(false, curtok));
					Advance();
					ParseContinuingPrimary();
					break;

				case TokenID.IntLiteral:
                    exprStack.Push(new IntegralPrimitive(strings[curtok.Data], IntegralType.Int, curtok));
					Advance();
					ParseContinuingPrimary();
					break;
				case TokenID.UIntLiteral:
                    exprStack.Push(new IntegralPrimitive(strings[curtok.Data], IntegralType.UInt, curtok));
					Advance();
					ParseContinuingPrimary();
					break;
				case TokenID.LongLiteral:
                    exprStack.Push(new IntegralPrimitive(strings[curtok.Data], IntegralType.Long, curtok));
					Advance();
					ParseContinuingPrimary();
					break;
				case TokenID.ULongLiteral:
                    exprStack.Push(new IntegralPrimitive(strings[curtok.Data], IntegralType.ULong, curtok));
					Advance();
					ParseContinuingPrimary();
					break;

				case TokenID.RealLiteral:
                    exprStack.Push(new RealPrimitive(strings[curtok.Data], curtok));
					Advance();
					ParseContinuingPrimary();
					break;

				case TokenID.CharLiteral:
                    exprStack.Push(new CharPrimitive(strings[curtok.Data], curtok));
					Advance();
					ParseContinuingPrimary();
					break;

				case TokenID.StringLiteral:
					string sval = strings[curtok.Data];
                    exprStack.Push(new StringPrimitive(sval, curtok));
					Advance();
					ParseContinuingPrimary();
					break;
				#endregion
				#region Predefined Types

				case TokenID.Bool:
				case TokenID.Byte:
				case TokenID.Char:
				case TokenID.Decimal:
				case TokenID.Double:
				case TokenID.Float:
				case TokenID.Int:
				case TokenID.Long:
				case TokenID.Object:
				case TokenID.SByte:
				case TokenID.Short:
				case TokenID.String:
				case TokenID.UInt:
				case TokenID.ULong:
				case TokenID.UShort:
                    exprStack.Push(ParseIdentifierOrKeyword(false, true, false, false));

                    if (curtok.ID == TokenID.Question)
                    {
                        Advance();
                        ((INullableType)exprStack.Peek()).IsNullableType = true;
                    }
                    else
                    {
                        if (curtok.ID == TokenID.Star)
                        {
                            Advance();
                            exprStack.Push(new TypePointerNode(exprStack.Pop()));
                        }   
                    }

					ParseContinuingPrimary();
					break;
				#endregion
				#region Binary Ops
					
				case TokenID.Plus:
					tempNode = ConsumeBinary(startToken);
					if (tempNode != null)
					{
                        exprStack.Push(new UnaryExpression(startToken, tempNode, tempNode.RelatedToken)); // unary
					}
					break;
				case TokenID.Minus:
                    if (exprStack.Count != 0 && exprStack.Peek() is PrimaryExpression)
                    {
                        tempNode = ConsumeBinary(startToken);
                    }
                    else
                    {
                        ConsumeUnary(TokenID.Minus);
                    }
					if (tempNode != null)
					{
						exprStack.Push(new UnaryExpression(startToken, tempNode, tempNode.RelatedToken)); // unary
					}
					break;

				case TokenID.Star:
                    // for this token, we have to control it is not a
                    // pointer type declaration
                    bool isPointer = false;

                    if ( exprStack.Count == 0
                        || !(exprStack.Peek() is IPointer) &&
                            (curTokNode != null && curTokNode.Value.ID == TokenID.Star || curTokNode.Previous.Previous.Value.ID == TokenID.Star))
                    {
                        // case : 
                        // int* p;
                        // *p = x;
                        Advance();//over the '*';

                        ParseExpressionSegment();
                        exprStack.Push(new DereferenceExpression(exprStack.Pop(), true ));
                    }
                    else
                    {
                        if (isLocalConst // if const kw -> local/member declaration
                            || exprStack.Peek() is IPointer)
                        {
                            //the expression inherits from IPointer, so this is a type expression
                            //and it might be a pointer
                            isPointer = true;
                        }
                        else
                        {
                            // if the next segment can not be an expression
                            TokenID id = (curTokNode != null) ? curTokNode.Value.ID : TokenID.Eof;
                            if (id == TokenID.Eof || id == TokenID.RCurly ||
                                id == TokenID.Semi || id == TokenID.RParen ||
                                id == TokenID.Comma || id == TokenID.Colon)
                            {
                                isPointer = true;
                            }
                        }

                        if (isPointer)
                        {
                            Advance();
                            ExpressionNode e = TagAsPointerType(exprStack.Pop());
                            exprStack.Push(e);
                        }
                        else
                        {
                            //the next segment is an expression. 
                            //at this sage it is impossible to determine if this is a pointer expression
                            ConsumeBinary(startToken);

                            if (curtok.ID == TokenID.Equal)
                            {
                                // the assignment means that the previous expression is not 
                                // a binary expression but a local pointer declaration

                                Advance(); // over equal

                                BinaryExpression bin = (BinaryExpression)exprStack.Pop();
                                LocalDeclarationStatement ldecl = new LocalDeclarationStatement((IType)TagAsPointerType(bin.Left), (IdentifierExpression)bin.Right, ParseExpression(TokenID.Comma) );

                                exprStack.Push(ldecl);

                                if (curtok.ID == TokenID.Comma)// multiple local declaration
                                {
                                    exprStack.Push((ExpressionNode)ldecl.Type);
                                    ParseLocalDeclaration();
                                }
                            }
                        }
                    }
                    break;
                case TokenID.Is:
                case TokenID.As:
				case TokenID.Slash:
				case TokenID.Percent:
				case TokenID.ShiftLeft:
				case TokenID.ShiftRight:
				case TokenID.Less:
				case TokenID.Greater:
				case TokenID.LessEqual:
				case TokenID.GreaterEqual:
				case TokenID.EqualEqual:
				case TokenID.NotEqual:
				case TokenID.BXor:
				case TokenID.BOr:
				case TokenID.And:
				case TokenID.Or:
					ConsumeBinary(startToken);
					break;

                case TokenID.BAnd:
                    if (exprStack.Count == 0)
                    {
                        //the expression stack is empty, so this is n identifier dereference
                        ParseAddressOfIdentifier();
                    }
                    else
                    {
                        ConsumeBinary(startToken);
                    }
                    break;

				#endregion
				#region Unary Ops

				case TokenID.Not:
				case TokenID.Tilde:
				case TokenID.PlusPlus:
				case TokenID.MinusMinus:
					ConsumeUnary(startToken);
					break;

				#endregion
				#region Conditional
				case TokenID.Question:
                    if (curtok.NullableDeclaration)
                    {
                        Advance();

                        ExpressionNode expr = TagAsNullableType(exprStack.Pop());
                        CheckRankSpecifier(expr);

                        exprStack.Push(expr);
                    }
                    else
                    {
                        Advance();

                        ConditionalExpression conditionalExpression = new ConditionalExpression(exprStack.Pop(), null, null);

                        exprStack.Push(conditionalExpression);

                        ExpressionNode cond1 = ParseExpression(TokenID.Equal);
                        AssertAndAdvance(TokenID.Colon);
                        ExpressionNode cond2 = ParseExpression();

                        conditionalExpression.Left = cond1;
                        conditionalExpression.Right = cond2;
                    }                    

					break;
                //case TokenID.ColonColon:

                //    Advance();
                    //break;
                case TokenID.QuestionQuestion:
                    ExpressionNode left = exprStack.Pop();
                    Advance();
                    ExpressionNode right = ParseExpression(TokenID.Semi);
                    exprStack.Push(new NullCoalescingExpression(left, right ));
                    break;
				#endregion
				#region Keywords
				// keywords
				case TokenID.Ref:
					Advance();
					ParseExpressionSegment();
                    exprStack.Push(new RefNode(exprStack.Pop()));
					break;

				case TokenID.Out:
					Advance();
					ParseExpressionSegment();
                    exprStack.Push(new OutNode(exprStack.Pop()));
					break;

				case TokenID.This:
                    exprStack.Push(ParseIdentifierOrKeyword(false, true, false, false));
					ParseContinuingPrimary();
					break;

				case TokenID.Void:
					// this can happen in typeof(void), nothing can follow
                    exprStack.Push(new VoidPrimitive(curtok)); 
                    Advance();
					break;

				case TokenID.Base:
					Advance();
					TokenID newToken = curtok.ID;
					if (newToken == TokenID.Dot)
					{
						Advance();// advance over dot
						exprStack.Push( new IdentifierExpression(strings[curtok.Data], curtok) );
						Advance();//advance over ident
					}
					else if (newToken == TokenID.LBracket)
					{
						Advance();//advance over left bracket
						exprStack.Push( ParseExpressionList(TokenID.RBracket) );
					}
                   
					ParseContinuingPrimary();

                    exprStack.Push(new BaseAccessExpression(exprStack.Pop()));
					break;

				case TokenID.Typeof:
					Advance();
					AssertAndAdvance(TokenID.LParen);
                    exprStack.Push(new TypeOfExpression(ParseExpression(TokenID.RParen)));
					AssertAndAdvance(TokenID.RParen);
					ParseContinuingPrimary();
					break;

				case TokenID.Checked:
					Advance();
					AssertAndAdvance(TokenID.LParen);
					//ParseExpressionSegment();
                    exprStack.Push(new CheckedExpression(ParseExpression(TokenID.RParen)));
					AssertAndAdvance(TokenID.RParen);
					ParseContinuingPrimary();
					break;

				case TokenID.Unchecked:
					Advance();
					AssertAndAdvance(TokenID.LParen);
					ParseExpressionSegment();
                    exprStack.Push(new UncheckedExpression(exprStack.Pop()));
					AssertAndAdvance(TokenID.RParen);
					ParseContinuingPrimary();
					break;
				#endregion
				#region Assignment

				case TokenID.Equal:
				case TokenID.PlusEqual:
				case TokenID.MinusEqual:
				case TokenID.StarEqual:
				case TokenID.SlashEqual:
				case TokenID.PercentEqual:
				case TokenID.BAndEqual:
				case TokenID.BOrEqual:
				case TokenID.BXorEqual:
				case TokenID.ShiftLeftEqual:
				case TokenID.ShiftRightEqual:
					TokenID op = curtok.ID;
					Advance();
					if (exprStack.Count > 0 && !(exprStack.Peek() is PrimaryExpression) && !(exprStack.Peek() is UnaryCastExpression))
					{
						ReportError("Left hand side of assignment must be a variable.");
					}
					ExpressionNode assignVar = exprStack.Pop();
					ExpressionNode rightSide = ParseExpression();
					exprStack.Push(new AssignmentExpression(op, assignVar, rightSide));
					break;

				#endregion
                #region Generic
                case TokenID.Default:
                    Advance();
                    AssertAndAdvance(TokenID.LParen);
                    ParseTypeParameterNode(false, false, false);
                    AssertAndAdvance(TokenID.RParen);
                    exprStack.Push(new DefaultConstantExpression(curTypeParameters[0] ));

                    curTypeParameters = new List<TypeParameterNode>();
                    ParseContinuingPrimary();
                    break;
                #endregion
                case TokenID.LCurly:
                    ArrayInitializerExpression aie = new ArrayInitializerExpression(curtok);
                    Advance();
					exprStack.Push(aie);
					aie.Expressions = ParseExpressionList(TokenID.RCurly);
					break;

				case TokenID.New:
					Advance();

                    isNewStatement = true;

                    // TODO : new int*() is allowed ? 
					IType newType = ParseType();

                    //ApplyTypeParameters(newType); -> not sure, but a type pointer can not be generic!

					if (curtok.ID == TokenID.LParen)
					{
						Advance();
						ExpressionList newList = ParseExpressionList(TokenID.RParen);
						exprStack.Push(new ObjectCreationExpression(newType, newList, newList.RelatedToken));
					}
					else if (curtok.ID == TokenID.LBracket)
					{
						ParseArrayCreation(newType);
					}
					ParseContinuingPrimary();

                    isNewStatement = false;
					break;

				case TokenID.Ident:

					//test for local decl
					bool isDecl = isAfterType();
					if (isDecl)
					{
						ParseLocalDeclaration();
					}
					else
					{
                        ExpressionNode expr = ParseIdentifierOrKeyword(false, true, false, false);

                        exprStack.Push(expr);
						ParseContinuingPrimary();
					}
					break;

				case TokenID.LParen:
					Advance();
					ParseCastOrGroup();
					break;

                case TokenID.Delegate://anonymous method
                    Advance();
                    ParseAnonymousMethod();
                    break;

                case TokenID.Sizeof:
                    ParseSizeOf();
                    break;

                case TokenID.Stackalloc:
                    ParseStackalloc();
                    break;

                case TokenID.MinusGreater:
                    // pointer member access
                    ParseContinuingPrimary();
                    break;

				default:
                    if (Lexer.IsKeyWord(curtok.ID))
                    {
                        // in this case a key word is used like a variable name.
                        goto case TokenID.Ident;
                    }
                    else
                    {
                        RecoverFromError("Unhandled case in ParseExpressionSegment ", curtok.ID); // todo: fill out error report
                    }
					break;
			}
		}
Esempio n. 2
0
        private ExpressionNode ParseSubexpression(int precBound, ExpressionNode left)
        {
            while (true)
            {
                int curPrec = precedence[(int)curtok.ID];
                if (curPrec < precBound) break;

                int associativity = ASSOC_LEFT;
                TokenID curOp = curtok.ID;
                switch (curOp)
                {
                    case TokenID.Equal:
                    case TokenID.PlusEqual:
                    case TokenID.MinusEqual:
                    case TokenID.StarEqual:
                    case TokenID.SlashEqual:
                    case TokenID.PercentEqual:
                    case TokenID.BAndEqual:
                    case TokenID.BOrEqual:
                    case TokenID.BXorEqual:
                    case TokenID.ShiftLeftEqual:
                    case TokenID.QuestionQuestion:
                        associativity = ASSOC_RIGHT;
                        goto case TokenID.Percent;		// "FALL THROUGH"

                    case TokenID.Greater:
                        Advance();
                        if (curtok.ID == TokenID.Greater && curtok.LastCharWasGreater)
                        {
                            curOp = TokenID.ShiftRight;
                            Advance();
                        }
                        else if (curtok.ID == TokenID.GreaterEqual && curtok.LastCharWasGreater)
                        {
                            curOp = TokenID.ShiftRightEqual;
                            associativity = ASSOC_RIGHT;
                            Advance();
                        }
                        goto parseBinOp;

                    case TokenID.Or:
                    case TokenID.And:
                    case TokenID.BOr:
                    case TokenID.BXor:
                    case TokenID.BAnd:
                    case TokenID.EqualEqual:
                    case TokenID.NotEqual:
                    case TokenID.Less:
                    case TokenID.LessEqual:
                    case TokenID.GreaterEqual:
                    case TokenID.ShiftLeft:
                    case TokenID.Plus:
                    case TokenID.Minus:
                    case TokenID.Star:
                    case TokenID.Slash:
                    case TokenID.Percent:
                        Advance();
                    parseBinOp: left = new BinaryExpression(curOp, left, ParseSubexpression(curPrec + associativity));
                    break;

                    case TokenID.PlusPlus:								// postfix
                    Advance();
                    left = new PostIncrementExpression(left);
                    break;

                    case TokenID.MinusMinus:							// postfix
                    Advance();
                    left = new PostDecrementExpression(left);
                    break;

                    case TokenID.Is:
                    case TokenID.As:
                    Advance();
                    left = new BinaryExpression(curOp, left, ParseType(true));
                    break;

                    case TokenID.Question:
                    {
                        Advance();
                        ExpressionNode thenExpr = ParseExpression();
                        AssertAndAdvance(TokenID.Colon);
                        left = new ConditionalExpression(left, thenExpr, ParseExpression());
                        break;
                    }

                    case TokenID.LParen:								// invocation
                    Advance();
                    left = new InvocationExpression(left, ParseArgumentList());
                    AssertAndAdvance(TokenID.RParen);
                    break;

                    case TokenID.LBracket:								// element access
                    Advance();
                    left = new ElementAccessExpression(left, ParseExpressionList());
                    AssertAndAdvance(TokenID.RBracket);
                    break;

                    case TokenID.Dot:									// member access
                    case TokenID.MinusGreater:
                    left = ParseMemberAccess(left);
                    break;

                    default:
                    ReportError("Unexpected token", curtok);
                    return left;
                }
            }
            return left;
        }
Esempio n. 3
0
        private void ParseExpressionSegment()
        {
            #region Chart
            // baseAccess	base		: Dot
            //				base		: LBracket
            // delgCre		new			: delgType : LParen
            // typeof		typeof		: LParen
            // checked		checked		: LParen
            // unchecked	unchecked	: LParen
            #endregion

            bool stackCountUnaltered = false;
            int startStackCount = exprStack.Count;
            TokenID startToken = curtok.ID;
            switch (curtok.ID)
            {
                #region Conditional
                case TokenID.Question:
                    mayBeLocalDecl = false;
                    stackCountUnaltered = true;
                    if (curtok.NullableDeclaration)
                    {
                        Advance();

                        ExpressionNode expr = TagAsNullableType(exprStack.Pop());
                        CheckRankSpecifier(expr);

                        exprStack.Push(expr);
                    }
                    else
                    {
                        Advance();

                        ConditionalExpression conditionalExpression = new ConditionalExpression(exprStack.Pop(), null, null);

                        exprStack.Push(conditionalExpression);

                        ExpressionNode cond1 = ParseExpression(TokenID.Equal);
                        AssertAndAdvance(TokenID.Colon);
                        ExpressionNode cond2 = ParseExpression();

                        conditionalExpression.Left = cond1;
                        conditionalExpression.Right = cond2;
                    }

                    break;

                #endregion

                #region Keywords
                // keywords
                case TokenID.Ref:
                    mayBeLocalDecl = false;
                    Advance();
                    ParseExpressionSegment();
                    exprStack.Push(new RefNode(exprStack.Pop()));
                    break;

                case TokenID.Out:
                    mayBeLocalDecl = false;
                    Advance();
                    ParseExpressionSegment();
                    exprStack.Push(new OutNode(exprStack.Pop()));
                    break;

                case TokenID.Void:
                    // this can happen in typeof(void) or void* x;
                    exprStack.Push(new VoidPrimitive(curtok));
                    Advance();
                    if (curtok.ID == TokenID.Star)
                    {
                        do
                        {
                            Advance();
                            exprStack.Push(new TypePointerNode(exprStack.Pop()));
                        }
                        while (curtok.ID == TokenID.Star);
                    }
                    else
                        mayBeLocalDecl = false;
                    break;

                #endregion

                case TokenID.Stackalloc:
                    mayBeLocalDecl = false;
                    ParseStackalloc();
                    break;
            }

            if (exprStack.Count != startStackCount + (stackCountUnaltered ? 0 : 1))
            {
                ReportError("Internal compiler error: Expression stack inconsistent!", curtok);
            }
        }
Esempio n. 4
0
        public virtual object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data)
        {
            stackMap.Push(conditionalExpression);
            conditionalExpression.Test.AcceptVisitor(this, data);
            conditionalExpression.Left.AcceptVisitor(this, data);
            conditionalExpression.Right.AcceptVisitor(this, data);

            stackMap.Pop();
            return null;

        }