diff trunk/src/Lexer.d @ 51:cadd2bfe686c

- Displaying error messages in XML. - Made fixes to the special token scanner.
author aziz
date Wed, 27 Jun 2007 16:43:00 +0000
parents 4a27b7840ea9
children f65a83c27638
line wrap: on
line diff
--- a/trunk/src/Lexer.d	Wed Jun 27 12:53:03 2007 +0000
+++ b/trunk/src/Lexer.d	Wed Jun 27 16:43:00 2007 +0000
@@ -116,7 +116,9 @@
   UnterminatedCharacterLiteral,
   EmptyCharacterLiteral,
   // #line
-  ExpectedIdentifierLine,
+  ExpectedIdentifierSTLine,
+  ExpectedNormalStringLiteral,
+  ExpectedNumberAfterSTLine,
   NewlineInSpecialToken,
   UnterminatedSpecialToken,
   // ""
@@ -147,8 +149,10 @@
   "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 newline after special token.",
+  "expected a terminating newline after special token.",
   // ""
   "unterminated string literal.",
   // x""
@@ -233,7 +237,9 @@
 
       if (c == 0)
       {
+        assert(*p == 0);
         ++p;
+        assert(p == end);
         t.type = TOK.EOF;
         t.end = p;
         return;
@@ -683,7 +689,8 @@
         return;
       case '#':
         scanSpecialToken();
-        break;
+        c = *p;
+        continue;
       default:
       }
 
@@ -696,8 +703,11 @@
   void peek(ref Token t)
   {
     char* tmp = p;
+    uint len = errors.length;
     scan(t);
     p = tmp;
+    if (errors.length != len)
+      errors = errors[0..len];
   }
 
   void scanNormalStringLiteral(ref Token t)
@@ -1040,74 +1050,97 @@
   }
 
   /// Scan special token: #line Integer [Filespec] EndOfLine
+  // TODO: Handle case like: #line 0 #line 2
   void scanSpecialToken()
   {
     assert(*p == '#');
+
     ++p;
     MID mid;
     Token t;
+    uint oldloc = this.loc, newloc;
 
-    scan(t);
-    if (!(t.type == TOK.Identifier && t.span == "line")) {
-      mid = MID.ExpectedIdentifierLine;
+    peek(t);
+    if (!(this.loc == oldloc && p == t.start && t.type == TOK.Identifier && t.span == "line"))
+    {
+      this.loc = oldloc; // reset this.loc because we took a peek at the next token
+      mid = MID.ExpectedIdentifierSTLine;
+      goto Lerr;
+    }
+    p = t.end; // consume token
+
+    peek(t);
+    if (this.loc == oldloc && t.type == TOK.Number)
+    {
+      newloc = t._uint - 1;
+      p = t.end;
+    }
+    else
+    {
+      this.loc = oldloc;
+      mid = MID.ExpectedNumberAfterSTLine;
       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)
+    peek(t);
+    if (this.loc != oldloc)
     {
-      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;
+      this.loc = oldloc;
+      mid = MID.NewlineInSpecialToken;
+      goto Lerr;
     }
-
-    peek(t);
-
     if (t.type == TOK.String)
     {
-      // Check whole token with preceding whitespace for newline.
-      if (hasNewline(t.end))
+      if (*t.start != '"')
+      {
+        mid = MID.ExpectedNormalStringLiteral;
         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;
+/+
+    peek(t);
+    if (this.loc == oldloc && t.type != TOK.EOF)
+    {
+      mid = MID.UnterminatedSpecialToken;
+      goto Lerr;
+    }
++/
     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]))
+      switch (*p)
+      {
+      case '\r':
+        if (p[1] == '\n')
+          ++p;
+      case '\n':
+        ++p;
         break;
-      else {
+      case LS[0]:
+        if (p[1] == LS[1] && (p[2] == LS[2] || p[2] == PS[2]))
+        {
+          p += 2;
+          break;
+        }
+      case 0, _Z_:
+        break;
+      default:
+        if (isspace(*p)) {
+          ++p;
+          continue;
+        }
         mid = MID.UnterminatedSpecialToken;
         goto Lerr;
       }
+      break;
     }
 
-    this.loc = loc;
+    this.loc = newloc;
     return;
   Lerr:
     error(mid);