static void GetDoneVersionDebugSpecs(ConditionSet cs, MutableConditionFlagSet l, DBlockNode m, ResolutionContext ctxt) { if (m.StaticStatements == null || m.StaticStatements.Count == 0) return; foreach(var ss in m.StaticStatements) { if(ss is VersionSpecification) { var vs = (VersionSpecification)ss; if(!_checkForMatchinSpecConditions(m,cs,ss,ctxt)) continue; if(vs.SpecifiedId==null) l.AddVersionCondition(vs.SpecifiedNumber); else l.AddVersionCondition(vs.SpecifiedId); } else if(ss is DebugSpecification) { var ds = (DebugSpecification)ss; if(!_checkForMatchinSpecConditions(m,cs,ss, ctxt)) continue; if (ds.SpecifiedId == null) l.AddDebugCondition(ds.SpecifiedDebugLevel); else l.AddDebugCondition(ds.SpecifiedId); } } }
public override void VisitBlock(DBlockNode bn) { var back = ctxt.ScopedBlock; using(ctxt.Push(bn)) { if (ctxt.ScopedBlock != back) OnScopedBlockChanged (bn); base.VisitBlock(bn); } }
public void PushBlock (DBlockNode bn) { var back = ctxt.ScopedBlock; using(ctxt.Push(bn)) { if (ctxt.ScopedBlock != back) OnScopedBlockChanged (bn); VisitBlock(bn); } }
/// <summary> /// Calls VisitDNode already. /// </summary> public virtual void VisitBlock(DBlockNode block) { VisitChildren(block); VisitDNode(block); if (block.StaticStatements.Count != 0) foreach (var s in block.StaticStatements) s.Accept(this); if (block.MetaBlocks.Count != 0) foreach (var mb in block.MetaBlocks) mb.Accept(this); }
public static void TestString(string literal, string content, bool ProvideObjModule = true) { ResolutionContext ctxt = null; var block = new DBlockNode(); if (ProvideObjModule) ctxt = ResolutionTests.CreateDefCtxt(ResolutionTests.CreateCache(), block); else ctxt = ResolutionTests.CreateDefCtxt(new LegacyParseCacheView(new string[] { }), block); var x = DParser.ParseExpression(literal); Assert.That(x,Is.TypeOf(typeof(IdentifierExpression))); var id = (IdentifierExpression)x; var v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v,Is.TypeOf(typeof(ArrayValue))); var av = (ArrayValue)v; Assert.That(av.IsString, Is.True); Assert.AreEqual(av.StringValue, content); Assert.That(av.RepresentedType, Is.TypeOf(typeof(ArrayType))); var ar = (ArrayType)av.RepresentedType; Assert.That (ar.ValueType, Is.TypeOf (typeof(PrimitiveType))); var pt = ar.ValueType as PrimitiveType; Assert.That (pt.Modifier, Is.EqualTo (DTokens.Immutable)); switch (id.Subformat) { case LiteralSubformat.Utf8: Assert.AreEqual(DTokens.Char, pt.TypeToken); break; case LiteralSubformat.Utf16: Assert.AreEqual(DTokens.Wchar, pt.TypeToken); break; case LiteralSubformat.Utf32: Assert.AreEqual(DTokens.Dchar, pt.TypeToken); break; default: Assert.Fail(); return; } }
/// <summary> /// Calls VisitDNode already. /// </summary> public virtual void VisitBlock(DBlockNode block) { VisitChildren(block); VisitDNode(block); if (block.StaticStatements.Count != 0) { foreach (var s in block.StaticStatements) { s.Accept(this); } } if (block.MetaBlocks.Count != 0) { foreach (var mb in block.MetaBlocks) { mb.Accept(this); } } }
INode Constructor(DBlockNode scope,bool IsStruct) { Expect(This); var dm = new DMethod(){ Parent = scope, SpecialType = DMethod.MethodType.Constructor, Location = t.Location, Name = DMethod.ConstructorIdentifier, NameLocation = t.Location }; ApplyAttributes (dm); dm.Description = GetComments(); if (IsTemplateParameterList()) TemplateParameterList(dm); // http://dlang.org/struct.html#StructPostblit if (IsStruct && laKind == (OpenParenthesis) && Peek(1).Kind == (This)) { var dv = new DVariable { Parent = dm, Name = "this" }; dm.Parameters.Add(dv); Step(); Step(); Expect(CloseParenthesis); } else { dm.Parameters = Parameters(dm); } // handle post argument attributes FunctionAttributes(dm); if (laKind == If) Constraint(dm); // handle post argument attributes FunctionAttributes(dm); if(IsFunctionBody) FunctionBody(dm); return dm; }
IMetaDeclarationBlock AttributeBlock(DBlockNode module) { int popCount = DeclarationAttributes.Count; /* * If there are attributes given, put their references into the meta block. * Also, pop them from the declarationAttributes stack on to the block attributes so they will be assigned to all child items later on. */ IMetaDeclarationBlock metaDeclBlock; if (popCount != 0) metaDeclBlock = new AttributeMetaDeclarationBlock(DeclarationAttributes.ToArray()) { BlockStartLocation = la.Location }; else metaDeclBlock = new MetaDeclarationBlock { BlockStartLocation = la.Location }; while (DeclarationAttributes.Count > 0) BlockAttributes.Push(DeclarationAttributes.Pop()); ClassBody(module, true, false); // Pop the previously pushed attributes back off the stack for (int i = popCount; i > 0; i--) BlockAttributes.Pop(); // Store the meta block metaDeclBlock.EndLocation = t.EndLocation; if(module!=null) module.Add(metaDeclBlock); return metaDeclBlock; }
/// <summary> /// /// </summary> /// <param name="module"></param> /// <param name="previouslyParsedAttribute"></param> /// <param name="RequireDeclDef">If no colon and no open curly brace is given as lookahead, a DeclDef may be parsed otherwise, if parameter is true.</param> /// <returns></returns> IMetaDeclaration AttributeTrail(DBlockNode module, DAttribute previouslyParsedAttribute, bool RequireDeclDef = false) { if (laKind == Colon) { Step(); PushAttribute(previouslyParsedAttribute, true); AttributeMetaDeclarationSection metaDecl = null; //TODO: Put all remaining block/decl(?) attributes into the section definition.. if(module!=null) module.Add(metaDecl = new AttributeMetaDeclarationSection(previouslyParsedAttribute) { EndLocation = t.EndLocation }); return metaDecl; } else PushAttribute(previouslyParsedAttribute, false); if (laKind == OpenCurlyBrace) return AttributeBlock(module); else { if (IsEOF && module != null && previouslyParsedAttribute != null) // To enable attribute completion, add dummy node module.Add (new DVariable{ Attributes = new List<DAttribute>{ previouslyParsedAttribute } }); if (RequireDeclDef) DeclDef(module); return new AttributeMetaDeclaration(previouslyParsedAttribute) { EndLocation = previouslyParsedAttribute.EndLocation }; } }
static bool _checkForMatchinSpecConditions(DBlockNode m,ConditionSet cs,StaticStatement ss, ResolutionContext ctxt) { return ss.Attributes == null || cs.IsMatching(ss.Attributes,ctxt); }
void DeclDef(DBlockNode module) { //AttributeSpecifier while (IsAttributeSpecifier()) { AttributeSpecifier(module); if (t.Kind == Colon || laKind == CloseCurlyBrace || IsEOF) return; } if (laKind == Semicolon) { LastParsedObject = null; Step(); return; } //ImportDeclaration if (laKind == Import) module.Add(ImportDeclaration(module)); //Constructor else if (laKind == (This)) module.Add(Constructor(module, module is DClassLike ? ((DClassLike)module).ClassType == DTokens.Struct : false)); //Destructor else if (laKind == (Tilde) && Lexer.CurrentPeekToken.Kind == (This)) module.Add(Destructor()); //Invariant else if (laKind == (Invariant)) module.Add(_Invariant()); //UnitTest else if (laKind == (Unittest)) { Step(); var dbs = new DMethod(DMethod.MethodType.Unittest); ApplyAttributes(dbs); LastParsedObject = dbs; dbs.Location = t.Location; FunctionBody(dbs); dbs.EndLocation = t.EndLocation; module.Add(dbs); } /* * VersionSpecification: * version = Identifier ; * version = IntegerLiteral ; * * DebugSpecification: * debug = Identifier ; * debug = IntegerLiteral ; */ else if ((laKind == Version || laKind == Debug) && Peek(1).Kind == Assign) { DebugSpecification ds = null; VersionSpecification vs = null; if (laKind == Version) LastParsedObject = vs = new VersionSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; else LastParsedObject = ds = new DebugSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; Step(); Step(); if (laKind == Literal) { Step(); if (t.LiteralFormat != LiteralFormat.Scalar) SynErr(t.Kind, "Integer literal expected!"); try { if (vs != null) vs.SpecifiedNumber = Convert.ToInt32(t.LiteralValue); else ds.SpecifiedDebugLevel = Convert.ToInt32(t.LiteralValue); } catch { } } else if (laKind == Identifier) { Step(); if (vs != null) vs.SpecifiedId = t.Value; else ds.SpecifiedId = t.Value; } else if (ds == null) Expect(Identifier); Expect(Semicolon); if (vs == null) ds.EndLocation = t.EndLocation; else vs.EndLocation = t.EndLocation; module.Add(vs as StaticStatement ?? ds); } else if (laKind == Version || laKind == Debug || (laKind == Static && Lexer.CurrentPeekToken.Kind == If)) DeclarationCondition(module); //StaticAssert else if (laKind == (Assert)) { Step(); if (!Modifier.ContainsAttribute(DeclarationAttributes, Static)) SynErr(Static, "Static assert statements must be explicitly marked as static"); var ass = new StaticAssertStatement { Attributes = GetCurrentAttributeSet_Array(), Location = t.Location }; if (Expect(OpenParenthesis)) { ass.AssertedExpression = AssignExpression(); if (laKind == (Comma)) { Step(); ass.Message = AssignExpression(); } if(Expect(CloseParenthesis)) Expect(Semicolon); } ass.EndLocation = t.EndLocation; module.Add(ass); } //TemplateMixinDeclaration else if (laKind == Mixin) { if (Peek(1).Kind == Template) module.Add(TemplateDeclaration(module)); //TemplateMixin else if (Lexer.CurrentPeekToken.Kind == Identifier) { var tmx = TemplateMixin(module); if(tmx.MixinId==null) module.Add(tmx); else module.Add(new NamedTemplateMixinNode(tmx)); } //MixinDeclaration else if (Lexer.CurrentPeekToken.Kind == OpenParenthesis) module.Add(MixinDeclaration(module,null)); else { Step(); SynErr(Identifier); } } // { else if (laKind == (OpenCurlyBrace)) AttributeBlock(module); // Class Allocators // Note: Although occuring in global scope, parse it anyway but declare it as semantic nonsense;) else if (laKind == (New)) { Step(); var dm = new DMethod(DMethod.MethodType.Allocator) { Location = t.Location }; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); } // Class Deallocators else if (laKind == Delete) { Step(); var dm = new DMethod(DMethod.MethodType.Deallocator) { Location = t.Location }; dm.Name = "delete"; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); } // else: else { var decls = Declaration(module); if(module != null && decls!=null) module.AddRange(decls); } }
public void DeclDef(DBlockNode module) { if (IsAttributeSpecifier) { do AttributeSpecifier (module); while(IsAttributeSpecifier); var tkind = t.Kind; if(tkind == Semicolon || tkind == CloseCurlyBrace || tkind == Colon) return; } if (laKind == Semicolon) { Step(); return; } switch (laKind) { case Import: module.Add(ImportDeclaration(module)); break; case This: module.Add(Constructor(module, module is DClassLike && ((DClassLike)module).ClassType == DTokens.Struct)); break; case Tilde: if (Lexer.CurrentPeekToken.Kind != This) goto default; module.Add(Destructor()); break; case Invariant: module.Add(_Invariant()); break; case Unittest: Step(); var dbs = new DMethod(DMethod.MethodType.Unittest); ApplyAttributes(dbs); dbs.Location = t.Location; FunctionBody(dbs); dbs.EndLocation = t.EndLocation; module.Add(dbs); break; /* * VersionSpecification: * version = Identifier ; * version = IntegerLiteral ; * * DebugSpecification: * debug = Identifier ; * debug = IntegerLiteral ; */ case Version: case Debug: if (Peek(1).Kind == Assign) { DebugSpecification ds = null; VersionSpecification vs = null; if (laKind == Version) vs = new VersionSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; else ds = new DebugSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; Step(); Step(); if (laKind == Literal) { Step(); if (t.LiteralFormat != LiteralFormat.Scalar) SynErr(t.Kind, "Integer literal expected!"); try { if (vs != null) vs.SpecifiedNumber = Convert.ToInt32(t.LiteralValue); else ds.SpecifiedDebugLevel = Convert.ToInt32(t.LiteralValue); } catch { } } else if (laKind == Identifier) { Step(); if (vs != null) vs.SpecifiedId = t.Value; else ds.SpecifiedId = t.Value; } else if (ds == null) Expect(Identifier); Expect(Semicolon); ((AbstractStatement)ds ?? vs).EndLocation = t.EndLocation; module.Add(vs as StaticStatement ?? ds); } else DeclarationCondition(module); break; case Static: if (Lexer.CurrentPeekToken.Kind == If) goto case Version; goto default; case Assert: Step(); CheckForStorageClasses(module); if (!Modifier.ContainsAttribute(DeclarationAttributes, Static)) SynErr(Static, "Static assert statements must be explicitly marked as static"); var ass = new StaticAssertStatement { Attributes = GetCurrentAttributeSet_Array(), Location = t.Location }; if (Expect(OpenParenthesis)) { ass.AssertedExpression = AssignExpression(); if (laKind == (Comma)) { Step(); ass.Message = AssignExpression(); } if (Expect(CloseParenthesis)) Expect(Semicolon); } ass.EndLocation = t.EndLocation; module.Add(ass); break; case Mixin: if (Peek(1).Kind == Template) module.Add(TemplateDeclaration(module)); //TemplateMixin else if (Lexer.CurrentPeekToken.Kind == Identifier) { var tmx = TemplateMixin(module); if (tmx.MixinId == null) module.Add(tmx); else module.Add(new NamedTemplateMixinNode(tmx)); } //MixinDeclaration else if (Lexer.CurrentPeekToken.Kind == OpenParenthesis) module.Add(MixinDeclaration(module, null)); else { Step(); SynErr(Identifier); } break; case OpenCurlyBrace: AttributeBlock(module); break; // Class Allocators // Note: Although occuring in global scope, parse it anyway but declare it as semantic nonsense;) case New: Step(); var dm = new DMethod(DMethod.MethodType.Allocator) { Location = t.Location }; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); break; case Delete: Step(); var ddm = new DMethod(DMethod.MethodType.Deallocator) { Location = t.Location }; ddm.Name = "delete"; ApplyAttributes(ddm); ddm.Parameters = Parameters(ddm); FunctionBody(ddm); ddm.EndLocation = t.EndLocation; module.Add(ddm); break; default: var decls = Declaration(module); if(module != null && decls!=null) module.AddRange(decls); break; } }
/* * public imports only affect the directly superior module: * * module A: * import B; * * foo(); // Will fail, because foo wasn't found * * --------------------------- * module B: * import C; * * --------------------------- * module C: * public import D; * * --------------------------- * module D: * void foo() {} * * --------------------------- * Whereas * module B: * public import C; * * -- will compile because we have a closed import hierarchy in which all imports are public. * */ /// <summary> /// Handle the node's static statements (but not the node itself) /// </summary> bool HandleDBlockNode(DBlockNode dbn, MemberFilter VisibleMembers, bool takePublicImportsOnly=false) { if (dbn != null && dbn.StaticStatements != null) { foreach (var stmt in dbn.StaticStatements) { var dstmt = stmt as IDeclarationContainingStatement; if (dstmt != null) { if (takePublicImportsOnly && dstmt is ImportStatement && !DAttribute.ContainsAttribute(dstmt.Attributes, DTokens.Public)) continue; /* * Mainly used for selective imports/import module aliases */ if (dstmt.Declarations != null) foreach (var d in dstmt.Declarations) if (HandleItem(d)) //TODO: Handle visibility? return true; if (dstmt is ImportStatement) { var impStmt = (ImportStatement)dstmt; foreach (var imp in impStmt.Imports) if (string.IsNullOrEmpty(imp.ModuleAlias)) if (HandleNonAliasedImport(imp, VisibleMembers)) return true; } } } } // Every module imports 'object' implicitly if (!takePublicImportsOnly) if (HandleNonAliasedImport(_objectImport, VisibleMembers)) return true; return false; }
public void ClassBody(DBlockNode ret,bool KeepBlockAttributes=false,bool UpdateBoundaries=true) { var OldPreviousCommentString = PreviousComment; PreviousComment = ""; if (Expect(OpenCurlyBrace)) { var stk_backup = BlockAttributes; if(!KeepBlockAttributes) BlockAttributes = new Stack<DAttribute>(); if(UpdateBoundaries) ret.BlockStartLocation = t.Location; while (!IsEOF && laKind != (CloseCurlyBrace)) { DeclDef(ret); } if (!IsEOF) LastParsedObject = ret; if (Expect(CloseCurlyBrace)) LastParsedObject = null; if(UpdateBoundaries) ret.EndLocation = t.EndLocation; if(!KeepBlockAttributes) BlockAttributes = stk_backup; } PreviousComment = OldPreviousCommentString; ret.Description += CheckForPostSemicolonComment(); }
protected bool scanChildren(DBlockNode curScope, MemberFilter VisibleMembers, bool publicImports = false, bool isBaseClass = false, bool isMixinAst = false, bool takeStaticChildrenOnly = false, bool scopeIsInInheritanceHierarchy =false) { bool foundItems = false; //ConditionsStack.Push (new ConditionsFrame (curScope.StaticStatements, curScope.MetaBlocks)); var ch = PrefilterSubnodes(curScope); if (ch != null) foreach (var n in ch) { //ContinueHandleStaticStatements (n.Location); if (!CanHandleNode (n as DNode, VisibleMembers, isBaseClass, isMixinAst, takeStaticChildrenOnly, publicImports, scopeIsInInheritanceHierarchy)) continue; // Add anonymous enums' items if (n is DEnum && n.NameHash == 0) { var ch2 = PrefilterSubnodes(n as DEnum); if (ch2 != null) foundItems |= HandleItems(ch2); continue; } foundItems |= HandleItem(n); } if (foundItems) { //ConditionsStack.Pop (); return true; } if (!dontHandleTemplateParamsInNodeScan) { if (curScope.TemplateParameters != null && (VisibleMembers & MemberFilter.TypeParameters) != 0) { var t = ctxt.ScopedBlock; while (t != null) { if (t == curScope) { if (HandleItems (curScope.TemplateParameterNodes as IEnumerable<INode>)) { //ConditionsStack.Pop (); return true; } break; } t = t.Parent as IBlockNode; } } } else dontHandleTemplateParamsInNodeScan = false; //ContinueHandleStaticStatements (curScope.EndLocation); ConditionsStack.Pop (); return HandleDBlockNode(curScope, VisibleMembers, publicImports); }
IMetaDeclarationBlock AttributeBlock(DBlockNode module) { /* * If there are attributes given, put their references into the meta block. * Also, pop them from the declarationAttributes stack on to the block attributes so they will be assigned to all child items later on. */ IMetaDeclarationBlock metaDeclBlock; if (DeclarationAttributes.Count != 0) metaDeclBlock = new AttributeMetaDeclarationBlock(DeclarationAttributes.ToArray()) { BlockStartLocation = la.Location }; else metaDeclBlock = new MetaDeclarationBlock { BlockStartLocation = la.Location }; var stk_backup = BlockAttributes; BlockAttributes = new Stack<DAttribute>(); foreach (var attr in stk_backup) { if (attr is Modifier) { switch ((attr as Modifier).Token) { case DTokens.Virtual: case DTokens.Final: continue; } } else if (attr is BuiltInAtAttribute) { switch ((attr as BuiltInAtAttribute).Kind) { case BuiltInAtAttribute.BuiltInAttributes.Safe: case BuiltInAtAttribute.BuiltInAttributes.System: case BuiltInAtAttribute.BuiltInAttributes.Trusted: continue; } } BlockAttributes.Push(attr); } while (DeclarationAttributes.Count > 0) BlockAttributes.Push(DeclarationAttributes.Pop()); ClassBody(module, true, false); BlockAttributes = stk_backup; // Store the meta block metaDeclBlock.EndLocation = t.EndLocation; if(module!=null) module.Add(metaDeclBlock); return metaDeclBlock; }
void DeclDef(DBlockNode module) { //AttributeSpecifier while (IsAttributeSpecifier()) { AttributeSpecifier(); if (t.Kind == Colon) return; } if (laKind == Semicolon) { LastParsedObject = null; Step(); return; } //ImportDeclaration if (laKind == Import) module.Add(ImportDeclaration()); //Constructor else if (laKind == (This)) module.Add(Constructor(module is DClassLike ? ((DClassLike)module).ClassType == DTokens.Struct : false)); //Destructor else if (laKind == (Tilde) && Lexer.CurrentPeekToken.Kind == (This)) module.Add(Destructor()); //Invariant else if (laKind == (Invariant)) module.Add(_Invariant()); //UnitTest else if (laKind == (Unittest)) { Step(); var dbs = new DMethod(DMethod.MethodType.Unittest); LastParsedObject = dbs; dbs.Location = t.Location; FunctionBody(dbs); dbs.EndLocation = t.EndLocation; module.Add(dbs); } /* * VersionSpecification: * version = Identifier ; * version = IntegerLiteral ; * * DebugSpecification: * debug = Identifier ; * debug = IntegerLiteral ; */ else if ((laKind == Version || laKind == Debug) && Peek(1).Kind == Assign) { Step(); var ass = new VersionDebugSpecification { Token = t.Kind, Location = t.Location }; LastParsedObject = ass; Step(); if (laKind == Literal) { Step(); ass.SpecifiedValue = new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; } else if (Expect(Identifier)) ass.SpecifiedValue = new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; Expect(Semicolon); ass.EndLocation = t.EndLocation; module.Add(ass); } else if (laKind == Version || laKind == Debug || laKind == If) { Step(); var c = new DeclarationCondition(t.Kind); LastParsedObject = c; /* * http://www.d-programming-language.org/version.html#VersionSpecification * VersionCondition: * version ( IntegerLiteral ) * version ( Identifier ) * version ( unittest ) */ if (c.IsVersionCondition && Expect(OpenParenthesis)) { if (laKind == Unittest) { Step(); c.Condition = new TokenExpression(Unittest) { Location = t.Location, EndLocation = t.EndLocation }; } else if (laKind == Literal) { Step(); c.Condition = new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; } else if (Expect(Identifier)) c.Condition = new IdentifierExpression(t.Value, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; if (Expect(CloseParenthesis)) TrackerVariables.ExpectingIdentifier = false; } /* * DebugCondition: * debug * debug ( IntegerLiteral ) * debug ( Identifier ) */ else if (c.IsDebugCondition) { if (laKind == OpenParenthesis) { Step(); if (laKind == Literal) { Step(); c.Condition = new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; } else if (Expect(Identifier)) c.Condition = new IdentifierExpression(t.Value, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; Expect(CloseParenthesis); } } /* * StaticIfCondition: * static if ( AssignExpression ) */ else if (c.IsStaticIfCondition && Expect(OpenParenthesis)) { if (DAttribute.ContainsAttribute(DeclarationAttributes, Static)) DeclarationAttributes.Clear(); else SynErr(Static, "Conditional declaration checks must be static"); c.Condition = AssignExpression(); Expect(CloseParenthesis); } if (laKind == Colon) { Step(); PushAttribute(c, true); return; } else if (laKind == OpenCurlyBrace) { BlockAttributes.Push(c); ClassBody(module, true, false); BlockAttributes.Pop(); } else { DeclarationAttributes.Push(c); DeclDef(module); } if (laKind == Else) { Step(); c = c.Clone() as DeclarationCondition; c.Negate(); if (laKind == OpenCurlyBrace) { BlockAttributes.Push(c); ClassBody(module, true, false); BlockAttributes.Pop(); } else { DeclarationAttributes.Push(c); DeclDef(module); } } } //StaticAssert else if (laKind == (Assert)) { Step(); if (DAttribute.ContainsAttribute(DeclarationAttributes, Static)) { //HACK: Assume that there's only our 'static' attribute applied to the 'if'-statement DeclarationAttributes.Clear(); } else SynErr(Static, "Static assert statements must be explicitly marked as static"); if (Expect(OpenParenthesis)) { AssignExpression(); if (laKind == (Comma)) { Step(); AssignExpression(); } Expect(CloseParenthesis); } Expect(Semicolon); } //TemplateMixinDeclaration else if (laKind == Mixin) { if (Peek(1).Kind == Template) module.Add(TemplateDeclaration(module)); //TemplateMixin else if (Lexer.CurrentPeekToken.Kind == Identifier) module.Add(TemplateMixin()); //MixinDeclaration else if (Lexer.CurrentPeekToken.Kind == OpenParenthesis) module.Add(MixinDeclaration()); else { Step(); SynErr(Identifier); } } // { else if (laKind == (OpenCurlyBrace)) { int popCount = DeclarationAttributes.Count; while (DeclarationAttributes.Count > 0) BlockAttributes.Push(DeclarationAttributes.Pop()); ClassBody(module, true, false); for (int i = popCount; i > 0; i--) BlockAttributes.Pop(); } // Class Allocators // Note: Although occuring in global scope, parse it anyway but declare it as semantic nonsense;) else if (laKind == (New)) { Step(); var dm = new DMethod(DMethod.MethodType.Allocator) { Location=t.Location }; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); } // Class Deallocators else if (laKind == Delete) { Step(); var dm = new DMethod(DMethod.MethodType.Deallocator) { Location=t.Location }; dm.Name = "delete"; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); } // else: else module.AddRange(Declaration(module)); }
/// <summary> /// /// </summary> /// <param name="module"></param> /// <param name="previouslyParsedAttribute"></param> /// <param name="RequireDeclDef">If no colon and no open curly brace is given as lookahead, a DeclDef may be parsed otherwise, if parameter is true.</param> /// <returns></returns> IMetaDeclaration AttributeSpecifier(DBlockNode module, DAttribute previouslyParsedAttribute, bool RequireDeclDef = false) { DAttribute[] attrs; if (laKind == Colon) { Step(); PushAttribute(previouslyParsedAttribute, true); attrs = new DAttribute[1 + DeclarationAttributes.Count]; DeclarationAttributes.CopyTo(attrs, 0); DeclarationAttributes.Clear(); attrs[attrs.Length - 1] = previouslyParsedAttribute; AttributeMetaDeclarationSection metaDecl = null; //TODO: Put all remaining block/decl(?) attributes into the section definition.. if(module!=null) module.Add(metaDecl = new AttributeMetaDeclarationSection(attrs) { EndLocation = t.EndLocation }); return metaDecl; } else PushAttribute(previouslyParsedAttribute, false); if (laKind == OpenCurlyBrace) return AttributeBlock(module); else { if (IsEOF && module != null && previouslyParsedAttribute != null) // To enable attribute completion, add dummy node module.Add (new DVariable{ Attributes = new List<DAttribute>{ previouslyParsedAttribute } }); if (RequireDeclDef) { DeclDef(module); attrs = new DAttribute[1 + DeclarationAttributes.Count]; DeclarationAttributes.CopyTo(attrs, 0); DeclarationAttributes.Clear(); attrs[attrs.Length - 1] = previouslyParsedAttribute; return new AttributeMetaDeclaration(attrs) { EndLocation = previouslyParsedAttribute.EndLocation }; } } return null; }
public void DeclDef(DBlockNode module) { if (IsAttributeSpecifier) { do AttributeSpecifier (module); while(IsAttributeSpecifier); var tkind = t.Kind; if(tkind == Semicolon || tkind == CloseCurlyBrace || tkind == Colon) return; } if (laKind == Semicolon) { Step(); return; } switch (laKind) { case DTokens.Module: var mod = module as DModule; var ddoc = GetComments (); var ms = ModuleDeclaration (); ms.ParentNode = module; ddoc += CheckForPostSemicolonComment (); if (mod != null) { if (mod.StaticStatements.Count != 0 || mod.Children.Count != 0) SynErr (DTokens.Module, "Module declaration must stand at a module's beginning."); mod.OptionalModuleStatement = ms; mod.Description = ddoc; if (ms.ModuleName!=null) mod.ModuleName = ms.ModuleName.ToString(); } else SynErr (DTokens.Module, "Module statements only allowed in module scope."); module.Add (ms); break; case Import: module.Add(ImportDeclaration(module)); break; case This: module.Add(Constructor(module, module is DClassLike && ((DClassLike)module).ClassType == DTokens.Struct)); break; case Tilde: if (Lexer.CurrentPeekToken.Kind != This) goto default; module.Add(Destructor()); break; case Invariant: module.Add(_Invariant()); break; case Unittest: Step(); var dbs = new DMethod(DMethod.MethodType.Unittest); ApplyAttributes(dbs); dbs.Location = t.Location; FunctionBody(dbs); module.Add(dbs); break; /* * VersionSpecification: * version = Identifier ; * version = IntegerLiteral ; * * DebugSpecification: * debug = Identifier ; * debug = IntegerLiteral ; */ case Version: case Debug: if (Peek(1).Kind == Assign) { DebugSpecification ds = null; VersionSpecification vs = null; if (laKind == Version) vs = new VersionSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; else ds = new DebugSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; Step(); Step(); if (laKind == Literal) { Step (); if (t.LiteralFormat != LiteralFormat.Scalar) SynErr (t.Kind, "Integer literal expected!"); try { if (vs != null) vs.SpecifiedNumber = Convert.ToUInt64 (t.LiteralValue); else ds.SpecifiedDebugLevel = Convert.ToUInt64 (t.LiteralValue); } catch { } } else if (laKind == Identifier) { Step (); if (vs != null) vs.SpecifiedId = t.Value; else ds.SpecifiedId = t.Value; } else if (IsEOF) { if (vs != null) vs.SpecifiedId = DTokens.IncompleteId; else ds.SpecifiedId = DTokens.IncompleteId; } else if (ds == null) Expect(Identifier); Expect(Semicolon); ((AbstractStatement)ds ?? vs).EndLocation = t.EndLocation; module.Add(vs as StaticStatement ?? ds); } else DeclarationCondition(module); break; case Static: if (Lexer.CurrentPeekToken.Kind == If) goto case Version; goto default; case Assert: Step(); CheckForStorageClasses(module); if (!Modifier.ContainsAttribute(DeclarationAttributes, Static)) SynErr(Static, "Static assert statements must be explicitly marked as static"); module.Add(ParseStaticAssertStatement(module)); Expect(Semicolon); break; case Mixin: switch(Peek(1).Kind) { case Template: module.Add (TemplateDeclaration (module)); break; case DTokens.__vector: case DTokens.Typeof: case Dot: case Identifier://TemplateMixin var tmx = TemplateMixin (module); if (tmx.MixinId == null) module.Add (tmx); else module.Add (new NamedTemplateMixinNode (tmx)); break; case OpenParenthesis: module.Add (MixinDeclaration (module, null)); break; default: Step (); SynErr (Identifier); break; } break; case OpenCurlyBrace: AttributeBlock(module); break; // Class Allocators // Note: Although occuring in global scope, parse it anyway but declare it as semantic nonsense;) case New: Step(); var dm = new DMethod(DMethod.MethodType.Allocator) { Location = t.Location }; ApplyAttributes(dm); Parameters(dm); FunctionBody(dm); module.Add(dm); break; case Delete: Step(); var ddm = new DMethod(DMethod.MethodType.Deallocator) { Location = t.Location }; ddm.Name = "delete"; ApplyAttributes(ddm); Parameters(ddm); FunctionBody(ddm); module.Add(ddm); break; default: var decls = Declaration(module); if(module != null && decls!=null) module.AddRange(decls); break; } }
public override void VisitBlock(DBlockNode bn) { var back = ctxt.ScopedBlock; if (bn != back) { ctxt.PushNewScope (bn); OnScopedBlockChanged (bn); } base.VisitBlock (bn); if(bn != back) ctxt.Pop (); }
void DeclarationCondition(DBlockNode module) { var sl = la.Location; var c = Condition(module); c.Location = sl; c.EndLocation = t.EndLocation; bool allowElse = laKind != Colon; var metaBlock = AttributeTrail(module, c, true) as AttributeMetaDeclaration; if (allowElse && metaBlock == null) { SynErr(t.Kind, "Wrong meta block type. (see DeclarationCondition();)"); return; } else if (allowElse && laKind == Else) { Step(); c = new NegatedDeclarationCondition(c); BlockAttributes.Push(c); if (laKind == OpenCurlyBrace) { metaBlock.OptionalElseBlock = new ElseMetaDeclarationBlock { Location = t.Location, BlockStartLocation = la.Location }; ClassBody (module, true, false); } else if (laKind == Colon) { metaBlock.OptionalElseBlock = new ElseMetaDeclarationSection { Location = t.Location, EndLocation =la.EndLocation }; Step (); return; } else { metaBlock.OptionalElseBlock = new ElseMetaDeclaration { Location = t.Location }; DeclDef(module); } BlockAttributes.Pop(); metaBlock.OptionalElseBlock.EndLocation = t.EndLocation; } }
public override void VisitBlock(DBlockNode block) { if(block is DModule) { base.VisitBlock(block); return; } FormatAttributedNode(block); EnforceBraceStyle(policy.TypeBlockBraces, block.BlockStartLocation, block.EndLocation.Line, block.EndLocation.Column-1); curIndent.Push(IndentType.Block); base.VisitBlock(block); curIndent.Pop(); EnsureBlankLinesAfter(block.EndLocation, policy.LinesAfterNode); }
public void ClassBody(DBlockNode ret,bool KeepBlockAttributes=false,bool UpdateBoundaries=true) { var OldPreviousCommentString = PreviousComment; PreviousComment = new StringBuilder (); if (laKind == OpenCurlyBrace) { Step(); var stk_backup = BlockAttributes; if (!KeepBlockAttributes) BlockAttributes = new Stack<DAttribute>(); if (UpdateBoundaries) ret.BlockStartLocation = t.Location; while (!IsEOF && laKind != (CloseCurlyBrace)) DeclDef(ret); Expect(CloseCurlyBrace); if (UpdateBoundaries) ret.EndLocation = t.EndLocation; if (!KeepBlockAttributes) BlockAttributes = stk_backup; } else Expect(Semicolon); PreviousComment = OldPreviousCommentString; if(ret!=null) ret.Description += CheckForPostSemicolonComment(); }
private void AttributeSpecifier(DBlockNode scope) { DAttribute attr; if(IsAtAttribute) attr = AtAttribute(scope); else if (laKind == Pragma) attr=_Pragma(); else if(laKind == Deprecated) { Step(); var loc = t.Location; IExpression lc = null; if(laKind == OpenParenthesis) { Step(); lc = AssignExpression(scope); Expect(CloseParenthesis); } attr = new DeprecatedAttribute(loc, t.EndLocation, lc); } else { var m = new Modifier(laKind, la.Value) { Location = la.Location }; attr = m; LastParsedObject = attr; if (laKind == Extern && Lexer.CurrentPeekToken.Kind == OpenParenthesis) { Step(); // Skip extern Step(); // Skip ( TrackerVariables.ExpectingIdentifier = true; var sb = new StringBuilder (); while (!IsEOF && laKind != CloseParenthesis) { Step(); sb.Append(t.ToString()); TrackerVariables.ExpectingIdentifier = false; if (t.Kind == Identifier && laKind == Identifier) sb.Append(' '); } m.LiteralContent = sb.ToString(); if (!Expect(CloseParenthesis)) return; } else if (laKind == Align && Lexer.CurrentPeekToken.Kind == OpenParenthesis) { Step(); Step(); if (Expect(Literal)) m.LiteralContent = new IdentifierExpression(t.LiteralValue, t.LiteralFormat); if (!Expect(CloseParenthesis)) return; } else Step(); m.EndLocation = t.EndLocation; } if (laKind == Colon) LastParsedObject = null; //TODO: What about these semicolons after e.g. a pragma? Enlist these attributes anyway in the meta decl list? if (laKind != Semicolon) AttributeTrail(scope, attr); }
public override void VisitBlock(DBlockNode block) { VisitChildren(block); VisitDNode(block); if (block.StaticStatements.Count != 0) foreach (var s in block.StaticStatements) { if (s.Location > caret) break; s.Accept(this); } if (block.MetaBlocks.Count != 0) foreach (var mb in block.MetaBlocks) { if (mb.Location > caret) break; mb.Accept(this); } }
// http://www.digitalmars.com/d/2.0/declaration.html bool CheckForStorageClasses(DBlockNode scope) { bool ret = false; while (IsStorageClass ) { if (IsAttributeSpecifier()) // extern, align AttributeSpecifier(scope); else { Step(); // Always allow more than only one property DAttribute if (!Modifier.ContainsAttribute(DeclarationAttributes.ToArray(), t.Kind)) PushAttribute(new Modifier(t.Kind, t.Value) { Location = t.Location, EndLocation = t.EndLocation }, false); } ret = true; } return ret; }
public static DBlockNode ParseDeclDefs(string Code) { var p = Create(new StringReader(Code)); p.Step(); var block = new DBlockNode(); while (!p.IsEOF) { p.DeclDef(block); } block.EndLocation = p.la.Location; return block; }
/// <summary> /// Handle the node's static statements (but not the node itself) /// </summary> bool HandleDBlockNode(DBlockNode dbn, MemberFilter VisibleMembers, bool takePublicImportsOnly = false) { bool foundItems = false; if (dbn != null && dbn.StaticStatements != null) { foreach (var stmt in dbn.StaticStatements) { var dstmt = stmt as IDeclarationContainingStatement; if (dstmt != null) { var impStmt = dstmt as ImportStatement; if ((takePublicImportsOnly && impStmt!=null && !impStmt.IsPublic) || !MatchesCompilationEnv(stmt) || impStmt.IsStatic) continue; /* * Mainly used for selective imports/import module aliases */ if (dstmt.Declarations != null) foreach (var d in dstmt.Declarations) foundItems |= HandleItem(d); //TODO: Handle visibility? if (impStmt!=null) { foreach (var imp in impStmt.Imports) if (imp.ModuleAlias == null) foundItems |= HandleNonAliasedImport(imp, VisibleMembers); } } else if(stmt is MixinStatement) { if(MatchesCompilationEnv(stmt)) foundItems |= HandleMixin(stmt as MixinStatement,true,VisibleMembers); } else if(stmt is TemplateMixin) { if (MatchesCompilationEnv(stmt)) foundItems |= HandleUnnamedTemplateMixin(stmt as TemplateMixin, true, VisibleMembers); } } } // Every module imports 'object' implicitly if (dbn is DModule && !takePublicImportsOnly) foundItems |= HandleNonAliasedImport(_objectImport, VisibleMembers); return foundItems; }