# HG changeset patch # User aziz # Date 1188301260 0 # Node ID 511c14950cacc653984105a282287055ed500576 # Parent 0faf57d99c1c1a60906e436023937a841104d1a4 - Added messages MissingLinkageType and UnrecognizedLinkageType. - Changed enum Linkage into a class. - Added method parseLinkage() to Parser. - Added MAX to enum TOK. - Added methods nextNWS() and prevNWS() to Token. - Fixed tokToString table. diff -r 0faf57d99c1c -r 511c14950cac trunk/src/dil/Declarations.d --- a/trunk/src/dil/Declarations.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/dil/Declarations.d Tue Aug 28 11:41:00 2007 +0000 @@ -473,6 +473,8 @@ { super(TOK.Extern, decls); mixin(set_kind); + if (linkage) + this.children ~= linkage; this.linkage = linkage; } } diff -r 0faf57d99c1c -r 511c14950cac trunk/src/dil/Messages.d --- a/trunk/src/dil/Messages.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/dil/Messages.d Tue Aug 28 11:41:00 2007 +0000 @@ -60,6 +60,8 @@ TemplateTupleParameter, InContract, OutContract, + MissingLinkageType, + UnrecognizedLinkageType, // Help messages: HelpMain, diff -r 0faf57d99c1c -r 511c14950cac trunk/src/dil/Parser.d --- a/trunk/src/dil/Parser.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/dil/Parser.d Tue Aug 28 11:41:00 2007 +0000 @@ -535,16 +535,65 @@ return func; } + Linkage parseLinkage() + { + if (token.type != T.LParen) + return null; + + nT(); // Skip ( + if (token.type == T.RParen) + { + error(MID.MissingLinkageType); + nT(); + return null; + } + + auto begin = token; + auto ident = requireId(); + + Linkage.Type linktype; + switch (ident ? ident.identifier : null) + { + case "C": + if (token.type == T.PlusPlus) + { + nT(); + linktype = Linkage.Type.Cpp; + break; + } + linktype = Linkage.Type.C; + break; + case "D": + linktype = Linkage.Type.D; + break; + case "Windows": + linktype = Linkage.Type.Windows; + break; + case "Pascal": + linktype = Linkage.Type.Pascal; + break; + case "System": + linktype = Linkage.Type.System; + break; + default: + error(MID.UnrecognizedLinkageType, token.srcText); + nT(); + } + auto linkage = new Linkage(linktype); + set(linkage, begin); + require(T.RParen); + return linkage; + } + Declaration parseStorageAttribute() { StorageClass stc, tmp; + Linkage.Category link_cat; void addStorageClass() { if (stc & tmp) - { error(MID.RedundantStorageClass, token.srcText); - } else stc |= tmp; } @@ -552,46 +601,27 @@ Declaration parse() { Declaration decl; + auto begin = token; switch (token.type) { case T.Extern: - tmp = StorageClass.Extern; - addStorageClass(); + stc |= StorageClass.Extern; nT(); - Linkage linkage = Linkage.Extern; - if (token.type == T.LParen) + Linkage linkage = parseLinkage(); + + // Check for redundancy. + Linkage.Category link_cat_tmp = Linkage.getCategory(linkage); + if (link_cat & link_cat_tmp) { - nT(); - auto ident = requireId(); - switch (ident ? ident.identifier : null) - { - case "C": - if (token.type == T.PlusPlus) - { - nT(); - linkage = Linkage.Cpp; - break; - } - linkage = Linkage.C; - break; - case "D": - linkage = Linkage.D; - break; - case "Windows": - linkage = Linkage.Windows; - break; - case "Pascal": - linkage = Linkage.Pascal; - break; - case "System": - linkage = Linkage.System; - break; - default: - // TODO: issue error msg. Unrecognized LinkageType. - } - require(T.RParen); + char[] srcText = begin.srcText; + if (link_cat_tmp == Linkage.Category.MangleSymbol) + srcText = begin.start[0 .. prevToken.end - begin.start]; + error(MID.RedundantStorageClass, srcText); } - decl = new ExternDeclaration(linkage, parse()); + else + link_cat |= link_cat_tmp; + + decl = set(new ExternDeclaration(linkage, parse()), begin); break; case T.Override: tmp = StorageClass.Override; @@ -622,6 +652,7 @@ version(D2) { case T.Invariant: // D 2.0 + // TODO: could this be a class invariant? if (peekNext() == T.LParen) goto case_Declaration; tmp = StorageClass.Invariant; @@ -637,7 +668,7 @@ addStorageClass(); auto tok = token.type; nT(); - decl = new AttributeDeclaration(tok, parse()); + decl = set(new AttributeDeclaration(tok, parse()), begin); break; case T.Identifier: case_Declaration: @@ -1772,6 +1803,7 @@ Statement parseAttributeStatement() { StorageClass stc, tmp; + Linkage.Category link_cat; void addStorageClass() { @@ -1790,42 +1822,22 @@ switch (token.type) { case T.Extern: - tmp = StorageClass.Extern; - addStorageClass(); + stc |= StorageClass.Extern; nT(); - Linkage linkage = Linkage.Extern; - if (token.type == T.LParen) + Linkage linkage = parseLinkage(); + + // Check for redundancy. + Linkage.Category link_cat_tmp = Linkage.getCategory(linkage); + if (link_cat & link_cat_tmp) { - nT(); - auto ident = requireId(); - switch (ident ? ident.identifier : null) - { - case "C": - if (token.type == T.PlusPlus) - { - nT(); - linkage = Linkage.Cpp; - break; - } - linkage = Linkage.C; - break; - case "D": - linkage = Linkage.D; - break; - case "Windows": - linkage = Linkage.Windows; - break; - case "Pascal": - linkage = Linkage.Pascal; - break; - case "System": - linkage = Linkage.System; - break; - default: - // TODO: issue error msg. Unrecognized LinkageType. - } - require(T.RParen); + char[] srcText = begin.srcText; + if (link_cat_tmp == Linkage.Category.MangleSymbol) + srcText = begin.start[0 .. prevToken.end - begin.start]; + error(MID.RedundantStorageClass, srcText); } + else + link_cat |= link_cat_tmp; + s = new ExternStatement(linkage, parse()); break; case T.Static: diff -r 0faf57d99c1c -r 511c14950cac trunk/src/dil/Statements.d --- a/trunk/src/dil/Statements.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/dil/Statements.d Tue Aug 28 11:41:00 2007 +0000 @@ -549,6 +549,7 @@ this(TOK tok, Statement statement) { mixin(set_kind); + assert(statement !is null); this.children = [statement]; this.tok = tok; this.statement = statement; @@ -562,6 +563,8 @@ { super(TOK.Extern, statement); mixin(set_kind); + if (linkage) + this.children ~= linkage; this.linkage = linkage; } } diff -r 0faf57d99c1c -r 511c14950cac trunk/src/dil/SyntaxTree.d --- a/trunk/src/dil/SyntaxTree.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/dil/SyntaxTree.d Tue Aug 28 11:41:00 2007 +0000 @@ -208,6 +208,7 @@ TemplateTupleParameter, TemplateParameters, TemplateArguments, + Linkage, } /// This string is mixed into the constructor of a class that inherits from Node. diff -r 0faf57d99c1c -r 511c14950cac trunk/src/dil/Token.d --- a/trunk/src/dil/Token.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/dil/Token.d Tue Aug 28 11:41:00 2007 +0000 @@ -36,7 +36,7 @@ VENDOR, VERSION, - // Numbers + // Number literals Int32, Int64, Uint32, Uint64, // Floating point number scanner relies on this order. (FloatXY + 3 == ImaginaryXY) Float32, Float64, Float80, @@ -107,7 +107,8 @@ Ushort,Version,Void,Volatile,Wchar,While,With, HEAD, // start of linked list - EOF + EOF, + MAX } alias TOK.Abstract KeywordsBegin; @@ -153,6 +154,38 @@ return start[0 .. end - start]; } + /// Find next non-whitespace token. Returns 'this' token if the next token is TOK.EOF or null. + Token* nextNWS() + out(token) + { + assert(token !is null); + } + body + { + auto token = next; + while (token !is null && token.isWhitespace) + token = token.next; + if (token is null || token.type == TOK.EOF) + return this; + return token; + } + + /// Find previous non-whitespace token. Returns 'this' token if the previous token is TOK.HEAD or null. + Token* prevNWS() + out(token) + { + assert(token !is null); + } + body + { + auto token = prev; + while (token !is null && token.isWhitespace) + token = token.prev; + if (token is null || token.type == TOK.HEAD) + return this; + return token; + } + static string toString(TOK tok) { return tokToString[tok]; @@ -193,18 +226,26 @@ } } -string[] tokToString = [ +const string[] tokToString = [ "Invalid", "Comment", "#! /shebang/", "#line", + `"filespec"`, "Identifier", "String", - "Special", "CharLiteral", "WCharLiteral", "DCharLiteral", + "__FILE__", + "__LINE__", + "__DATE__", + "__TIME__", + "__TIMESTAMP__", + "__VENDOR__", + "__VERSION__", + "Int32", "Int64", "Uint32", "Uint64", "Float32", "Float64", "Float80", "Imaginary32", "Imaginary64", "Imaginary80", @@ -262,9 +303,11 @@ "mixin","module","new","null","out","override","package", "pragma","private","protected","public","real","ref","return", "scope","short","static","struct","super","switch","synchronized", - "template","this","throw","true","try","typedef","typeid", + "template","this","throw","__traits","true","try","typedef","typeid", "typeof","ubyte","ucent","uint","ulong","union","unittest", "ushort","version","void","volatile","wchar","while","with", + "HEAD", "EOF" ]; +static assert(tokToString.length == TOK.MAX); \ No newline at end of file diff -r 0faf57d99c1c -r 511c14950cac trunk/src/dil/Types.d --- a/trunk/src/dil/Types.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/dil/Types.d Tue Aug 28 11:41:00 2007 +0000 @@ -7,15 +7,46 @@ import dil.Token; import dil.Expressions; -enum Linkage +class Linkage : Node { - Extern, - C, - Cpp, - D, - Windows, - Pascal, - System + enum Type + { + Extern, + C, + Cpp, + D, + Windows, + Pascal, + System + } + + /++ + This enum is used by the parser to find redundant + or conflicting extern attribute declarations. + +/ + enum Category + { + Unset, + ExternSymbol = 1<<1, /// Extern + MangleSymbol = 1<<2 /// C, Cpp, D, Windows, Pascal, System + } + + Linkage.Type type; + + this(typeof(type) type) + { + super(NodeCategory.Other); + mixin(set_kind); + this.type = type; + } + + static Category getCategory(Linkage linkage) + { + if (linkage is null) + return Category.ExternSymbol; + else + return Category.MangleSymbol; + } } enum StorageClass diff -r 0faf57d99c1c -r 511c14950cac trunk/src/dil_xml.css --- a/trunk/src/dil_xml.css Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/dil_xml.css Tue Aug 28 11:41:00 2007 +0000 @@ -46,7 +46,10 @@ op[t=le] { content: "≤"; } /*<=*/ op[t=ge] { content: "≥"; } /*>=*/ op[t=lg] { content: "≶"; } /*<>*/ - +o[t=Linkage] i, o[t=Linkage] op +{ + color: red; +} /* d = Declaration s = Statement diff -r 0faf57d99c1c -r 511c14950cac trunk/src/lang_de.d --- a/trunk/src/lang_de.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/lang_de.d Tue Aug 28 11:41:00 2007 +0000 @@ -44,7 +44,7 @@ "Überlauf in Binärzahl.", "Überlauf in Oktalzahl.", "Überlauf in Fließkommazahl.", - "die Ziffern 8 und 9 sind in Oktalzahlen verboten.", + "die Ziffern 8 und 9 sind in Oktalzahlen unzulässig.", "ungültige Hexzahl; mindestens eine Hexziffer erforderlich.", "ungültige Binärzahl; mindestens eine Binärziffer erforderlich.", "der Exponent einer hexadezimalen Fließkommazahl ist erforderlich.", @@ -57,6 +57,8 @@ "Template-Tupel-Parameter dürfen nur am Ende auftreten.", "der 'in'-Vertrag der Funktion wurde bereits geparsed.", "der 'out'-Vertrag der Funktion wurde bereits geparsed.", + "es wurde kein Verknüpfungstyp angegeben.", + "unbekannter Verknüpfungstyp '{1}'; gültig sind C, C++, D, Windows, Pascal und System.", // Help messages: `dil v{1} diff -r 0faf57d99c1c -r 511c14950cac trunk/src/lang_en.d --- a/trunk/src/lang_en.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/lang_en.d Tue Aug 28 11:41:00 2007 +0000 @@ -57,6 +57,8 @@ "template tuple parameters can only be last.", "the functions 'in' contract was already parsed.", "the functions 'out' contract was already parsed.", + "no linkage type was specified.", + "unrecognized linkage type '{1}'; valid types are C, C++, D, Windows, Pascal und System.", // Help messages: `dil v{1} diff -r 0faf57d99c1c -r 511c14950cac trunk/src/lang_tr.d --- a/trunk/src/lang_tr.d Sun Aug 26 15:59:02 2007 +0000 +++ b/trunk/src/lang_tr.d Tue Aug 28 11:41:00 2007 +0000 @@ -57,6 +57,8 @@ "şablon tuple parametre son sırada olmalı.", "fonksiyonun 'in' kontratı daha önceden ayrıştırılmış.", "fonksiyonun 'out' kontratı daha önceden ayrıştırılmış.", + "bağlantı tüp (linkage type) belirtilmedi.", + "bilinmeyen bağlantı tüpü (linkage type) '{1}'; geçerli olanlar C, C++, D, Windows, Pascal ve System.", // Help messages: `dil v{1}