[svn] r7506: nemerle/trunk/ncc/parsing/Lexer.n

divan svnadmin at nemerle.org
Thu Mar 1 19:15:30 CET 2007


Log:
Fix bugs 946 and 961.

Author: divan
Date: Thu Mar  1 19:15:28 2007
New Revision: 7506

Modified:
   nemerle/trunk/ncc/parsing/Lexer.n

Modified: nemerle/trunk/ncc/parsing/Lexer.n
==============================================================================
--- nemerle/trunk/ncc/parsing/Lexer.n	(original)
+++ nemerle/trunk/ncc/parsing/Lexer.n	Thu Mar  1 19:15:28 2007
@@ -234,16 +234,16 @@
   [Accessor] mutable location   : Location;
   [Accessor]         text       : string;
 
-  internal SetEndRegion(loc : Location) : void
+  internal SetEndRegion (loc : Location) : void
   {
     when (isComplete)
-      throw System.InvalidOperationException("region is complete.");
+      throw System.InvalidOperationException ("region is complete.");
 
     when (location.FileIndex != loc.FileIndex)
-      throw System.InvalidOperationException("invalid endregion.");
+      throw System.InvalidOperationException ("invalid endregion.");
 
     isComplete = true;
-    location   = Location(location.FileIndex, location.Line, location.Column, loc.Line, loc.Column)
+    location   = Location (location.FileIndex, location.Line, location.Column, loc.Line, loc.Column)
   }
 }
 
@@ -309,13 +309,22 @@
   /** if there was only white chars from beginnig of line */
   protected mutable white_beginning : bool;  
 
-  protected mutable eating_stack : Stack[int]; // stack of nested #if
+  protected mutable eating_stack : Stack[int]; // stack of states (nested #if)
 
-  /** -1 = now inside true preprocessing section
-       0 = no preprocessing currently in action
-       1 = there were no true preprocessing sections in this set
-       2 = there already was true preprocessing section in this set
-       3 = we are now inside #else section, but it is not analyzed   */
+  /**
+    states:
+     now processing:
+      -4 region
+      -3 else
+      -1 if/elif
+       0 no preprocessor
+     not processing:
+       1 if/elif, but some other block possibly will be processed
+       2 if/elif, and other blocks won't be processed 
+        (there already was processed block, or parent block isn't processed)
+       3 else
+       4 region
+  */
   protected mutable eating_now : int;
 
   mutable   line_stack : int;    // real line number at moment of `#line 3' occurence
@@ -1139,7 +1148,7 @@
 
   read_to_the_end_of_line () : string
   {
-    mutable c = ' ';
+    mutable c = read_or_eol ();
     def line = StringBuilder (80);
     while (c != '\n') {
       if (c == '/') {
@@ -1162,7 +1171,7 @@
   {
     def eat_spaces () : void {
       mutable c = peek ();
-      while (Char.IsWhiteSpace (c)) 
+      while (Char.IsWhiteSpace (c) && c != '\n') 
       {
         ignore (read ());
         c = peek ();
@@ -1185,46 +1194,45 @@
     match (directive) {
       | "if" =>
         eating_stack.Push (eating_now);
-        if (evaluate_preprocessing_expr (read_to_the_end_of_line ().Trim ()))
-          unless (eating_now > 0)          
-            eating_now = -1
+        def now = evaluate_preprocessing_expr (read_to_the_end_of_line ().Trim ());
+        if (eating_now > 0)          
+          eating_now = 2
         else
-          eating_now = 1
+          eating_now = if (now) -1 else 1
 
       | "elif" =>
         def now = evaluate_preprocessing_expr (read_to_the_end_of_line ().Trim ());
-        if (!eating_stack.IsEmpty) {
-          def x = eating_stack.Top;    
-          unless (x > 0)
           match (eating_now) {
-            | 1 => when (now) eating_now = -1
+          | -4 | 4 => throw LexerBase.Error ("unexpected #elif inside region")
+          | -3 | 3 => throw LexerBase.Error ("unexpected #elif after #else")
+          | 1 => eating_now = if (now) -1 else 1
             | -1 | 2 => eating_now = 2
             | _ => throw LexerBase.Error ("unbalanced preprocessing directives")
           }
-        }
-        else
-          throw LexerBase.Error ("unbalanced #else");
 
       | "else" =>
-        ignore (read_to_the_end_of_line ());
-        if (!eating_stack.IsEmpty) {
-          def x = eating_stack.Top;    
-          unless (x > 0)
+        eat_spaces ();
+        when (read_to_the_end_of_line () != "")
+          throw LexerBase.Error ("extra tokens after #else");
             match (eating_now) {
-              | 1 => eating_now = -1
+          | -4 | 4 => throw LexerBase.Error ("unexpected #else inside region")
+          | -3 | 3 => throw LexerBase.Error ("unexpected #else after #else")
+          | 1 => eating_now = -3
               | -1 | 2 => eating_now = 3
               | _ => throw LexerBase.Error ("unbalanced preprocessing directives")
             }
-        }
-        else
-          throw LexerBase.Error ("unbalanced #else");
         
       | "endif" =>
-        ignore (read_to_the_end_of_line ());
-        if (!eating_stack.IsEmpty)
+        eat_spaces ();
+        when (read_to_the_end_of_line () != "")
+          throw LexerBase.Error ("extra tokens after #endif");
+        match (eating_now)
+        {
+          | -4 | 4 => throw LexerBase.Error ("unexpected #endif inside region")
+          | 0 => throw LexerBase.Error ("unbalanced preprocessing directives")
+          | _ => ()
+        }
           eating_now = eating_stack.Pop ();
-        else
-          throw LexerBase.Error ("unbalanced #endif");
 
       | "line" =>
         eat_spaces ();
@@ -1232,7 +1240,9 @@
         def (new_line, new_file) =
           if (c == 'd') {
             if (read_word () == "default") {
-              ignore (read_to_the_end_of_line ());
+              eat_spaces ();
+              when (read_to_the_end_of_line () != "")
+                throw LexerBase.Error ("extra tokens after directive");
               (-1, null)
             }
             else
@@ -1282,9 +1292,14 @@
         Message.Warning (this.Location, read_to_the_end_of_line ().Trim ());
 
       | "region" =>
-        incompleteRegions ::= Region(this.Location, read_to_the_end_of_line ().Trim ());
+        eating_stack.Push (eating_now);
+        eating_now = if (eating_now > 0) 4 else -4;
+        incompleteRegions ::= Region (this.Location, read_to_the_end_of_line ().Trim ());
 
       | "endregion" =>
+        when (eating_now != 4 && eating_now != -4)
+          throw LexerBase.Error ("Unexpected #endregion");
+        eating_now = eating_stack.Pop ();          
         match (incompleteRegions)
         {
           | h :: t =>
@@ -1300,7 +1315,7 @@
         when (w == "")
           throw LexerBase.Error ("#define should be followed by name to define");
         when (w == "true" || w == "false")
-          throw LexerBase.Error ($ "Attempt to define $w");
+          throw LexerBase.Error ($ "Attempt to define ``$w''");
         defines = defines.Replace (w, true);
         _ = read_to_the_end_of_line ()
 
@@ -1309,7 +1324,7 @@
         when (w == "")
           throw LexerBase.Error ("#undef should be followed by name to undefine");
         when (w == "true" || w == "false")
-          throw LexerBase.Error ($ "Attempt to undefine $w");
+          throw LexerBase.Error ($ "Attempt to undefine ``$w''");
         defines = defines.Replace (w, false);
         _ = read_to_the_end_of_line ()
 



More information about the svn mailing list