Mercurial > projects > dil
changeset 309:b4d842b0d2c7
- Added new files Settings.d, config.d and lang_en.d
- Removed redundant break statements from Lexer.d.
- Added function Cast() to SyntaxTree.d.
- Relocated compiler version info to Settings.d.
- Removed messages variable from module Messages. Compiler messages are loaded dynamically now.
- Relocated some functions from module Information to module Messages, and added some format functions to it.
- Message tables are located in their own lang_*.d files.
- Added getString() method to class StringLiteralsExpression.
- Module Settings has a static struct GlobalSettings. It loads global settings from config.d and a language file.
author | aziz |
---|---|
date | Wed, 15 Aug 2007 16:07:05 +0000 |
parents | 3b9fc1e72210 |
children | f01cdff9db0c |
files | trunk/src/Expressions.d trunk/src/Information.d trunk/src/Lexer.d trunk/src/Messages.d trunk/src/Settings.d trunk/src/SyntaxTree.d trunk/src/config.d trunk/src/lang_en.d trunk/src/main.d |
diffstat | 9 files changed, 244 insertions(+), 111 deletions(-) [+] |
line wrap: on
line diff
--- a/trunk/src/Expressions.d Tue Aug 14 18:35:02 2007 +0000 +++ b/trunk/src/Expressions.d Wed Aug 15 16:07:05 2007 +0000 @@ -693,6 +693,16 @@ mixin(set_kind); this.strings = strings; } + + string getString() + { + char[] buffer; + foreach (strTok; strings) + { + buffer ~= strTok.str[0..$-1]; + } + return buffer; + } } class ArrayLiteralExpression : Expression
--- a/trunk/src/Information.d Tue Aug 14 18:35:02 2007 +0000 +++ b/trunk/src/Information.d Wed Aug 15 16:07:05 2007 +0000 @@ -4,7 +4,6 @@ +/ module Information; import Messages; -import std.string; import std.stdarg; enum InfoType @@ -31,31 +30,6 @@ string getMsg() { - char[] msg = messages[id]; - - if (arguments.length == 0) - return msg; - - foreach (i, arg; arguments) - msg = replace(msg, format("{%s}", i+1), arg); - - return msg; + return format_args(GetMsg(id), arguments); } } - -char[][] arguments(TypeInfo[] tinfos, void* argptr) -{ - char[][] args; - foreach (ti; tinfos) - { - if (ti == typeid(char[])) - args ~= format(va_arg!(char[])(argptr)); - else if (ti == typeid(int)) - args ~= format(va_arg!(int)(argptr)); - else if (ti == typeid(dchar)) - args ~= format(va_arg!(dchar)(argptr)); - else - assert(0, "argument type not supported yet."); - } - return args; -}
--- a/trunk/src/Lexer.d Tue Aug 14 18:35:02 2007 +0000 +++ b/trunk/src/Lexer.d Wed Aug 15 16:07:05 2007 +0000 @@ -879,13 +879,9 @@ ++p; if (c == 0xFFFF) error(MID.UndefinedHTMLEntity, (begin-1)[0..p-(begin-1)]); - break; } else - { error(MID.UnterminatedHTMLEntity); - break; - } } else error(MID.InvalidBeginHTMLEntity);
--- a/trunk/src/Messages.d Tue Aug 14 18:35:02 2007 +0000 +++ b/trunk/src/Messages.d Wed Aug 15 16:07:05 2007 +0000 @@ -3,10 +3,13 @@ License: GPL3 +/ module Messages; +import Settings; +import std.stdarg; -/// Index into table of error messages. +/// Index into table of compiler messages. enum MID { + // Lexer messages: InvalidUnicodeCharacter, InvalidUTF8Sequence, // '' @@ -51,57 +54,55 @@ HexFloatMissingExpDigits, FloatExponentDigitExpected, - // Parser messages + // Parser messages: ExpectedButFound, RedundantStorageClass, + + // Help messages: + HelpMain, +} + +string GetMsg(MID mid) +{ + assert(mid < GlobalSettings.messages.length); + return GlobalSettings.messages[mid]; +} + +char[] format(MID mid, ...) +{ + auto args = arguments(_arguments, _argptr); + return format_args(GetMsg(mid), args); +} + +char[] format(char[] format_str, ...) +{ + auto args = arguments(_arguments, _argptr); + return format_args(format_str, args); } -string[] messages = [ - "invalid Unicode character.", - "invalid UTF-8 sequence.", - // '' - "unterminated character literal.", - "empty character literal.", - // #line - "expected 'line' after '#'.", - `the filespec must be defined in a double quote string literal (e.g. "filespec".)`, - "positive integer expected after #line", - "newline not allowed inside special token.", - "expected a terminating newline after special token.", - // "" - "unterminated string literal.", - // x"" - "non-hex character '{1}' found in hex string.", - "odd number of hex digits in hex string.", - "unterminated hex string.", - // /* */ /+ +/ - "unterminated block comment (/* */).", - "unterminated nested comment (/+ +/).", - // `` r"" - "unterminated raw string.", - "unterminated back quote string.", - // \x \u \U - "found undefined escape sequence.", - "insufficient number of hex digits in escape sequence.", - // \&[a-zA-Z][a-zA-Z0-9]+; - "undefined HTML entity '{1}'", - "unterminated HTML entity.", - "html entities must begin with a letter.", - // integer overflows - "decimal number overflows sign bit.", - "overflow in decimal number.", - "overflow in hexadecimal number.", - "overflow in binary number.", - "overflow in octal number.", - "overflow in float number.", - "digits 8 and 9 are not allowed in octal numbers.", - "invalid hex number; at least one hex digit expected.", - "invalid binary number; at least one binary digit expected.", - "the exponent of a hexadecimal float number is required.", - "missing decimal digits in hexadecimal float exponent.", - "exponents have to start with a digit.", +char[] format_args(char[] format_str, char[][] args) +{ + char[] result = format_str; + + foreach (i, arg; args) + result = std.string.replace(result, std.string.format("{%s}", i+1), arg); + + return result; +} - // Parser messages - "expected '{1}', but found '{2}'.", - "'{1}' is redundant", -]; +char[][] arguments(TypeInfo[] tinfos, void* argptr) +{ + char[][] args; + foreach (ti; tinfos) + { + if (ti == typeid(char[])) + args ~= va_arg!(char[])(argptr); + else if (ti == typeid(int)) + args ~= std.string.format(va_arg!(int)(argptr)); + else if (ti == typeid(dchar)) + args ~= std.string.format(va_arg!(dchar)(argptr)); + else + assert(0, "argument type not supported yet."); + } + return args; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/Settings.d Wed Aug 15 16:07:05 2007 +0000 @@ -0,0 +1,101 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ +module Settings; +import Parser, SyntaxTree, Declarations, Expressions; +import std.metastrings; + +version(D2) +{ + const VERSION_MAJOR = 2; + const VERSION_MINOR = 0; +} +else +{ + const VERSION_MAJOR = 1; + const VERSION_MINOR = 0; +} +const string VERSION = Format!("%s.%s", VERSION_MAJOR, VERSION_MINOR); + +const COMPILED_WITH = __VENDOR__; +const COMPILED_VERSION = Format!("%s.%s", __VERSION__/1000, __VERSION__%1000); +const COMPILED_DATE = __TIMESTAMP__; + +const usageHighlight = "highlight (hl) file.d"; + +struct GlobalSettings +{ +static: + string language; /// Language of messages catalogue to load. + string[] messages; /// Table of localized compiler messages. + void load() + { + auto fileName = "config.d"[]; + auto sourceText = cast(char[]) std.file.read(fileName); + auto parser = new Parser(sourceText, fileName); + parser.start(); + auto root = parser.parseModule(); + + if (parser.errors.length || parser.lx.errors.length) + { + throw new Exception("There are errors in " ~ fileName ~ "."); + } + + foreach (decl; root.children) + { + auto v = Cast!(VariableDeclaration)(decl); + if (v && v.idents[0].srcText == "language") + { + auto e = v.values[0]; + if (!e) + throw new Exception("language variable has no value set."); + auto val = Cast!(StringLiteralsExpression)(e); + if (val) + { + GlobalSettings.language = val.getString(); + break; + } + } + } + + // Load messages + if (GlobalSettings.language.length) + { + fileName = "lang_" ~ GlobalSettings.language ~ ".d"; + sourceText = cast(char[]) std.file.read(fileName); + parser = new Parser(sourceText, fileName); + parser.start(); + root = parser.parseModule(); + + if (parser.errors.length || parser.lx.errors.length) + { + throw new Exception("There are errors in "~fileName~"."); + } + + char[][] messages; + foreach (decl; root.children) + { + auto v = Cast!(VariableDeclaration)(decl); + if (v && v.idents[0].srcText == "messages") + { + auto e = v.values[0]; + if (!e) + throw new Exception("messages variable in "~fileName~" has no value set."); + if (auto array = Cast!(ArrayInitializer)(e)) + { + foreach (value; array.values) + { + if (auto str = Cast!(StringLiteralsExpression)(value)) + messages ~= str.getString(); + } + } + else + throw new Exception("messages variable is set to "~e.classinfo.name~" instead of an ArrayInitializer."); + } + } + GlobalSettings.messages = messages; + } + } + +}
--- a/trunk/src/SyntaxTree.d Tue Aug 14 18:35:02 2007 +0000 +++ b/trunk/src/SyntaxTree.d Wed Aug 15 16:07:05 2007 +0000 @@ -209,6 +209,14 @@ /// 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 Cast(Class)(Node n) +{ + assert(n !is null); + if (n.kind == mixin("NodeKind." ~ typeof(Class).stringof)) + return cast(Class)cast(void*)n; + return null; +} + class Node { NodeCategory category;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/config.d Wed Aug 15 16:07:05 2007 +0000 @@ -0,0 +1,1 @@ +option language = "en";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/lang_en.d Wed Aug 15 16:07:05 2007 +0000 @@ -0,0 +1,65 @@ +/++ + Author: Aziz Köksal + License: GPL3 ++/ + +string[] messages = [ + "invalid Unicode character.", + "invalid UTF-8 sequence.", + // '' + "unterminated character literal.", + "empty character literal.", + // #line + "expected 'line' after '#'.", + `the filespec must be defined in a double quote string literal (e.g. "filespec".)`, + "integer expected after #line", + "newline not allowed inside special token.", + "expected a terminating newline after special token.", + // "" + "unterminated string literal.", + // x"" + "non-hex character '{1}' found in hex string.", + "odd number of hex digits in hex string.", + "unterminated hex string.", + // /* */ /+ +/ + "unterminated block comment (/* */).", + "unterminated nested comment (/+ +/).", + // `` r"" + "unterminated raw string.", + "unterminated back quote string.", + // \x \u \U + "found undefined escape sequence.", + "insufficient number of hex digits in escape sequence.", + // \&[a-zA-Z][a-zA-Z0-9]+; + "undefined HTML entity '{1}'", + "unterminated HTML entity.", + "html entities must begin with a letter.", + // integer overflows + "decimal number overflows sign bit.", + "overflow in decimal number.", + "overflow in hexadecimal number.", + "overflow in binary number.", + "overflow in octal number.", + "overflow in float number.", + "digits 8 and 9 are not allowed in octal numbers.", + "invalid hex number; at least one hex digit expected.", + "invalid binary number; at least one binary digit expected.", + "the exponent of a hexadecimal float number is required.", + "missing decimal digits in hexadecimal float exponent.", + "exponents have to start with a digit.", + + // Parser messages + "expected '{1}', but found '{2}'.", + "'{1}' is redundant.", + + `dil v{1} +Copyright (c) 2007 by Aziz Köksal. All rights reserved. Licensed under GPL3. + +Subcommands: + {2} + +Type 'dil help <subcommand>' for more help on a particular subcommand. + +Compiled with {3} v{4} on {5}. +` +]; \ No newline at end of file
--- a/trunk/src/main.d Tue Aug 14 18:35:02 2007 +0000 +++ b/trunk/src/main.d Wed Aug 15 16:07:05 2007 +0000 @@ -9,45 +9,22 @@ import Messages; import std.stdio; import std.file; -import std.metastrings; - -import Declarations, SyntaxTree; - -version(D2) -{ - const VERSION_MAJOR = 2; - const VERSION_MINOR = 0; -} -else -{ - const VERSION_MAJOR = 1; - const VERSION_MINOR = 0; -} -const string VERSION = Format!("%s.%s", VERSION_MAJOR, VERSION_MINOR); - -const char[] usageHighlight = "highlight (hl) file.d"; -const string helpMain = `dil v`~VERSION~` -Copyright (c) 2007 by Aziz Köksal - -Subcommands: - `~usageHighlight~` - -Type 'dil help <subcommand>' for more help on a particular subcommand. - -Compiled with `~__VENDOR__~` `~Format!("v%s.%s", __VERSION__/1000, __VERSION__%1000)~` on `~__TIMESTAMP__~`. -`; +import Settings; +import Declarations, Expressions, SyntaxTree; void main(char[][] args) { + GlobalSettings.load(); + if (args.length <= 1) - return writefln(helpMain); + return writefln(format(MID.HelpMain, VERSION, usageHighlight, COMPILED_WITH, COMPILED_VERSION, COMPILED_DATE)); string command = args[1]; switch (command) { case "hl", "highlight": if (args.length == 3) - highlightTokens(args[2]); + tokensToXML(args[2]); break; default: } @@ -90,7 +67,7 @@ return result; } -void highlightTokens(string fileName) +void tokensToXML(string fileName) { auto sourceText = cast(char[]) std.file.read(fileName); auto lx = new Lexer(sourceText, fileName);