private ExpressionNode ConsumeBinary(TokenID startOp) { ExpressionNode result = null; if ((exprStack.Count == 0 || precedence[(int)curTokNode.Previous.Previous.Value.ID] > 0)) { // assert +,-,!,~,++,--,cast Advance(); ParseExpressionSegment(); while (precedence[(int)curtok.ID] > precedence[(int)startOp]) { ParseExpressionSegment(); } result = exprStack.Pop(); // this signals it was a unary operation } else { BinaryExpression bNode = new BinaryExpression(startOp, curtok); Advance(); bNode.Left = exprStack.Pop(); exprStack.Push(bNode); // push node ParseExpressionSegment(); // right side // consume now or let next op consume? while (precedence[(int)curtok.ID] > precedence[(int)startOp]) { ParseExpressionSegment(); } bNode.Right = exprStack.Pop(); } return result; }
private void ParsePreprocessorExpressionSegment(int oldLine) { int startStackCount = exprStack.Count; TokenID startToken = curtok.ID; switch (curtok.ID) { case TokenID.True: exprStack.Push(new BooleanPrimitive(true, curtok)); Advance(); break; case TokenID.False: exprStack.Push(new BooleanPrimitive(false, curtok)); Advance(); break; case TokenID.And: case TokenID.Or: Advance(); if (!SameLine(oldLine)) return; BinaryExpression bNode = new BinaryExpression(startToken, curtok); bNode.Left = exprStack.Pop(); exprStack.Push(bNode); // push node ParsePreprocessorExpressionSegment(oldLine); // right side // consume now or let next op consume? while (precedence[(int)curtok.ID] > precedence[(int)startToken] && curtok.Line == oldLine) { ParsePreprocessorExpressionSegment(oldLine); } bNode.Right = exprStack.Pop(); break; case TokenID.Not: Advance(); do { if (!SameLine(oldLine)) return; ParsePreprocessorExpressionSegment(oldLine); } while (precedence[(int)curtok.ID] >= precedence[(int)TokenID.LParen]); // LParen for precedence of unary operator ExpressionNode node = exprStack.Pop(); UnaryExpression uNode = new UnaryExpression(startToken, node.RelatedToken); uNode.Child = node; exprStack.Push(uNode); break; case TokenID.LParen: Advance(); if (!SameLine(oldLine)) return; exprStack.Push(new ParenthesizedExpression(ParsePreprocessorExpression())); if (!SameLine(oldLine)) return; AssertAndAdvance(TokenID.RParen); break; case TokenID.Ident: exprStack.Push(ParseIdentifierOrKeyword(false, false, false, false, false)); break; default: if (Lexer.IsKeyWord(curtok.ID)) { // in this case a key word is used like a variable name. goto case TokenID.Ident; } else { ReportError("Unexpected token", curtok); } break; } }
private ExpressionNode ParseExpressionOrType(bool inStatementContext) { // Can the interior be a type? (A.2.2) switch (curtok.ID) { // type-name case TokenID.Ident: // simple-type case TokenID.SByte: case TokenID.Byte: case TokenID.Short: case TokenID.UShort: case TokenID.Int: case TokenID.UInt: case TokenID.Long: case TokenID.ULong: case TokenID.Char: case TokenID.Float: case TokenID.Double: case TokenID.Decimal: case TokenID.Bool: // class-type case TokenID.Object: case TokenID.String: // yes, it can break; default: // no, it can not return ParseExpression(); } ExpressionNode expr = ParseIdentifierOrKeyword(false, false, false, false, false); if (curtok.ID == TokenID.ColonColon) { // id :: id type-parameter-list_opt QualifiedIdentifierExpression qualID = new QualifiedIdentifierExpression(curtok); // TODO: Replace by QualifiedAliasMember instance qualID.IsNamespaceAliasQualifier = true; qualID.Expressions.Add(expr); Advance(); // over ColonColon qualID.Expressions.Add(ParseMember(inStatementContext)); expr = qualID; } else if (ParsePossibleTypeParameterNode(false, false, false, inStatementContext)) { expr = new TypeNode(expr); ApplyTypeParameters((TypeNode)expr); } while (curtok.ID == TokenID.Dot) { Advance(); // over Dot if (curtok.ID != TokenID.Ident) { RecoverFromError(TokenID.Ident); return expr; } expr = new MemberAccessExpression(expr, ParseMember(inStatementContext), TokenID.Dot); } bool hasQuestionMark = false; int starCount = 0; bool hasBracket = false; if (curtok.ID == TokenID.Question) { Advance(); hasQuestionMark = true; } while (curtok.ID == TokenID.Star) { Advance(); starCount++; } // return (a * b); // return (a ? b : c); // a* b = c; // a? b = c; // a b = c; //if(curtok.ID == TokenID.Ident || (hasQuestionMark || starCount > 0) && curtok.ID == TokenID.RParen) goto foundType; if (curtok.ID == TokenID.Ident) { if (inStatementContext) goto foundType; else if (!hasQuestionMark && starCount == 0) goto foundType; // it is a parse error } else if (curtok.ID == TokenID.RParen) { if (hasQuestionMark || starCount > 0) goto foundType; } else if (curtok.ID == TokenID.LBracket) { Advance(); hasBracket = true; if (hasQuestionMark || starCount > 0 || curtok.ID == TokenID.Comma || curtok.ID == TokenID.RBracket) goto foundType; } // // treat as expression // if (hasQuestionMark) { // hasBracket is false ExpressionNode trueExpr = ParseSubexpression(starCount > 0 ? (int)PRECEDENCE_UNARY : 1); while (starCount-- > 0) trueExpr = new DereferenceExpression(trueExpr); AssertAndAdvance(TokenID.Colon); return new ConditionalExpression(expr, trueExpr, ParseExpression()); } else if (starCount > 0) { // hasBracket is false starCount--; ExpressionNode right = ParseSubexpression(starCount > 0 ? PRECEDENCE_UNARY : PRECEDENCE_MULTIPLICATIVE + ASSOC_LEFT); while (starCount-- > 0) right = new DereferenceExpression(right); expr = new BinaryExpression(TokenID.Star, expr, right); } else if (hasBracket) { expr = new ElementAccessExpression(expr, ParseExpressionList()); AssertAndAdvance(TokenID.RBracket); } return ParseSubexpression(1, expr); // // treat as type // foundType: TypeNode typeNode = new TypeNode(expr); if (hasQuestionMark) typeNode.IsNullableType = true; while (starCount-- > 0) typeNode = new TypePointerNode(typeNode); if (hasBracket) { while (true) { int numCommas = 0; while (curtok.ID == TokenID.Comma) { Advance(); numCommas++; } AssertAndAdvance(TokenID.RBracket); typeNode.RankSpecifiers.Add(numCommas); if (curtok.ID != TokenID.LBracket) break; Advance(); } } return typeNode; }
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; }
public virtual object VisitBinaryOperatorExpression(BinaryExpression binaryOperatorExpression, object data) { stackMap.Push(binaryOperatorExpression); binaryOperatorExpression.Left.AcceptVisitor(this, data); binaryOperatorExpression.Right.AcceptVisitor(this, data); stackMap.Pop(); return null; }