public override bool Parse(ParseContext context, IAstNode parent) { TokenStream<RToken> tokens = context.Tokens; Debug.Assert(context.Tokens.CurrentToken.TokenType == RTokenType.Identifier || context.Tokens.CurrentToken.TokenType == RTokenType.String); this.Identifier = RParser.ParseToken(context, this); this.EqualsSign = RParser.ParseToken(context, this); if (context.Tokens.CurrentToken.TokenType != RTokenType.Comma && context.Tokens.CurrentToken.TokenType != RTokenType.CloseBrace) { Expression exp = new Expression(inGroup: true); if (exp.Parse(context, this)) { this.DefaultValue = exp; } } else { this.DefaultValue = new NullExpression(); if (context.Tokens.IsEndOfStream()) { context.AddError(new ParseError(ParseErrorType.ExpressionExpected, ErrorLocation.Token, context.Tokens.CurrentToken)); } else { context.AddError(new ParseError(ParseErrorType.ExpressionExpected, ErrorLocation.Token, EqualsSign)); } } return base.Parse(context, parent); }
private ParseErrorType HandleOperator(ParseContext context, out OperationType operationType) { var currentOperator = new TokenOperator(firstInExpression: _operands.Count == 0); currentOperator.Parse(context, null); var isUnary = currentOperator.IsUnary; operationType = isUnary ? OperationType.UnaryOperator : OperationType.BinaryOperator; if (currentOperator.OperatorType == OperatorType.Not) { //This comes from the fact that // x < -1 // y < -1 // 2 + !x + y // yields 2 (i.e. bang applies to the entire expression that follows isUnary = true; if (!IsInGroup && context.Tokens.IsLineBreakAfter(context.TextProvider, context.Tokens.Position - 1)) { // Make sure expression that follows is not empty return(ParseErrorType.RightOperandExpected); } var exp = new Expression(IsInGroup); if (!exp.Parse(context, null)) { return(ParseErrorType.RightOperandExpected); } _operators.Push(currentOperator); _operands.Push(exp); operationType = OperationType.Operand; return(ParseErrorType.None); } return(HandleOperatorPrecedence(context, currentOperator)); }
private ParseErrorType HandleOperator(ParseContext context, IAstNode parent, out bool isUnary) { ParseErrorType errorType = ParseErrorType.None; // If operands stack is empty the operator is unary. // If operator is preceded by another operator, // it is interpreted as unary. TokenOperator currentOperator = new TokenOperator(_operands.Count == 0); currentOperator.Parse(context, null); isUnary = currentOperator.IsUnary; IOperator lastOperator = _operators.Peek(); if (isUnary && lastOperator != null && lastOperator.IsUnary) { // !!!x is treated as !(!(!x))) // Step back and re-parse as expression context.Tokens.Position -= 1; var exp = new Expression(inGroup: false); if (exp.Parse(context, null)) { _operands.Push(exp); return ParseErrorType.None; } } if (currentOperator.Precedence <= lastOperator.Precedence && !(currentOperator.OperatorType == lastOperator.OperatorType && currentOperator.Association == Association.Right)) { // New operator has lower or equal precedence. We need to make a tree from // the topmost operator and its operand(s). Example: a*b+c. + has lower priority // and a and b should be on the stack along with * on the operator stack. // Repeat until there are no more higher precendece operators on the stack. errorType = this.ProcessHigherPrecendenceOperators(context, currentOperator); } if (errorType == ParseErrorType.None) { _operators.Push(currentOperator); } return errorType; }