Anirban Bhattacharjee <banirban@novell.com>
[mono.git] / mcs / mbas / mb-parser.jay
index 86c25894505b0f2d0758e422dc582d1ef196f93a..8463b685797863637342a9f23ce8bf603fd2871b 100644 (file)
@@ -3,13 +3,12 @@
 // Mono.MonoBASIC.Parser.cs (from .jay): The Parser for the MonoBASIC compiler
 //
 // Author: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
+//                Anirban Bhattacharjee (banirban@novell.com)
 //
 // Licensed under the terms of the GNU GPL
 //
 // Copyright (C) 2001 A Rafael D Teixeira
 //
-// TODO:
-//     Nearly everything
 //
 
 namespace Mono.MonoBASIC
@@ -21,6 +20,18 @@ namespace Mono.MonoBASIC
        using Mono.Languages;
        using Mono.MonoBASIC;
 
+       public class MBASException : ApplicationException
+       {
+               public int code;
+               public Location loc;
+
+               public MBASException(int code, Location loc, string text) : base(text)
+               {
+                       this.code = code;
+                       this.loc = loc;
+               }
+       }
+
        /// <summary>
        ///    The MonoBASIC Parser
        /// </summary>
@@ -128,7 +139,7 @@ namespace Mono.MonoBASIC
                Stack expr_stack; 
                
                Stack tmp_blocks;
-           Stack statement_stack;
+               Stack statement_stack;
 
                // A stack for With expressions.
                //
@@ -154,6 +165,205 @@ namespace Mono.MonoBASIC
                        return list;
                }
 
+               bool in_external_source = false;
+               int in_marked_region = 0;
+
+               TokenizerController tokenizerController;
+               IfElseStateMachine ifElseStateMachine;
+
+               
+               public class IfElseStateMachine {
+                       
+                       public enum State {
+                       START,
+                       IF_SEEN,
+                       ELSEIF_SEEN,
+                       ELSE_SEEN,
+                       ENDIF_SEEN,
+                       MAX
+                       }
+               
+                       public enum Token {
+                       START,
+                       IF,
+                       ELSEIF,
+                       ELSE,
+                       ENDIF,
+                       EOF,
+                       MAX
+                       }
+
+                       State state;
+                       Stack stateStack;
+
+                       public static Hashtable errStrings = new Hashtable();
+
+                       int err=0;
+                       static int[,] errTable = new int[(int)State.MAX, (int)Token.MAX];
+               
+                       static IfElseStateMachine()
+                       {
+                               // FIXME: Fix both the error nos and the error strings. 
+                               // Currently the error numbers and the error strings are 
+                               // just placeholders for getting the state-machine going.
+
+                               errStrings.Add(0, "");
+                               errStrings.Add(30012, "#If must end with a matching #End If");
+                               errStrings.Add(30013, "#ElseIf, #Else or #End If must be preceded by a matching #If");
+                               errStrings.Add(30014, "#ElseIf must be preceded by a matching #If or #ElseIf");
+                               errStrings.Add(30028, "#Else must be preceded by a matching #If or #ElseIf");
+                               errStrings.Add(32030, "#ElseIf cannot follow #Else as part of #If block");
+
+                               errTable[(int)State.START, (int)Token.IF] = 0;
+                               errTable[(int)State.START, (int)Token.ELSEIF] = 30014;
+                               errTable[(int)State.START, (int)Token.ELSE] = 30028;
+                               errTable[(int)State.START, (int)Token.ENDIF] = 30013;
+                               errTable[(int)State.START, (int)Token.EOF] = 0;
+
+                               errTable[(int)State.IF_SEEN, (int)Token.IF] = 0;
+                               errTable[(int)State.IF_SEEN, (int)Token.ELSEIF] = 0;
+                               errTable[(int)State.IF_SEEN, (int)Token.ELSE] = 0;
+                               errTable[(int)State.IF_SEEN, (int)Token.ENDIF] = 0;
+                               errTable[(int)State.IF_SEEN, (int)Token.EOF] = 30012;
+
+                               errTable[(int)State.ELSEIF_SEEN, (int)Token.IF] = 0;
+                               errTable[(int)State.ELSEIF_SEEN, (int)Token.ELSEIF] = 0;
+                               errTable[(int)State.ELSEIF_SEEN, (int)Token.ELSE] = 0;
+                               errTable[(int)State.ELSEIF_SEEN, (int)Token.ENDIF] = 0;
+                               errTable[(int)State.ELSEIF_SEEN, (int)Token.EOF] = 30012;
+
+                               errTable[(int)State.ELSE_SEEN, (int)Token.IF] = 0;
+                               errTable[(int)State.ELSE_SEEN, (int)Token.ELSEIF] = 32030;
+                               errTable[(int)State.ELSE_SEEN, (int)Token.ELSE] = 32030;
+                               errTable[(int)State.ELSE_SEEN, (int)Token.ENDIF] = 0;
+                               errTable[(int)State.ELSE_SEEN, (int)Token.EOF] = 30012;
+
+                               errTable[(int)State.ENDIF_SEEN, (int)Token.IF] = 0;
+                               errTable[(int)State.ENDIF_SEEN, (int)Token.ELSEIF] = 30014;
+                               errTable[(int)State.ENDIF_SEEN, (int)Token.ELSE] = 30028;
+                               errTable[(int)State.ENDIF_SEEN, (int)Token.ENDIF] = 30013;
+                               errTable[(int)State.ENDIF_SEEN, (int)Token.EOF] = 0;
+                       }
+
+                       public IfElseStateMachine()
+                       {
+                               state = State.START;
+
+                               stateStack = new Stack();
+                               stateStack.Push(state);
+                       }
+
+                       // The parameter here need not be qualified with IfElseStateMachine
+                       // But it hits a bug in mcs. So temporarily scoping it so that builds
+                       // are not broken.
+
+                       public void HandleToken(IfElseStateMachine.Token tok)
+                       {
+                               err = (int) errTable[(int)state, (int)tok];
+
+                               if(err != 0)
+                                       throw new ApplicationException("Unexpected pre-processor directive #"+tok); 
+                               
+                               if(tok == Token.IF) {
+                                       stateStack.Push(state);
+                                       state = (State) tok;
+                               }
+                               else if(tok == Token.ENDIF) {
+                                       state = (State)stateStack.Pop();
+                               }
+                               else
+                                       state = (State)tok;
+                       }
+
+                       public int Error {
+                               get {
+                                       return err;
+                               }
+                       }
+
+                       public string ErrString {
+                               get {
+                                       return (string) errStrings[err];
+                               }
+                       }
+               }
+
+               
+               public class TokenizerController {
+                       
+                       struct State
+                       {
+                               public bool CanAcceptTokens;
+                               public bool CanSelectBlock;
+
+                       }
+
+                       State currentState;
+                       Stack stateStack;
+                       Tokenizer lexer;
+
+                       public TokenizerController(Tokenizer lexer)
+                       {
+                               this.lexer = lexer;
+                               stateStack = new Stack();
+
+                               currentState.CanAcceptTokens = true;
+                               currentState.CanSelectBlock = true;
+
+                               stateStack.Push(currentState);
+                       }
+
+                       State parentState {
+                               get {
+                                       return (State)stateStack.Peek();
+                               }
+                       }
+
+                       public bool IsAcceptingTokens {
+                               get {
+                                       return currentState.CanAcceptTokens;
+                               }
+                       }
+
+                       public void PositionCursorAtNextPreProcessorDirective()
+                       {
+                               lexer.PositionCursorAtNextPreProcessorDirective();
+                       }
+
+                       public void PositionTokenizerCursor(IfElseStateMachine.Token tok, BoolLiteral expr)
+                       {
+                               if(tok == IfElseStateMachine.Token.ENDIF) {
+                                       currentState = (State)stateStack.Pop();
+
+                                       if(currentState.CanAcceptTokens)
+                                               return;
+                                       else {
+                                               PositionCursorAtNextPreProcessorDirective();
+                                               return;
+                                       }
+                               }
+                               
+                               if(tok == IfElseStateMachine.Token.IF) {
+                                       stateStack.Push(currentState);
+                                       
+                                       currentState.CanAcceptTokens = parentState.CanAcceptTokens;
+                                       currentState.CanSelectBlock = true;
+                               }
+                       
+                               if(parentState.CanAcceptTokens && 
+                                   currentState.CanSelectBlock && (bool)(expr.GetValue()) ) {
+                                   
+                                   currentState.CanAcceptTokens = true;
+                                   currentState.CanSelectBlock = false; 
+                                   return;
+                               }
+                               else {
+                                       currentState.CanAcceptTokens = false;
+                                       PositionCursorAtNextPreProcessorDirective();
+                                       return;
+                               }
+                       }
+               }
 %}
 
 %token EOF
@@ -204,12 +414,14 @@ namespace Mono.MonoBASIC
 %token DEFAULT 
 %token DELEGATE        
 %token DIM
+%token DIRECTCAST
 %token DO      
 %token DOUBLE  
 %token EACH    
 %token ELSE
 %token ELSEIF
-%token END     
+%token END
+%token ENDIF
 %token ENUM    
 %token EOL
 %token ERASE
@@ -223,7 +435,8 @@ namespace Mono.MonoBASIC
 %token FRIEND
 %token FUNCTION
 %token GET
-//%token GETTYPE
+%token GETTYPE
+%token GOSUB
 %token GOTO    
 %token HANDLES
 %token IF      
@@ -301,6 +514,7 @@ namespace Mono.MonoBASIC
 %token UNICODE
 %token UNTIL
 %token VARIANT 
+%token WEND
 %token WHEN    
 %token WHILE   
 %token WITH
@@ -309,6 +523,8 @@ namespace Mono.MonoBASIC
 %token XOR
 %token YIELD // MonoBASIC extension
 
+%token HASH
+
 /* MonoBASIC single character operators/punctuation. */
 
 %token OPEN_BRACKET  "["
@@ -330,7 +546,7 @@ namespace Mono.MonoBASIC
 %token DIV            "/"
 %token OP_EXP         "^"
 %token INTERR         "?"
-%token OP_IDIV        "\\"
+%token OP_IDIV        "\\" //FIXME: This should be "\"
 %token OP_CONCAT      "&"
 %token EXCLAMATION    "!"
 
@@ -395,15 +611,27 @@ namespace Mono.MonoBASIC
 %start compilation_unit
 %%
 
+end_of_stmt
+       : logical_end_of_line
+       | COLON
+       ;       
+
+logical_end_of_line
+       : EOL
+       | logical_end_of_line pp_directive 
+       ;
+
 compilation_unit
-       : opt_option_directives
+       : logical_end_of_line
+         opt_option_directives
          opt_imports_directives 
          opt_attributes
          opt_declarations 
          EOF
          {
-               $$ = $4;
+               $$=$5;
          }
+       
        ;
          
 opt_option_directives
@@ -449,7 +677,7 @@ text_or_binary
        ;
          
 option_explicit_directive
-       : OPTION EXPLICIT on_off EOL
+       : OPTION EXPLICIT on_off logical_end_of_line
          {
                if (!UseExtendedSyntax)
                        OptionExplicit = (bool)$3;
@@ -462,7 +690,7 @@ option_explicit_directive
          
                        
 option_strict_directive
-       : OPTION STRICT on_off EOL
+       : OPTION STRICT on_off logical_end_of_line
          {
                if (!UseExtendedSyntax)
                        OptionStrict = (bool)$3;
@@ -474,7 +702,7 @@ option_strict_directive
        ;
          
 option_compare_directive
-       : OPTION COMPARE text_or_binary EOL
+       : OPTION COMPARE text_or_binary logical_end_of_line
          {
                OptionCompareBinary = (bool)$3;
          }
@@ -539,7 +767,7 @@ opt_type_character
 
 qualified_identifier
        : identifier
-       | qualified_identifier DOT identifier 
+       | qualified_identifier DOT identifier // FIXME: It should be qualified_identifier DOT identifier-or-keyword
          { 
            $$ = (($1).ToString ()) + "." + ($3.ToString ()); 
          }
@@ -556,148 +784,123 @@ imports_directives
        ;
 
 imports_directive
-       : IMPORTS imports_terms EOL
+       : IMPORTS imports_terms logical_end_of_line
        ;
 
 imports_terms
        : imports_term
-       | imports_terms COMMA imports_terms
+       | imports_terms COMMA imports_term
        ;
        
 imports_term
-       : qualified_identifier
+       : namespace_or_type_name 
          {
                RootContext.SourceBeingCompiled.Imports ((string) $1, lexer.Location);
          }
-       | qualified_identifier ASSIGN qualified_identifier
+       | identifier ASSIGN namespace_or_type_name 
          {
                RootContext.SourceBeingCompiled.ImportsWithAlias ((string) $1, (string) $3, lexer.Location);
          }
        ;
 
-opt_attributes
-       : /* empty */
-       | attribute_sections    { $$ = $1; }
+opt_params
+       : /* empty */   { $$ = Parameters.EmptyReadOnlyParameters; }
+       | OPEN_PARENS CLOSE_PARENS      { $$ = Parameters.EmptyReadOnlyParameters; }
+       | OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS    { $$ = $2; }
+       ;
+
+global_attribute_list
+       : global_attribute
+       | global_attribute_list COMMA global_attribute
        ;
 
-attribute_sections
-       : attribute_section
-          { 
-               AttributeSection sect = (AttributeSection) $1;
+global_attribute
+       : attribute_modifier COLON attribute
 
-               if (sect.Target == "assembly") 
-                       RootContext.AddGlobalAttributeSection (current_container, sect);
-               
-               $$ = new Attributes ((AttributeSection) $1, lexer.Location);
-               
-          }    
-          /* 
-             FIXME: we should check if extended syntax is enabled;
-                    otherwise an exception should be thrown since VB.NET 
-                    only allows one attribute section 
-          */  
-       | attribute_sections attribute_section
-         {
-               Attributes attrs = null;
-               AttributeSection sect = (AttributeSection) $2;
-
-               if (sect.Target == "assembly")
-                       RootContext.AddGlobalAttributeSection (current_container, sect);
-
-               if ($1 != null) {
-                       attrs = (Attributes) $1;
-                       attrs.AddAttributeSection (sect);
-               }
-               
-               $$ = attrs;
-         }     
+attribute_modifier
+       : ASSEMBLY 
+       | MODULE
+       | identifier 
+          { 
+               Report.Error (658, lexer.Location, "`" + (string)$1 + "' is an invalid attribute target");
+          }
        ;
-       
-attribute_section
-       : OP_LT attribute_target_specifier attribute_list OP_GT
-         { 
-               string target = null;
-               
-               if ($2 != null)
-                       target = (string) $2;
-               
-               $$ = new AttributeSection (target, (ArrayList) $3);
-         }     
-       | OP_LT attribute_list OP_GT
-         {
-               $$ = new AttributeSection (null, (ArrayList) $2);
-         }     
-       ; 
 
-attribute_target_specifier
-       : attribute_target COLON
-         {
-               $$ = $1;
-         }
+opt_attributes
+       : /* empty */
+       | attributes    { $$ = $1; }
+       ;
+
+attr_begin
+       : OP_LT
        ;
 
-attribute_target
-       : identifier
-         {
-               CheckAttributeTarget ((string) $1);
-               $$ = $1;
-         }
-        | EVENT  { $$ = "event"; }       
-        | RETURN { $$ = "return"; }
+attr_end
+       : OP_GT
        ;
-       
+
+attributes
+       : attr_begin attribute_list attr_end
+         {
+               AttributeSection sect = new AttributeSection (null, (ArrayList) $2);
+               $$ = new Attributes (sect, lexer.Location);
+         }
+       | attr_begin global_attribute_list attr_end logical_end_of_line
+       ; 
+
 attribute_list
-       : attribute 
-         {
-               ArrayList attrs = new ArrayList ();
-               attrs.Add ($1);
+       : attribute 
+         {
+               ArrayList attrs = new ArrayList ();
+               attrs.Add ($1);
 
-               $$ = attrs;
+               $$ = attrs;
               
-         }     
-       | attribute_list COMMA attribute
-         {
-               ArrayList attrs = (ArrayList) $1;
-               attrs.Add ($3);
+         }     
+       | attribute_list COMMA attribute
+         {
+               ArrayList attrs = (ArrayList) $1;
+               attrs.Add ($3);
+
+               $$ = attrs;
+         }     
+       ;
 
-               $$ = attrs;
-         }     
-       ;
-       
 attribute 
-       : attribute_name
-         {
-               $$ = lexer.Location;
-         }
-         opt_attribute_arguments
-         {
-               $$ = new Mono.MonoBASIC.Attribute ((string) $1, (ArrayList) $3, (Location) $2);
-         }       
-       ;
-       
+       : attribute_name
+         {
+               $$ = lexer.Location;
+         }
+         opt_attribute_arguments
+         {
+               $$ = new Mono.MonoBASIC.Attribute ((string) $1, (ArrayList) $3, (Location) $2);
+         }       
+       ;
+
 attribute_name
-       : type_name 
+       : namespace_or_type_name 
        ;
                        
 opt_attribute_arguments
        : /* empty */   { $$ = null; }
-       | OPEN_PARENS attribute_arguments CLOSE_PARENS
+       | OPEN_PARENS opt_attribute_arguments_list CLOSE_PARENS
          {
                $$ = $2;
          }     
        ;
+
+opt_attribute_arguments_list
+       : /* empty */
+       | attribute_arguments_list
+       ;               
        
-attribute_arguments
-       : opt_positional_argument_list
+attribute_arguments_list
+       : positional_argument_list
          {
-               if ($1 == null)
-                       $$ = null;
-               else {
-                       ArrayList args = new ArrayList ();
-                       args.Add ($1);
-               
-                       $$ = args;
-               }
+               ArrayList args = new ArrayList ();
+               args.Add ($1);
+       
+               $$ = args;
          }
         | positional_argument_list COMMA named_argument_list
          {
@@ -717,21 +920,15 @@ attribute_arguments
          }
         ;
 
-
-opt_positional_argument_list
-       : /* empty */           { $$ = null; } 
-       | positional_argument_list
-       ;
-
 positional_argument_list
-       : expression
+       : constant_expression
          {
                ArrayList args = new ArrayList ();
                args.Add (new Argument ((Expression) $1, Argument.AType.Expression));
 
                $$ = args;
          }
-        | positional_argument_list COMMA expression
+        | positional_argument_list COMMA constant_expression
         {
                ArrayList args = (ArrayList) $1;
                args.Add (new Argument ((Expression) $3, Argument.AType.Expression));
@@ -758,7 +955,7 @@ named_argument_list
         ;
 
 named_argument
-       : identifier ATTR_ASSIGN expression
+       : identifier ATTR_ASSIGN constant_expression //FIXME: It should be identifier_or_keyword ATTR_ASSIGN constant_expression
          {
                $$ = new DictionaryEntry (
                        (string) $1, 
@@ -767,21 +964,12 @@ named_argument
        ;
                                
 namespace_declaration
-       : opt_attributes NAMESPACE qualified_identifier EOL
+       : NAMESPACE qualified_identifier logical_end_of_line
          {
-               Attributes attrs = (Attributes) $1;
-
-               if (attrs != null) {
-                       foreach (AttributeSection asec in attrs.AttributeSections)
-                               if (asec.Target == "assembly")
-                                       RootContext.AddGlobalAttributeSection (current_container, asec);
-               }
-                         
-               current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$3);
+               current_namespace = RootContext.Tree.RecordNamespace(current_namespace, name, (string)$2);
          } 
-         opt_imports_directives
          opt_declarations
-         END NAMESPACE EOL
+         END NAMESPACE logical_end_of_line
          { 
                current_namespace = current_namespace.Parent;
          }
@@ -807,8 +995,14 @@ type_spec_declaration
        ;
 
 class_declaration
-       : CLASS identifier EOL opt_inherits opt_implements
+       : CLASS identifier logical_end_of_line opt_inherits opt_implements
          {
+               // Module members are static by default, but Class *can't* be declared static
+               // so we must fix it, if mbas was the one actually responsible for this
+               // instead of triggering an error.
+               if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+                       current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+         
                Class new_class;
                string name;
                
@@ -821,10 +1015,20 @@ class_declaration
                RootContext.Tree.RecordDecl (name, new_class);
          }
          opt_class_member_declarations
-         END CLASS EOL
+         END CLASS logical_end_of_line
          {
                Class new_class = (Class) current_container;
-               new_class.Bases = (ArrayList) $4;       
+               
+               ArrayList bases = (ArrayList) $4;
+
+               ArrayList ifaces = (ArrayList) $5;
+               if (ifaces != null){
+                       if (bases != null)      
+                               bases.AddRange(ifaces);
+                       else
+                               bases = ifaces;
+               }
+               new_class.Bases = bases;
        
                current_container = current_container.Parent;
                CheckDef (current_container.AddClass (new_class), new_class.Name, new_class.Location);
@@ -835,12 +1039,12 @@ class_declaration
 
 opt_inherits
        : /* empty */                           { $$ = null; }
-       | INHERITS type_list EOL        { $$ = $2; }
+       | INHERITS type_list logical_end_of_line        { $$ = $2; }
        ;
 
 opt_implements
        : /* empty */                           { $$ = null; }
-       | IMPLEMENTS type_list EOL      { $$ = $2; }
+       | IMPLEMENTS type_list logical_end_of_line      { $$ = $2; }
        ;
 
 opt_modifiers
@@ -882,7 +1086,7 @@ modifier
        ;
 
 module_declaration
-       : MODULE identifier EOL
+       : MODULE identifier logical_end_of_line
          { 
                Module new_module;
                string name;
@@ -897,7 +1101,7 @@ module_declaration
                RootContext.Tree.RecordDecl(name, new_module);
          }
          opt_module_member_declarations
-         END MODULE EOL
+         END MODULE logical_end_of_line
          {
                Module new_module = (Module)current_container;
 
@@ -937,7 +1141,7 @@ module_member_declaration
        ;
 
 module_member_declarator
-       :  static_constructor_declaration
+       :  constructor_declaration
        |  method_declaration
           { 
                Method method = (Method) $1;
@@ -952,7 +1156,7 @@ module_member_declarator
        ;
        
 constant_declaration
-       : CONST constant_declarators EOL
+       : CONST constant_declarators logical_end_of_line
        {
                // Module members are static by default, but constants *can't* be declared static
                // so we must fix it, if mbas was the one actually responsible for this
@@ -1019,9 +1223,7 @@ class_member_declarator
        |  property_declaration                 
        |  event_declaration    
        |  withevents_declaration       /* This is a field but must be treated specially, see below */
-       /*|  type_declaration  */
-       |  class_declaration            
-       |  enum_declaration             
+       |  type_spec_declaration
        ;
        
        
@@ -1037,7 +1239,7 @@ must_override_declaration
        ;
        
 must_override_sub_declaration
-       : MUSTOVERRIDE SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
+       : MUSTOVERRIDE SUB identifier opt_params logical_end_of_line
          {     
                if (current_container is Module)
                        Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
@@ -1048,22 +1250,21 @@ must_override_sub_declaration
                current_modifiers |= Modifiers.ABSTRACT;
                                        
                Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $3,
-                                           (Parameters) $5, null, null, lexer.Location);
+                                           (Parameters) $4, null, null, lexer.Location);
                                            
                if (!(current_container is Class))
                        Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");               
                        
-               // FIXME ASAP: This will crash the compiler at resolution time                  
                $$ = method;                        
          }
        ;
 
        
 must_override_func_declaration
-       : MUSTOVERRIDE FUNCTION identifier opt_type_character OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_type_with_ranks EOL
+       : MUSTOVERRIDE FUNCTION identifier opt_type_character opt_params opt_type_with_ranks logical_end_of_line
          {     
-               Expression ftype = ($8 == null) ? (($4 == null) ? TypeManager.  
-                       system_object_expr : (Expression) $4 ) : (Expression) $8;
+               Expression ftype = ($6 == null) ? (($4 == null) ? TypeManager.  
+                       system_object_expr : (Expression) $4 ) : (Expression) $6;
 
                if (current_container is Module)
                        Report.Error (433, "Methods in a Module cannot be declared 'MustOverride'.");
@@ -1074,7 +1275,7 @@ must_override_func_declaration
                current_modifiers |= Modifiers.ABSTRACT;
                                                        
                Method method = new Method ((Expression) ftype, (int) current_modifiers, 
-                                               (string) $3,(Parameters) $6, null, null, 
+                                               (string) $3,(Parameters) $5, null, null, 
                                                lexer.Location);
                                            
                if (!(current_container is Class))
@@ -1085,54 +1286,68 @@ must_override_func_declaration
        ;
        
 sub_declaration
-       : SUB identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_evt_handler opt_implement_clause EOL
+       : SUB identifier opt_params opt_evt_handler opt_implement_clause logical_end_of_line
          { 
-               current_local_parameters = (Parameters) $4;
+               current_local_parameters = (Parameters) $3;
                start_block(); 
 
                // Structure members are Public by default                      
                if ((current_container is Struct) && (current_modifiers == 0))
                        current_modifiers = Modifiers.PUBLIC;           
-                       
+
                member_location = lexer.Location;
          }
          opt_statement_list 
-         END SUB EOL
+         END SUB logical_end_of_line
          {
                Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
-                                           (Parameters) current_local_parameters, null, (Expression) $7
-                                           member_location);
+                                           (Parameters) current_local_parameters, (Attributes) current_attributes
+                                           (ArrayList) $5, member_location);
        
                method.Block = (Block) end_block();
                $$ = method;
 
-               if ($6 != null) { /* we have an event handler to take care of */
-                       // This wouldn't work: AddHandler ((Expression)$6, (string) $2);
+               if ($4 != null) { 
+                       // we have an event handler to take care of 
+
                        string evt_def = ((MemberAccess)$6).ToString();
                        int pos = evt_def.LastIndexOf (".");
-                       string evt_target = ((string) $2).Substring (0, pos);
+                       string evt_target = evt_def.Substring (0, pos);
+                       bool found = false;
+               
+                       if (current_container.Properties != null) {
+                               foreach (Property p in current_container.Properties) {
+                                       if (p.Name == evt_target) {
+                                               Location loc = lexer.Location;
 
-                       foreach (Property p in current_container.Properties) {
-                               if (p.Name == evt_target) {
-                                       // FIXME: See below 
-                                       // RemoveHandler (p.Set.Block, (Expression)$6, (string) $2);
-                                       AddHandler (p.Set.Block, (Expression)$6, (string) $2);
-                                       break;
-                               }
-                       }                               
+                                               Statement addhnd = (Statement) new AddHandler ((Expression) $4, 
+                                                                                       DecomposeQI((string) $2, loc), 
+                                                                                       DecomposeQI(evt_target, loc), loc);
+
+                                               current_container.AddEventHandler (addhnd);
+                                               found = true;
+                                               break;
+                                       }
+                               }               
+                       }
+
+                       if (!found){
+                               Report.Error(30506, lexer.Location,
+                                               evt_target + " is not declared with WithEvents");
+                       }
                }       
          }       
        ;
        
 func_declaration
        : FUNCTION identifier opt_type_character
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_type_with_ranks opt_implement_clause EOL
+         opt_params opt_type_with_ranks opt_implement_clause logical_end_of_line
          { 
-               current_local_parameters = (Parameters) $5;
+               current_local_parameters = (Parameters) $4;
                member_location = lexer.Location;
                start_block(); 
                                
-               Expression ftype = ($7 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $7;
+               Expression ftype = ($5 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5;
 
                // Structure members are Public by default                      
                if ((current_container is Struct) && (current_modifiers == 0))
@@ -1144,20 +1359,20 @@ func_declaration
                declare_local_variables ((Expression) ftype, retval, lexer.Location);
          }       
          opt_statement_list
-         END FUNCTION EOL
+         END FUNCTION logical_end_of_line
          {
-               Expression ftype = ($7 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $7;
+               Expression ftype = ($5 == null) ? (($3 == null) ? TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5;
 
                Method method = new Method ((Expression) ftype, (int) current_modifiers, (string) $2,
-                                           (Parameters) current_local_parameters, null, 
-                                           (Expression) $8, member_location);
+                                           (Parameters) current_local_parameters, (Attributes) current_attributes,/* (Attributes) currx ent_attributes,  */
+                                           (ArrayList) $6, member_location);
                method.Block = end_block();
                $$ = method;
          }       
        ;               
 
 struct_declaration
-       : STRUCTURE identifier EOL
+       : STRUCTURE identifier logical_end_of_line
          opt_implement_clause
          {
                Struct new_struct;
@@ -1187,7 +1402,7 @@ struct_declaration
                CheckDef (current_container.AddStruct (new_struct), new_struct.Name, new_struct.Location);
                $$ = new_struct;
          }
-         END STRUCTURE EOL
+         END STRUCTURE logical_end_of_line
        ;
        
 opt_struct_member_declarations
@@ -1204,14 +1419,19 @@ struct_member_declaration
        : opt_modifiers
          struct_member_declarator
        ;
+       
 struct_member_declarator       
        : field_declaration
-       //| constant_declaration
+       | constant_declaration
+       | constructor_declaration
        | method_declaration
+         { 
+               Method method = (Method) $1;
+               CheckDef (current_container.AddMethod (method), method.Name, method.Location);
+         }     
        | property_declaration
        | event_declaration
-       | constructor_declaration
-       | type_declaration
+       | type_spec_declaration
 
        /*
         * This is only included so we can flag error 575:
@@ -1221,26 +1441,59 @@ struct_member_declarator
        ;
        
 event_declaration
-       : EVENT identifier AS type EOL
+       : EVENT identifier AS type opt_implement_clause logical_end_of_line
          {
                VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
 
                Event e = new Event ((Expression) $4, var.identifier, 
                                     null, current_modifiers, null, null, 
-                                    current_attributes, lexer.Location);
+                                    current_attributes, (ArrayList) $5,
+                                    lexer.Location);
 
                CheckDef (current_container.AddEvent (e), e.Name, e.Location);
-
          }
-//     | EVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
-//       {
-//             throw new NotSupportedException();
-//       }
-       ;       
+       | EVENT identifier opt_params opt_implement_clause logical_end_of_line
+         {
+               string delName = null;
+
+               if ($4 == null) {
+                       delName = (string) $2;
+                       delName = delName + "EventHandler";
+                       Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate 
+                                                       (current_container, TypeManager.system_void_expr, 
+                                                       (int) current_modifiers, MakeName(delName), (Parameters) $3, 
+                                                       (Attributes) current_attributes, lexer.Location);
+                                                         
+                       del.Namespace = current_namespace;
+                       CheckDef (current_container.AddDelegate (del), del.Name, lexer.Location);
+               } else {
+                       ArrayList impls = (ArrayList) $4;
+                       if (impls.Count > 1) {
+                               string expstr = "Event '" + ((Expression) impls[1]).ToString () +
+                                       "' can not be implemented with Event '" +
+                                       (string) $2 + "', since it's delegate type does not match " +
+                                       "with the delegate type of '" + ((Expression) impls[0]).ToString () + "'";
+                               Report.Error (31407, lexer.Location, expstr);
+                       }                       
+                       Expression impl = (Expression) impls[0];  
+                       delName = impl.ToString();
+                       delName = delName.Substring (delName.LastIndexOf(".") + 1);
+                       delName = delName + "EventHandler";
+               }
+               
+               Event e = new Event (DecomposeQI (delName, lexer.Location),
+                                        (string) $2, 
+                                    null, current_modifiers, null, null, 
+                                    current_attributes, (ArrayList) $4, 
+                                    lexer.Location);
 
+               CheckDef (current_container.AddEvent (e), e.Name, e.Location);
+         }
+       ;
+       
 enum_declaration
-       : ENUM identifier opt_type_spec EOL
-         opt_enum_member_declarations
+       : ENUM identifier opt_type_spec logical_end_of_line
+         opt_enum_member_declarations // FIXME: BC30280: Enum must contain atleast one member
          { 
                Location enum_location = lexer.Location;
                string full_name = MakeName ((string) $2);
@@ -1271,7 +1524,7 @@ enum_declaration
                RootContext.Tree.RecordDecl (full_name, e);
 
          }
-         END ENUM EOL
+         END ENUM logical_end_of_line
        ;
 
 opt_enum_member_declarations
@@ -1298,7 +1551,7 @@ enum_member_declarations
        ;
 
 enum_member_declaration
-       : opt_attributes identifier EOL
+       : opt_attributes identifier logical_end_of_line
          {
                $$ = new VariableDeclaration ((string) $2, null, lexer.Location, (Attributes) $1);
          }
@@ -1306,14 +1559,14 @@ enum_member_declaration
          {
                  $$ = lexer.Location;
          }
-          ASSIGN expression EOL
+          ASSIGN expression logical_end_of_line
          { 
                $$ = new VariableDeclaration ((string) $2, $5, lexer.Location, (Attributes) $1);
          }
        ;
                
 interface_declaration
-       : INTERFACE identifier EOL
+       : INTERFACE identifier logical_end_of_line
          {
                Interface new_interface;
                string full_interface_name = MakeName ((string) $2);
@@ -1341,7 +1594,7 @@ interface_declaration
                          new_interface.Name, new_interface.Location);
 
          }
-         END INTERFACE EOL
+         END INTERFACE logical_end_of_line
        ;
 
 opt_interface_base
@@ -1384,85 +1637,197 @@ interface_member_declarations
        ;
 
 interface_member_declaration
+       : opt_attributes
+         opt_modifiers
+         { 
+               current_attributes = (Attributes) $1;
+               current_modifiers = ((int)$2) | Modifiers.ABSTRACT; 
+         }
+         interface_member_declarator
+         {
+               $$ = $3;
+         }
+       ;
+       
+interface_member_declarator
        : interface_method_declaration          
          { 
-               InterfaceMethod m = (InterfaceMethod) $1;
-
+               Method m = (Method) $1;
                CheckDef (current_interface.AddMethod (m), m.Name, m.Location);
          }
        | interface_property_declaration        
-         { 
-               InterfaceProperty p = (InterfaceProperty) $1;
-               
-               CheckDef (current_interface.AddProperty (p), p.Name, p.Location);
-          }
        | interface_event_declaration 
-          { 
-               InterfaceEvent e = (InterfaceEvent) $1;
-
-               CheckDef (current_interface.AddEvent (e), e.Name, lexer.Location);
-         }
        ;
 
-opt_new
-       : /* empty */   { $$ = false; }
-       | NEW           { $$ = true; }
-       ;
-       
 interface_method_declaration
-       : SUB identifier
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
-         {
-               $$ = new InterfaceMethod (TypeManager.system_void_expr, (string) $2, false,
-                                         (Parameters) $4, current_attributes, lexer.Location);
-         }
-       | FUNCTION identifier opt_type_character
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS AS type
+       : SUB identifier opt_params logical_end_of_line
          {
-               if ($3 != null && $3 != $8)
-                       Report.Error (-1, lexer.Location, "Type character conflicts with declared type."); // TODO: Correct error number and message text
+               Method method = new Method (TypeManager.system_void_expr, (int) current_modifiers, (string) $2,
+                                           (Parameters) $3, current_attributes, null, lexer.Location);
                
-               $$ = new InterfaceMethod (
-                                         (Expression) $8, (string) $2, false, (Parameters) $5,
-                                         current_attributes, lexer.Location);
+               $$ = method;
          }
-       | FUNCTION identifier type_character
-         OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
+       | FUNCTION identifier opt_type_character opt_params opt_type_with_ranks logical_end_of_line
          {
-               $$ = new InterfaceMethod (
-                                         (Expression) $3, (string) $2, false, (Parameters) $5,
-                                         current_attributes, lexer.Location);
+               Expression ftype = ($5 == null) ? (($3 == null) ? TypeManager.  
+                       system_object_expr : (Expression) $3 ) : (Expression) $5;
+               
+               Method method = new Method ((Expression) ftype, (int) current_modifiers, 
+                                               (string) $2,(Parameters) $4, current_attributes, null, 
+                                               lexer.Location);
+               
+               $$ = method;
          }
        ;
 
 interface_property_declaration
-       : opt_modifiers PROPERTY identifier
-         OPEN_PARENS
-         opt_formal_parameter_list
-         CLOSE_PARENS opt_type_spec EOL
+       : PROPERTY identifier opt_type_character opt_property_parameters opt_type_spec logical_end_of_line
          {
-               // FIXME we MUST pass property parameters
-               $$ = new InterfaceProperty ((Expression) $6, (string) $2, false,
-                                           true, true, current_attributes,
-                                           lexer.Location);
+               Expression ftype = ($5 == null) ? (($3 == null) ? 
+                               TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5;
+
+               current_local_parameters = (Parameters) $4;
+               if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
+                       get_parameters = current_local_parameters.Copy (lexer.Location);
+                       set_parameters = current_local_parameters.Copy (lexer.Location);
+                       
+                       Parameter implicit_value_parameter = new Parameter (
+                                       ftype, "Value", Parameter.Modifier.NONE, null);
+                       
+                       set_parameters.AppendParameter (implicit_value_parameter);
+               }
+               else
+               {
+                       get_parameters = Parameters.EmptyReadOnlyParameters;
+                       set_parameters = new Parameters (null, null ,lexer.Location); 
+                       
+                       Parameter implicit_value_parameter = new Parameter (
+                                       ftype, "Value", Parameter.Modifier.NONE, null);
+                       
+                       set_parameters.AppendParameter (implicit_value_parameter);
+               }
+               lexer.PropertyParsing = true;
+               
+               Accessor get_block = new Accessor (null, null); 
+               Accessor set_block = new Accessor (null, null); 
+                               
+               Property prop = new Property ((Expression) ftype, (string) $2, current_modifiers,
+                                        get_block, set_block, current_attributes, lexer.Location,
+                                        null, get_parameters, set_parameters, null);
+    
+               CheckDef (current_interface.AddProperty (prop), prop.Name, lexer.Location);
+               
+               get_implicit_value_parameter_type = null;
+               set_implicit_value_parameter_type = null;
+               get_parameters = null;
+               set_parameters = null;
+               current_local_parameters = null;                        
          }
        ;
        
 interface_event_declaration
-       : opt_attributes opt_new EVENT type identifier EOL
+       : EVENT identifier AS type logical_end_of_line
+         {
+               VariableDeclaration var = new VariableDeclaration ((string) $2, (Expression) $4, lexer.Location);
+
+               Event e = new Event ((Expression) $4, var.identifier, 
+                                    null, current_modifiers, null, null, 
+                                    current_attributes, lexer.Location);
+
+               CheckDef (current_interface.AddEvent (e), e.Name, e.Location);
+
+         }
+       | EVENT identifier opt_params logical_end_of_line
          {
-               $$ = new InterfaceEvent ((Expression) $4, (string) $5, (bool) $2, (Attributes) $1,
-                                        lexer.Location);
+               string delName = (string) $2;
+               delName = delName + "EventHandler";
+               int delModifiers = (current_modifiers & ~Modifiers.ABSTRACT);
+           Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate 
+                                               (current_container, TypeManager.system_void_expr, 
+                                            (int) delModifiers, MakeName(delName), (Parameters) $3, 
+                                            (Attributes) current_attributes, lexer.Location);
+                                                 
+               del.Namespace = current_namespace;
+               CheckDef (current_interface.AddDelegate (del), del.Name, lexer.Location);
+         
+               Event e = new Event (DecomposeQI (delName, lexer.Location),
+                                        (string) $2, 
+                                    null, current_modifiers, null, null, 
+                                    current_attributes, lexer.Location);
+
+               CheckDef (current_interface.AddEvent (e), e.Name, e.Location);
          }
        ;
 
- property_declaration
-         : opt_modifiers PROPERTY identifier opt_property_parameters AS type opt_implement_clause EOL
-         {
-               get_implicit_value_parameter_type = (Expression) $6;
-               get_implicit_value_parameter_name = (string) $3;
+property_declaration
+       : abstract_propery_declaration
+       | non_abstract_propery_declaration 
+       ;
+       
+abstract_propery_declaration
+       : MUSTOVERRIDE PROPERTY identifier opt_type_character opt_property_parameters opt_type_spec logical_end_of_line
+         {     
+               Expression ftype = ($6 == null) ? (($4 == null) ? 
+                               TypeManager.system_object_expr : (Expression) $4 ) : (Expression) $6;
+
+               if (current_container is Module)
+                       Report.Error (30503, "Properties in a Module cannot be declared 'MustOverride'.");
+                       
+               if (current_container is Struct)
+                       Report.Error (435, "Methods in a Structure cannot be declared 'MustOverride'.");
+                               
+               current_modifiers |= Modifiers.ABSTRACT;
+               
+               current_local_parameters = (Parameters) $5;
+               if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
+                       get_parameters = current_local_parameters.Copy (lexer.Location);
+                       set_parameters = current_local_parameters.Copy (lexer.Location);
+                       
+                       Parameter implicit_value_parameter = new Parameter (
+                                       ftype, "Value", Parameter.Modifier.NONE, null);
+                       
+                       set_parameters.AppendParameter (implicit_value_parameter);
+               }
+               else
+               {
+                       get_parameters = Parameters.EmptyReadOnlyParameters;
+                       set_parameters = new Parameters (null, null ,lexer.Location); 
+                       
+                       Parameter implicit_value_parameter = new Parameter (
+                                       ftype, "Value", Parameter.Modifier.NONE, null);
+                       
+                       set_parameters.AppendParameter (implicit_value_parameter);
+               }
+               lexer.PropertyParsing = true;
                
-               current_modifiers = (int) $1; 
+               Accessor get_block = new Accessor (null, null); 
+               Accessor set_block = new Accessor (null, null); 
+                               
+               Property prop = new Property ((Expression) ftype, (string) $3, current_modifiers, 
+                                        get_block, set_block, current_attributes, lexer.Location,
+                                        null, get_parameters, set_parameters, null);
+    
+               if (!(current_container is Class))
+                       Report.Error (9999, "THIS SHOULD NEVER HAPPEN!");
+                       
+               CheckDef (current_container.AddProperty (prop), prop.Name, lexer.Location);
+               
+               get_implicit_value_parameter_type = null;
+               set_implicit_value_parameter_type = null;
+               get_parameters = null;
+               set_parameters = null;
+               current_local_parameters = null;                                
+         }     
+       ;
+       
+       
+ non_abstract_propery_declaration
+         : PROPERTY identifier opt_type_character opt_property_parameters opt_type_spec opt_implement_clause logical_end_of_line
+         {
+               get_implicit_value_parameter_type  = 
+                       ($5 == null) ? (($3 == null) ? 
+                               TypeManager.system_object_expr : (Expression) $3 ) : (Expression) $5;
+               get_implicit_value_parameter_name = (string) $2;
                
                current_local_parameters = (Parameters) $4;
                if (current_local_parameters != Parameters.EmptyReadOnlyParameters) { 
@@ -1479,24 +1844,34 @@ interface_event_declaration
                $$ = lexer.Location;
          }
          accessor_declarations 
-         END PROPERTY EOL
+         END PROPERTY logical_end_of_line
          {
                lexer.PropertyParsing = false;
 
                Property prop;
-               Pair pair = (Pair) $10;
-               Accessor get_block = (Accessor) pair.First;
-               Accessor set_block = (Accessor) pair.Second;
-
+               Pair pair = (Pair) $9;
+               
+               Accessor get_block = null;
+               Accessor set_block = null;
+               
+               if (pair.First != null){
+                       get_block = (Accessor) pair.First;
+               }
+               
+               if (pair.Second != null) {
+                       set_block = (Accessor) pair.Second;
+               }
+               
                Location loc = lexer.Location;
                
                // Structure members are Public by default                      
                if ((current_container is Struct) && (current_modifiers == 0))
                        current_modifiers = Modifiers.PUBLIC;                           
                        
-               prop = new Property ((Expression) $6, (string) $3, current_modifiers, get_block, set_block,
+               prop = new Property ((Expression) get_implicit_value_parameter_type, 
+                                        (string) $2, current_modifiers, get_block, set_block,
                                     current_attributes, loc, set_implicit_value_parameter_name, 
-                                    get_parameters, set_parameters, (Expression) $7);
+                                    get_parameters, set_parameters, (ArrayList) $6);
                
                CheckDef (current_container.AddProperty (prop), prop.Name, loc);
                get_implicit_value_parameter_type = null;
@@ -1523,10 +1898,26 @@ opt_implement_clause
          {
                $$ = null;
          }
-       | IMPLEMENTS qualified_identifier
+       | IMPLEMENTS implement_clause_list
+         {
+               $$ = $2;
+         }
+       ;
+       
+implement_clause_list
+       : qualified_identifier
+         {
+           ArrayList impl_list = new ArrayList ();
+           impl_list.Add (DecomposeQI ((string)$1, lexer.Location));
+               $$ = impl_list;
+         }     
+       | implement_clause_list COMMA qualified_identifier
          {
-               $$ = DecomposeQI ((string)$2, lexer.Location);
+               ArrayList impl_list = (ArrayList) $1;
+               impl_list.Add (DecomposeQI ((string)$3, lexer.Location));
+               $$ = impl_list;
          }     
+         
        ;
        
 accessor_declarations
@@ -1551,8 +1942,11 @@ opt_set_accessor_declaration
        ;
 
 get_accessor_declaration
-       : opt_attributes GET EOL
+       : opt_attributes GET logical_end_of_line
          {
+               if ((current_modifiers & Modifiers.WRITEONLY) != 0)
+                       Report.Error (30023, "'WriteOnly' properties cannot have a 'Get' accessor");
+         
                current_local_parameters = get_parameters;
                
                lexer.PropertyParsing = false;
@@ -1563,10 +1957,9 @@ get_accessor_declaration
                ArrayList retval = new ArrayList ();
                retval.Add (new VariableDeclaration (get_implicit_value_parameter_name, get_implicit_value_parameter_type, lexer.Location));
                declare_local_variables (get_implicit_value_parameter_type, retval, lexer.Location);    
-               
          }
-          opt_statement_list
-          END GET EOL
+         opt_statement_list
+         END GET logical_end_of_line
          {
                $$ = new Accessor ((Block) end_block(), (Attributes) $1);
                current_local_parameters = null;
@@ -1575,8 +1968,11 @@ get_accessor_declaration
        ;
 
 set_accessor_declaration
-       : opt_attributes SET opt_set_parameter EOL
+       : opt_attributes SET opt_set_parameter logical_end_of_line
          {
+        if ((current_modifiers & Modifiers.READONLY) != 0)
+                       Report.Error (30022, "'ReadOnly' properties cannot have a 'Set' accessor");
+                       
                Parameter implicit_value_parameter = new Parameter (
                        set_implicit_value_parameter_type, 
                        set_implicit_value_parameter_name, 
@@ -1589,7 +1985,7 @@ set_accessor_declaration
                lexer.PropertyParsing = false;
          }
          opt_statement_list
-         END SET EOL
+         END SET logical_end_of_line
          {
                $$ = new Accessor ((Block) end_block(), (Attributes) $1);
                current_local_parameters = null;
@@ -1600,21 +1996,29 @@ set_accessor_declaration
 opt_set_parameter
        : /* empty */
        {
-               set_implicit_value_parameter_type = (Expression) TypeManager.system_object_expr;
+               set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type; // TypeManager.system_object_expr;
+               set_implicit_value_parameter_name = "Value";
+       }       
+       |OPEN_PARENS CLOSE_PARENS
+       {
+               set_implicit_value_parameter_type = (Expression) get_implicit_value_parameter_type;
                set_implicit_value_parameter_name = "Value";
        }       
        | OPEN_PARENS opt_parameter_modifier opt_identifier opt_type_spec CLOSE_PARENS
        {
-               /* FIXME: possible syntax error which must be caught
-                  Set ( As <type>) is currently (and wrongly so) legal
-               */
                Parameter.Modifier pm = (Parameter.Modifier)$2;
                if ((pm | Parameter.Modifier.VAL) != 0)
                        Report.Error (31065, 
                                lexer.Location, 
                                "Set cannot have a paremeter modifier other than 'ByVal'");
-               
+                               
                set_implicit_value_parameter_type = (Expression) $4;
+               
+               if (set_implicit_value_parameter_type != get_implicit_value_parameter_type)
+                       Report.Error (31064, 
+                               lexer.Location, 
+                               "Set value parameter type can not be different from property type");
+               
                if ($2 != null)
                        set_implicit_value_parameter_name = (string) $3;
                else
@@ -1624,10 +2028,9 @@ opt_set_parameter
                        
 field_declaration
        : opt_dim_stmt 
-         variable_declarators EOL
+         variable_declarators logical_end_of_line
          {               
                int mod = (int) current_modifiers;
-               
 
                VariableDeclaration.FixupTypes ((ArrayList) $2);
                VariableDeclaration.FixupArrayTypes ((ArrayList) $2);
@@ -1638,6 +2041,9 @@ field_declaration
                // Structure members are Public by default                      
                if ((current_container is Struct) && (mod == 0))
                        mod = Modifiers.PUBLIC;                 
+               
+               if ((mod & Modifiers.Accessibility) == 0)
+                       mod |= Modifiers.PRIVATE;
                                        
                foreach (VariableDeclaration var in (ArrayList) $2){
                        Location l = var.Location;
@@ -1651,14 +2057,20 @@ field_declaration
        ;
        
 withevents_declaration
-       : WITHEVENTS variable_declarators EOL
+       : opt_dim_stmt WITHEVENTS variable_declarators logical_end_of_line
          {
+               // Module members are static by default, but delegates *can't* be declared static
+               // so we must fix it, if mbas was the one actually responsible for this
+               // instead of triggering an error.
+               if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+                       current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+         
                /* WithEvents Fields must be resolved into properties
                   with a bit of magic behind the scenes */
                  
-               VariableDeclaration.FixupTypes ((ArrayList) $2);
+               VariableDeclaration.FixupTypes ((ArrayList) $3);
                
-               foreach (VariableDeclaration var in (ArrayList) $2) {
+               foreach (VariableDeclaration var in (ArrayList) $3) {
                        // 1 - We create a private field
                        Location l = var.Location;
                        Property prop;
@@ -1668,7 +2080,7 @@ withevents_declaration
                        Field field = new Field (var.type, Modifiers.PRIVATE, "_" + var.identifier, 
                                                 var.expression_or_array_initializer, 
                                                 (Attributes) null, l);
-
+                                                
                        CheckDef (current_container.AddField (field), field.Name, l);   
                        
                        // 2 - Public property
@@ -1692,7 +2104,7 @@ delegate_declaration
          identifier OPEN_PARENS 
          opt_formal_parameter_list
          CLOSE_PARENS 
-         EOL
+         logical_end_of_line
          {
                Location l = lexer.Location;
                // Module members are static by default, but delegates *can't* be declared static
@@ -1701,9 +2113,10 @@ delegate_declaration
                if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
                        current_modifiers = (current_modifiers & ~Modifiers.STATIC);
                                        
-               Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (current_container, TypeManager.system_void_expr, 
+               Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (current_container, 
+                                                TypeManager.system_void_expr, 
                                             (int) current_modifiers, 
-                                            MakeName ((string) $3), (Parameters) $5, 
+                                MakeName ((string) $3), (Parameters) $5, 
                                             (Attributes) current_attributes, l);
                                                  
                del.Namespace = current_namespace;
@@ -1712,12 +2125,21 @@ delegate_declaration
        | DELEGATE FUNCTION       
          identifier OPEN_PARENS 
          opt_formal_parameter_list
-         CLOSE_PARENS AS type
+         CLOSE_PARENS opt_type_spec logical_end_of_line
          {
                Location l = lexer.Location;
+               
+               // Module members are static by default, but delegates *can't* be declared static
+               // so we must fix it, if mbas was the one actually responsible for this
+               // instead of triggering an error.
+               if (implicit_modifiers && ((current_modifiers & Modifiers.STATIC) != 0))
+                       current_modifiers = (current_modifiers & ~Modifiers.STATIC);
+                       
+               Expression ftype = ($7 == null) ? TypeManager.system_object_expr : (Expression) $7;
+                       
                Mono.MonoBASIC.Delegate del = new Mono.MonoBASIC.Delegate (
                        current_container,
-                       (Expression) $8, (int) current_modifiers, MakeName ((string) $3), 
+                       ftype, (int) current_modifiers, MakeName ((string) $3), 
                        (Parameters) $5, (Attributes) current_attributes, l);
 
                del.Namespace = current_namespace;
@@ -1739,42 +2161,15 @@ opt_evt_handler
          }
        ;       
 
-opt_empty_parens
-       : /* empty */
-       | OPEN_PARENS CLOSE_PARENS
-       ;       
-       
-static_constructor_declaration
-       : SHARED SUB NEW opt_empty_parens EOL
-         {
-               current_local_parameters = Parameters.EmptyReadOnlyParameters;
-               start_block();
-               oob_stack.Push (lexer.Location);
-
-               Location l = (Location) oob_stack.Pop ();
-               $$ = new Constructor ((string) "New", Parameters.EmptyReadOnlyParameters, (ConstructorInitializer) null, l);
-         }
-         opt_statement_list
-         { 
-               Constructor c = (Constructor) $1;
-               c.Block = (Block) end_block();
-               c.ModFlags = (int) current_modifiers;
-               c.OptAttributes = current_attributes;
-               
-               CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
-               current_local_parameters = null;
-         }
-         END SUB EOL
-       
 constructor_declaration
-       : SUB NEW OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS EOL
+       : SUB NEW opt_params logical_end_of_line
          {
-               current_local_parameters = (Parameters) $4;
+               current_local_parameters = (Parameters) $3;
                start_block();
                oob_stack.Push (lexer.Location);
 
                Location l = (Location) oob_stack.Pop ();
-               $$ = new Constructor ((string) "New", (Parameters) $4, (ConstructorInitializer) null, l);
+               $$ = new Constructor ((string) "New", (Parameters) $3, (ConstructorInitializer) null, l);
                $1 = $$;
          }
          opt_statement_list
@@ -1789,7 +2184,7 @@ constructor_declaration
                CheckDef (current_container.AddConstructor(c), c.Name, c.Location);
                current_local_parameters = null;
          }
-         END SUB EOL
+         END SUB logical_end_of_line
        ;
        
 opt_formal_parameter_list
@@ -1855,7 +2250,7 @@ fixed_parameter
                Expression ptype;
                
                if (opt_parm && ($7 == null))
-                       Report.Error (999, "Optional parameters must have a default value");
+                       Report.Error (30812, "Optional parameters must have a default value");
                
                if (opt_parm) {
                        if ((pm & Parameter.Modifier.REF) !=0)
@@ -1926,38 +2321,68 @@ statement_list
 statement : 
            declaration_statement
            {
-               if ($1 != null && (Block) $1 != current_block){
+                 if ($1 != null && (Block) $1 != current_block){
                        current_block.AddStatement ((Statement) $1);
                        current_block = (Block) $1;
-               }
+                 }
            }
          | embedded_statement
            {
-               Statement s = (Statement) $1;
+                 Statement s = (Statement) $1;
 
-               current_block.AddStatement ((Statement) $1);
+                 current_block.AddStatement ((Statement) $1);
            } 
          | labeled_statement 
          | ADDHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
-          {
-               AddHandler ((Expression) $2, (string) $5);
-          }
-         | RAISEEVENT identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
            {
-               RaiseEvent ((string) $2, (ArrayList) $4);
+                 AddHandler ((Expression) $2, (string) $5);
+           }
+         | REMOVEHANDLER prefixed_unary_expression COMMA ADDRESSOF qualified_identifier
+               {
+                 RemoveHandler ((Expression) $2, (string) $5);
+           }
+         | RAISEEVENT identifier opt_raise_event_args  //OPEN_PARENS opt_argument_list CLOSE_PARENS
+           {
+             RaiseEvent ((string) $2, (ArrayList) $3);
            }
          /* | array_handling_statement */
          /* | empty_statement */
          | with_statement 
            {
-               Statement s = (Statement) $1;
+                 Statement s = (Statement) $1;
 
-               current_block.AddStatement ((Statement) $1);
+             current_block.AddStatement ((Statement) $1);
            }     
          ;     
+         
+opt_raise_event_args 
+       : /* empty */   { $$ = null; }
+       | OPEN_PARENS opt_argument_list CLOSE_PARENS
+         {
+               $$ = $2;
+         }
+       ;
+
+label_name
+       : identifier
+       | LITERAL_INTEGER
+       {
+               $$ = $1.ToString();
+       }
+       ;
 
 labeled_statement
-       : identifier COLON end_of_stmt 
+       : label_name COLON
+         {
+               LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
+
+               if (!current_block.AddLabel ((string) $1, labeled)){
+                       Location l = lexer.Location;
+                       Report.Error (140, l, "The label '" + ((string) $1) + "' is a duplicate");
+               }       
+               current_block.AddStatement (labeled);
+         }
+       | label_name COLON
          {
                LabeledStatement labeled = new LabeledStatement ((string) $1, lexer.Location);
 
@@ -1975,6 +2400,7 @@ embedded_statement
        | selection_statement
        | iteration_statement
        | try_statement
+       | synclock_statement
        | jump_statement
        | array_handling_statement 
        ;
@@ -2095,7 +2521,7 @@ jump_statement
        ;
                
 goto_statement
-       : GOTO identifier  
+       : GOTO label_name  
          {
                $$ = new Goto (current_block, (string) $2, lexer.Location);
          }
@@ -2215,7 +2641,17 @@ yield_statement
          }
        ;
 
-
+synclock_statement
+       : SYNCLOCK expression end_of_stmt
+         {   
+               start_block();  
+         }
+         opt_statement_list 
+         END SYNCLOCK
+         {
+               $$ = new Lock ((Expression) $2, (Statement) (Block) end_block(), lexer.Location);
+         }
+       ;
 
 try_statement
        : try_catch
@@ -2771,10 +3207,14 @@ array_creation_expression
                }
                        
                Expression atype = n.RequestedType;
+
+               ArrayList init = (ArrayList) $2;
+               if (init.Count == 0)
+                       init = null;
        
                if (VariableDeclaration.IndexesSpecifiedInRank(dims)) {
                        VariableDeclaration.VBFixIndexList (ref dims);
-                       $$ = new ArrayCreation (atype, dims, "", (ArrayList) $2, lexer.Location); 
+                       $$ = new ArrayCreation (atype, dims, "", init, lexer.Location); 
                }
                else
                {
@@ -2799,7 +3239,6 @@ declaration_statement
                        $$ = declare_local_variables ((Expression) de.Key, (ArrayList) de.Value, lexer.Location);
                }
          }
-
        | local_constant_declaration 
          {
                if ($1 != null){
@@ -2926,21 +3365,28 @@ variable_declarator
                        if ($2 is Pair) {
                                vartype = (Expression) ((Pair) $2).First;
                                
-                               if ($3 != null && $3 is ArrayList)
-                                       Report.Error (205, "End of statement expected.");
+                               /*if ($3 != null && $3 is ArrayList)
+                                       Report.Error (205, "End of statement expected.");*/
                                        
                                ArrayList args = (ArrayList) ((Pair) $2).Second;
+                               if (current_rank_specifiers != null)
+                                       Report.Error (31087, lexer.Location,
+                                                "Array types specified in too many places");   
+                               
                                if (VariableDeclaration.IndexesSpecifiedInRank (args))            
-                                       Report.Error (638, "Array bounds cannot appear in type specifiers.");   
-               
-                               string s_vartype = vartype.ToString();                          
+                                       Report.Error (30638, "Array bounds cannot appear in type specifiers."); 
+                               
+                               current_rank_specifiers = new ArrayList ();
+                               current_rank_specifiers.Add (args);
+                               
+                               /*string s_vartype = vartype.ToString();                                
                                s_vartype += "[";
                                if (args != null)
                                        for (int x = 0; x < args.Count; x++)
                                                s_vartype += ",";
                                        
                                s_vartype += "]";       
-                               vartype = DecomposeQI(s_vartype, Location.Null);                                                
+                               vartype = DecomposeQI(s_vartype, Location.Null);        */
                        }
                        else
                                vartype = ($2 == null) ? ((vname.Type == null) ? TypeManager.system_object_expr : (Expression) vname.Type ) : (Expression) $2;
@@ -3046,7 +3492,7 @@ opt_type_decl
          {
                $$ = $1;
          }
-       | AS type OPEN_PARENS opt_argument_list CLOSE_PARENS
+       | AS type OPEN_PARENS /*opt_argument_list*/ opt_dim_separators CLOSE_PARENS
          {
                $$ = new Pair ($2, $4);
          }
@@ -3060,7 +3506,16 @@ opt_type_decl
                New n = new New ((Expression)$3, (ArrayList) $5, lexer.Location);
                $$ = (Expression) n;
          }
-       ;
+       /*| AS NEW type OPEN_PARENS ADDRESSOF expression CLOSE_PARENS 
+         {
+           ArrayList args = new ArrayList();
+               Argument arg = new Argument ((Expression) $6, Argument.AType.Expression);
+               args.Add (arg);
+               
+               New n = new New ((Expression)$3, (ArrayList) args, lexer.Location);
+               $$ = (Expression) n;
+         }*/
+       ;
                
 opt_array_name_modifier
        : /* empty */                           { $$ = null; }
@@ -3198,25 +3653,27 @@ dim_specifiers
          }     
        ;
        
-/* Expressions */
 primary_expression
        : literal
          {
-               // 7.5.1: Literals
+               //TODO
          }
-
+       | parenthesized_expression
+       | this_access
+       | base_access
        | qualified_identifier
          {
                string name = (string) $1;
-
                $$ = DecomposeQI (name, lexer.Location);
          }
-       | parenthesized_expression
+       //FIXME: address_of_expression is apparently missing here
+       | get_type_expression
+         {
+               // TODO
+         }
        | member_access
        | invocation_expression
        //| element_access
-       | this_access
-       | base_access
        | new_expression
        | cast_expression
        ;
@@ -3384,22 +3841,19 @@ argument
          {
                $$ = new Argument (new EmptyExpression (), Argument.AType.NoArg);
          }
+       | ADDRESSOF expression
+         {
+               $$ = new Argument ((Expression) $2, Argument.AType.AddressOf);
+         }
        ;
 
 variable_reference
        : expression {/* note ("section 5.4"); */  $$ = $1;  }
        ;
 
-negation_expression
-       : NOT expression 
-         {
-               $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
-         }
-       ;
                
 expression
-       : conditional_expression { $$ = $1; }
-       | negation_expression
+       : conditional_xor_expression { $$ = $1; }
        /*| assignment_expression*/
        ;
 
@@ -3421,24 +3875,19 @@ this_access
          }
        ;
 
-unary_expression
-       : primary_expression
-       /*| NOT prefixed_unary_expression
-         {
-               $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
-         }
-       | cast_expression */
-       ;
-       
 cast_expression
-        : cast_operator OPEN_PARENS expression CLOSE_PARENS
+        : DIRECTCAST OPEN_PARENS expression COMMA type CLOSE_PARENS
          {
-                 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
-         }     
+               // TODO
+         } 
        | CTYPE OPEN_PARENS expression COMMA type CLOSE_PARENS
          {
                  $$ = new Cast ((Expression) $5, (Expression) $3, lexer.Location);
-         }                       
+         }     
+        | cast_operator OPEN_PARENS expression CLOSE_PARENS
+         {
+                 $$ = new Cast ((Expression) $1, (Expression) $3, lexer.Location);
+         }     
        ;
        
 cast_operator
@@ -3455,27 +3904,34 @@ cast_operator
        | CSNG          { $$ = TypeManager.system_single_expr;          }
        | CSTR          { $$ = TypeManager.system_string_expr;  }
        ;
+
+get_type_expression
+       : GETTYPE OPEN_PARENS type CLOSE_PARENS
+         {
+               //TODO
+         }
+       ;
+       
+exponentiation_expression
+       : primary_expression
+       | exponentiation_expression OP_EXP primary_expression
+         {
+               //TODO
+         }                             
+       ;
        
-       //
-       // The idea to split this out is from Rhys' grammar
-       // to solve the problem with casts.
-       //
 prefixed_unary_expression
-       : unary_expression
+       : exponentiation_expression
        | PLUS prefixed_unary_expression
          {
+               //FIXME: Is this rule correctly defined ?
                $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, lexer.Location);
          }
        | MINUS prefixed_unary_expression
          {
+               //FIXME: Is this rule correctly defined ?
                $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, lexer.Location);
          }
-       | ADDRESSOF prefixed_unary_expression
-         {
-               // FIXME: We should generate an error if AddressOf is NOT used
-               // during delegate creation
-               $$ = $2;
-         }       
        ;
 
 multiplicative_expression
@@ -3490,112 +3946,123 @@ multiplicative_expression
                $$ = new Binary (Binary.Operator.Division,
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | multiplicative_expression OP_IDIV prefixed_unary_expression
-         {
+       ;
+
+integer_division_expression
+       : multiplicative_expression
+       | integer_division_expression OP_IDIV multiplicative_expression
+          {
+               //FIXME: Is this right ?
                $$ = new Binary (Binary.Operator.Division,
-                                (Expression) $1, (Expression) $3, lexer.Location);
-         }       
-       | multiplicative_expression MOD prefixed_unary_expression
+                          (Expression) $1, (Expression) $3, lexer.Location);
+          }
+       ;
+
+mod_expression
+       : integer_division_expression
+       | mod_expression MOD integer_division_expression
          {
-               $$ = new Binary (Binary.Operator.Modulus,
-                                (Expression) $1, (Expression) $3, lexer.Location);
+             $$ = new Binary (Binary.Operator.Modulus,
+                              (Expression) $1, (Expression) $3, lexer.Location);
          }
        ;
-
+       
 additive_expression
-       : multiplicative_expression
-       | additive_expression PLUS multiplicative_expression
+       : mod_expression
+       | additive_expression PLUS mod_expression
          {
                $$ = new Binary (Binary.Operator.Addition,
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | additive_expression MINUS multiplicative_expression
+       | additive_expression MINUS mod_expression
          {
                $$ = new Binary (Binary.Operator.Subtraction,
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | additive_expression OP_CONCAT multiplicative_expression
+       ;
+
+concat_expression
+       : additive_expression
+       | concat_expression OP_CONCAT additive_expression
+          {
+             // FIXME: This should only work for String expressions
+             // We probably need to use something from the runtime
+             $$ = new Binary (Binary.Operator.Addition,
+                              (Expression) $1, (Expression) $3, lexer.Location);
+         }     
+       ;
+
+shift_expression
+       : concat_expression
+       | shift_expression OP_SHIFT_LEFT concat_expression
          {
-               // FIXME: This should only work for String expressions
-               // We probably need to use something from the runtime
-               $$ = new Binary (Binary.Operator.Addition,
-                                (Expression) $1, (Expression) $3, lexer.Location);
-         }       
+               // TODO
+         }
+       | shift_expression OP_SHIFT_RIGHT concat_expression
+         {
+               //TODO
+         }
        ;
 
 relational_expression
-       : additive_expression
-       | relational_expression OP_LT additive_expression
+       : shift_expression
+       | relational_expression ASSIGN shift_expression
+         {
+               $$ = new Binary (Binary.Operator.Equality,
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }
+       | relational_expression OP_NE shift_expression
+         {
+               $$ = new Binary (Binary.Operator.Inequality, 
+                                (Expression) $1, (Expression) $3, lexer.Location);
+         }       
+       | relational_expression OP_LT shift_expression
          {
                $$ = new Binary (Binary.Operator.LessThan,
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | relational_expression OP_GT additive_expression
+       | relational_expression OP_GT shift_expression
          {
                $$ = new Binary (Binary.Operator.GreaterThan,
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | relational_expression OP_LE additive_expression
+       | relational_expression OP_LE shift_expression
          {
                $$ = new Binary (Binary.Operator.LessThanOrEqual,
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | relational_expression OP_GE additive_expression
+       | relational_expression OP_GE shift_expression
          {
                $$ = new Binary (Binary.Operator.GreaterThanOrEqual,
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | relational_expression IS unary_expression
+       | relational_expression IS shift_expression
          {
-               $$ = new Binary (Binary.Operator.Equality,
-                       (Expression) $1, (Expression) $3, lexer.Location);
+               //FIXME: Is this rule correctly defined ?
          }
-       | relational_expression AS type_name
+       | TYPEOF shift_expression IS namespace_or_type_name
          {
-               $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
+                 //FIXME: Is this rule correctly defined ?
          }
        ;
 
-equality_expression
+negation_expression
        : relational_expression
-       | equality_expression ASSIGN relational_expression
-         {
-               $$ = new Binary (Binary.Operator.Equality,
-                                (Expression) $1, (Expression) $3, lexer.Location);
-         }
-       | equality_expression OP_NE relational_expression
-         {
-               $$ = new Binary (Binary.Operator.Inequality, 
-                                (Expression) $1, (Expression) $3, lexer.Location);
-         }       
-       ;
-
-and_expression
-       : equality_expression
-       | and_expression AND equality_expression
-         {
-               $$ = new Binary (Binary.Operator.BitwiseAnd,
-                                (Expression) $1, (Expression) $3, lexer.Location);
-         }
-       ;
-
-exclusive_or_expression
-       : and_expression
-       | exclusive_or_expression OP_XOR and_expression
+       | NOT negation_expression 
          {
-               $$ = new Binary (Binary.Operator.ExclusiveOr,
-                                (Expression) $1, (Expression) $3, lexer.Location);
+               //FIXME: Is this rule correctly defined ?
+               $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, lexer.Location);
          }
        ;
-
+       
 conditional_and_expression
-       : exclusive_or_expression
-       | conditional_and_expression AND exclusive_or_expression
+       : negation_expression
+       | conditional_and_expression AND negation_expression
          {
                $$ = new Binary (Binary.Operator.LogicalAnd,
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | conditional_and_expression ANDALSO exclusive_or_expression
+       | conditional_and_expression ANDALSO negation_expression
          {     // FIXME: this is likely to be broken
                $$ = new Binary (Binary.Operator.LogicalAnd,
                                 (Expression) $1, (Expression) $3, lexer.Location);
@@ -3616,8 +4083,13 @@ conditional_or_expression
          }
        ;
 
-conditional_expression
+conditional_xor_expression
        : conditional_or_expression
+       | conditional_xor_expression XOR conditional_or_expression
+       {
+             $$ = new Binary (Binary.Operator.ExclusiveOr,
+                              (Expression) $1, (Expression) $3, lexer.Location);
+       }
        ;
 
 assignment_expression
@@ -3625,70 +4097,33 @@ assignment_expression
          { 
                $$ = new Assign ((Expression) $1, (Expression) $3, lexer.Location);
          }
-       | prefixed_unary_expression OP_MULT_ASSIGN expression
-         {
-               Location l = lexer.Location;
-
-               $$ = new CompoundAssign (
-                       Binary.Operator.Multiply, (Expression) $1, (Expression) $3, l);
-         }
-       | prefixed_unary_expression OP_DIV_ASSIGN expression
-         {
-               Location l = lexer.Location;
-
-               $$ = new CompoundAssign (
-                       Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
-         }
-       | prefixed_unary_expression OP_IDIV_ASSIGN expression
-         {
-               Location l = lexer.Location;
-
-               $$ = new CompoundAssign (
-                       Binary.Operator.Division, (Expression) $1, (Expression) $3, l);
-         }       
-       | prefixed_unary_expression OP_ADD_ASSIGN expression
-         {
-               Location l = lexer.Location;
-
-               $$ = new CompoundAssign (
-                       Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
-         }
-       | prefixed_unary_expression OP_SUB_ASSIGN expression
-         {
-               Location l = lexer.Location;
-
-               $$ = new CompoundAssign (
-                       Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, l);
+       | prefixed_unary_expression ASSIGN ADDRESSOF expression
+         { 
+           ArrayList args = new ArrayList();
+               Argument arg = new Argument ((Expression) $4, Argument.AType.Expression);
+               args.Add (arg);
+               
+               New n = new New ((Expression) $1, (ArrayList) args, lexer.Location);
+               n.isDelegate = true;
+               $$ = new Assign ((Expression) $1, (Expression) n, lexer.Location);
          }
-       | prefixed_unary_expression OP_CONCAT_ASSIGN expression
-         {
-               Location l = lexer.Location;
-
-               $$ = new CompoundAssign (
-                       Binary.Operator.Addition, (Expression) $1, (Expression) $3, l);
-         }               
        ;
 
-/*constant_expression
+constant_expression
        : expression
        ;
-*/
 
 boolean_expression
        : expression
        ;
 
 type
-       : type_name {   /* class_type */
-               /*
-                  This does interfaces, delegates, struct_types, class_types,
-                  parent classes, and more! 4.2
-                */
+       : namespace_or_type_name 
+         {     
                $$ = DecomposeQI ((string) $1, lexer.Location); 
          }
        | builtin_types 
-       /*| array_type 
-        | pointer_type */
+       //| array_type 
        ;
 
 type_list
@@ -3708,43 +4143,174 @@ type_list
          }
        ;
 
-type_name
-       : namespace_or_type_name
-       ;
-       
 namespace_or_type_name
        : qualified_identifier
        ;
 
-/* Built-in / Integral types */
 builtin_types
        : OBJECT        { $$ = TypeManager.system_object_expr; }
-       | STRING        { $$ = TypeManager.system_string_expr; }
+       | primitive_type
+       ;
+
+primitive_type
+       : numeric_type
        | BOOLEAN       { $$ = TypeManager.system_boolean_expr; }
-       | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
-       | SINGLE        { $$ = TypeManager.system_single_expr; }
-       | DOUBLE        { $$ = TypeManager.system_double_expr; }
        | DATE          { $$ = TypeManager.system_date_expr; }
-       | integral_type
+       | CHAR          { $$ = TypeManager.system_char_expr; }
+       | STRING        { $$ = TypeManager.system_string_expr; }
+       ;
+       
+
+numeric_type
+       : integral_type
+       | floating_point_type
+       | DECIMAL       { $$ = TypeManager.system_decimal_expr; }
        ;
 
 integral_type
        :
        | BYTE          { $$ = TypeManager.system_byte_expr; }
        | SHORT         { $$ = TypeManager.system_int16_expr; }
-       | LONG          { $$ = TypeManager.system_int64_expr; }
        | INTEGER       { $$ = TypeManager.system_int32_expr; }
-       | CHAR          { $$ = TypeManager.system_char_expr; }
+       | LONG          { $$ = TypeManager.system_int64_expr; }
+       ;
+       
+floating_point_type
+       : SINGLE        { $$ = TypeManager.system_single_expr; }
+       | DOUBLE        { $$ = TypeManager.system_double_expr; }
        ;
 
 interface_type
-       : type_name
+       : namespace_or_type_name
        ;
        
-end_of_stmt
-       : EOL
-       | COLON
-       ;       
+pp_directive
+       : HASH IDENTIFIER OPEN_PARENS LITERAL_STRING COMMA LITERAL_INTEGER CLOSE_PARENS EOL
+         { 
+               if(tokenizerController.IsAcceptingTokens)
+               {
+                       if(in_external_source) 
+                               Report.Error (30580, lexer.Location, "#ExternalSource directives may not be nested");
+                       else {
+                               in_external_source = true;
+                       
+                               lexer.EffectiveSource = (string) $4;
+                               lexer.EffectiveLine = (int) $6;
+                       }
+               }
+         }
+       | HASH IDENTIFIER LITERAL_STRING EOL
+         {
+               if(tokenizerController.IsAcceptingTokens) 
+               {
+                       string id = ($2 as string);
+               
+                       if(!($2 as string).ToLower().Equals("region"))
+                               Report.Error (30205, lexer.Location, "Invalid Pre-processor directive");
+                       else
+                       {
+                               ++in_marked_region;
+                       }
+               }
+         }
+       | HASH END IDENTIFIER EOL
+         {
+               if(tokenizerController.IsAcceptingTokens)
+               {
+                       if( ($3 as string).ToLower().Equals("externalsource")) {
+                               if(!in_external_source)
+                                       Report.Error (30578, lexer.Location, "'#End ExternalSource' must be preceded by a matching '#ExternalSource'");
+                               else {
+                                       in_external_source = false;
+                                       lexer.EffectiveSource = lexer.Source;
+                                       lexer.EffectiveLine = lexer.Line;
+                               }
+                       }
+                       else if(($3 as string).ToLower().Equals("region")) {
+                               if(in_marked_region > 0)
+                                       --in_marked_region;
+                               else
+                                       Report.Error (30205, lexer.Location, "'#End Region' must be preceded  by a matching '#Region'");
+                       }
+                       else {
+                               Report.Error (29999, lexer.Location, "Unrecognized Pre-Processor statement");
+                       }       
+               }
+         }
+       | HASH CONST IDENTIFIER ASSIGN boolean_literal EOL
+         {
+               if(tokenizerController.IsAcceptingTokens)
+               {
+                       //TODO;
+               }
+         }
+       | HASH IF 
+         {
+               IfElseStateMachine.Token tok = IfElseStateMachine.Token.IF;
+
+               try {
+                       ifElseStateMachine.HandleToken(tok);
+               }
+               catch(ApplicationException) {
+                       throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+               }
+         }
+          boolean_literal opt_then  EOL 
+         {
+               HandleConditionalDirective(IfElseStateMachine.Token.IF, (BoolLiteral)$4);
+         }
+       | HASH ELSEIF 
+         {
+                     IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSEIF;
+                     try {
+                             ifElseStateMachine.HandleToken(tok);
+                     }
+                     catch(ApplicationException) {
+                             throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+                     }
+         }
+          boolean_literal opt_then  EOL 
+         { 
+                 HandleConditionalDirective(IfElseStateMachine.Token.ELSEIF, (BoolLiteral)$4);
+         }
+       | HASH ELSE  
+         {
+                   IfElseStateMachine.Token tok = IfElseStateMachine.Token.ELSE;
+                   try {
+                           ifElseStateMachine.HandleToken(tok);
+                   }
+                   catch(ApplicationException) {
+                           throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+                   }
+         }
+         EOL 
+         { 
+               HandleConditionalDirective(IfElseStateMachine.Token.ELSE, new BoolLiteral(true));
+         }
+       | HASH END IF  
+         {
+                 IfElseStateMachine.Token tok = IfElseStateMachine.Token.ENDIF;
+                 try {
+                         ifElseStateMachine.HandleToken(tok);
+                 }
+                 catch(ApplicationException) {
+                         throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+                 }
+         }
+         EOL 
+         { 
+               HandleConditionalDirective(IfElseStateMachine.Token.ENDIF, new BoolLiteral(false));
+         }
+       | HASH error EOL          
+       {
+               if(tokenizerController.IsAcceptingTokens)
+                       Report.Error(2999, lexer.Location, "Unrecognized Pre-Processor statement");
+               else
+                       Report.Warning (9999, lexer.Location,   "Unrecognized Pre-Processor statement");
+       }
+         
+       ;               
+
 %%
 
 
@@ -4155,20 +4721,13 @@ private void RaiseEvent (string evt_name, ArrayList args)
        current_block.AddStatement (s); 
 }
 
-// FIXME: THIS DOES NOT WORK!!!
 private void RemoveHandler (Block b, Expression evt_definition, string handler_name)
 {
-       Location loc = lexer.Location;
-       ArrayList neh_args = new ArrayList();
-       neh_args.Add (new Argument (DecomposeQI(handler_name, loc), Argument.AType.Expression));
-       
-       ExpressionStatement se = (ExpressionStatement)new New (DecomposeQI("System.EventHandler", loc), neh_args, loc);
-       
-       CompoundAssign ca = new CompoundAssign (
-                       Binary.Operator.Subtraction, evt_definition, (Expression) se, loc);
-                       
-       Statement s = (Statement)(new StatementExpression ((ExpressionStatement) ca, loc)); 
-       b.AddStatement (s);     
+       Location loc = lexer.Location;
+       string evt_target = evt_definition.ToString();
+       evt_target = evt_target.Substring (0, evt_target.LastIndexOf('.'));
+       Statement s = (Statement) new RemoveHandler (evt_definition, DecomposeQI(handler_name, loc), DecomposeQI(evt_target, loc), loc);
+       b.AddStatement (s);
 }
 
 // <summary>
@@ -4254,14 +4813,24 @@ protected override int parse ()
        OptionCompareBinary = InitialOptionCompareBinary;
 
        lexer = new Tokenizer (input, name, defines);
+       
+       ifElseStateMachine = new IfElseStateMachine();
+       tokenizerController = new TokenizerController(lexer);
+       
        StringBuilder value = new StringBuilder ();
        try {
                if (yacc_verbose_flag)
                        yyparse (lexer, new yydebug.yyDebugSimple ());
-               else
+               else {
                        yyparse (lexer);
-       } catch (Exception e) {
-               Report.Error (29999, lexer.Location, lexer.location + "\nParsing error in " + lexer.ref_name + "\n" + e.ToString());
+                       cleanup();
+               }
+       } 
+       catch(MBASException e) {
+               Report.Error(e.code, e.loc, e.Message);
+       }
+       catch (Exception e) {
+               Report.Error (29999, lexer.Location, lexer.location + "\nParsing error in " + lexer.EffectiveSource + "\n" + e.ToString());
        }
 
        RootContext.VerifyImports();
@@ -4269,5 +4838,36 @@ protected override int parse ()
        return Report.Errors;
 }
 
+void cleanup()
+{
+       try {
+               ifElseStateMachine.HandleToken(IfElseStateMachine.Token.EOF);
+       }
+       catch(ApplicationException) {
+               throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+       }
+
+       if(in_external_source) 
+               Report.Error (30579, lexer.Location, "'#ExternalSource' directives must end with matching '#End ExternalSource'");
+
+       if(in_marked_region > 0)
+               Report.Error (30205, lexer.Location, "'#Region' directive must be followed by a matching '#End Region'");
+}
+
+void HandleConditionalDirective(IfElseStateMachine.Token tok, BoolLiteral expr)
+{
+       try {
+               tokenizerController.PositionTokenizerCursor(tok, expr);
+       }
+       catch(ApplicationException) {
+               tok = IfElseStateMachine.Token.EOF;
+               try {
+                       ifElseStateMachine.HandleToken(tok);
+               }
+               catch(ApplicationException) {
+                       throw new MBASException(ifElseStateMachine.Error, lexer.Location, ifElseStateMachine.ErrString);
+               }
+       }
+}
 /* end end end */
 }