changeset 172:01c2c49775ef

- Changed Parser to be more clean on type parsing. - Parsing int function(int), and the like, types.(Function pointers) - Fixed a design fault that made Symbol be wrong. Now Symbols are created with a factory with the help of types.
author Anders Johnsen <skabet@gmail.com>
date Thu, 24 Jul 2008 20:31:24 +0200
parents f0385c044065
children 50b98a06a200
files ast/Decl.d ast/Exp.d lexer/Token.d parser/Action.d parser/Parser.d sema/AstAction.d sema/ScopeBuilder.d sema/ScopeCheck.d sema/Visitor.d tests/parser/function_pointer.d tools/AstPrinter.d
diffstat 11 files changed, 482 insertions(+), 376 deletions(-) [+]
line wrap: on
line diff
--- a/ast/Decl.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/ast/Decl.d	Thu Jul 24 20:31:24 2008 +0200
@@ -76,7 +76,7 @@
 
 class VarDecl : Decl
 {
-    this(Identifier type, Identifier identifier,
+    this(IdentifierTypeExp type, Identifier identifier,
             Exp e = null)
     {
         super(DeclType.VarDecl);
@@ -121,14 +121,14 @@
 
 class FuncDecl : Decl
 {
-    this(Identifier type, Identifier identifier)
+    this(IdentifierTypeExp type, Identifier identifier)
     {
         super(DeclType.FuncDecl);
         this.returnType = type;
         this.identifier = identifier;
     }
 
-    void addParam(Identifier type, Identifier name = null)
+    void addParam(IdentifierTypeExp type, Identifier name = null)
     {
         funcArgs ~= new VarDecl(type, name, null);
     }
@@ -246,8 +246,8 @@
         this.identifier = identifier;
         
         auto name = new Identifier(identifier.loc, "__vptr");
-        auto type = new Identifier(identifier.loc, "int");
-        auto p_type = new PointerIdentifier(type);
+        auto type = new IdentifierTypeExp(identifier.loc, "int");
+        auto p_type = new PointerTypeExp(type);
         decls ~= new VarDecl(p_type, name, null);
     }
 
--- a/ast/Exp.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/ast/Exp.d	Thu Jul 24 20:31:24 2008 +0200
@@ -24,14 +24,17 @@
     MemberReference,
     Index,
     Identifier,
-    ArrayIdentifier,
-    StaticArrayIdentifier,
-    PointerIdentifier,
     AssignExp,
     CallExp,
     CastExp,
     StringExp,
     NewExp,
+
+    IdentifierTypeExp,
+    ArrayTypeExp,
+    StaticArrayTypeExp,
+    PointerTypeExp,
+    FunctionTypeExp,
 }
 
 abstract class Exp
@@ -523,63 +526,6 @@
     Symbol callSym;
 }
 
-class PointerIdentifier : Identifier
-{
-    this(Identifier pointerOf)
-    {
-        super(ExpType.PointerIdentifier, pointerOf.loc);
-        this.pointerOf = pointerOf;
-        this.name = pointerOf.name;
-    }
-
-    override DType type()
-    {
-        return pointerOf.type.getPointerTo();
-    }
-
-    Identifier pointerOf;
-}
-
-class StaticArrayIdentifier : Identifier
-{
-    this(Identifier arrayOf, IntegerLit size)
-    {
-        super(ExpType.StaticArrayIdentifier, arrayOf.loc);
-        this.arrayOf = arrayOf;
-        this.size = Integer.parse(size.get);
-        this.name = arrayOf.name;
-    }
-
-    override DType type()
-    {
-        return arrayOf.type.getAsStaticArray(size);
-    }
-
-    Identifier arrayOf;
-    int size;
-
-    private DType myType;
-}
-
-class ArrayIdentifier : Identifier
-{
-    this(Identifier arrayOf)
-    {
-        super(ExpType.ArrayIdentifier, arrayOf.loc);
-        this.arrayOf = arrayOf;
-        this.name = arrayOf.name;
-    }
-
-    override DType type()
-    {
-        return arrayOf.type.getAsArray();
-    }
-
-    Identifier arrayOf;
-
-    private DType myType;
-}
-
 class Identifier : Exp
 {
     this(SLoc loc, char[] name)
@@ -667,3 +613,101 @@
     private DType myType;
 }
 
+class IdentifierTypeExp : Identifier
+{
+    this(SLoc loc, char[] name)
+    {
+        super(ExpType.IdentifierTypeExp, loc);
+        this.name = name;
+    }
+
+    protected this(ExpType t, SLoc loc)
+    {
+        super(t, loc);
+    }
+}
+
+class PointerTypeExp : IdentifierTypeExp
+{
+    this(IdentifierTypeExp pointerOf)
+    {
+        super(ExpType.PointerTypeExp, pointerOf.loc);
+        this.pointerOf = pointerOf;
+        this.name = pointerOf.name;
+    }
+
+    override DType type()
+    {
+        return pointerOf.type.getPointerTo();
+    }
+
+    Identifier pointerOf;
+}
+
+class StaticArrayTypeExp : IdentifierTypeExp
+{
+    this(IdentifierTypeExp arrayOf, IntegerLit size)
+    {
+        super(ExpType.StaticArrayTypeExp, arrayOf.loc);
+        this.arrayOf = arrayOf;
+        this.size = Integer.parse(size.get);
+        this.name = arrayOf.name;
+    }
+
+    override DType type()
+    {
+        return arrayOf.type.getAsStaticArray(size);
+    }
+
+    Identifier arrayOf;
+    int size;
+
+    private DType myType;
+}
+
+class ArrayTypeExp : IdentifierTypeExp
+{
+    this(IdentifierTypeExp arrayOf)
+    {
+        super(ExpType.ArrayTypeExp, arrayOf.loc);
+        this.arrayOf = arrayOf;
+        this.name = arrayOf.name;
+    }
+
+    override DType type()
+    {
+        return arrayOf.type.getAsArray();
+    }
+
+    Identifier arrayOf;
+
+    private DType myType;
+}
+
+class FunctionTypeExp : IdentifierTypeExp
+{
+    this(IdentifierTypeExp returnType, VarDecl[] decls)
+    {
+        super(ExpType.FunctionTypeExp, returnType.loc);
+        this.returnType = returnType;
+        this.decls = decls;
+    }
+
+    override DType type()
+    {
+        if (myType)
+            return myType;
+        auto t  = new DFunction(returnType);
+        t.returnType = returnType.type;
+        foreach (decl ; decls)
+            t.params ~= decl.identifier.type;
+
+        myType = t.getPointerTo;
+        return myType;
+    }
+
+    VarDecl[] decls;
+    IdentifierTypeExp returnType;
+    private DType myType;
+}
+
--- a/lexer/Token.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/lexer/Token.d	Thu Jul 24 20:31:24 2008 +0200
@@ -255,6 +255,7 @@
         Tok.Dchar:"Dchar",
         Tok.Bool:"Bool",
         Tok.Void:"Void",
+        Tok.Function:"Function",
         Tok.Eq:"Eq",
         Tok.Ne:"Ne",
         Tok.Lt:"Lt",
--- a/parser/Action.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/parser/Action.d	Thu Jul 24 20:31:24 2008 +0200
@@ -40,11 +40,11 @@
     Token tok;
 }
 
-class PointerId : Id
+class PointerTypeId : Id
 {
-    public static PointerId opCall(Id id)
+    public static PointerTypeId opCall(Id id)
     {
-        auto p = new PointerId();
+        auto p = new PointerTypeId();
         p.id = id;
         return p;
     }
@@ -52,11 +52,11 @@
     Id id;
 }
 
-class StaticArrayId : Id
+class StaticArrayTypeId : Id
 {
-    public static StaticArrayId opCall(Id id, Object number)
+    public static StaticArrayTypeId opCall(Id id, Object number)
     {
-        auto a = new StaticArrayId();
+        auto a = new StaticArrayTypeId();
         a.id = id;
         a.number = number;
         return a;
@@ -66,6 +66,20 @@
     Object number;
 }
 
+class FunctionTypeId : Id
+{
+    public static FunctionTypeId opCall(Id id, DeclT[] decls)
+    {
+        auto f = new FunctionTypeId();
+        f.id = id;
+        f.decls = decls;
+        return f;
+    }
+
+    Id id;
+    DeclT[] decls;
+}
+
 /**
   Represents a fully qualified name, with some packages and a final identifier.
   The identifier should always be set, but packages may have length 0.
@@ -85,6 +99,18 @@
     }
 }
 
+    /**
+      A few aliases to indicate what methods should be dealing with the same
+      types.
+      Not typesafe, and not using typedef because users would need a lot of
+      casts (and base type would be void*, so no possibility to synchronize,
+      print etc.)
+     */
+alias Object ExprT;
+alias Object StmtT; /// ditto
+alias Object DeclT; /// ditto
+alias Object ModuleT; /// ditto
+
 /**
   All methods are optional.
 
@@ -93,18 +119,7 @@
  */
 abstract class Action
 {
-    /**
-      A few aliases to indicate what methods should be dealing with the same
-      types.
 
-      Not typesafe, and not using typedef because users would need a lot of
-      casts (and base type would be void*, so no possibility to synchronize,
-      print etc.)
-     */
-    alias Object ExprT;
-    alias Object StmtT; /// ditto
-    alias Object DeclT; /// ditto
-    alias Object ModuleT; /// ditto
 
     // -- Modules --
 
--- a/parser/Parser.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/parser/Parser.d	Thu Jul 24 20:31:24 2008 +0200
@@ -74,76 +74,61 @@
 
     Decl parseDecl(Attribute att)
     {
-        Token t = peek;
-
-        if (t.isBasicType || t.isIdentifier)
+        switch(peek.type)
         {
-            Id type;
-            Id iden;
-            int len = peekParseType;
-            if (peek(len).type == Tok.Identifier && len != 0)
-            {
-                type = parseType;
-parseDeclAfterInvalidType:
-                iden = Id(require(Tok.Identifier));
-                if ( isa(Tok.Seperator) )
+            case Tok.Struct:
+                Id type = Id(next());
+                Id iden = Id(require(Tok.Identifier));            
+                return parseStruct(type, iden, att);
+
+            case Tok.Class:
+                Id type = Id(next());
+                Id iden = Id(require(Tok.Identifier));            
+                return parseClass(type, iden, att);
+
+            case Tok.Interface:
+                Id type = Id(next());
+                Id iden = Id(require(Tok.Identifier));
+                return parseInterface(type, iden, att);
+
+            case Tok.Identifier:
+                Id type = parseType;
+                Id iden = Id(require(Tok.Identifier));
+                
+                switch(peek.type)
                 {
-                    Token sep = next();
-                    return action.actOnDeclarator(type, iden, null, att);
+                    case Tok.Seperator:
+                        Token sep = next();
+                        return action.actOnDeclarator(type, iden, null, att);
+
+                    case Tok.Assign:
+                        Token assign = next();
+                        Exp exp = parseExpression();
+                        require(Tok.Seperator);
+                        return action.actOnDeclarator(type, iden, exp, att);
+
+                    case Tok.OpenParentheses:
+                        return parseFunc(type, iden, att);
+
+                    default:
+                        auto n1 = next();
+                        messages.report(UnexpectedTok, n1.location).arg(n1.getType);
+                        return null;
                 }
-                else if ( isa(Tok.Assign) )
-                {
-                    Token assign = next();
-                    Exp exp = parseExpression();
-                    require(Tok.Seperator);
-                    return action.actOnDeclarator(type, iden, exp, att);
-                }
-                else if ( isa(Tok.OpenParentheses) )
-                    return parseFunc(type, iden, att);
-                else
-                {
-                    auto n1 = next();
-                    messages.report(UnexpectedTok, n1.location).arg(n1.getType);
-                }
+                messages.report(InvalidDeclType, peek.location)
+                    .arg(sm.getText(peek.asRange));
+
+            default:
+                if (peek.isBasicType)
+                    goto case Tok.Identifier;
+
+                messages.report(UnexpectedTok, peek.location)
+                    .arg(sm.getText(peek.asRange));
+
                 return null;
-            }
-            t = peek(len);
-            messages.report(InvalidDeclType, t.location)
-                .arg(sm.getText(t.asRange));
-            while(len--)
-                next();
-            while( !isa(Tok.Identifier) && !isa(Tok.EOF))
-                next();
-            if ( isa(Tok.EOF ) )
-                messages.report(UnexpectedTok, t.location)
-                    .fatal(ExitLevel.Parser);
-
-            type = Id(peek);
-            goto parseDeclAfterInvalidType;
         }
-        else if (t.type == Tok.Struct)
-        {
-            Id type = Id(next());
-            Id iden = Id(require(Tok.Identifier));
-            
-            return parseStruct(type, iden, att);
-        }
-        else if (t.type == Tok.Class)
-        {
-            Id type = Id(next());
-            Id iden = Id(require(Tok.Identifier));
-            
-            return parseClass(type, iden, att);
-        }
-        else if (t.type == Tok.Interface)
-        {
-            Id type = Id(next());
-            Id iden = Id(require(Tok.Identifier));
-            
-            return parseInterface(type, iden, att);
-        }
-        messages.report(UnexpectedTok, t.location)
-            .arg(t.getType)
+        messages.report(UnexpectedTok, peek.location)
+            .arg(peek.getType)
             .arg(Tok.Identifier)
             .fatal(ExitLevel.Parser);
     }
@@ -536,169 +521,175 @@
      */
     Stmt parseStatement()
     {
-        Token t = peek;
-
-        if (t.isReturn)
-        {
-            Token ret = next();
-            Exp exp;
-            if (peek.type != Tok.Seperator)
-                exp = parseExpression();
-            require(Tok.Seperator);
-            return action.actOnReturnStmt(ret, exp);
-        }
-        /*
-           if (cond)
-           single statement | compound statement
-           [else
-           single statement | compound statement]
-         */
-        else if (t.isIf)
-        {
-            Token _if = next();
-
-            require(Tok.OpenParentheses);
-            Exp cond = parseExpression();
-            require(Tok.CloseParentheses);
-
-            Stmt thenB = parseSingleOrCompoundStatement();
-
-            // if there is no else part we use the if as token, to have
-            // something than can be passed along
-            Token _else = _if;
-            Stmt elseB;
-            if (peek.type == Tok.Else)
-            {
-                _else = next();
-                elseB = parseSingleOrCompoundStatement();
-            }
-
-            return action.actOnIfStmt(_if, cond, thenB, _else, elseB);
-
-        }
-        /*
-           while (cond)
-           single statement | compound statement
-         */
-        else if (t.isWhile)
-        {
-            Token _while = next();
-            require(Tok.OpenParentheses);
-            Exp cond = parseExpression();
-            require(Tok.CloseParentheses);
-            Stmt bodyStmt = parseSingleOrCompoundStatement();
-            return action.actOnWhileStmt(_while, cond, bodyStmt);
-
-        }
-        else if (t.isFor)
+        switch (peek.type)
         {
-            Token _for = next();
-            require(Tok.OpenParentheses);
-            Stmt init;
-            if ( isa(Tok.Seperator))
+            case Tok.Return:
+                Token ret = next();
+                Exp exp;
+                if (peek.type != Tok.Seperator)
+                    exp = parseExpression();
                 require(Tok.Seperator);
-            else
-                init = parseStatement();
+                return action.actOnReturnStmt(ret, exp);
+
+            case Tok.If:
+                Token _if = next();
+
+                require(Tok.OpenParentheses);
+                Exp cond = parseExpression();
+                require(Tok.CloseParentheses);
+
+                Stmt thenB = parseSingleOrCompoundStatement();
 
-            Exp cond;
-            if ( !isa(Tok.Seperator))
-                cond = parseExpression();
-            require(Tok.Seperator);
+                // if there is no else part we use the if as token, to have
+                // something than can be passed along
+                Token _else = _if;
+                Stmt elseB;
+                if (peek.type == Tok.Else)
+                {
+                    _else = next();
+                    elseB = parseSingleOrCompoundStatement();
+                }
+                return action.actOnIfStmt(_if, cond, thenB, _else, elseB);
 
-            Exp incre;
-            if ( !isa(Tok.CloseParentheses))
-                incre = parseExpression();
-            require(Tok.CloseParentheses);
+            case Tok.While:
+                Token _while = next();
+                require(Tok.OpenParentheses);
+                Exp cond = parseExpression();
+                require(Tok.CloseParentheses);
+                Stmt bodyStmt = parseSingleOrCompoundStatement();
+                return action.actOnWhileStmt(_while, cond, bodyStmt);
+
+            case Tok.For:
+                Token _for = next();
+                require(Tok.OpenParentheses);
+                Stmt init;
+                if ( isa(Tok.Seperator))
+                    require(Tok.Seperator);
+                else
+                    init = parseStatement();
 
-            Stmt bodyStmt = parseSingleOrCompoundStatement();
-            return action.actOnForStmt(_for, init, cond, incre, bodyStmt);
-        }
-        else if (t.isBasicType || t.isIdentifier)
-        {
-            Token iden = peek;
-            Token n = peek(1);
-            // Must be an decl, if we start with a basic type, or two
-            // identifiers in a row
-            if ( n.type == Tok.Star || n.type == Tok.OpenBracket)
-            {
-                int len = peekParseType;
-                if(peek(len).type == Tok.Identifier && len != 0)
-                    return action.actOnDeclStmt(parseVarDecl());
+                Exp cond;
+                if ( !isa(Tok.Seperator))
+                    cond = parseExpression();
+                require(Tok.Seperator);
 
-                Exp exp = parseExpression();
-                require(Tok.Seperator);
-                return action.actOnExprStmt(exp);
-            }
+                Exp incre;
+                if ( !isa(Tok.CloseParentheses))
+                    incre = parseExpression();
+                require(Tok.CloseParentheses);
+
+                Stmt bodyStmt = parseSingleOrCompoundStatement();
+                return action.actOnForStmt(_for, init, cond, incre, bodyStmt);
 
-            if (n.isIdentifier())
-                return action.actOnDeclStmt(parseVarDecl());
+            case Tok.Switch:                
+                auto t = next();
+                require(Tok.OpenParentheses);
+                auto target = parseExpression();
+                auto res = action.actOnStartOfSwitchStmt(t, target);
+                require(Tok.CloseParentheses);
+                require(Tok.OpenBrace);
+                while (true)
+                {
+                    Stmt[] statements;
+                    if (isa(Tok.Default))
+                    {
+                        Token _default = next();
+                        require(Tok.Colon);
+                        statements.length = 0;
+                        while (peek.type != Tok.Case
+                                && peek.type != Tok.Default
+                                && peek.type != Tok.CloseBrace)
+                            statements ~= parseStatement();
+                        action.actOnDefaultStmt(res, _default, statements);
+                        continue;
+                    }
 
-            // Expression: a.b, a = b, a(b) etc.
-            Exp exp = parseExpression();
-            require(Tok.Seperator);
-            return action.actOnExprStmt(exp);
-        }
-        else if (t.isSwitch)
-        {
-            next();
-            require(Tok.OpenParentheses);
-            auto target = parseExpression();
-            auto res = action.actOnStartOfSwitchStmt(t, target);
-            require(Tok.CloseParentheses);
-            require(Tok.OpenBrace);
-            while (true)
-            {
-                Stmt[] statements;
-                if (isa(Tok.Default))
-                {
-                    Token _default = next();
+                    Token _case = peek;
+                    if (_case.type != Tok.Case)
+                        break;
+                    next();
+
+                    Exp[] literals;
+                    do
+                    {
+                        Exp e = parseExpression();
+                        literals ~= e;
+                    }
+                    while (skip(Tok.Comma));
                     require(Tok.Colon);
-                    statements.length = 0;
+
                     while (peek.type != Tok.Case
                             && peek.type != Tok.Default
                             && peek.type != Tok.CloseBrace)
                         statements ~= parseStatement();
-                    action.actOnDefaultStmt(res, _default, statements);
-                    continue;
+
+                    action.actOnCaseStmt(res, _case, literals, statements);
+
+                    if (peek.type == Tok.CloseBrace)
+                        break;
+                }
+                require(Tok.CloseBrace);
+                return res;
+        
+            case Tok.Star:
+                auto exp = parseExpression();
+                require(Tok.Seperator);
+                return action.actOnExprStmt(exp);
+
+            case Tok.Identifier:
+                // If it's a '*' it must be a method. Otherwise it won't give 
+                // any sense.
+                if (isa(Tok.Function, 1)   ||
+                    isa(Tok.Identifier, 1) ||
+                    isa(Tok.Star, 1))      
+                    return action.actOnDeclStmt(parseDecl(Attribute()));
+
+                if (isa(Tok.OpenBracket, 1))
+                {
+                    int i = 1;
+                    while (isa(Tok.OpenBracket, i)  || 
+                           isa(Tok.Star, i)         ||
+                           isa(Tok.Identifier, i))
+                    {
+                        if (isa(Tok.Identifier, i))
+                            return action.actOnDeclStmt(parseDecl(Attribute()));
+
+                        i++;
+                        if (isa(Tok.Star,i-1))
+                            continue;
+                        // Must be OpenBracket here..
+
+                        if (isa(Tok.Integer, i))
+                            i++;
+                        else
+                            if (isa(Tok.CloseBracket, i))
+                                return action.actOnDeclStmt(parseDecl(Attribute()));
+                            else
+                                i++;
+
+                        if (!isa(Tok.CloseBracket, i))
+                            break;
+                        i++;
+                    }
+                    if (isa(Tok.Function, i))
+                        return action.actOnDeclStmt(parseDecl(Attribute()));
                 }
 
-                Token _case = peek;
-                if (_case.type != Tok.Case)
-                    break;
-                next();
-
-                Exp[] literals;
-                do
-                {
-                    Exp e = parseExpression();
-                    literals ~= e;
-                }
-                while (skip(Tok.Comma));
-                require(Tok.Colon);
-
-                while (peek.type != Tok.Case
-                        && peek.type != Tok.Default
-                        && peek.type != Tok.CloseBrace)
-                    statements ~= parseStatement();
+                // Expression: a.b, a = b, a(b) etc.
+                Exp exp = parseExpression();
+                require(Tok.Seperator);
+                return action.actOnExprStmt(exp);
+            
+            case Tok.Void: // And all basic types
+                return action.actOnDeclStmt(parseVarDecl());
 
-                action.actOnCaseStmt(res, _case, literals, statements);
+            default:
+                if (peek.isBasicType)
+                    goto case Tok.Void;
 
-                if (peek.type == Tok.CloseBrace)
-                    break;
-            }
-            require(Tok.CloseBrace);
-            return res;
-        }
-        else if (t.type == Tok.Star)
-        {
-            auto exp = parseExpression();
-            require(Tok.Seperator);
-            return action.actOnExprStmt(exp);
-        }
-        else
-        {
-            messages.report(UnexpectedBeginStmt, t.location).arg(t.getType);
-            return null;
+                messages.report(UnexpectedBeginStmt, peek.location).arg(peek.getType);
+                require(Tok.Seperator);
+                return null;
         }
     }
 
@@ -833,70 +824,56 @@
             messages.report(InvalidType, type.location);
 
         currentType = Id(type);
-        type = peek;
 
-        while(type.type == Tok.Star || type.type == Tok.OpenBracket)
+        while(true)
         {
-            if(type.type == Tok.Star)
-            {
-                currentType = PointerId(currentType);
-                next();
-            }
-            else
+            switch(peek.type)
             {
-                next();
-                if(peek.type == Tok.Integer)
-                    currentType = StaticArrayId(
-                            currentType, 
-                            action.actOnNumericConstant(
-                                require(Tok.Integer)));
-                require(Tok.CloseBracket);
+                case Tok.Star:
+                    currentType = PointerTypeId(currentType);
+                    next();
+                    break;
+                case Tok.OpenBracket:
+                    next();
+                    if (isa(Tok.Integer))
+                        currentType = StaticArrayTypeId(
+                                currentType, 
+                                action.actOnNumericConstant(
+                                    require(Tok.Integer)));
+                    require(Tok.CloseBracket);
+                    break;
+                case Tok.Function:
+                    next();
 
-            }
-            type = peek;
-        }
 
-        return currentType;
-    }
-
-    int peekParseType()
-    {
-        int i;
-        Token type = peek(i);
+                    require(Tok.OpenParentheses); // Remove the "(" token.
 
-        Id currentType;
+                    DeclT[] decls;
 
-        if ( !(type.isBasicType || type.type == Tok.Identifier) )
-            return 0;
+                    while(peek.type != Tok.CloseParentheses)
+                    {
+                        auto t = parseType();
+                        Id i;
+                        if(peek.type == Tok.Identifier)
+                            i = parseIdentifier();
 
-        currentType = Id(type);
-        type = peek(++i);
+                        // Act on function type param
+                        decls ~= action.actOnDeclarator(t, i, null, Attribute());
+
+                        if(peek.type == Tok.Comma)
+                            next();
+                    }
 
-        while(type.type == Tok.Star || type.type == Tok.OpenBracket)
-        {
-            if(type.type == Tok.Star)
-            {
-                i++;
+                    currentType = FunctionTypeId(currentType, decls);
+
+                    require(Tok.CloseParentheses); // Remove the ")"
+                    break;
+                default:
+                    goto end;
             }
-            else
-            {
-                if(peek(i++).type != Tok.OpenBracket)
-                    return 0;
-                if(peek(i).type == Tok.Integer)
-                {
-                    i++;
-                    if(peek(i++).type != Tok.CloseBracket)    
-                        return 0;
-                }
-                else
-                    if(peek(i++).type != Tok.CloseBracket)
-                        return 0;
-
-            }
-            type = peek(i);
         }
-
-        return i;
+end:
+        return currentType;
     }
 
 private:
@@ -1143,9 +1120,9 @@
         return true;
     }
 
-    bool isa(Tok t)
+    bool isa(Tok t, int i = 0)
     {
-        return peek.type == t;
+        return peek(i).type == t;
     }
 
     Token next()
--- a/sema/AstAction.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/sema/AstAction.d	Thu Jul 24 20:31:24 2008 +0200
@@ -27,14 +27,16 @@
     }
     private SourceManager sm;
 
-    private Identifier handleType(Id type)
+    private IdentifierTypeExp handleType(Id type)
     {
-        if(auto t = cast(PointerId)type)
-            return new PointerIdentifier(handleType(t.id));
-        if(auto t = cast(StaticArrayId)type)
-            return new StaticArrayIdentifier(handleType(t.id), cast(IntegerLit)t.number);
-        else
-            return identifierFromTok(type.tok);
+        if(auto t = cast(PointerTypeId)type)
+            return new PointerTypeExp(handleType(t.id));
+        if(auto t = cast(StaticArrayTypeId)type)
+            return new StaticArrayTypeExp(handleType(t.id), cast(IntegerLit)t.number);
+        if(auto t = cast(FunctionTypeId)type)
+            return new FunctionTypeExp(handleType(t.id), cast(VarDecl[])t.decls);
+        
+        return new IdentifierTypeExp(type.tok.location, sm.getText(type.tok.asRange));
     }
 
     private Identifier identifierFromTok(Token t)
@@ -139,7 +141,7 @@
 
     DeclT actOnStartOfFunctionDef(ref Id type, ref Id name, Attribute att)
     {
-        auto res = new FuncDecl(identifierFromTok(type.tok), identifierFromTok(name.tok));
+        auto res = new FuncDecl(handleType(type), identifierFromTok(name.tok));
         res.att = att;
         return res;
     }
@@ -150,7 +152,7 @@
         if(name)
             fd.addParam(handleType(type), identifierFromTok(name.tok));
         else
-            fd.addParam(identifierFromTok(type.tok));
+            fd.addParam(handleType(type));
     }
 
     DeclT actOnEndOfFunction(DeclT func, StmtT stmts)
--- a/sema/ScopeBuilder.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/sema/ScopeBuilder.d	Thu Jul 24 20:31:24 2008 +0200
@@ -10,11 +10,33 @@
 import sema.Visitor,
        basic.SmallArray;
 
+class SymbolFactory
+{
+    void put(Symbol symbol, DType type)
+    {
+        types[type] = symbol;
+    }
+
+    Symbol get(Symbol owner, DType type, Identifier i, Decl decl)
+    {
+        if (type in types)
+            return owner.createAlias(i.get, types[type], decl);
+        else
+            return owner.createMember(i.get, type, decl);
+    }
+
+    Symbol[DType] types;
+}
+
 class ForwardReference : Visitor!(void)
 {
+    this(SymbolFactory sf)
+    {
+        this.sf = sf;
+    }
     override void visit(Module[] modules)
     {
-        (new TypeBuilder).visit(modules);
+        (new TypeBuilder(sf)).visit(modules);
         this.modules = modules;
         inFunctionBodyStack.push(false);
         foreach (mod; modules)
@@ -62,10 +84,7 @@
             visitExp(d.init);
 
         DType t = typeOf(d.varType, d.env);
-        d.sym = current.symbol.createAlias(
-                d.identifier.get,
-                d.env.find(d.varType.get)[0].sym,
-                d);
+        d.sym = sf.get(current.symbol, t, d.identifier, d);
         d.sym.type = t;
     }
 
@@ -99,22 +118,40 @@
         current.symbol = old;
     }
 
+    override void visitFunctionTypeExp(FunctionTypeExp f)
+    {
+    }
+
     DType typeOf(Identifier id, Scope sc)
     {
-        if(auto i = cast(PointerIdentifier)id)
+        if(auto i = cast(PointerTypeExp)id)
             return (typeOf(i.pointerOf, sc)).getPointerTo();
-        else if(auto i = cast(StaticArrayIdentifier)id)
+        else if(auto i = cast(StaticArrayTypeExp)id)
             return typeOf(i.arrayOf, sc).getAsStaticArray(i.size);
+        else if(auto i = cast(FunctionTypeExp)id)
+        {
+            auto d = new DFunction(id);
+            d.returnType = typeOf(i.returnType, sc);
+            foreach (decl ; i.decls)
+                d.params ~= typeOf(decl.varType, sc);
+            return d;
+        }
         return sc.findType(id.get);
     }
 
     Module[] modules;
     Module current;
     SmallArray!(bool) inFunctionBodyStack;
+    SymbolFactory sf;
 }
 
 class TypeBuilder : Visitor!(void)
 {
+    this(SymbolFactory sf)
+    {
+        this.sf = sf;
+    }
+
     override void visit(Module[] modules)
     {
         foreach (mod; modules)
@@ -132,6 +169,7 @@
                 s.identifier.get, 
                 st,
                 s.env.find(s.identifier.get)[0]);
+        sf.put(s.sym, st);
 
         foreach (decl; s.decls)
         {
@@ -160,6 +198,8 @@
                 st,
                 s.env.find(s.identifier.get)[0]);
 
+        sf.put(s.sym, st);
+
         foreach (decl; s.decls)
         {
             DType type;
@@ -186,6 +226,7 @@
                 s.identifier.get, 
                 st,
                 s.env.find(s.identifier.get)[0]);
+        sf.put(s.sym, st);
 
         foreach (decl; s.decls)
         {
@@ -209,14 +250,15 @@
 
     DType typeOf(Identifier id, Scope sc)
     {
-        if(auto i = cast(PointerIdentifier)id)
+        if(auto i = cast(PointerTypeExp)id)
             return (typeOf(i.pointerOf, sc)).getPointerTo();
-        else if(auto i = cast(StaticArrayIdentifier)id)
+        else if(auto i = cast(StaticArrayTypeExp)id)
             return typeOf(i.arrayOf, sc).getAsStaticArray(i.size);
         return sc.findType(id.get);
     }
 
     Module current;
+    SymbolFactory sf;
 }
 
 
@@ -235,6 +277,7 @@
 
     this()
     {
+        sf = new SymbolFactory();
     }
 
     override void visit(Module[] modules)
@@ -242,7 +285,7 @@
         foreach(m ; modules)
             visitModule(m);
 
-        auto fr = new ForwardReference();
+        auto fr = new ForwardReference(sf);
 
         fr.visit(modules);
     }
@@ -446,6 +489,7 @@
 
 private:
     Scope[] table;
+    SymbolFactory sf;
 
     Scope push()
     {
--- a/sema/ScopeCheck.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/sema/ScopeCheck.d	Thu Jul 24 20:31:24 2008 +0200
@@ -29,7 +29,7 @@
 
     override void visitVarDecl(VarDecl d)
     {
-        if(!d.env.findType(d.varType.get))
+        if(d.identifier.get is null)
             messages.report(UndefinedType, d.varType.loc)
                 .arg(d.varType.get);
 
--- a/sema/Visitor.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/sema/Visitor.d	Thu Jul 24 20:31:24 2008 +0200
@@ -99,10 +99,14 @@
                 return visitCastExp(cast(CastExp)exp);
             case ExpType.Identifier:
                 return visitIdentifier(cast(Identifier)exp);
-            case ExpType.PointerIdentifier:
-                return visitPointerIdentifier(cast(PointerIdentifier)exp);
-            case ExpType.StaticArrayIdentifier:
-                return visitStaticArrayIdentifier(cast(StaticArrayIdentifier)exp);
+            case ExpType.IdentifierTypeExp:
+                return visitIdentifier(cast(Identifier)exp);
+            case ExpType.PointerTypeExp:
+                return visitPointerTypeExp(cast(PointerTypeExp)exp);
+            case ExpType.StaticArrayTypeExp:
+                return visitStaticArrayTypeExp(cast(StaticArrayTypeExp)exp);
+            case ExpType.FunctionTypeExp:
+                return visitFunctionTypeExp(cast(FunctionTypeExp)exp);
             case ExpType.StringExp:
                 return visitStringExp(cast(StringExp)exp);
             case ExpType.Index:
@@ -387,7 +391,7 @@
             return ExpT.init;
     }
 
-    ExpT visitPointerIdentifier(PointerIdentifier exp)
+    ExpT visitPointerTypeExp(PointerTypeExp exp)
     {
         visitExp(exp.pointerOf);
 
@@ -397,7 +401,7 @@
             return ExpT.init;
     }
 
-    ExpT visitStaticArrayIdentifier(StaticArrayIdentifier exp)
+    ExpT visitStaticArrayTypeExp(StaticArrayTypeExp exp)
     {
         visitExp(exp.arrayOf);
 
@@ -407,6 +411,19 @@
             return ExpT.init;
     }
 
+    ExpT visitFunctionTypeExp(FunctionTypeExp exp)
+    {
+        visitExp(exp.returnType);
+
+        foreach (decl ; exp.decls)
+            visitDecl(decl);
+
+        static if (is(ExpT == void))
+            return;
+        else
+            return ExpT.init;
+    }
+
     ExpT visitIndexExp(IndexExp exp)
     {
         visitExp(exp.target);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/parser/function_pointer.d	Thu Jul 24 20:31:24 2008 +0200
@@ -0,0 +1,6 @@
+
+int main()
+{
+}
+
+int function(int x) f;
--- a/tools/AstPrinter.d	Thu Jul 24 12:27:34 2008 +0200
+++ b/tools/AstPrinter.d	Thu Jul 24 20:31:24 2008 +0200
@@ -197,8 +197,8 @@
                 auto iden = cast(Identifier)exp;
                 printIdentifier(iden);
                 break;
-            case ExpType.PointerIdentifier:
-                auto iden = cast(PointerIdentifier)exp;
+            case ExpType.PointerTypeExp:
+                auto iden = cast(PointerTypeExp)exp;
                 printExp(iden.pointerOf);
                 print("*");
                 break;