# HG changeset patch # User Aziz K?ksal # Date 1196975995 -3600 # Node ID 9c208925a3d4bd98c89ae5f8026fbaa4814b0d87 # Parent b991f49628a8174eaf55265b3e1414a63c78c7a7 Added module ImportParser and new stuff from DMD2.008. Moved ImportParser from module Parser to its own module. Added a few methods from class Parser and simplified them. Now protection attributes are taken into consideration as well. Added class TemplateThisParameter. Adapted TypeofType so that typeof(return) can be recognized. diff -r b991f49628a8 -r 9c208925a3d4 trunk/src/dil/Declarations.d --- a/trunk/src/dil/Declarations.d Tue Dec 04 23:33:13 2007 +0100 +++ b/trunk/src/dil/Declarations.d Thu Dec 06 22:19:55 2007 +0100 @@ -349,7 +349,8 @@ TemplateParameters tparams; Parameters params; FunctionBody funcBody; - this(Type returnType, Token* funcName, TemplateParameters tparams, Parameters params, FunctionBody funcBody) + this(Type returnType, Token* funcName, TemplateParameters tparams, + Parameters params, FunctionBody funcBody, StorageClass stc) { super.hasBody = funcBody.funcBody !is null; mixin(set_kind); @@ -358,6 +359,7 @@ addChild(params); addChild(funcBody); + this.stc = stc; this.returnType = returnType; this.funcName = funcName; this.tparams = tparams; diff -r b991f49628a8 -r 9c208925a3d4 trunk/src/dil/ImportParser.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/dil/ImportParser.d Thu Dec 06 22:19:55 2007 +0100 @@ -0,0 +1,375 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module dil.ImportParser; +import dil.Parser; +import dil.Token; +import dil.Enums; +import dil.Declarations; +import dil.Statements; +import dil.SyntaxTree; +import common; + +private alias TOK T; + +class ImportParser : Parser +{ + this(char[] srcText, string fileName) + { + super(srcText, fileName); + } + + override Declarations start() + { + auto decls = new Declarations; + super.init(); + if (token.type == T.Module) + decls ~= parseModuleDeclaration(); + while (token.type != T.EOF) + parseDeclarationDefinition(Protection.None); + return decls; + } + + void parseDeclarationDefinitionsBlock(Protection prot) + { + skip(T.LBrace); + while (token.type != T.RBrace && token.type != T.EOF) + parseDeclarationDefinition(prot); + skip(T.RBrace); + } + + void parseDeclarationsBlock(Protection prot) + { + switch (token.type) + { + case T.LBrace: + parseDeclarationDefinitionsBlock(prot); + break; + case T.Colon: + nT(); + while (token.type != T.RBrace && token.type != T.EOF) + parseDeclarationDefinition(prot); + break; + default: + parseDeclarationDefinition(prot); + } + } + + bool skipToClosing(T opening, T closing) + { + Token* next = token; + uint level = 1; + while (1) + { + lx.peek(next); + if (next.type == opening) + ++level; + else if (next.type == closing && --level == 0) + return true; + else if (next.type == T.EOF) + break; + } + return false; + } + + void skipToTokenAfterClosingParen() + { + skipToClosing(T.LParen, T.RParen); + nT(); + } + + void skipToTokenAfterClosingBrace() + { + skipToClosing(T.LBrace, T.RBrace); + nT(); + } + + void skip(TOK tok) + { + token.type == tok && nT(); + } + + void parseProtectionAttribute() + { + Protection prot; + switch (token.type) + { + case T.Private: + prot = Protection.Private; break; + case T.Package: + prot = Protection.Package; break; + case T.Protected: + prot = Protection.Protected; break; + case T.Public: + prot = Protection.Public; break; + case T.Export: + prot = Protection.Export; break; + default: + assert(0); + } + nT(); + parseDeclarationsBlock(prot); + } + + void parseDeclarationDefinition(Protection prot) + { + switch (token.type) + { + case T.Align: + nT(); + if (token.type == T.LParen) + nT(), nT(), nT(); // ( Integer ) + parseDeclarationsBlock(prot); + break; + case T.Pragma: + nT(); + skipToTokenAfterClosingParen(); + parseDeclarationsBlock(prot); + break; + case T.Export, + T.Private, + T.Package, + T.Protected, + T.Public: + parseProtectionAttribute(); + break; + // Storage classes + case T.Extern: + nT(); + token.type == T.LParen && skipToTokenAfterClosingParen(); + parseDeclarationsBlock(prot); + break; + case T.Const: + version(D2) + { + if (peekNext() == T.LParen) + goto case_Declaration; + } + case T.Override, + T.Deprecated, + T.Abstract, + T.Synchronized, + // T.Static, + T.Final, + T.Auto, + T.Scope: + case_StaticAttribute: + case_InvariantAttribute: + nT(); + parseDeclarationsBlock(prot); + break; + // End of storage classes. + case T.Alias, T.Typedef: + nT(); + goto case_Declaration; + case T.Static: + switch (peekNext()) + { + case T.Import: + goto case_Import; + case T.This: + nT(), nT(); // static this + skipToTokenAfterClosingParen(); + parseFunctionBody(); + break; + case T.Tilde: + nT(), nT(), nT(), nT(), nT(); // static ~ this ( ) + parseFunctionBody(); + break; + case T.If: + nT(), nT(); + skipToTokenAfterClosingParen(); + parseDeclarationsBlock(prot); + if (token.type == T.Else) + nT(), parseDeclarationsBlock(prot); + break; + case T.Assert: + nT(), nT(); // static assert + skipToTokenAfterClosingParen(); + skip(T.Semicolon); + break; + default: + goto case_StaticAttribute; + } + break; + case T.Import: + case_Import: + auto decl = parseImportDeclaration(); + assert(decl && decl.kind == NodeKind.ImportDeclaration); + decl.prot = prot; // Set the protection attribute. + imports ~= cast(ImportDeclaration)cast(void*)decl; + break; + case T.Enum: + nT(); + token.type == T.Identifier && nT(); + if (token.type == T.Colon) + { + nT(); + while (token.type != T.LBrace && token.type != T.EOF) + nT(); + } + if (token.type == T.Semicolon) + nT(); + else + skipToTokenAfterClosingBrace(); + break; + case T.Class: + case T.Interface: + nT(), skip(T.Identifier); // class Identifier + token.type == T.LParen && skipToTokenAfterClosingParen(); // Skip template params. + if (token.type == T.Colon) + { // BaseClasses + nT(); + while (token.type != T.LBrace && token.type != T.EOF) + if (token.type == T.LParen) // Skip ( tokens... ) + skipToTokenAfterClosingParen(); + else + nT(); + } + if (token.type == T.Semicolon) + nT(); + else + parseDeclarationDefinitionsBlock(Protection.None); + break; + case T.Struct, T.Union: + nT(); skip(T.Identifier); + token.type == T.LParen && skipToTokenAfterClosingParen(); + if (token.type == T.Semicolon) + nT(); + else + parseDeclarationDefinitionsBlock(Protection.None); + break; + case T.Tilde: + nT(); // ~ + case T.This: + nT(); nT(); nT(); // this ( ) + parseFunctionBody(); + break; + case T.Invariant: + version(D2) + { + auto next = token; + if (peekAfter(next) == T.LParen) + { + if (peekAfter(next) != T.RParen) + goto case_Declaration; + } + else + goto case_InvariantAttribute; + } + token.type == T.LParen && skipToTokenAfterClosingParen(); + parseFunctionBody(); + break; + case T.Unittest: + nT(); + parseFunctionBody(); + break; + case T.Debug: + nT(); + if (token.type == T.Assign) + { + nT(), nT(), nT(); // = Condition ; + break; + } + if (token.type == T.LParen) + nT(), nT(), nT(); // ( Condition ) + parseDeclarationsBlock(prot); + if (token.type == T.Else) + nT(), parseDeclarationsBlock(prot); + break; + case T.Version: + nT(); + if (token.type == T.Assign) + { + nT(), nT(), nT(); // = Condition ; + break; + } + nT(), nT(), nT(); // ( Condition ) + parseDeclarationsBlock(prot); + if (token.type == T.Else) + nT(), parseDeclarationsBlock(prot); + break; + case T.Template: + nT(); + skip(T.Identifier); + skipToTokenAfterClosingParen(); + parseDeclarationDefinitionsBlock(Protection.None); + break; + case T.New: + nT(); + skipToTokenAfterClosingParen(); + parseFunctionBody(); + break; + case T.Delete: + nT(); + skipToTokenAfterClosingParen(); + parseFunctionBody(); + break; + case T.Mixin: + while (token.type != T.Semicolon && token.type != T.EOF) + if (token.type == T.LParen) + skipToTokenAfterClosingParen(); + else + nT(); + skip(T.Semicolon); + break; + case T.Semicolon: + nT(); + break; + // Declaration + case T.Identifier, T.Dot, T.Typeof: + // IntegralType + case T.Char, T.Wchar, T.Dchar, T.Bool, + T.Byte, T.Ubyte, T.Short, T.Ushort, + T.Int, T.Uint, T.Long, T.Ulong, + T.Float, T.Double, T.Real, + T.Ifloat, T.Idouble, T.Ireal, + T.Cfloat, T.Cdouble, T.Creal, T.Void: + case_Declaration: + while (token.type != T.Semicolon && token.type != T.EOF) + if (token.type == T.LParen) + skipToTokenAfterClosingParen(); + else if (token.type == T.LBrace) + skipToTokenAfterClosingBrace(); + else + nT(); + skip(T.Semicolon); + break; + default: + nT(); + } + } + + FunctionBody parseFunctionBody() + { + while (1) + { + switch (token.type) + { + case T.LBrace: + skipToTokenAfterClosingBrace(); + break; + case T.Semicolon: + nT(); + break; + case T.In: + nT(); + skipToTokenAfterClosingBrace(); + continue; + case T.Out: + nT(); + if (token.type == T.LParen) + nT(), nT(), nT(); // ( Identifier ) + skipToTokenAfterClosingBrace(); + continue; + case T.Body: + nT(); + goto case T.LBrace; + default: + } + break; // Exit loop. + } + return null; + } +} diff -r b991f49628a8 -r 9c208925a3d4 trunk/src/dil/Module.d --- a/trunk/src/dil/Module.d Tue Dec 04 23:33:13 2007 +0100 +++ b/trunk/src/dil/Module.d Thu Dec 06 22:19:55 2007 +0100 @@ -6,6 +6,7 @@ import dil.SyntaxTree; import dil.Declarations; import dil.Parser; +import dil.ImportParser; import dil.Lexer; import dil.File; import tango.io.FilePath; @@ -28,7 +29,7 @@ Module[] modules; - this(string filePath, bool isLight = false) + this(string filePath, bool isLightweight = false) { this.filePath = filePath; this.isLightweight = isLightweight; diff -r b991f49628a8 -r 9c208925a3d4 trunk/src/dil/Parser.d --- a/trunk/src/dil/Parser.d Tue Dec 04 23:33:13 2007 +0100 +++ b/trunk/src/dil/Parser.d Thu Dec 06 22:19:55 2007 +0100 @@ -17,35 +17,10 @@ private alias TOK T; -class ImportParser : Parser -{ - this(char[] srcText, string fileName) - { - super(srcText, fileName); - } - - override Declarations start() - { - auto decls = new Declarations; - super.init(); - if (token.type == T.Module) - decls ~= parseModuleDeclaration(); - while (token.type != T.EOF) - { - if (token.type == T.Import) - { - auto decl = parseImportDeclaration(); - assert(decl && decl.kind == NodeKind.ImportDeclaration); - super.imports ~= cast(ImportDeclaration)cast(void*)decl; - decls ~= decl; - } - else - nT(); - } - return decls; - } -} - +/++ + The Parser produces an abstract syntax tree (AST) by analyzing + the tokens of the provided source code. ++/ class Parser { Lexer lx; @@ -61,7 +36,7 @@ lx = new Lexer(srcText, filePath); } - private void init() + protected void init() { nT(); prevToken = token; @@ -452,9 +427,24 @@ } auto params = parseParameterList(); + version(D2) + { + switch (token.type) + { + case T.Const: + stc |= StorageClass.Const; + nT(); + break; + case T.Invariant: + stc |= StorageClass.Invariant; + nT(); + break; + default: + } + } // ReturnType FunctionName ( ParameterList ) auto funcBody = parseFunctionBody(); - return set(new FunctionDeclaration(type, ident, tparams, params, funcBody), begin); + return set(new FunctionDeclaration(type, ident, tparams, params, funcBody, stc), begin); } type = parseDeclaratorSuffix(type); } @@ -1420,6 +1410,27 @@ return new DeleteDeclaration(parameters, funcBody); } + Type parseTypeofType() + { + assert(token.type == T.Typeof); + Type type; + requireNext(T.LParen); + switch (token.type) + { + version(D2) + { + case T.Return: + nT(); + type = new TypeofType(); + break; + } + default: + type = new TypeofType(parseExpression()); + } + require(T.RParen); + return type; + } + /+ DotListExpression: . DotListItems @@ -1448,9 +1459,7 @@ } else if (token.type == T.Typeof) { - requireNext(T.LParen); - auto type = new TypeofType(parseExpression()); - require(T.RParen); + auto type = parseTypeofType(); set(type, begin); identList ~= set(new TypeofExpression(type), begin); if (token.type != T.Dot) @@ -1515,10 +1524,7 @@ } else if (token.type == T.Typeof) { - requireNext(T.LParen); - auto type = new TypeofType(parseExpression()); - require(T.RParen); - identList ~= set(type, begin); + identList ~= set(parseTypeofType(), begin); if (token.type != T.Dot) goto Lreturn; nT(); @@ -4322,6 +4328,17 @@ goto LTemplateValueParameter; } break; + version(D2) + { + case T.This: + // TemplateThisParameter + // this TemplateTypeParameter + nT(); // Skip 'this' keyword. + ident = requireId(); + parseSpecAndOrDefaultType(); + tp = new TemplateThisParameter(ident, specType, defType); + break; + } default: LTemplateValueParameter: // TemplateValueParameter: diff -r b991f49628a8 -r 9c208925a3d4 trunk/src/dil/SyntaxTree.d --- a/trunk/src/dil/SyntaxTree.d Tue Dec 04 23:33:13 2007 +0100 +++ b/trunk/src/dil/SyntaxTree.d Thu Dec 06 22:19:55 2007 +0100 @@ -210,6 +210,7 @@ BaseClass, TemplateAliasParameter, TemplateTypeParameter, + TemplateThisParameter, // D2.0 TemplateValueParameter, TemplateTupleParameter, TemplateParameters, diff -r b991f49628a8 -r 9c208925a3d4 trunk/src/dil/Types.d --- a/trunk/src/dil/Types.d Tue Dec 04 23:33:13 2007 +0100 +++ b/trunk/src/dil/Types.d Thu Dec 06 22:19:55 2007 +0100 @@ -179,6 +179,24 @@ } } +version(D2) +{ +class TemplateThisParameter : TemplateParameter +{ + Token* ident; + Type specType, defType; + this(Token* ident, Type specType, Type defType) + { + mixin(set_kind); + addOptChild(specType); + addOptChild(defType); + this.ident = ident; + this.specType = specType; + this.defType = defType; + } +} +} + class TemplateValueParameter : TemplateParameter { Type valueType; @@ -354,10 +372,20 @@ Expression e; this(Expression e) { + this(); + addChild(e); + this.e = e; + } + + this() + { super(TID.Typeof); mixin(set_kind); - addChild(e); - this.e = e; + } + + bool isTypeofReturn() + { + return e is null; } }