diff --git a/build.sh b/build.sh index f0f544f..bbf0ff4 100755 --- a/build.sh +++ b/build.sh @@ -1,2 +1,2 @@ -dmd *.d std/d/*.d -release -noboundscheck -O -w -wi -m64 -property -ofdscanner -L-lsqlite3 #-inline -#dmd *.d std/d/*.d -g -m64 -w -wi -property -ofdscanner -L-lsqlite3 #-unittest +#dmd *.d std/d/*.d -release -noboundscheck -O -w -wi -m64 -property -ofdscanner -L-lsqlite3 #-inline +dmd *.d std/d/*.d -g -m64 -w -wi -property -ofdscanner -L-lsqlite3 #-unittest diff --git a/circularbuffer.d b/circularbuffer.d index 9c45128..11e1053 100644 --- a/circularbuffer.d +++ b/circularbuffer.d @@ -14,28 +14,28 @@ class CircularBuffer(T) : InputRange!(T) { public: - this (size_t size, InputRange!(T) range) - { - this.range = range; - this.margin = size; - data = new T[(margin * 2) + 1]; - if (range.empty()) - { - _empty = true; - return; - } - for (size_t i = 0; i <= margin && !this.range.empty(); ++i) - { - data[i] = this.range.front(); - this.range.popFront(); + this (size_t size, InputRange!(T) range) + { + this.range = range; + this.margin = size; + data = new T[(margin * 2) + 1]; + if (range.empty()) + { + _empty = true; + return; + } + for (size_t i = 0; i <= margin && !this.range.empty(); ++i) + { + data[i] = this.range.front(); + this.range.popFront(); end++; - } - } + } + } - override T front() const @property - { - return data[index]; - } + override T front() @property + { + return data[index]; + } T peek(int offset = 1) in @@ -52,32 +52,32 @@ public: return abs(offset) <= margin && sourceIndex + offset >= 0; } - override void popFront() + override void popFront() in { assert (!_empty); } body - { + { index = (index + 1) % data.length; ++sourceIndex; - if (range.empty()) + if (range.empty()) { if (index == end) _empty = true; } - else - { + else + { data[end] = range.front(); end = (end + 1) % data.length; range.popFront(); - } - } + } + } - bool empty() const @property - { - return _empty; - } + bool empty() const @property + { + return _empty; + } override T moveFront() { @@ -94,6 +94,7 @@ public: result = dg(front); if (result) break; + popFront(); } return result; } @@ -107,18 +108,19 @@ public: result = dg(i, front); if (result) break; + popFront(); } return result; } private: - InputRange!(T) range; - immutable size_t margin; - T[] data; + InputRange!(T) range; + immutable size_t margin; + T[] data; size_t sourceIndex; size_t end; - size_t index; - bool _empty; + size_t index; + bool _empty; } unittest @@ -131,10 +133,10 @@ unittest unittest { - int[] arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - auto buf = CircularBuffer!(int, int[])(2, arr); - assert (buf.data.length == 5); - auto iterated = array(buf); + int[] arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + auto buf = CircularBuffer!(int, int[])(2, arr); + assert (buf.data.length == 5); + auto iterated = array(buf); assert (iterated == arr); } diff --git a/highlighter.d b/highlighter.d index 324712d..6bd4482 100644 --- a/highlighter.d +++ b/highlighter.d @@ -10,8 +10,6 @@ import std.stdio; import std.array; import std.d.lexer; -import langutils; - void writeSpan(string cssClass, string value) { stdout.write(``, value.replace("&", "&").replace("<", "<"), ``); diff --git a/langutils.d b/langutils.d index cf0c995..00bd391 100644 --- a/langutils.d +++ b/langutils.d @@ -6,6 +6,7 @@ module langutils; import std.array; +import std.algorithm; import std.d.lexer; @@ -43,7 +44,7 @@ string combineTokens(ref const Token[] tokens) return app.data; } -pure string getTypeFromToken(const Token t) +pure nothrow string getTypeFromToken(const Token t) { switch (t.type) { @@ -73,8 +74,14 @@ pure string getTypeFromToken(const Token t) } } -pure bool isIdentifierOrType(inout Token t) +pure bool isIdentifierOrType(const Token t) { return t.type == TokenType.Identifier || (t.type > TokenType.TYPES_BEGIN && TokenType.TYPES_END); } + +pure bool isDocComment(ref const Token t) +{ + return t.value.startsWith("///") || t.value.startsWith("/**") + || t.value.startsWith("/++"); +} diff --git a/main.d b/main.d index 848cd0a..0e77918 100644 --- a/main.d +++ b/main.d @@ -15,6 +15,7 @@ import std.parallelism; import std.path; import std.regex; import std.stdio; +import std.range; import std.d.lexer; import autocomplete; @@ -28,7 +29,7 @@ import circularbuffer; immutable size_t CIRC_BUFF_SIZE = 4; -pure bool isLineOfCode(TokenType t) +pure nothrow bool isLineOfCode(TokenType t) { switch(t) { @@ -138,36 +139,21 @@ int main(string[] args) { if (args.length == 1) { - auto f = appender!string(); - char[] buf; - while (stdin.readln(buf)) - f.put(buf); - writeln(f.data.byToken().count!(a => isLineOfCode(a.type))()); + writeln(stdin.byLine(KeepTerminator.yes).join().byToken().count!(a => isLineOfCode(a.type))()); } else { - writeln(args[1..$].map!(a => a.readText().byToken())().joiner() - .count!(a => isLineOfCode(a.type))()); + writeln(args[1..$].map!(a => File(a).byLine(KeepTerminator.yes).join().byToken())() + .joiner().count!(a => isLineOfCode(a.type))()); } return 0; } if (highlight) { - if (args.length == 1) - { - auto f = appender!string(); - char[] buf; - while (stdin.readln(buf)) - f.put(buf); - highlighter.highlight(f.data.byToken(IterationStyle.Everything, - StringStyle.Source)); - } - else - { - highlighter.highlight(args[1].readText().byToken( - IterationStyle.Everything, StringStyle.Source)); - } + File f = args.length == 1 ? stdin : File(args[1]); + highlighter.highlight(f.byLine(KeepTerminator.yes).join().byToken( + IterationStyle.Everything, StringStyle.Source)); return 0; } @@ -213,20 +199,9 @@ int main(string[] args) if (json) { CircularBuffer!(Token) tokens; - if (args.length == 1) - { - // Read from stdin - auto f = appender!string(); - char[] buf; - while (stdin.readln(buf)) - f.put(buf); - tokens = new CircularBuffer!(Token)(CIRC_BUFF_SIZE, byToken!string(f.data)); - } - else - { - // read given file - tokens = new CircularBuffer!(Token)(CIRC_BUFF_SIZE, byToken!string(readText(args[1]))); - } + File f = args.length == 1 ? stdin : File(args[1]); + tokens = new CircularBuffer!(Token)(CIRC_BUFF_SIZE, + f.byLine(KeepTerminator.yes).join().byToken!(char[])()); auto mod = parseModule(tokens); mod.writeJSONTo(stdout); return 0; diff --git a/parser.d b/parser.d index 70498a8..55f94ba 100644 --- a/parser.d +++ b/parser.d @@ -26,6 +26,7 @@ public: this(InputRange!Token tokens, TokenType open, TokenType close) { super(0, tokens); + this.range = tokens; this.open = open; this.close = close; } @@ -35,7 +36,7 @@ public: return _empty; } - override Token front() const @property + override Token front() @property { return range.front; } @@ -47,14 +48,20 @@ public: ++depth; else if (range.front == close) --depth; - _empty = depth == 0; + _empty = depth == 0 || range.empty; } + invariant() + { + assert (range); + assert (depth >= 0); + } + private: int depth; TokenType open; TokenType close; - TokenBuffer range; + InputRange!(Token) range; bool _empty; } diff --git a/std/d/lexer.d b/std/d/lexer.d index 840b76e..1ac8019 100644 --- a/std/d/lexer.d +++ b/std/d/lexer.d @@ -1,71 +1,71 @@ // Written in the D programming language /** - * This module contains a range-based lexer for the D programming language. - * - * Examples: - * - * Generate HTML markup of D code. - * --- - * import std.stdio; - * import std.array; - * import std.file; - * import std.d.lexer; - * - * void writeSpan(string cssClass, string value) - * { - * stdout.write(``, value.replace("&", "&").replace("<", "<"), ``); - * } - * - * void highlight(R)(R tokens) - * { - * stdout.writeln(q"[ - * - *
- * - * - * - *]");
- *
- * foreach (Token t; tokens)
- * {
- * if (t.type > TokenType.TYPES_BEGIN && t.type < TokenType.TYPES_END)
- * writeSpan("type", t.value);
- * else if (t.type > TokenType.KEYWORDS_BEGIN && t.type < TokenType.KEYWORDS_END)
- * writeSpan("kwrd", t.value);
- * else if (t.type == TokenType.Comment)
- * writeSpan("com", t.value);
- * else if (t.type > TokenType.STRINGS_BEGIN && t.type < TokenType.STRINGS_END)
- * writeSpan("str", t.value);
- * else if (t.type > TokenType.NUMBERS_BEGIN && t.type < TokenType.NUMBERS_END)
- * writeSpan("num", t.value);
- * else if (t.type > TokenType.OPERATORS_BEGIN && t.type < TokenType.OPERATORS_END)
- * writeSpan("op", t.value);
- * else
- * stdout.write(t.value.replace("<", "<"));
- * }
- * stdout.writeln("\n");
- * }
- *
- * void main(string[] args)
- * {
- * args[1].readText().byToken(IterationStyle.Everything, StringStyle.Source).highlight();
- * }
- * ---
- *
- * Copyright: Brian Schott 2013
- * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt Boost, License 1.0)
- * Authors: Brian Schott
- * Source: $(PHOBOSSRC std/d/_lexer.d)
- */
+* This module contains a range-based lexer for the D programming language.
+*
+* Examples:
+*
+* Generate HTML markup of D code.
+* ---
+* import std.stdio;
+* import std.array;
+* import std.file;
+* import std.d.lexer;
+*
+* void writeSpan(string cssClass, string value)
+* {
+* stdout.write(``, value.replace("&", "&").replace("<", "<"), ``);
+* }
+*
+* void highlight(R)(R tokens)
+* {
+* stdout.writeln(q"[
+*
+*
+*
+*
+*
+* ]");
+*
+* foreach (Token t; tokens)
+* {
+* if (t.type > TokenType.TYPES_BEGIN && t.type < TokenType.TYPES_END)
+* writeSpan("type", t.value);
+* else if (t.type > TokenType.KEYWORDS_BEGIN && t.type < TokenType.KEYWORDS_END)
+* writeSpan("kwrd", t.value);
+* else if (t.type == TokenType.Comment)
+* writeSpan("com", t.value);
+* else if (t.type > TokenType.STRINGS_BEGIN && t.type < TokenType.STRINGS_END)
+* writeSpan("str", t.value);
+* else if (t.type > TokenType.NUMBERS_BEGIN && t.type < TokenType.NUMBERS_END)
+* writeSpan("num", t.value);
+* else if (t.type > TokenType.OPERATORS_BEGIN && t.type < TokenType.OPERATORS_END)
+* writeSpan("op", t.value);
+* else
+* stdout.write(t.value.replace("<", "<"));
+* }
+* stdout.writeln("\n");
+* }
+*
+* void main(string[] args)
+* {
+* args[1].readText().byToken(IterationStyle.Everything, StringStyle.Source).highlight();
+* }
+* ---
+*
+* Copyright: Brian Schott 2013
+* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt Boost, License 1.0)
+* Authors: Brian Schott
+* Source: $(PHOBOSSRC std/d/_lexer.d)
+*/
module std.d.lexer;
@@ -81,8 +81,8 @@ import std.d.entities;
public:
/**
- * Represents a D token
- */
+* Represents a D token
+*/
struct Token
{
/// The token type.
@@ -98,28 +98,28 @@ struct Token
uint startIndex;
/**
- * Check to see if the token is of the same type and has the same string
- * representation as the given token.
- */
+ * Check to see if the token is of the same type and has the same string
+ * representation as the given token.
+ */
bool opEquals(ref const(Token) other) const
{
return other.type == type && other.value == value;
}
/**
- * Checks to see if the token's string representation is equal to the given
- * string.
- */
+ * Checks to see if the token's string representation is equal to the given
+ * string.
+ */
bool opEquals(string value) const { return this.value == value; }
/**
- * Checks to see if the token is of the given type.
- */
+ * Checks to see if the token is of the given type.
+ */
bool opEquals(TokenType type) const { return type == type; }
/**
- * Comparison operator orders tokens by start index.
- */
+ * Comparison operator orders tokens by start index.
+ */
int opCmp(size_t i) const
{
if (startIndex < i) return -1;
@@ -129,8 +129,8 @@ struct Token
}
/**
- * Configure the behavior of the byToken() function
- */
+* Configure the behavior of the byToken() function
+*/
enum IterationStyle
{
/// Only include code, not whitespace or comments
@@ -139,58 +139,59 @@ enum IterationStyle
IncludeComments = 0b0001,
/// Includes whitespace
IncludeWhitespace = 0b0010,
- /// Include $(LINK2 http://dlang.org/lex.html#specialtokens, special tokens)
- IncludeSpecialTokens = 0b0100,
+ /// Include $(LINK2 http://dlang.org/lex.html#specialtokens, special tokens)
+ IncludeSpecialTokens = 0b0100,
/// Include everything
Everything = IncludeComments | IncludeWhitespace
}
/**
- * Configuration of the string lexing style
- */
+* Configuration of the string lexing style
+*/
enum StringStyle : uint
{
/**
- * Escape sequences will be replaced with their equivalent characters,
- * enclosing quote characters will not be included. Useful for creating a
- * compiler or interpreter.
- */
+ * Escape sequences will be replaced with their equivalent characters,
+ * enclosing quote characters will not be included. Useful for creating a
+ * compiler or interpreter.
+ */
Default = 0b0000,
/**
- * Escape sequences will not be processed. An escaped quote character will
- * not terminate string lexing, but it will not be replaced with the quote
- * character in the token.
- */
+ * Escape sequences will not be processed. An escaped quote character will
+ * not terminate string lexing, but it will not be replaced with the quote
+ * character in the token.
+ */
NotEscaped = 0b0001,
/**
- * Strings will include their opening and closing quote characters as well
- * as any prefixes or suffixes $(LPAREN)e.g.: $(D_STRING "abcde"w) will
- * include the $(D_STRING 'w') character as well as the opening and closing
- * quotes$(RPAREN)
- */
+ * Strings will include their opening and closing quote characters as well
+ * as any prefixes or suffixes $(LPAREN)e.g.: $(D_STRING "abcde"w) will
+ * include the $(D_STRING 'w') character as well as the opening and closing
+ * quotes$(RPAREN)
+ */
IncludeQuotes = 0x0010,
/**
- * Strings will be read exactly as they appeared in the source, including
- * their opening and closing quote characters. Useful for syntax
- * highlighting.
- */
+ * Strings will be read exactly as they appeared in the source, including
+ * their opening and closing quote characters. Useful for syntax
+ * highlighting.
+ */
Source = NotEscaped | IncludeQuotes,
}
/**
- * Iterate over the given range of characters by D tokens.
- * Params:
- * range = the range of characters
- * iterationStyle = See IterationStyle
- * stringStyle = see StringStyle
- * Returns:
- * an input range of tokens
- */
+* Iterate over the given range of characters by D tokens.
+* Params:
+* range = the range of characters
+* iterationStyle = See IterationStyle
+* stringStyle = see StringStyle
+* Returns:
+* an input range of tokens
+*/
TokenRange!(R) byToken(R)(R range, const IterationStyle iterationStyle = IterationStyle.CodeOnly,
- const StringStyle stringStyle = StringStyle.Default) if (isForwardRange!(R) && isSomeChar!(ElementType!(R)))
+ const StringStyle stringStyle = StringStyle.Default)
+ if (isForwardRange!(R) && (isSomeChar!(ElementType!(R)) || is (ElementType!(R) == ubyte)))
{
auto r = new TokenRange!(R)(range);
r.stringStyle = stringStyle;
@@ -201,9 +202,9 @@ TokenRange!(R) byToken(R)(R range, const IterationStyle iterationStyle = Iterati
}
/**
- * Range of tokens. Avoid creating instances of this manually. Use
- * $(DDOC_PSYMBOL byToken$(LPAREN)$(RPAREN)) instead, as it does some initialization work.
- */
+* Range of tokens. Avoid creating instances of this manually. Use
+* $(DDOC_PSYMBOL byToken$(LPAREN)$(RPAREN)) instead, as it does some initialization work.
+*/
class TokenRange(R) : InputRange!(Token)
{
this(ref R range)
@@ -212,16 +213,16 @@ class TokenRange(R) : InputRange!(Token)
}
/**
- * Returns: true if the range is empty
- */
+ * Returns: true if the range is empty
+ */
override bool empty() const @property
{
return _empty;
}
/**
- * Returns: the current token
- */
+ * Returns: the current token
+ */
override Token front() const @property
{
enforce(!_empty, "Cannot call front() on empty token range");
@@ -229,8 +230,8 @@ class TokenRange(R) : InputRange!(Token)
}
/**
- * Returns the current token and then removes it from the range
- */
+ * Returns the current token and then removes it from the range
+ */
override Token moveFront()
{
auto r = front();
@@ -265,38 +266,38 @@ class TokenRange(R) : InputRange!(Token)
return result;
}
- override void popFront()
- {
- // Filter out tokens we don't care about
- loop: do
- {
- advance();
- switch (current.type)
- {
- case TokenType.Comment:
- if (iterStyle & IterationStyle.IncludeComments)
- break loop;
- break;
- case TokenType.Whitespace:
- if (iterStyle & IterationStyle.IncludeWhitespace)
- break loop;
- break;
- case TokenType.SpecialTokenSequence:
- if (iterStyle & IterationStyle.IncludeSpecialTokens)
- break loop;
- break;
- default:
- break loop;
- }
- }
- while (!empty());
- }
+ override void popFront()
+ {
+ // Filter out tokens we don't care about
+ loop: do
+ {
+ advance();
+ switch (current.type)
+ {
+ case TokenType.Comment:
+ if (iterStyle & IterationStyle.IncludeComments)
+ break loop;
+ break;
+ case TokenType.Whitespace:
+ if (iterStyle & IterationStyle.IncludeWhitespace)
+ break loop;
+ break;
+ case TokenType.SpecialTokenSequence:
+ if (iterStyle & IterationStyle.IncludeSpecialTokens)
+ break loop;
+ break;
+ default:
+ break loop;
+ }
+ }
+ while (!empty());
+ }
private:
/*
- * Advances the range to the next token
- */
+ * Advances the range to the next token
+ */
void advance()
{
if (range.empty)
@@ -311,8 +312,8 @@ private:
if (std.uni.isWhite(range.front))
{
- current = lexWhitespace(range, index, lineNumber);
- return;
+ current = lexWhitespace(range, index, lineNumber);
+ return;
}
outer: switch (range.front)
{
@@ -456,22 +457,22 @@ private:
}
else
goto default;
- case '#':
- string special = lexSpecialTokenSequence(range, index, lineNumber);
- if (special)
- {
- current.type = TokenType.SpecialTokenSequence;
- current.value = special;
- }
- else
- {
- current.type = TokenType.Hash;
- current.value = "#";
- range.popFront();
+ case '#':
+ string special = lexSpecialTokenSequence(range, index, lineNumber);
+ if (special)
+ {
+ current.type = TokenType.SpecialTokenSequence;
+ current.value = special;
+ }
+ else
+ {
+ current.type = TokenType.Hash;
+ current.value = "#";
+ range.popFront();
++index;
break;
- }
- break;
+ }
+ break;
default:
auto app = appender!(ElementType!(R)[])();
while(!range.isEoF() && !isSeparating(range.front))
@@ -497,38 +498,38 @@ private:
unittest
{
- import std.stdio;
- auto a = "/**comment*/\n#lin #line 10 \"test.d\"\nint a;//test\n";
- foreach (t; byToken(a))
- writeln(t);
+ import std.stdio;
+ auto a = "/**comment*/\n#lin #line 10 \"test.d\"\nint a;//test\n";
+ foreach (t; byToken(a))
+ writeln(t);
}
/**
- * Listing of all the tokens in the D language.
- *
- * Token types are arranged so that it is easy to group tokens while iterating
- * over them. For example:
- * ---
- * assert(TokenType.Increment < TokenType.OPERATORS_END);
- * assert(TokenType.Increment > TokenType.OPERATORS_BEGIN);
- * ---
- * The non-token values are documented below:
- *
- * $(BOOKTABLE ,
- * $(TR $(TH Begin) $(TH End) $(TH Content) $(TH Examples))
- * $(TR $(TD OPERATORS_BEGIN) $(TD OPERATORS_END) $(TD operatiors) $(TD +, -, <<=))
- * $(TR $(TD TYPES_BEGIN) $(TD TYPES_END) $(TD types) $(TD bool, char, double))
- * $(TR $(TD KEYWORDS_BEGIN) $(TD KEYWORDS) $(TD keywords) $(TD class, if, assert))
- * $(TR $(TD ATTRIBUTES_BEGIN) $(TD ATTRIBUTES_END) $(TD attributes) $(TD override synchronized, __gshared))
- * $(TR $(TD ATTRIBUTES_BEGIN) $(TD ATTRIBUTES_END) $(TD protection) $(TD public, protected))
- * $(TR $(TD CONSTANTS_BEGIN) $(TD CONSTANTS_END) $(TD compile-time constants) $(TD __FILE__, __TIME__))
- * $(TR $(TD LITERALS_BEGIN) $(TD LITERALS_END) $(TD string and numeric literals) $(TD "str", 123))
- * $(TR $(TD NUMBERS_BEGIN) $(TD NUMBERS_END) $(TD numeric literals) $(TD 0x123p+9, 0b0110))
- * $(TR $(TD STRINGS_BEGIN) $(TD STRINGS_END) $(TD string literals) $(TD `123`c, q{tokens;}, "abcde"))
- * $(TR $(TD MISC_BEGIN) $(TD MISC_END) $(TD anything else) $(TD whitespace, comments, identifiers))
- * )
- * Note that several of the above ranges overlap.
- */
+* Listing of all the tokens in the D language.
+*
+* Token types are arranged so that it is easy to group tokens while iterating
+* over them. For example:
+* ---
+* assert(TokenType.Increment < TokenType.OPERATORS_END);
+* assert(TokenType.Increment > TokenType.OPERATORS_BEGIN);
+* ---
+* The non-token values are documented below:
+*
+* $(BOOKTABLE ,
+* $(TR $(TH Begin) $(TH End) $(TH Content) $(TH Examples))
+* $(TR $(TD OPERATORS_BEGIN) $(TD OPERATORS_END) $(TD operatiors) $(TD +, -, <<=))
+* $(TR $(TD TYPES_BEGIN) $(TD TYPES_END) $(TD types) $(TD bool, char, double))
+* $(TR $(TD KEYWORDS_BEGIN) $(TD KEYWORDS) $(TD keywords) $(TD class, if, assert))
+* $(TR $(TD ATTRIBUTES_BEGIN) $(TD ATTRIBUTES_END) $(TD attributes) $(TD override synchronized, __gshared))
+* $(TR $(TD ATTRIBUTES_BEGIN) $(TD ATTRIBUTES_END) $(TD protection) $(TD public, protected))
+* $(TR $(TD CONSTANTS_BEGIN) $(TD CONSTANTS_END) $(TD compile-time constants) $(TD __FILE__, __TIME__))
+* $(TR $(TD LITERALS_BEGIN) $(TD LITERALS_END) $(TD string and numeric literals) $(TD "str", 123))
+* $(TR $(TD NUMBERS_BEGIN) $(TD NUMBERS_END) $(TD numeric literals) $(TD 0x123p+9, 0b0110))
+* $(TR $(TD STRINGS_BEGIN) $(TD STRINGS_END) $(TD string literals) $(TD `123`c, q{tokens;}, "abcde"))
+* $(TR $(TD MISC_BEGIN) $(TD MISC_END) $(TD anything else) $(TD whitespace, comments, identifiers))
+* )
+* Note that several of the above ranges overlap.
+*/
enum TokenType: uint
{
// Operators
@@ -599,38 +600,38 @@ enum TokenType: uint
OPERATORS_END, ///
- // Keywords
+ // Keywords
KEYWORDS_BEGIN, ///
- TYPES_BEGIN, ///
- Bool, /// $(D_KEYWORD bool)
- Byte, /// $(D_KEYWORD byte)
- Cdouble, /// $(D_KEYWORD cdouble)
- Cent, /// $(D_KEYWORD cent)
- Cfloat, /// $(D_KEYWORD cfloat)
- Char, /// $(D_KEYWORD char)
- Creal, /// $(D_KEYWORD creal)
- Dchar, /// $(D_KEYWORD dchar)
- Double, /// $(D_KEYWORD double)
- DString, /// $(D_KEYWORD dstring)
- Float, /// $(D_KEYWORD float)
- Function, /// $(D_KEYWORD function)
- Idouble, /// $(D_KEYWORD idouble)
- Ifloat, /// $(D_KEYWORD ifloat)
- Int, /// $(D_KEYWORD int)
- Ireal, /// $(D_KEYWORD ireal)
- Long, /// $(D_KEYWORD long)
- Real, /// $(D_KEYWORD real)
- Short, /// $(D_KEYWORD short)
- String, /// $(D_KEYWORD string)
- Ubyte, /// $(D_KEYWORD ubyte)
- Ucent, /// $(D_KEYWORD ucent)
- Uint, /// $(D_KEYWORD uint)
- Ulong, /// $(D_KEYWORD ulong)
- Ushort, /// $(D_KEYWORD ushort)
- Void, /// $(D_KEYWORD void)
- Wchar, /// $(D_KEYWORD wchar)
- WString, /// $(D_KEYWORD wstring)
- TYPES_END, ///
+ TYPES_BEGIN, ///
+ Bool, /// $(D_KEYWORD bool)
+ Byte, /// $(D_KEYWORD byte)
+ Cdouble, /// $(D_KEYWORD cdouble)
+ Cent, /// $(D_KEYWORD cent)
+ Cfloat, /// $(D_KEYWORD cfloat)
+ Char, /// $(D_KEYWORD char)
+ Creal, /// $(D_KEYWORD creal)
+ Dchar, /// $(D_KEYWORD dchar)
+ Double, /// $(D_KEYWORD double)
+ DString, /// $(D_KEYWORD dstring)
+ Float, /// $(D_KEYWORD float)
+ Function, /// $(D_KEYWORD function)
+ Idouble, /// $(D_KEYWORD idouble)
+ Ifloat, /// $(D_KEYWORD ifloat)
+ Int, /// $(D_KEYWORD int)
+ Ireal, /// $(D_KEYWORD ireal)
+ Long, /// $(D_KEYWORD long)
+ Real, /// $(D_KEYWORD real)
+ Short, /// $(D_KEYWORD short)
+ String, /// $(D_KEYWORD string)
+ Ubyte, /// $(D_KEYWORD ubyte)
+ Ucent, /// $(D_KEYWORD ucent)
+ Uint, /// $(D_KEYWORD uint)
+ Ulong, /// $(D_KEYWORD ulong)
+ Ushort, /// $(D_KEYWORD ushort)
+ Void, /// $(D_KEYWORD void)
+ Wchar, /// $(D_KEYWORD wchar)
+ WString, /// $(D_KEYWORD wstring)
+ TYPES_END, ///
ATTRIBUTES_BEGIN, ///
Align, /// $(D_KEYWORD align)
Deprecated, /// $(D_KEYWORD deprecated)
@@ -699,7 +700,7 @@ enum TokenType: uint
Struct, /// $(D_KEYWORD struct)
Super, /// $(D_KEYWORD super)
Switch, /// $(D_KEYWORD switch)
- Template, /// $(D_KEYWORD template)
+ Template, /// $(D_KEYWORD template)
This, /// $(D_KEYWORD this)
Throw, /// $(D_KEYWORD throw)
True, /// $(D_KEYWORD true)
@@ -729,7 +730,7 @@ enum TokenType: uint
Identifier, /// anything else
ScriptLine, // Line at the beginning of source file that starts from #!
Whitespace, /// whitespace
- SpecialTokenSequence, /// #line 10 "file.d"
+ SpecialTokenSequence, /// #line 10 "file.d"
MISC_END, ///
// Literals
@@ -1122,53 +1123,53 @@ Token lexHexString(R, C = ElementType!R)(ref R input, ref uint index, ref uint l
const StringStyle style = StringStyle.Default)
in
{
- assert (input.front == 'x');
+ assert (input.front == 'x');
}
body
{
- Token t;
- t.lineNumber = lineNumber;
- t.startIndex = index;
- t.type = TokenType.StringLiteral;
- auto app = appender!(C[])();
- if (style & StringStyle.IncludeQuotes)
- app.put("x\"");
- input.popFront();
- input.popFront();
- index += 2;
- while (!input.isEoF())
- {
- if (isNewline(input))
- {
- app.put(popNewline(input, index));
- ++lineNumber;
- }
- else if (isHexDigit(input.front))
- {
- app.put(input.front);
- input.popFront();
- ++index;
- }
- else if (std.uni.isWhite(input.front) && (style & StringStyle.NotEscaped))
- {
- app.put(input.front);
- input.popFront();
- ++index;
- }
- else if (input.front == '"')
- {
- if (style & StringStyle.IncludeQuotes)
- app.put('"');
- input.popFront();
- ++index;
- break;
- }
- else
- {
- // This is an error
- }
- }
- if (!input.isEoF())
+ Token t;
+ t.lineNumber = lineNumber;
+ t.startIndex = index;
+ t.type = TokenType.StringLiteral;
+ auto app = appender!(C[])();
+ if (style & StringStyle.IncludeQuotes)
+ app.put("x\"");
+ input.popFront();
+ input.popFront();
+ index += 2;
+ while (!input.isEoF())
+ {
+ if (isNewline(input))
+ {
+ app.put(popNewline(input, index));
+ ++lineNumber;
+ }
+ else if (isHexDigit(input.front))
+ {
+ app.put(input.front);
+ input.popFront();
+ ++index;
+ }
+ else if (std.uni.isWhite(input.front) && (style & StringStyle.NotEscaped))
+ {
+ app.put(input.front);
+ input.popFront();
+ ++index;
+ }
+ else if (input.front == '"')
+ {
+ if (style & StringStyle.IncludeQuotes)
+ app.put('"');
+ input.popFront();
+ ++index;
+ break;
+ }
+ else
+ {
+ // This is an error
+ }
+ }
+ if (!input.isEoF())
{
switch (input.front)
{
@@ -1188,43 +1189,43 @@ body
break;
}
}
- if (style & StringStyle.NotEscaped)
+ if (style & StringStyle.NotEscaped)
t.value = to!string(app.data);
else
- {
- auto a = appender!(char[])();
- foreach (b; std.range.chunks(app.data, 2))
- a.put(to!string(cast(dchar) parse!uint(b, 16)));
- t.value = to!string(a.data);
- }
+ {
+ auto a = appender!(char[])();
+ foreach (b; std.range.chunks(app.data, 2))
+ a.put(to!string(cast(dchar) parse!uint(b, 16)));
+ t.value = to!string(a.data);
+ }
- return t;
+ return t;
}
unittest
{
- uint i;
- uint l;
+ uint i;
+ uint l;
- auto a = `x"204041"`;
- auto ar = lexHexString(a, i, l);
- assert (ar == " @A");
- assert (ar == TokenType.StringLiteral);
+ auto a = `x"204041"`;
+ auto ar = lexHexString(a, i, l);
+ assert (ar == " @A");
+ assert (ar == TokenType.StringLiteral);
- auto b = `x"20"w`;
- auto br = lexHexString(b, i, l);
- assert (br == " ");
- assert (br == TokenType.WStringLiteral);
+ auto b = `x"20"w`;
+ auto br = lexHexString(b, i, l);
+ assert (br == " ");
+ assert (br == TokenType.WStringLiteral);
- auto c = `x"6d"`;
- auto cr = lexHexString(c, i, l, StringStyle.NotEscaped);
- assert (cr == "6d");
+ auto c = `x"6d"`;
+ auto cr = lexHexString(c, i, l, StringStyle.NotEscaped);
+ assert (cr == "6d");
- auto d = `x"5e5f"d`;
- auto dr = lexHexString(d, i, l, StringStyle.NotEscaped | StringStyle.IncludeQuotes);
- assert (dr == `x"5e5f"d`);
- assert (dr == TokenType.DStringLiteral);
+ auto d = `x"5e5f"d`;
+ auto dr = lexHexString(d, i, l, StringStyle.NotEscaped | StringStyle.IncludeQuotes);
+ assert (dr == `x"5e5f"d`);
+ assert (dr == TokenType.DStringLiteral);
}
Token lexString(R)(ref R input, ref uint index, ref uint lineNumber,
@@ -1582,7 +1583,7 @@ body
unittest
{
- import std.stdio;
+ import std.stdio;
uint i;
uint l;
auto a = "q{import std.stdio;} abcd";
@@ -2178,106 +2179,106 @@ unittest
}
string lexSpecialTokenSequence(R)(ref R input, ref uint index,
- ref uint lineNumber)
+ ref uint lineNumber)
in
{
- assert (input.front == '#');
+ assert (input.front == '#');
}
body
{
- auto i = index;
- auto r = input.save;
- auto l = lineNumber;
- r.popFront();
- ++i;
- auto app = appender!(ElementType!(R)[])();
- app.put('#');
+ auto i = index;
+ auto r = input.save;
+ auto l = lineNumber;
+ r.popFront();
+ ++i;
+ auto app = appender!(ElementType!(R)[])();
+ app.put('#');
- auto specialType = appender!(ElementType!(R)[])();
+ auto specialType = appender!(ElementType!(R)[])();
- while (!r.empty && !isSeparating(r.front))
- {
- specialType.put(r.front);
- ++i;
- r.popFront();
- }
+ while (!r.empty && !isSeparating(r.front))
+ {
+ specialType.put(r.front);
+ ++i;
+ r.popFront();
+ }
- if (to!string(specialType.data) != "line")
- return null;
- app.put(specialType.data);
+ if (to!string(specialType.data) != "line")
+ return null;
+ app.put(specialType.data);
- if (std.uni.isWhite(r.front))
- app.put(lexWhitespace(r, i, l).value);
+ if (std.uni.isWhite(r.front))
+ app.put(lexWhitespace(r, i, l).value);
- if (!isDigit(r.front))
- return null;
+ if (!isDigit(r.front))
+ return null;
- auto t = lexNumber(r, i, l);
- if (t != TokenType.IntLiteral)
- return null;
+ auto t = lexNumber(r, i, l);
+ if (t != TokenType.IntLiteral)
+ return null;
- app.put(t.value);
- l = to!uint(t.value);
+ app.put(t.value);
+ l = to!uint(t.value);
- if (!isNewline(r))
- {
- if (!r.empty && std.uni.isWhite(r.front))
- app.put(lexWhitespace(r, i, l).value);
+ if (!isNewline(r))
+ {
+ if (!r.empty && std.uni.isWhite(r.front))
+ app.put(lexWhitespace(r, i, l).value);
- if (!r.empty && r.front == '"')
- {
- auto fSpecApp = appender!(ElementType!(R)[])();
- fSpecApp.put(r.front);
- r.popFront();
- ++i;
- while (!r.empty)
- {
- if (r.front == '"')
- {
- fSpecApp.put('"');
- ++i;
- r.popFront();
- break;
- }
- ++i;
- fSpecApp.put(r.front);
- r.popFront();
- }
- app.put(fSpecApp.data);
- }
- else
- return null;
- }
+ if (!r.empty && r.front == '"')
+ {
+ auto fSpecApp = appender!(ElementType!(R)[])();
+ fSpecApp.put(r.front);
+ r.popFront();
+ ++i;
+ while (!r.empty)
+ {
+ if (r.front == '"')
+ {
+ fSpecApp.put('"');
+ ++i;
+ r.popFront();
+ break;
+ }
+ ++i;
+ fSpecApp.put(r.front);
+ r.popFront();
+ }
+ app.put(fSpecApp.data);
+ }
+ else
+ return null;
+ }
- app.put(popNewline(r, i));
- input.popFrontN(i - index);
- index = i;
- lineNumber = l;
- return to!string(app.data);
+ app.put(popNewline(r, i));
+ input.popFrontN(i - index);
+ index = i;
+ lineNumber = l;
+ return to!string(app.data);
}
unittest
{
- uint i;
- uint l;
- auto a = "#line 10\n";
- auto ar = lexSpecialTokenSequence(a, i, l);
- assert (ar == "#line 10\n");
- assert (a == "");
- assert (l == 10);
+ uint i;
+ uint l;
+ auto a = "#line 10\n";
+ auto ar = lexSpecialTokenSequence(a, i, l);
+ assert (ar == "#line 10\n");
+ assert (a == "");
+ assert (l == 10);
- auto b = "#line 9201 \"test.d\"\n";
- auto br = lexSpecialTokenSequence(b, i, l);
- assert (l == 9201);
- assert (br == "#line 9201 \"test.d\"\n");
- assert (b == "");
+ auto b = "#line 9201 \"test.d\"\n";
+ auto br = lexSpecialTokenSequence(b, i, l);
+ assert (l == 9201);
+ assert (br == "#line 9201 \"test.d\"\n");
+ assert (b == "");
- auto c = `#lin`;
- auto cr = lexSpecialTokenSequence(c, i, l);
- assert (l == 9201);
- assert (cr is null);
- assert (c == `#lin`);
+ auto c = `#lin`;
+ auto cr = lexSpecialTokenSequence(c, i, l);
+ assert (l == 9201);
+ assert (cr is null);
+ assert (c == `#lin`);
}
pure nothrow bool isSeparating(C)(C ch) if (isSomeChar!C)
@@ -2477,8 +2478,8 @@ pure nothrow TokenType lookupTokenType(const string input)
class Trie(K, V) if (isInputRange!K): TrieNode!(K, V)
{
/**
- * Adds the given value to the trie with the given key
- */
+ * Adds the given value to the trie with the given key
+ */
void add(K key, V value) pure
{
TrieNode!(K,V) current = this;