public virtual object VisitAttributeArgumentNode(AttributeArgumentNode attributeArgumentNode, object data) { stackMap.Push(attributeArgumentNode); attributeArgumentNode.Attributes.AcceptVisitor(this, data); if (attributeArgumentNode.ArgumentName != null) { attributeArgumentNode.ArgumentName.AcceptVisitor(this, data); } if (attributeArgumentNode.Expression != null) { attributeArgumentNode.Expression.AcceptVisitor(this, data); } stackMap.Pop(); return(null); }
private void ParsePossibleAttributes(bool isGlobal) { while (curtok.ID == TokenID.LBracket) { // it is neccessary to save current typeparameter // because an attribute can be declared for a type parameter // so if we do not do that, the typeparameter will be considered // as the type parameter of his attribute declaration ... // i.e.: // class cons <[GenPar] A, [GenPar] B>{} // // without backup, A is considered as the type parameter of GenPar, // and the parser will generate the wrong output: class cons <[GenPar<A>]... List<TypeParameterNode> backupTypeParameters = curTypeParameters; curTypeParameters = new List<TypeParameterNode>(); Dictionary<string, Constraint> backupConstraints = curTypeParameterConstraints; curTypeParameterConstraints = new Dictionary<string, Constraint>(); Advance(); // advance over LBracket token if (curmods != Modifier.Empty) ReportError("Internal compiler error: Modifiers unused!", curtok); Modifier curAttribMods = ParseAttributeModifiers(); if (isGlobal && curAttribMods == Modifier.GlobalAttributeMods) { // nothing to check, globally positioned attributes can still apply to namespaces etc } else { if ((curAttribMods & ~Modifier.AttributeMods) != 0) ReportError("Attribute contains illegal modifiers."); } if (curAttribMods != Modifier.Empty) AssertAndAdvance(TokenID.Colon); while (curtok.ID != TokenID.RBracket && curtok.ID != TokenID.Eof) { AttributeNode node = new AttributeNode(curtok); curAttributes.Add(node); node.Modifiers = curAttribMods; node.Name = ParseQualifiedIdentifier(true, false, false); if (curtok.ID == TokenID.LParen) { // named argument //gtest-286, line 16 // [Test(typeof(C<string>))] // public static void Foo() // { // } // // the attribute is applied to the type parameter, so we back up it. NodeCollection<AttributeNode> backupAttributes = curAttributes; curAttributes = new NodeCollection<AttributeNode>(); // has attribute arguments Advance(); // over lparen // positional args are just expr bool hadAssign = false; while (curtok.ID != TokenID.Eof && curtok.ID != TokenID.RParen) { AttributeArgumentNode aNode = new AttributeArgumentNode(curtok); node.Arguments.Add(aNode); ExpressionNode expr = ParseExpression(); AssignmentExpression assignExpr = expr as AssignmentExpression; if (assignExpr != null) { IdentifierExpression idExpr = assignExpr.Variable as IdentifierExpression; if (idExpr == null) ReportError("Identifier expected", assignExpr.Variable.RelatedToken); aNode.ArgumentName = idExpr; aNode.Expression = assignExpr.RightSide; hadAssign = true; } else aNode.Expression = expr; if (curtok.ID != TokenID.Comma) goto endofattrargs; Advance(); // over comma if (curtok.ID == TokenID.RParen) ReportError("Unexpected token ')'", curtok); if (hadAssign) break; } // named args are ident = expr while (curtok.ID == TokenID.Ident) { AttributeArgumentNode aNode = new AttributeArgumentNode(curtok); aNode.ArgumentName = (IdentifierExpression)ParseIdentifierOrKeyword(false, false, false, false, false); AssertAndAdvance(TokenID.Equal); aNode.Expression = ParseExpression(); node.Arguments.Add(aNode); if (curtok.ID != TokenID.Comma) break; Advance(); // over comma if (curtok.ID == TokenID.RParen) ReportError("Unexpected token ')'", curtok); } endofattrargs: AssertAndAdvance(TokenID.RParen); // over rparen // restore the backup curAttributes = backupAttributes; } if (curtok.ID != TokenID.Comma) break; Advance(); // over comma } AssertAndAdvance(TokenID.RBracket); // over rbracket curTypeParameters = backupTypeParameters; curTypeParameterConstraints = backupConstraints; } }
private void ParsePossibleAttributes(bool isGlobal) { while (curtok.ID == TokenID.LBracket) { // is it neccessary to save current typeparameter // because an attribute can be declared for a type parameter // so if we do not do that, the typeparameter will be considered // as the type parameter of his attribute declaration ... // i.e. : // class cons <[GenPar] A, [GenPar] B>{} // // without backup, A is considered as the type parameter of GenPar, // and the parser will generate the wrong outpu : class cons <[GenPar<A>]... List<TypeParameterNode> backupTypeParameters = curTypeParameters; curTypeParameters = new List<TypeParameterNode>(); Dictionary<string, Constraint> backupConstraints = curTypeParameterConstraints; curTypeParameterConstraints = new Dictionary<string, Constraint>(); Advance(); // advance over LBracket token curmods = ParseAttributeModifiers(); if (isGlobal && curmods == Modifier.GlobalAttributeMods) { // nothing to check, globally positioned attributes can still apply to namespaces etc } else { uint attribMask = ~(uint)Modifier.AttributeMods; if (((uint)curmods & attribMask) != (uint)Modifier.Empty) ReportError("Attribute contains illegal modifiers."); } AttributeNode node = new AttributeNode(curtok); Modifier curAttribMods = curmods; curmods = Modifier.Empty; if (curAttribMods != Modifier.Empty) { AssertAndAdvance(TokenID.Colon); } curAttributes.Add(node); node.Modifiers = curAttribMods; while (curtok.ID != TokenID.RBracket && curtok.ID != TokenID.Eof) { node.Name = ParseQualifiedIdentifier(true, false, false); if (curtok.ID == TokenID.LParen) { // named argument //gtest-286, line 16 // [Test(typeof(C<string>))] // public static void Foo() // { // } // // the attribute is applied to the type parameter, so we back up it. NodeCollection<AttributeNode> backupAttributes = curAttributes; curAttributes = new NodeCollection<AttributeNode>(); // has attribute arguments Advance(); // over lparen // named args are ident = expr // positional args are just expr while (curtok.ID != TokenID.RParen && curtok.ID != TokenID.Eof) { AttributeArgumentNode aNode = new AttributeArgumentNode(curtok); if ( curTokNode != null && curTokNode.Next != null && curTokNode.Next.Next != null && curtok.ID == TokenID.Ident && curTokNode.Value.ID == TokenID.Equal) { aNode.ArgumentName = (IdentifierExpression)ParseIdentifierOrKeyword(false, false, false, false); Advance(); // over '=' } aNode.Expression = ParseExpression(); node.Arguments.Add(aNode); if (curtok.ID == TokenID.Comma) { Advance(); // over comma } } AssertAndAdvance(TokenID.RParen); // over rparen // restore the backup curAttributes = backupAttributes; if ( curTokNode != null && curTokNode.Next != null && curTokNode.Next.Next != null && curtok.ID == TokenID.Comma && curTokNode.Value.ID != TokenID.RBracket) { Advance(); // over comma node = new AttributeNode(curtok); curAttributes.Add(node); node.Modifiers = curAttribMods; } } if (curtok.ID == TokenID.Comma) { // comma can hang a t end like enums Advance(); } } AssertAndAdvance(TokenID.RBracket); // over rbracket curTypeParameters = backupTypeParameters; curTypeParameterConstraints = backupConstraints; } }
public virtual object VisitAttributeArgumentNode(AttributeArgumentNode attributeArgumentNode, object data) { stackMap.Push(attributeArgumentNode); attributeArgumentNode.Attributes.AcceptVisitor(this, data); if (attributeArgumentNode.ArgumentName != null) { attributeArgumentNode.ArgumentName.AcceptVisitor(this, data); } if (attributeArgumentNode.Expression != null) { attributeArgumentNode.Expression.AcceptVisitor(this, data); } stackMap.Pop(); return null; }