# HG changeset patch # User aziz # Date 1182760622 0 # Node ID 426767b9463516da2bd6837b237c7f88b58def07 # Parent ef83eea26bbd957d37a6d5fe64928c9a18a7432b - Added code for parsing the '#line' special token. - Added fileName to Lexer. - Added _uint to Token. - Added basic peek() method to Lexer. diff -r ef83eea26bbd -r 426767b94635 trunk/src/Lexer.d --- a/trunk/src/Lexer.d Sun Jun 24 18:01:02 2007 +0000 +++ b/trunk/src/Lexer.d Mon Jun 25 08:37:02 2007 +0000 @@ -9,6 +9,7 @@ import std.stdio; import std.utf; import std.uni; +import std.conv; /// ASCII character properties table. static const int ptable[256] = [ @@ -91,12 +92,18 @@ enum MID { UnterminatedCharacterLiteral, - EmptyCharacterLiteral + EmptyCharacterLiteral, + ExpectedIdentifierLine, + NewlineInSpecialToken, + UnterminatedSpecialToken } string[] Messages = [ "unterminated character literal." - "empty character literal." + "empty character literal.", + "expected 'line' after '#'." + "newline not allowed inside special token." + "expected newline after special token." ]; class Problem @@ -122,18 +129,22 @@ class Lexer { Token token; - char[] text; + string text; char* p; char* end; uint loc = 1; /// line of code + char[] fileName; + Problem[] errors; Identifier[string] idtable; - this(char[] text) + this(string text, string fileName) { + this.fileName = fileName; + this.text = text; this.text.length = this.text.length + 1; this.text[$-1] = 0; @@ -414,6 +425,10 @@ Lcommon2: t.end = p; return; + case '#': + ++p; + scanSpecialToken(); + break; default: } @@ -423,6 +438,13 @@ } } + void peek(ref Token t) + { + char* tmp = p; + scan(t); + p = tmp; + } + void scanCharacterLiteral(ref Token t) { assert(*p == '\''); @@ -462,6 +484,79 @@ while (isdigit(*++p)) {} t.type = TOK.Number; t.end = p; + t._uint = toInt(t.span); + } + + /// Scan special token: #line Integer [Filespec] EndOfLine + void scanSpecialToken() + { + MID mid; + Token t; + + scan(t); + if (!(t.type == TOK.Identifier && t.span == "line")) { + mid = MID.ExpectedIdentifierLine; + goto Lerr; + } + + scan(t); + if (t.type == TOK.Number) + loc = t._uint - 1; + + uint loc = this.loc; + + char* wsstart = t.end; + + bool hasNewline(char* end) + { + alias wsstart p; + uint c; + for(; p != end; c = *++p) + if (c == '\n' || c == '\r' || c == LS[0] && p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2])) { + mid = MID.NewlineInSpecialToken; + return true; + } + return false; + } + + peek(t); + + if (t.type == TOK.String) + { + // Check whole token with preceding whitespace for newline. + if (hasNewline(t.end)) + goto Lerr; + fileName = t.span[1..$-1]; // contents of "..." + p = t.end; + } + else if (t.type == TOK.Identifier && t.span == "__FILE__") + { + // Check preceding whitespace for newline. + if (hasNewline(t.start)) + goto Lerr; + p = t.end; + } + + uint c; + while (1) + { + c = *p++; + if (isspace(c)) + continue; + + if (c == '\n' || c == '\r' || c == 0 || + c == LS[0] && p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2])) + break; + else { + mid = MID.UnterminatedSpecialToken; + goto Lerr; + } + } + + this.loc = loc; + return; + Lerr: + error(mid); } uint decodeUTF() diff -r ef83eea26bbd -r 426767b94635 trunk/src/Token.d --- a/trunk/src/Token.d Sun Jun 24 18:01:02 2007 +0000 +++ b/trunk/src/Token.d Mon Jun 25 08:37:02 2007 +0000 @@ -81,12 +81,14 @@ { char[] str; dchar chr; + uint _uint; float f; double d; } string span() { + assert(start && end); return start[0 .. end - start]; } diff -r ef83eea26bbd -r 426767b94635 trunk/src/main.d --- a/trunk/src/main.d Sun Jun 24 18:01:02 2007 +0000 +++ b/trunk/src/main.d Mon Jun 25 08:37:02 2007 +0000 @@ -25,7 +25,7 @@ void main(char[][] args) { auto srctext = cast(char[]) std.file.read(args[1]); - auto lx = new Lexer(srctext); + auto lx = new Lexer(srctext, args[1]); auto tokens = lx.getTokens(); char* end = lx.text.ptr;