changeset 126:c3b24e7e8cf8

Carius changes to the parser. Parsing attributes, lexing many keywords(not all yet).
author Anders Johnsen <skabet@gmail.com>
date Tue, 27 May 2008 10:32:31 +0200
parents d604152de1eb
children d5b33ee318d4
files ast/Decl.d ast/Exp.d ast/Stmt.d basic/Attribute.d lexer/Keyword.d lexer/Lexer.d lexer/Token.d parser/Action.d parser/Parser.d sema/AstAction.d sema/TypeCheck.d tests/parser/assign_1.d tests/parser/float_1.d tests/parser/int_1.d tests/parser/public_1.d tools/AstPrinter.d
diffstat 16 files changed, 485 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/ast/Decl.d	Sun May 25 21:13:56 2008 +0200
+++ b/ast/Decl.d	Tue May 27 10:32:31 2008 +0200
@@ -9,7 +9,8 @@
 
 import sema.Scope,
        sema.DType,
-       basic.SmallArray;
+       basic.SmallArray,
+       basic.Attribute;
 
 enum DeclType
 {
@@ -34,6 +35,7 @@
 
     DeclType declType;
     Scope env;
+    Attribute att;
 }
 
 class VarDecl : Decl
--- a/ast/Exp.d	Sun May 25 21:13:56 2008 +0200
+++ b/ast/Exp.d	Tue May 27 10:32:31 2008 +0200
@@ -138,11 +138,11 @@
     }
 }
 
-class AssignExp : Exp
+class AssignExp : BinaryExp
 {
-    this(SLoc op, Exp identifier, Exp exp)
+    this(SLoc op_loc, Operator op, Exp identifier, Exp exp)
     {
-        super(ExpType.AssignExp, op);
+        super(ExpType.AssignExp, op_loc, op, identifier, exp);
         this.identifier = identifier;
         this.exp = exp;
     }
@@ -171,6 +171,11 @@
     public enum Operator
     {
         Assign,
+        AddAssign,
+        SubAssign,
+        MulAssign,
+        DivAssign,
+        ModAssign,
 
         Eq, Ne,
 
@@ -185,7 +190,7 @@
         And, Or, Xor,
     }
 
-    char[][] getOp = ["=","==","!=","<","<=",">",">=","+","-","*","/","%","<<",">>",">>>"];
+    char[][] getOp = ["=","+=","-=","*=","/=","%=","==","!=","<","<=",">",">=","+","-","*","/","%","<<",">>",">>>"];
 
     this(SLoc op_loc, Operator op, Exp left, Exp right)
     {
@@ -195,6 +200,14 @@
         this.right = right;
     }
 
+    protected this(ExpType e, SLoc op_loc, Operator op, Exp left, Exp right)
+    {
+        super(e, op_loc);
+        this.op = op;
+        this.left = left;
+        this.right = right;
+    }
+
     override DType type()
     {
         if (myType)
--- a/ast/Stmt.d	Sun May 25 21:13:56 2008 +0200
+++ b/ast/Stmt.d	Tue May 27 10:32:31 2008 +0200
@@ -71,7 +71,7 @@
         {
             auto i = new Identifier("ret.val");
             i.env = f.env;
-            auto ass = new AssignExp(SLoc.Invalid, i, exp);
+            auto ass = new AssignExp(SLoc.Invalid, BinaryExp.Operator.Assign, i, exp);
             ass.env = f.env;
             auto assStmt = new ExpStmt(ass);
             assStmt.env = f.env;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/basic/Attribute.d	Tue May 27 10:32:31 2008 +0200
@@ -0,0 +1,40 @@
+module basic.Attribute;
+
+enum Protection : uint
+{
+    Private   = 1<<0,
+    Public    = 1<<1,
+    Package   = 1<<2,
+    Protected = 1<<3,
+    Export    = 1<<4,
+}
+
+struct Attribute
+{
+
+    void setProtection(Protection p)
+    {
+        att &= 0xFFFFFFE0;
+        att |= ~p;
+    }
+
+    void setStatic()    { att &= ~Static; }
+    void setFinal()     { att &= ~Final; }
+    void setConst()     { att &= ~Const; }
+    void setAbstract()  { att &= ~Abstract; }
+    void setOverride()  { att &= ~Override; }
+    void setDepracted() { att &= ~Depracted; }
+    void setAuto()      { att &= ~Auto; }
+
+private:
+    uint att;
+
+
+    static const uint Static        = 1<<5;
+    static const uint Final         = 1<<6;
+    static const uint Const         = 1<<7;
+    static const uint Abstract      = 1<<8;
+    static const uint Override      = 1<<9;
+    static const uint Depracted     = 1<<10;
+    static const uint Auto          = 1<<11;
+}
--- a/lexer/Keyword.d	Sun May 25 21:13:56 2008 +0200
+++ b/lexer/Keyword.d	Tue May 27 10:32:31 2008 +0200
@@ -35,6 +35,16 @@
 
         // type related
         "struct"    : Tok.Struct,
+        "function"  : Tok.Function,
+        "delegate"  : Tok.Delegate,
+        "class"     : Tok.Class,
+        "interface" : Tok.Interface,
+        "union"     : Tok.Union,
+        "typedef"   : Tok.Typedef,
+        "typeid"    : Tok.Typeid,
+        "typeof"    : Tok.Typeof,
+        "sizeof"    : Tok.Sizeof,
+        "alias"     : Tok.Alias,
 
         // control flow
         "if"        : Tok.If,
@@ -43,11 +53,40 @@
         "switch"    : Tok.Switch,
         "case"      : Tok.Case,
         "default"   : Tok.Default,
+        "break"     : Tok.Break,
         "return"    : Tok.Return,
         "cast"      : Tok.Cast,
 
         // modules
         "module"    : Tok.Module,
-        "import"    : Tok.Import
+        "import"    : Tok.Import,
+
+        // attributse
+        "public"    : Tok.Public,
+        "private"   : Tok.Public,
+        "protected" : Tok.Protected,
+        "package"   : Tok.Package,
+        "export"    : Tok.Export,
+        "static"    : Tok.Static,
+        "final"     : Tok.Final,
+        "const"     : Tok.Const,
+        "abstract"  : Tok.Abstract,
+        "override"  : Tok.Override,
+        "depracted" : Tok.Depracted,
+        "auto"      : Tok.Auto,
+
+        // exceptions
+        "assert"    : Tok.Assert,
+        "throw"     : Tok.Throw,
+        "try"       : Tok.Try,
+        "catch"     : Tok.Catch,
+        "finally"   : Tok.Finally,
+
+        // functions
+        "in"        : Tok.In,
+        "out"       : Tok.Out,
+        "body"      : Tok.Body,
+
+        "asm"       : Tok.Asm
     ];
 }
--- a/lexer/Lexer.d	Sun May 25 21:13:56 2008 +0200
+++ b/lexer/Lexer.d	Tue May 27 10:32:31 2008 +0200
@@ -208,20 +208,28 @@
     }
     Token plus() 
     {
+        if(source[position] == '=')
+            return Token(Tok.PlusAssign, Loc(position++ - 1), 2);
         return Token(Tok.Plus, Loc(position - 1), 1);
     }
     Token minus() 
     {
+        if(source[position] == '=')
+            return Token(Tok.MinusAssign, Loc(position++ - 1), 2);
         return Token(Tok.Minus, Loc(position - 1), 1);
     }
     Token star() 
     {
+        if(source[position] == '=')
+            return Token(Tok.StarAssign, Loc(position++ - 1), 2);
         return Token(Tok.Star, Loc(position - 1), 1);
     }
     Token slash()
     {
         switch(source[position])
         {
+            case '=':
+                return Token(Tok.SlashAssign, Loc(position++ - 1), 2);
             case '/':
                 while(getNextChar != CharType.EOF)
                 {
@@ -275,6 +283,8 @@
 
     Token percent() 
     {
+        if(source[position] == '=')
+            return Token(Tok.PercentAssign, Loc(position++ - 1), 2);
         return Token(Tok.Percent, Loc(position - 1), 1);
     }
 
--- a/lexer/Token.d	Sun May 25 21:13:56 2008 +0200
+++ b/lexer/Token.d	Tue May 27 10:32:31 2008 +0200
@@ -64,7 +64,47 @@
      */
     bool isAssignment()
     {
-        return type == Tok.Assign;
+        return type >= Tok.Assign && type <= Tok.PercentAssign;
+    }
+
+    /**
+      Returns true for all attributes( public, static, private...)
+     */
+    bool isAttribute()
+    {
+        return type >= Tok.Public && type <= Tok.Auto;
+    }
+
+    /**
+      just a shortcut to avoid `token.type == tok.Switch`.
+     */
+    bool isSwitch()
+    {
+        return type == Tok.Switch;
+    }
+
+    /**
+      just a shortcut to avoid `token.type == tok.While`.
+     */
+    bool isWhile()
+    {
+        return type == Tok.While;
+    }
+
+    /**
+      just a shortcut to avoid `token.type == tok.If`.
+     */
+    bool isIf()
+    {
+        return type == Tok.If;
+    }
+
+    /**
+      just a shortcut to avoid `token.type == tok.Return`.
+     */
+    bool isReturn()
+    {
+        return type == Tok.Return;
     }
 
     /**
@@ -90,11 +130,20 @@
     /* Basic types */
     Identifier,
     Integer,
+    String,
 
     /* Basic operators */
     Assign,
-    Plus, Minus,
-    Star, Slash, Percent,
+    PlusAssign,
+    MinusAssign,
+    StarAssign,
+    SlashAssign,
+    PercentAssign,
+    Plus, 
+    Minus, 
+    Star, 
+    Slash, 
+    Percent, 
     LeftShift, RightShift, UnsignedRightShift,
     Comma,
 
@@ -130,17 +179,38 @@
 
     Void,
 
-    Struct,
+    Struct, Function, Delegate, Class,
+    Interface, Union, Typedef, Typeid,
+    Typeof, Sizeof, Alias,
 
     If, Else,
     While,
-    Switch, Case, Default,
-    Return, Cast,
-
-    String,
+    Switch, Case, Default, Break,
+    Return, Cast, 
 
     Module, Import,
 
+    /* Attributes */
+    Public, Private, Package, Protected, Export,
+    Static,
+    Final,
+    Const,
+    Abstract,
+    Override,
+    Depracted,
+    Auto,
+
+    Align,
+
+    Asm,
+
+    In, Out, Body, 
+    
+    Assert, Throw, Try, Catch, Finally,
+
+            
+
+
 }
 
 /**
@@ -180,10 +250,15 @@
         Tok.Dot:"Dot",
         Tok.Assign:"Assign",
         Tok.Plus:"Plus",
+        Tok.PlusAssign:"PlusAssign",
         Tok.Minus:"Minus",
+        Tok.MinusAssign:"MinusAssign",
         Tok.Star:"Star",
+        Tok.StarAssign:"StarAssign",
         Tok.Slash:"Slash",
+        Tok.SlashAssign:"SlashAssign",
         Tok.Percent:"Percent",
+        Tok.PercentAssign:"PercentAssign",
         Tok.LeftShift:"LeftShift",
         Tok.RightShift:"RightShift",
         Tok.UnsignedRightShift:"UnsignedRightShift",
@@ -201,6 +276,19 @@
         Tok.Cast:"Cast",
         Tok.Module:"Module",
         Tok.Import:"Import",
-        Tok.String:"String"
+        Tok.String:"String",
+        Tok.Public:"Public",
+        Tok.Private:"Private",
+        Tok.Protected:"Protected",
+        Tok.Package:"Package",
+        Tok.Export:"Export",
+        Tok.Static:"Static",
+        Tok.Final:"Finale",
+        Tok.Public:"Public",
+        Tok.Const:"Const",
+        Tok.Abstract:"Abstract",
+        Tok.Override:"Override",
+        Tok.Depracted:"Depracted",
+        Tok.Auto:"Auto"
     ];
 }
--- a/parser/Action.d	Sun May 25 21:13:56 2008 +0200
+++ b/parser/Action.d	Tue May 27 10:32:31 2008 +0200
@@ -2,6 +2,8 @@
 
 import lexer.Token;
 
+import basic.Attribute;
+
 /**
   Used to indicate what type of operator is used in a given binary expression
   (and unary expressions?)
@@ -9,6 +11,11 @@
 public enum Operator
 {
     Assign,
+    AddAssign,
+    SubAssign,
+    MulAssign,
+    DivAssign,
+    ModAssign,
 
     Eq, Ne,
 
@@ -148,7 +155,7 @@
       
       The other solution is an addParamToFunc or similar.
      */
-    DeclT actOnDeclarator(ref Id type, ref Id name, ExprT init)
+    DeclT actOnDeclarator(ref Id type, ref Id name, ExprT init, Attribute att)
     {
         return null;
     }
--- a/parser/Parser.d	Sun May 25 21:13:56 2008 +0200
+++ b/parser/Parser.d	Tue May 27 10:32:31 2008 +0200
@@ -5,7 +5,8 @@
 
 import parser.Action;
 
-import basic.Message;
+import basic.Message,
+       basic.Attribute;
 
 import basic.SmallArray,
        basic.SourceManager;
@@ -47,27 +48,88 @@
             m = action.actOnImplicitModule(loc, sm.getFile(loc));
         }
 
+        Attribute att;
         while (lexer.peek.type != Tok.EOF)
-            foreach (d; parseDeclDef())
+            foreach (d; parseDeclDef(&att))
                 action.actOnModuleDecl(m, d);
 
         return m;
     }
 
 private:
-    Decl[] parseDeclDef()
+    Decl[] parseDeclDef(Attribute* a)
     {
         Token t = lexer.peek;
         if (t.type == Tok.Import)
             return parseImports();
         else
-            return [parseDecl()];
+            return [parseDecl(a)];
     }
 
-    Decl parseDecl()
+    Decl parseDecl(Attribute* all_res)
     {
         Token t = lexer.peek;
 
+        Attribute att = *all_res;
+
+        while ( t.isAttribute )
+        {
+            Attribute* a = &att;
+            bool sco;
+            if(lexer.peek(1).type == Tok.Colon)
+                sco = true;
+
+LSwitch:    switch(t.type)
+            {
+                case Tok.Public:
+                    a.setProtection(Protection.Public);
+                    break;
+                case Tok.Private:
+                    a.setProtection(Protection.Private);
+                    break;
+                case Tok.Package:
+                    a.setProtection(Protection.Package);
+                    break;
+                case Tok.Protected:
+                    a.setProtection(Protection.Protected);
+                    break;
+                case Tok.Export:
+                    a.setProtection(Protection.Export);
+                    break;
+                case Tok.Static:
+                    a.setStatic;
+                    break;
+                case Tok.Final:
+                    a.setFinal;
+                    break;
+                case Tok.Const:
+                    a.setConst;
+                    break;
+                case Tok.Abstract:
+                    a.setAbstract;
+                    break;
+                case Tok.Override:
+                    a.setOverride;
+                    break;
+                case Tok.Depracted:
+                    a.setDepracted;
+                    break;
+                case Tok.Auto:
+                    a.setAuto;
+                    break;
+            }
+            if(sco)
+            {
+                sco = false;
+                a = all_res;
+                lexer.next;
+                goto LSwitch;
+            }
+            lexer.next;
+            t = lexer.peek;
+        }
+
+
         if (t.isBasicType || t.isIdentifier)
         {
             Id type;
@@ -82,19 +144,20 @@
                 if (next.type == Tok.Seperator)
                 {
                     Token sep = lexer.next();
-                    return action.actOnDeclarator(type, iden, null);
+                    return action.actOnDeclarator(type, iden, null, att);
                 }
                 else if (next.type == Tok.Assign)
                 {
                     Token assign = lexer.next();
                     Exp exp = parseExpression();
                     require(Tok.Seperator);
-                    return action.actOnDeclarator(type, iden, exp);
+                    return action.actOnDeclarator(type, iden, exp, att);
                 }
                 else if (next.type == Tok.OpenParentheses)
                     return parseFunc(type, iden);
                 else
                     messages.report(UnexpectedTok, next.location).arg(next.getType);
+                return null;
             }
             t = lexer.peek(len);
             messages.report(InvalidDeclType, t.location)
@@ -111,7 +174,7 @@
             Id type = Id(lexer.next);
             Id iden = Id(require(Tok.Identifier));
             
-            return parseStruct(type, iden);
+            return parseStruct(type, iden, att);
         }
         messages.report(UnexpectedTok, t.location)
             .arg(t.getType)
@@ -202,34 +265,17 @@
     /**
       Parse struct
      */
-    Decl parseStruct(Id type, Id iden)
+    Decl parseStruct(Id type, Id iden, Attribute att)
     {
-        auto decl = action.actOnDeclarator(type, iden, null);
+        auto decl = action.actOnDeclarator(type, iden, null, att);
 
         require(Tok.OpenBrace);
 
-        while(lexer.peek.isBasicType || lexer.peek.isIdentifier)
+        Attribute a;
+        while(lexer.peek.isBasicType || lexer.peek.isIdentifier || lexer.peek.isAttribute)
         {
-            auto m_decl = parseDecl();
+            auto m_decl = parseDecl(&a);
             action.actOnStructMember(decl, m_decl); 
-/*            Id var_type = Id(lexer.next);
-            Id var_iden = Id(require(Tok.Identifier));
-            Token next = lexer.peek();
-            if (next.type == Tok.Seperator)
-            {
-                Token sep = lexer.next();
-                action.actOnStructMember(decl, var_type, var_iden, null);
-                continue;
-            }
-            else if (next.type == Tok.Assign)
-            {
-                Token assign = lexer.next();
-                Exp exp = parseExpression();
-                require(Tok.Seperator);
-                action.actOnStructMember(decl, var_type, var_iden, exp);
-                continue;
-            }
-            messages.report(UnexpectedTok, next.location).arg(next.getType);*/
         }
 
         require(Tok.CloseBrace);
@@ -246,54 +292,57 @@
     {
         Token t = lexer.peek;
 
-        switch(t.type)
+        if (t.isReturn)
         {
-            case Tok.Return:
-                Token ret = lexer.next;
-                Exp exp;
-                if (lexer.peek.type != Tok.Seperator)
-                    exp = parseExpression();
-                require(Tok.Seperator);
-                return action.actOnReturnStmt(ret, exp);
+            Token ret = lexer.next;
+            Exp exp;
+            if (lexer.peek.type != Tok.Seperator)
+                exp = parseExpression();
+            require(Tok.Seperator);
+            return action.actOnReturnStmt(ret, exp);
 
             /*
                if (cond)
-                single statement | compound statement
+               single statement | compound statement
                [else
-                single statement | compound statement]
+               single statement | compound statement]
              */
-            case Tok.If:
-                Token _if = lexer.next();
+        }
+        else if (t.isIf)
+        {
+            Token _if = lexer.next();
 
-                require(Tok.OpenParentheses);
-                Exp cond = parseExpression();
-                require(Tok.CloseParentheses);
+            require(Tok.OpenParentheses);
+            Exp cond = parseExpression();
+            require(Tok.CloseParentheses);
 
-                Stmt thenB = parseSingleOrCompoundStatement();
+            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 (lexer.peek.type == Tok.Else)
-                {
-                    _else = lexer.next;
-                    elseB = 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 (lexer.peek.type == Tok.Else)
+            {
+                _else = lexer.next;
+                elseB = parseSingleOrCompoundStatement();
+            }
 
-                return action.actOnIfStmt(_if, cond, thenB, _else, elseB);
+            return action.actOnIfStmt(_if, cond, thenB, _else, elseB);
 
             /*
                while (cond)
-                single statement | compound statement
+               single statement | compound statement
              */
-            case Tok.While:
-                Token _while = lexer.next;
-                require(Tok.OpenParentheses);
-                Exp cond = parseExpression();
-                require(Tok.CloseParentheses);
-                Stmt bodyStmt = parseSingleOrCompoundStatement();
-                return action.actOnWhileStmt(_while, cond, bodyStmt);
+        }
+        else if (t.isWhile)
+        {
+            Token _while = lexer.next;
+            require(Tok.OpenParentheses);
+            Exp cond = parseExpression();
+            require(Tok.CloseParentheses);
+            Stmt bodyStmt = parseSingleOrCompoundStatement();
+            return action.actOnWhileStmt(_while, cond, bodyStmt);
 
             /*
                One of four things:
@@ -304,48 +353,47 @@
 
                The assignments should be handled as binary expressions?
              */
-            case Tok.Identifier:
-                Token iden = lexer.peek;
-                Token n = lexer.peek(1);
-                // Must be an decl, if we start with a basic type, or two
-                // identifiers in a row
-                if (iden.isBasicType() || iden.isIdentifier())
-                {
-                    if ( n.type == Tok.Star || n.type == Tok.OpenBracket)
-                    {
-                        int len = peekParseType;
-                        if(lexer.peek(len).type == Tok.Identifier && len != 0)
-                            return action.actOnDeclStmt(parseVarDecl());
+        }
+        else if (t.isBasicType || t.isIdentifier)
+        {
+            Token iden = lexer.peek;
+            Token n = lexer.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(lexer.peek(len).type == Tok.Identifier && len != 0)
+                    return action.actOnDeclStmt(parseVarDecl());
 
-                        Exp exp = parseExpression();
-                        require(Tok.Seperator);
-                        return action.actOnExprStmt(exp);
-                    }
-                        
-                    if (n.isIdentifier())
-                        return action.actOnDeclStmt(parseVarDecl());
+                Exp exp = parseExpression();
+                require(Tok.Seperator);
+                return action.actOnExprStmt(exp);
+            }
+
+            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);
-                }
-
-            case Tok.Switch:
-                messages.report(UnexpectedTok, lexer.peek.location).arg(lexer.next.getType);
-                return null;
-
-            default:
-                if (t.isBasicType())
-                    goto case Tok.Identifier;
-                if (t.type == Tok.Star)
-                {
-                    auto exp = parseExpression();
-                    require(Tok.Seperator);
-                    return action.actOnExprStmt(exp);
-                }
-                messages.report(UnexpectedBeginStmt, lexer.peek.location).arg(lexer.next.getType);
-                return null;
+            // Expression: a.b, a = b, a(b) etc.
+            Exp exp = parseExpression();
+            require(Tok.Seperator);
+            return action.actOnExprStmt(exp);
+        }
+        else if(t.isSwitch)
+        {
+            messages.report(UnexpectedTok, lexer.peek.location).arg(lexer.next.getType);
+            return null;
+        }
+        else
+        {
+            if (t.type == Tok.Star)
+            {
+                auto exp = parseExpression();
+                require(Tok.Seperator);
+                return action.actOnExprStmt(exp);
+            }
+            messages.report(UnexpectedBeginStmt, lexer.peek.location).arg(lexer.next.getType);
+            return null;
         }
         messages.report(UnexpectedTok, t.location);
         return null;
@@ -361,7 +409,8 @@
         if (skip(Tok.Assign))
             init = parseExpression();
         require(Tok.Seperator);
-        Decl d = action.actOnDeclarator(type, id, init);
+        Attribute att;
+        Decl d = action.actOnDeclarator(type, id, init, att);
         return d;
     }
 
@@ -676,7 +725,12 @@
 
     static const BinOp[] _binary =
     [
-        {Tok.Assign,    1, false, Operator.Assign},
+        {Tok.Assign,        1, false, Operator.Assign},
+        {Tok.PlusAssign,    1, false, Operator.AddAssign},
+        {Tok.MinusAssign,   1, false, Operator.SubAssign},
+        {Tok.StarAssign,    1, false, Operator.MulAssign},
+        {Tok.SlashAssign,   1, false, Operator.DivAssign},
+        {Tok.PercentAssign, 1, false, Operator.ModAssign},
 
         // =, += etc. 1
         // (need special-case for the ternary operator at this level)
--- a/sema/AstAction.d	Sun May 25 21:13:56 2008 +0200
+++ b/sema/AstAction.d	Tue May 27 10:32:31 2008 +0200
@@ -4,7 +4,8 @@
 
 import lexer.Token;
 
-import basic.SourceManager;
+import basic.SourceManager,
+       basic.Attribute;
 
 import ast.Module,
        ast.Exp,
@@ -81,13 +82,17 @@
         d.explicitSymbols ~= [t, n];
     }
 
-    override DeclT actOnDeclarator(ref Id type, ref Id id, ExprT init)
+    override DeclT actOnDeclarator(ref Id type, ref Id id, ExprT init, Attribute att)
     {
+        Decl d;
         Exp exp = cast(Exp)init;
         if(type.tok.type == Tok.Struct)
-            return new StructDecl(identifierFromTok(id.tok));
+            d = new StructDecl(identifierFromTok(id.tok));
         else
-            return new VarDecl(handleType(type), identifierFromTok(id.tok), exp);
+            d = new VarDecl(handleType(type), identifierFromTok(id.tok), exp);
+
+        d.att = att;
+        return d;
     }
     
     override void actOnStructMember(DeclT st_decl, DeclT m_decl) //ref Id type, ref Id name, ExprT init)
@@ -186,12 +191,18 @@
     {
         Exp left = cast(Exp)l;
         Exp right = cast(Exp)r;
-        if (op == Operator.Assign)
-            return new AssignExp(op_loc, left, right);
-        else
+        switch(op)
         {
-            BinaryExp.Operator bin_op = cast(BinaryExp.Operator)op;
-            return new BinaryExp(op_loc, bin_op, left, right);
+            case Operator.Assign:
+            case Operator.AddAssign:
+            case Operator.SubAssign:
+            case Operator.MulAssign:
+            case Operator.DivAssign:
+            case Operator.ModAssign:
+                return new AssignExp(op_loc, cast(BinaryExp.Operator)op, left, right);
+            default:
+                BinaryExp.Operator bin_op = cast(BinaryExp.Operator)op;
+                return new BinaryExp(op_loc, bin_op, left, right);
         }
     }
 
--- a/sema/TypeCheck.d	Sun May 25 21:13:56 2008 +0200
+++ b/sema/TypeCheck.d	Tue May 27 10:32:31 2008 +0200
@@ -19,36 +19,67 @@
     {
         super.visitBinaryExp(exp);
 
-        if(exp.left.type.byteSize > exp.right.type.byteSize)
+        if(!(exp.left.type is exp.right.type))
         {
-            if(!exp.right.type.hasImplicitConversionTo(exp.left.type))
+            if (!exp.right.type.hasImplicitConversionTo(exp.left.type) &&
+                !exp.left.type.hasImplicitConversionTo(exp.right.type))
                 messages.report(InvalidImplicitCast, exp.loc)
                     .arg(exp.right.type.toString)
                     .arg(exp.left.type.toString);
-
-            auto castExp = new CastExp(
-                    SLoc.Invalid,
-                    new Identifier(exp.left.type.name),
-                    exp.right);
-            castExp.env = exp.env;
-            exp.right = castExp;
-        }
+            else
+            {
+                CastExp castExp;
+                if(exp.left.type.isReal && exp.right.type.isReal)
+                    if(exp.left.type.byteSize > exp.right.type.byteSize)
+                        castExp = new CastExp(
+                            SLoc.Invalid,
+                            new Identifier(exp.left.type.name),
+                            exp.right);
+                    else
+                        castExp = new CastExp(
+                            SLoc.Invalid,
+                            new Identifier(exp.right.type.name),
+                            exp.left);
+                else if(exp.left.type.isReal || exp.right.type.isReal)
+                    if(exp.left.type.isReal)
+                        castExp = new CastExp(
+                            SLoc.Invalid,
+                            new Identifier(exp.left.type.name),
+                            exp.right);
+                    else
+                        castExp = new CastExp(
+                            SLoc.Invalid,
+                            new Identifier(exp.right.type.name),
+                            exp.left);
+                else
+                    if(exp.left.type.byteSize > exp.right.type.byteSize)
+                        castExp = new CastExp(
+                            SLoc.Invalid,
+                            new Identifier(exp.left.type.name),
+                            exp.right);
+                    else if(exp.left.type.byteSize > exp.right.type.byteSize)
+                        castExp = new CastExp(
+                            SLoc.Invalid,
+                            new Identifier(exp.right.type.name),
+                            exp.left);
+                    else
+                        castExp = new CastExp(
+                            SLoc.Invalid,
+                            new Identifier(exp.left.type.name),
+                            exp.right);
 
-        if(exp.left.type.byteSize < exp.right.type.byteSize)
-        {
-            if(!exp.left.type.hasImplicitConversionTo(exp.right.type))
-                messages.report(InvalidImplicitCast, exp.loc)
-                    .arg(exp.right.type.toString)
-                    .arg(exp.left.type.toString);
 
-            auto castExp = new CastExp(
-                    SLoc.Invalid,
-                    new Identifier(exp.right.type.name),
-                    exp.left);
-            castExp.env = exp.env;
-            exp.left = castExp;
+                if(castExp)
+                {
+                    castExp.env = exp.env;
+                    if(castExp.exp == exp.right)
+                        exp.right = castExp;
+                    else
+                        exp.left = castExp;
+
+                }
+            }
         }
-
     }
 
     override void visitCallExp(CallExp exp)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/parser/assign_1.d	Tue May 27 10:32:31 2008 +0200
@@ -0,0 +1,13 @@
+
+
+int main()
+{
+    int x = 0;
+    x  = 2;
+    x += 5;
+    return x;
+/*    x -= 2;
+    x *= 3;
+    x /= 4;
+    x %= 3; */
+}
--- a/tests/parser/float_1.d	Sun May 25 21:13:56 2008 +0200
+++ b/tests/parser/float_1.d	Tue May 27 10:32:31 2008 +0200
@@ -2,7 +2,7 @@
 
 void main()
 {
-    float f1  = 4_.5_e5+4;
-    float f2  = 4._5_e+344;
-    float f3  = 4.__5_e-_2;
+    float f1  = 4_.5_e+54;
+    float f2  = 4._5_e+34;
+    float f3  = 4.__5_e-2;
 }
--- a/tests/parser/int_1.d	Sun May 25 21:13:56 2008 +0200
+++ b/tests/parser/int_1.d	Tue May 27 10:32:31 2008 +0200
@@ -16,6 +16,4 @@
     ulong i9  = 0UL;
     ulong i10 = 18_446_744_073_709_551_615LU;
 
-    ulong i10 = 18_446_744_073_709_551_615_23LU;
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/parser/public_1.d	Tue May 27 10:32:31 2008 +0200
@@ -0,0 +1,16 @@
+public struct name
+{
+static:
+    public void foo()
+    {
+    }
+
+    private void bar()
+    {
+    }
+    final int i;
+}
+
+void main()
+{
+}
--- a/tools/AstPrinter.d	Sun May 25 21:13:56 2008 +0200
+++ b/tools/AstPrinter.d	Tue May 27 10:32:31 2008 +0200
@@ -139,7 +139,9 @@
             case ExpType.AssignExp:
                 auto assignExp = cast(AssignExp)exp;
                 printExp(assignExp.identifier);
-                print(" = ");
+                print(" ");
+                print(assignExp.getOp[assignExp.op]);
+                print(" ");
                 printExp(assignExp.exp);
                 break;
             case ExpType.MemberReference: