Mercurial > projects > dil
view trunk/src/dil/ast/Node.d @ 673:64fec49651cf
Renamed VariableDeclaration to VariablesDeclaration.
Removed TryCast and CastTo template functions.
Renamed Node.iS() to Node.Is().
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Fri, 18 Jan 2008 16:44:20 +0100 |
parents | f1325a4506de |
children | c4e3a34e40f1 |
line wrap: on
line source
/++ Author: Aziz Köksal License: GPL3 +/ module dil.ast.Node; import common; public import dil.lexer.Token; public import dil.ast.NodesEnum; /// This string is mixed into the constructor of a class that inherits from Node. const string set_kind = `this.kind = mixin("NodeKind." ~ typeof(this).stringof);`; class Node { NodeCategory category; NodeKind kind; Node[] children; Token* begin, end; this(NodeCategory category) { assert(category != NodeCategory.Undefined); this.category = category; } void setTokens(Token* begin, Token* end) { this.begin = begin; this.end = end; } Class setToks(Class)(Class node) { node.setTokens(this.begin, this.end); return node; } void addChild(Node child) { assert(child !is null, "failed in " ~ this.classinfo.name); this.children ~= child; } void addOptChild(Node child) { child is null || addChild(child); } void addChildren(Node[] children) { assert(children !is null && delegate{ foreach (child; children) if (child is null) return false; return true; }(), "failed in " ~ this.classinfo.name ); this.children ~= children; } void addOptChildren(Node[] children) { children is null || addChildren(children); } Class Is(Class)() { if (kind == mixin("NodeKind." ~ typeof(Class).stringof)) return cast(Class)cast(void*)this; return null; } Class to(Class)() { return cast(Class)cast(void*)this; } static bool isDoxygenComment(Token* token) { // Doxygen: '/+!' '/*!' '//!' return token.type == TOK.Comment && token.start[2] == '!'; } static bool isDDocComment(Token* token) { // DDOC: '/++' '/**' '///' return token.type == TOK.Comment && token.start[1] == token.start[2]; } /++ Returns the surrounding documentation comment tokens. Note: this function works correctly only if the source text is syntactically correct. +/ Token*[] getDocComments(bool function(Token*) isDocComment = &isDDocComment) { Token*[] comments; // Get preceding comments. auto token = begin; // Scan backwards until we hit another declaration. while (1) { token = token.prev; if (token.type == TOK.LBrace || token.type == TOK.RBrace || token.type == TOK.Semicolon || token.type == TOK.HEAD || (kind == NodeKind.EnumMember && token.type == TOK.Comma)) break; if (token.type == TOK.Comment) { // Check that this comment doesn't belong to the previous declaration. if (kind == NodeKind.EnumMember && token.type == TOK.Comma) break; switch (token.prev.type) { case TOK.Semicolon, TOK.RBrace: break; default: if (isDocComment(token)) comments ~= token; } } } // Get single comment to the right. token = end.next; if (token.type == TOK.Comment && isDocComment(token)) comments ~= token; else if (kind == NodeKind.EnumMember) { token = end.nextNWS; if (token.type == TOK.Comma) { token = token.next; if (token.type == TOK.Comment && isDocComment(token)) comments ~= token; } } return comments; } }