changeset 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
files trunk/src/Lexer.d trunk/src/format.css trunk/src/main.d
diffstat 3 files changed, 86 insertions(+), 44 deletions(-) [+]
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);
--- a/trunk/src/format.css	Wed Jun 27 12:53:03 2007 +0000
+++ b/trunk/src/format.css	Wed Jun 27 16:43:00 2007 +0000
@@ -1,10 +1,12 @@
 @charset "utf-8";
-sourcetext {
+compilerinfo, sourcetext {
   display: block;
   white-space: pre;
   font-family: Monospace;
   font-size: 0.8em;
 }
+compilerinfo { white-space: normal; border: 1px solid #A22; padding: 0.5em; margin: 1em;}
+compilerinfo error { display: block; }
 k { color: darkblue; font-weight: bold; }
 c[c=lc], c[c=bc] { color: green; }
 c[c=nc] { color: darkgreen; }
--- a/trunk/src/main.d	Wed Jun 27 12:53:03 2007 +0000
+++ b/trunk/src/main.d	Wed Jun 27 16:43:00 2007 +0000
@@ -32,8 +32,15 @@
 
   writef(`<?xml version="1.0"?>
 <?xml-stylesheet href="format.css" type="text/css"?>
+<root>
+<compilerinfo>`\n);
+  foreach (error; lx.errors)
+  {
+    writefln(`<error t="%s">%s(%d): %s</error>`, "l", lx.fileName, error.loc, messages[error.id]);
+  }
+  writef(`</compilerinfo>
 <sourcetext>`);
-  foreach(ref token; tokens)
+  foreach (ref token; tokens)
   {
     if (end != token.start)
       writef("%s", xmlescape(end[0 .. token.start - end]));
@@ -120,5 +127,5 @@
     }
     end = token.end;
   }
-  writef("\n</sourcetext>");
+  writef("\n</sourcetext>\n</root>");
 }
\ No newline at end of file