[svn] r5878: nemerle/trunk/ncc: parsing/Lexer.n parsing/PreParser.n passes.n testsuite/positive/pragma-ind...

malekith svnadmin at nemerle.org
Fri Nov 4 11:31:57 CET 2005


Log:
Move LexerFileIndent implementation into LexerBase (it should also work for LexerString, which is used for completion). Implement PreParser-switching when #pragma indent is seen.

Author: malekith
Date: Fri Nov  4 11:31:56 2005
New Revision: 5878

Added:
   nemerle/trunk/ncc/testsuite/positive/pragma-indent.n
Modified:
   nemerle/trunk/ncc/parsing/Lexer.n
   nemerle/trunk/ncc/parsing/PreParser.n
   nemerle/trunk/ncc/passes.n

Modified: nemerle/trunk/ncc/parsing/Lexer.n
==============================================================================
--- nemerle/trunk/ncc/parsing/Lexer.n	(original)
+++ nemerle/trunk/ncc/parsing/Lexer.n	Fri Nov  4 11:31:56 2005
@@ -31,6 +31,7 @@
 using System;
 
 using Nemerle.Collections;
+using Nemerle.Utility;
 
 namespace Nemerle.Compiler {
 
@@ -236,6 +237,68 @@
 
   protected id_buffer : StringBuilder = StringBuilder ();
 
+  #region Indentation syntax
+  // Variables for indentation-based syntax
+  // The location where a token should be automatically inserted
+  protected mutable insert_location : Location;
+  // Used by GetToken() to store that token that it postpones when insert_indent = true
+  protected mutable tok_pending : Token;
+  // Whether we are currently adding whitespaces to indentString
+  protected mutable counting_indentation : bool;
+  // Whether GetToken() should return a Token.Indent
+  protected mutable insert_indent : bool;
+  // String holding the current line's indent
+  protected mutable indent_string : string;
+
+  [Accessor]
+  protected mutable in_indentation_mode : bool;
+
+  public SwitchToIndentationMode () : void
+  {
+    in_indentation_mode = true;
+    counting_indentation = true;
+    indent_string = "";
+  }
+
+  pragma_indent () : void
+  {
+    unless (in_indentation_mode) {
+      SwitchToIndentationMode ();
+      _ = read_to_the_end_of_line ();
+      throw PragmaIndent ()
+    }
+  }
+  
+  do_read () : char
+  {
+    def ch = read_from_input ();
+    // Message.Debug (Location, $"ch = '$ch'");
+
+    when (in_indentation_mode) {
+      // Start counting indentation anew after a newline
+      if (ch == '\n' || ch == '\r') {
+        // Message.Debug (Location, $"start");
+        indent_string = "";
+        counting_indentation = true;
+        //Message.Debug (Location (file_idx, line, col), "countingIndentation ON");
+      }
+      else when (counting_indentation) {
+        if (ch == '\t' || ch == ' ')
+          indent_string += ch.ToString();
+        // We have a non-space character, so stop counting indentation
+        //  and indicate that we have a new line to process
+        else {
+          // Message.Debug (Location, $"stop");
+          counting_indentation = false;
+          insert_indent = true;
+        }
+      }
+    }
+    
+    ch
+  }
+  #endregion
+
 
   #region PREPROCESSOR VARIABLES
   /** if there was only white chars from beginnig of line */
@@ -263,6 +326,10 @@
     public this (name : string) { this.name = name; }
   }
 
+  public class PragmaIndent : System.Exception
+  {
+  }
+
   protected this ()
   {
     line = 1;
@@ -277,7 +344,7 @@
     line_stack = -1;
   }
 
-  abstract protected do_read () : char;
+  abstract protected read_from_input () : char;
 
   public abstract Dispose () : void;
   
@@ -765,6 +832,10 @@
   {
     mutable eof = false;
     
+    // Location where possible automatic token insertion will take place
+    when (in_indentation_mode)
+      insert_location = Location;
+    
     def loop (shift : bool) {
       when (shift) ignore (read ()); 
       def ch = 
@@ -948,26 +1019,37 @@
     }      
   }
 
+
   public virtual GetToken () : Token
   {
+    if (tok_pending != null) {
+      def tok = tok_pending;
+      tok_pending = null;
+      tok
+    } else {
     unless (isPendingChar)
       _ = eat_whitespace ();
     
+      if (insert_indent) {
+        insert_indent = false;
+        Token.Indent (insert_location, indent_string)
+      } else {
     def last_line = line;
     def last_col = col;
     def tok = do_get_token ();
     tok.Location = Location (file_idx, last_line, last_col, line, col);
     tok
   }
+    }
+  }
 
   public Location : Location
   {
     get { Location (file_idx, line, col) }
   }
 
-  parse_preprocessor () : void
+  read_to_the_end_of_line () : string
   {
-    def read_to_the_end_of_line () {
       mutable c = ' ';
       def line = StringBuilder (80);
       while (c != '\n') {
@@ -976,7 +1058,10 @@
         catch { _ is LexerBase.Error => c = '\n' }
       };
       line.ToString ()
-    };
+  }
+
+  parse_preprocessor () : void
+  {
     // eof isn't checked, because we are eating and expecting something
     // not white before end of line
     def eat_spaces () : char {
@@ -1128,6 +1213,9 @@
              unless (did_something)
                WarningOptions.AddPragmaWarning (file_idx, line, 1 * negate)
              
+          | "indent" =>
+            pragma_indent ();
+             
           | _ =>
             Message.Warning (1633, this.Location, "unrecognized #pragma directive");
             _ = read_to_the_end_of_line ();
@@ -1332,7 +1420,7 @@
       
   }
 
-  override protected do_read () : char
+  override protected read_from_input () : char
   {
     def inp = reader.Read ();
     if (inp >= 0)
@@ -1449,7 +1537,7 @@
 
   public override Dispose () : void { }
   
-  override protected do_read () : char
+  override protected read_from_input () : char
   {
     if (pos < reader.Length) {
       def ch = reader[pos];
@@ -1526,84 +1614,6 @@
   }
 }
 
-
-public class LexerFileIndent : LexerFile
-{
-  // Variables for indentation-based syntax
-  // The location where a token should be automatically inserted
-  protected mutable insertLocation : Location;
-  // Used by GetToken() to store that token that it postpones when insert_indent = true
-  protected mutable tokPending : Token;
-  // Whether we are currently adding whitespaces to indentString
-  protected mutable countingIndentation : bool;
-  // Whether GetToken() should return a Token.Indent
-  protected mutable insert_indent : bool;
-  // String holding the current line's indent
-  protected mutable indentString : string;
-  
-  
-  public this (fn : string)
-  {
-    base (fn);
-    countingIndentation = true;
-    indentString = "";
-  }
-  
-  override protected do_read () : char
-  {
-    def ch = base.do_read ();
-    // Message.Debug (Location, $"ch = '$ch'");
-    
-    // Start counting indentation anew after a newline
-    if (ch == '\n' || ch == '\r') {
-      // Message.Debug (Location, $"start");
-      indentString = "";
-      countingIndentation = true;
-      //Message.Debug (Location (file_idx, line, col), "countingIndentation ON");
-    }
-    else when (countingIndentation) {
-      if (ch == '\t' || ch == ' ')
-        indentString += ch.ToString();
-      // We have a non-space character, so stop counting indentation
-      //  and indicate that we have a new line to process
-      else {
-        // Message.Debug (Location, $"stop");
-        countingIndentation = false;
-        insert_indent = true;
-      }
-    }
-    
-    ch
-  }
-        
-  override protected eat_whitespace () : bool
-  {
-    // Location where possible automatic token insertion will take place
-    insertLocation = Location (file_idx, line, col);
-    
-    base.eat_whitespace ();
-  }
-
-  public override GetToken () : Token
-  {
-    if (tokPending != null) {
-      def tok = tokPending;
-      tokPending = null;
-      tok;
-    } else {
-      unless (isPendingChar)
-        _ = eat_whitespace ();
-      
-      if (insert_indent) {
-        insert_indent = false;
-        Token.Indent (insertLocation, indentString)
-      } else 
-        base.GetToken ()
-    }
-  }
-} // LexerFileIndent
-
-
 public enum SyntaxType {
   | Identifier 
   | Keyword 

Modified: nemerle/trunk/ncc/parsing/PreParser.n
==============================================================================
--- nemerle/trunk/ncc/parsing/PreParser.n	(original)
+++ nemerle/trunk/ncc/parsing/PreParser.n	Fri Nov  4 11:31:56 2005
@@ -437,16 +437,36 @@
       }
     }
 
+    indention_based_copy () : PreParser
+    {
+      def copy = PreParserIndent (lexer);
+      copy.last_token = last_token;
+      copy.Env = Env;
+      copy.finished = finished;
+      copy
+    }
+
     public ParseTopLevel () : Token.BracesGroup {
+      try {
       def stream = ParseTopLevelImpl ();
       lexer.Dispose (); // make lexer release file handle
       Token.BracesGroup (stream)
+      } catch {
+        | _ is LexerBase.PragmaIndent =>
+          indention_based_copy ().ParseTopLevel ()
+      }
     }
     
     public PreParse () : Token.BracesGroup {
+      try {
       def top = parse_brace_group (Location.Default);
-      unless (finished) Message.Error (lexer.Location, "expected end of file, encountered closing brace");
+        unless (finished)
+          Message.Error (lexer.Location, "expected end of file, encountered closing brace");
       top
+      } catch {
+        | _ is LexerBase.PragmaIndent =>
+          indention_based_copy ().PreParse ()
+      }
     }
   }
 }

Modified: nemerle/trunk/ncc/passes.n
==============================================================================
--- nemerle/trunk/ncc/passes.n	(original)
+++ nemerle/trunk/ncc/passes.n	Fri Nov  4 11:31:56 2005
@@ -134,7 +134,11 @@
       // if it was not initialized outside the Run
       when (LexingPipeline == null)
         if (Options.IndentationSyntax)
-          LexingPipeline = LexerFileIndent;
+          LexingPipeline = fun (fn) {
+            def l = LexerFile (fn);
+            l.SwitchToIndentationMode ();
+            l
+          }
         else
           LexingPipeline = LexerFile;
       when (OnInit != null) OnInit ();

Added: nemerle/trunk/ncc/testsuite/positive/pragma-indent.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/positive/pragma-indent.n	Fri Nov  4 11:31:56 2005
@@ -0,0 +1,7 @@
+#pragma indent
+class C
+   foo = 13
+   bar : string
+   baz : bool
+
+()



More information about the svn mailing list