diff parser/Parser.d @ 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 6cb2f4201e2a
children dc9bf56b7ace
line wrap: on
line diff
--- 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()