Пример #1
0
 public BinaryExpression(ExpressionNodeBase lvalue, Operator oper, ExpressionNodeBase rvalue)
     : base(lvalue.Location, rvalue.Location)
 {
     this.LeftValue = lvalue;
     this.RightValue = rvalue;
     this.Operator = oper;
 }
Пример #2
0
        private ExpressionNodeBase ParseExpression(ExpressionContext context)
        {
            if(!isNextTokenAValidForFirstTokenInExpression())
                _errorCollector.UnexpectedToken(_lexer.NextToken());
            ExpressionNodeBase retval;
            Stack<AstNodeBase> expStack = new Stack<AstNodeBase>();
            Stack<Operator> operatorStack = new Stack<Operator>();
            int parenCount = 0;

            Token currToken = _lexer.PeekToken();
            HappySourceLocation startLocation = currToken.Location;

            Action<Operator> insertOperatorAndUpdateStacks = oper =>
                                                       {
                                                       	while (operatorStack.Count > 0 &&
                                                       	       operatorStack.Peek().PrecedenceLevel >= oper.PrecedenceLevel)
                                                       		expStack.Push(operatorStack.Pop());
                                                       	operatorStack.Push(oper);
                                                       };

            if (currToken.HappyTokenKind == HappyTokenKind.LiteralNull)
            {
                _lexer.NextToken();
                retval = this.PromoteToExpression(currToken);
            }
            else
            {
                //Rules for existing the while loop below:
                //  Always stop parsing when a keyword other than new is encountered.
                //  If the languageContext is argument list, stop parsing when "," or ")" that is not matched by a corresponding "(" is encountered
                //  if the languageContext is nested parens, stop parsing when ")" that is not matched by a corresponding "(" is encountered
                //  if the languageContext is new statement, stop parsing when "(" is encountered
                while (
                    (!currToken.IsKeyword || currToken.HappyTokenKind == HappyTokenKind.KeywordNew)
                    && !(context == ExpressionContext.ArgumentList && currToken.HappyTokenKind == HappyTokenKind.Comma)
                    && !((context == ExpressionContext.NestedParens || context == ExpressionContext.ArgumentList) && parenCount == 0 && currToken.HappyTokenKind == HappyTokenKind.OperatorCloseParen)
                    && !(context == ExpressionContext.Indexer && (currToken.HappyTokenKind == HappyTokenKind.OperatorCloseBracket || currToken.HappyTokenKind == HappyTokenKind.Comma)))
                {

                    //Check exit conditions first:
                    bool lastWasArithOperator;
                    _lexer.NextToken();
                    if (currToken.IsOperator)
                    {
                        lastWasArithOperator = false;
                        switch(currToken.HappyTokenKind)
                        {
                        case HappyTokenKind.OperatorOpenParen:
                            parenCount++;
                            break;
                        case HappyTokenKind.OperatorCloseParen:
                            parenCount--;
                            if (parenCount < 0)
                            {
                                HappySourceLocation location = HappySourceLocation.Merge(startLocation, this._lexer.PeekToken().Location);
                                this._errorCollector.MismatchedCloseParen(location);
                                throw new AbortParseException(location);
                            }
                            break;
                        case HappyTokenKind.OperatorOpenBracket:
                            List<ExpressionNodeBase> arguments = new List<ExpressionNodeBase> { this.ParseExpression(ExpressionContext.Indexer) };

                            while (this.EatNextTokenIf(HappyTokenKind.Comma))
                                arguments.Add(this.ParseExpression(ExpressionContext.Indexer));

                            var endsAt = this.Expect(HappyTokenKind.OperatorCloseBracket, "]").Location;

                            var indexOperator = new Operator(currToken);

                            insertOperatorAndUpdateStacks(indexOperator);

                            expStack.Push(new ArgumentList(HappySourceLocation.Merge(currToken.Location, endsAt), arguments.ToArray()));

                            break;
                        default:
                            lastWasArithOperator = true;

                            Operator oper = new Operator(currToken) { PrecedenceLevelModifier = parenCount * Operator.PrecedenceModifierStep };

                            insertOperatorAndUpdateStacks(oper);
                            break;
                        }
                    }
                    else if(currToken.HappyTokenKind == HappyTokenKind.KeywordNew)
                    {
                        Expect(HappyTokenKind.OperatorOpenParen, "(");
                        ExpressionNodeBase exp = this.ParseExpression(ExpressionContext.ArgumentList);
                        List<ExpressionNodeBase> constructorArgs = new List<ExpressionNodeBase>();
                        Token commaOrCloseParen = Expect(HappyTokenKind.OperatorCloseParen, HappyTokenKind.Comma, MiscMessages.CommaOrCloseParen);
                        if (commaOrCloseParen.HappyTokenKind == HappyTokenKind.Comma)
                            do
                            {
                                constructorArgs.Add(this.ParseExpression(ExpressionContext.ArgumentList));
                                commaOrCloseParen = this.Expect(HappyTokenKind.Comma, HappyTokenKind.OperatorCloseParen, MiscMessages.CommaOrCloseParen);
                            } while (commaOrCloseParen.HappyTokenKind != HappyTokenKind.OperatorCloseParen);

                        ExpressionNodeBase newExpression = new NewObjectExpression(currToken.Location, commaOrCloseParen.Location, exp, constructorArgs.ToArray());
                        expStack.Push(newExpression);
                        lastWasArithOperator = false;
                    }
                    else
                    {
                        expStack.Push(this.PromoteToExpression(currToken));
                        lastWasArithOperator = false;
                    }

                    currToken = _lexer.PeekToken();

                    if (!lastWasArithOperator && !currToken.IsOperator && parenCount <= 0)
                        break;
                }

                if (parenCount > 0)
                {
                    HappySourceLocation location = HappySourceLocation.Merge(startLocation, currToken.Location);
                    _errorCollector.MismatchedOpenParen(location);
                    throw new AbortParseException(location);
                }

                while (operatorStack.Count > 0)
                    expStack.Push(operatorStack.Pop());

                retval = this.RecurseExp(expStack);
            }

            return retval;
        }
Пример #3
0
 public UnaryExpression(ExpressionNodeBase value, Operator oper)
     : base(oper.Location, value.Location)
 {
     this.Value = value;
     this.Operator = oper;
 }