diff parser/Parser.d @ 99:857f0d530789 new_gen

Imports and improved module statement Allow "module a.b.c" Supports most forms of D's import. import A, B; import A, B = C; import A, B : a = b, c;
author Anders Halager <halager@gmail.com>
date Tue, 06 May 2008 21:59:22 +0200
parents 48bb2287c035
children 5f258eaf9517
line wrap: on
line diff
--- a/parser/Parser.d	Tue May 06 21:55:29 2008 +0200
+++ b/parser/Parser.d	Tue May 06 21:59:22 2008 +0200
@@ -22,8 +22,6 @@
     alias Object Decl;
     alias Object Module;
 
-public:
-
     this(MessageHandler messages)
     {
         this.messages = messages;
@@ -35,31 +33,35 @@
         this.lexer = lexer;
         this.action = act;
 
-        auto m = parseModule();
+        Module m;
+        if (lexer.peek.type == Tok.Module)
+        {
+            Token _module = lexer.next;
+            ModuleName name = parseModuleName();
+            m = action.actOnModule(_module, sm.getText(name.asRange()));
+            require(Tok.Seperator);
+        }
+        else
+        {
+            SLoc loc = lexer.peek.location;
+            m = action.actOnImplicitModule(loc, sm.getFile(loc));
+        }
 
-        while(lexer.peek.type != Tok.EOF)
-            action.actOnModuleDecl(m, parseDecl());
+        while (lexer.peek.type != Tok.EOF)
+            foreach (d; parseDeclDef())
+                action.actOnModuleDecl(m, d);
 
         return m;
     }
 
-    Module parseModule()
+private:
+    Decl[] parseDeclDef()
     {
-        if(lexer.peek.type == Tok.Module)
-        {
-            lexer.next;
-            if(lexer.peek.type != Tok.Identifier)
-                messages.report(UnexpectedTok, lexer.peek.location)
-                    .arg(lexer.peek.type)
-                    .arg(Tok.Identifier)
-                    .fatal(ExitLevel.Parser);
-    
-            auto m = action.actOnModule(sm.getText(lexer.next.asRange));
-            require(Tok.Seperator);
-            return m;
-        }
-
-        return action.actOnModule(sm.getFile(lexer.peek.location));
+        Token t = lexer.peek;
+        if (t.type == Tok.Import)
+            return parseImports();
+        else
+            return [parseDecl()];
     }
 
     Decl parseDecl()
@@ -118,6 +120,83 @@
     }
 
     /**
+      Parse a series of imports belonging to a single import token.
+     */
+    Decl[] parseImports()
+    {
+        Token _import = require(Tok.Import);
+        SmallArray!(Decl) res;
+        void addToRes(Decl d) { res ~= d; }
+
+        bool done = false;
+        while (!done && !on_a(Tok.Seperator))
+        {
+            ModuleName mod = parseModuleName();
+            Token tok = lexer.peek;
+            switch (tok.type)
+            {
+                case Tok.Comma:
+                    // import A, B.C;
+                    // parse another module-name
+                    lexer.next();
+                    res ~= action.actOnImport(_import, mod, null);
+                    break;
+                case Tok.Assign:
+                    // import B = A.A;
+                    //        ^- must be a single identifier
+                    // renamed import
+                    if (mod.packages.length != 0)
+                    {
+                        SLoc loc = mod.packages[0].tok.location;
+                        messages.report(RenameMustBeSingleIdent, loc);
+                    }
+                    //if (isStatic)
+                    //    error("Static imports cannot be renamed");
+                    lexer.next();
+                    Id name = mod.id;
+                    mod = parseModuleName();
+                    // create from mod and rename to `name`
+                    res ~= action.actOnImport(_import, mod, &name);
+                    break;
+                case Tok.Colon:
+                    // import A : a;
+                    // selective imports, potentially import A : print = a
+                    lexer.next();
+                    Decl d = action.actOnImport(_import, mod, null);
+                    // do-while on a comma:
+                    //   add explicit symbol
+                    do
+                    {
+                        Id sym = parseIdentifier();
+                        Id dummy;
+                        Id* name = null;
+                        if (skip(Tok.Assign))
+                        {
+                            dummy = sym;
+                            name = &dummy;
+                            sym = parseIdentifier();
+                        }
+                        action.addSelectiveImport(d, sym, name);
+
+                    } while (skip(Tok.Comma));
+                    require(Tok.Seperator);
+                    res ~= d;
+                    return res.safe();
+                default:
+                    goto Lerror;
+            }
+            res ~= action.actOnImport(_import, mod, null);
+        }
+
+        require(Tok.Seperator);
+        return res.safe();
+Lerror:
+        while (!on_a (Tok.Seperator))
+            lexer.next();
+        return res.safe();
+    }
+
+    /**
       Parse struct
      */
     Decl parseStruct(Id type, Id iden)
@@ -152,6 +231,7 @@
         
         return decl;
     }
+
     /**
       Parse statements.
 
@@ -237,14 +317,13 @@
                         return action.actOnExprStmt(exp);
                     }
                         
-                    if ( n.isIdentifier())
+                    if (n.isIdentifier())
                         return action.actOnDeclStmt(parseVarDecl());
 
                     // Expression: a.b, a = b, a(b) etc.
                     Exp exp = parseExpression();
                     require(Tok.Seperator);
                     return action.actOnExprStmt(exp);
-                    break;
                 }
 
             case Tok.Switch:
@@ -261,6 +340,7 @@
                     return action.actOnExprStmt(exp);
                 }
                 messages.report(UnexpectedBeginStmt, lexer.peek.location).arg(lexer.next.getType);
+                return null;
         }
         messages.report(UnexpectedTok, t.location);
         return null;
@@ -332,8 +412,10 @@
             return parseCompoundStatement();
         return parseStatement();
     }
+
     /**
-      Parses a function-body or similar, expects { to be current token.
+      Parses a function-body or similar, expects an opening brace to be the
+      current token.
       
       Will consume both the starting { and ending }
      */
@@ -359,6 +441,28 @@
             .arg(Tok.Identifier);
     }
 
+    ModuleName parseModuleName()
+    {
+        auto id = parseIdentifier();
+        ModuleName mod;
+        while (skip(Tok.Dot))
+        {
+            mod.packages ~= id;
+            if (lexer.peek.type != Tok.Identifier) {
+                messages.report(ExpectedIdAfterPackage, lexer.peek.location);
+                goto Lerror;
+            }
+            id = parseIdentifier();
+        }
+        mod.id = id;
+        return mod;
+Lerror:
+        while (!skip(Tok.Seperator))
+            lexer.next();
+        return mod;
+    }
+
+
     /**
       Parse a type - this includes pointer and array(at some point) types.
      */
@@ -609,6 +713,12 @@
         return true;
     }
 
+    bool on_a(Tok t)
+    {
+        return lexer.peek.type == t;
+    }
+
     Lexer lexer;
     SourceManager sm;
 }
+