diff --git a/src/language.yacc b/src/language.yacc
index 06bab33542b1b41a2ea91c5a73d2401fbf29edfb..f9cd3bd3c786c3e774c5bcae1315db751d3d00d6 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -156,6 +156,7 @@
 %token F_XOR_EQ
 %token F_NOP
 %token F_UNDEFINED
+%token F_OPTIONAL
 
 %token F_ALIGN
 %token F_POINTER
@@ -184,7 +185,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.149 1999/12/17 19:47:19 hubbe Exp $");
+RCSID("$Id: language.yacc,v 1.150 1999/12/17 21:09:48 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -780,6 +781,17 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER push_compiler_frame0
     yyerror("Missing ';'.");
    /* yychar = '}';	*/ /* Put the '}' back on the input stream */
   }
+  | modifiers
+   '{' 
+    {
+      $<number>$=lex.pragmas;
+      lex.pragmas|=$1;
+    }
+      program
+   '}'
+    {
+      lex.pragmas=$<number>3;
+    }
   ;
 
 optional_dot_dot_dot: F_DOT_DOT_DOT { $$=1; }
@@ -838,6 +850,7 @@ arguments2: new_arg_name { $$ = 1; }
 modifier: F_NO_MASK    { $$ = ID_NOMASK; }
   | F_FINAL_ID   { $$ = ID_NOMASK; }
   | F_STATIC     { $$ = ID_STATIC; }
+  | F_OPTIONAL   { $$ = ID_OPTIONAL; }
   | F_PRIVATE    { $$ = ID_PRIVATE | ID_STATIC; }
   | F_LOCAL_ID   { $$ = ID_INLINE; }
   | F_PUBLIC     { $$ = ID_PUBLIC; }
@@ -854,6 +867,7 @@ magic_identifiers1:
   | F_PUBLIC     { $$ = "public"; }
   | F_PROTECTED  { $$ = "protected"; }
   | F_INLINE     { $$ = "inline"; }
+  | F_OPTIONAL   { $$ = "optional"; }
   ;
 
 magic_identifiers2:
@@ -895,14 +909,15 @@ magic_identifiers3:
   | F_TYPEOF     { $$ = "typeof"; }
   ;
 
-magic_identifiers: magic_identifiers1 | magic_identifiers2 | magic_identifiers3
-magic_identifier: magic_identifiers
+magic_identifiers: magic_identifiers1 | magic_identifiers2 | magic_identifiers3 ;
+
+magic_identifier: F_IDENTIFIER 
+  | magic_identifiers
   {
     struct pike_string *tmp=make_shared_string($1);
     $$=mkstrnode(tmp);
     free_string(tmp);
   }
-  | F_IDENTIFIER
   ;
 
 modifiers: modifier_list
@@ -2069,7 +2084,6 @@ expr4: string
   {
     $$=mknode(F_ARROW,$1,$3);
   }
-  | expr4 F_ARROW bad_identifier {}
   | expr4 F_ARROW error {}
   ;
 
@@ -2451,6 +2465,8 @@ bad_expr_ident:
   { yyerror("protected is a reserved word."); }
   | F_PUBLIC
   { yyerror("public is a reserved word."); }
+  | F_OPTIONAL
+  { yyerror("optional is a reserved word."); }
   | F_STATIC
   { yyerror("static is a reserved word."); }
   | F_FINAL_ID
diff --git a/src/lexer.h b/src/lexer.h
index dbe93edd7bbb1d7152e57e719506673985c80ae2..c0261b6096abacff106b0a7c0fc47ca494e851fd 100644
--- a/src/lexer.h
+++ b/src/lexer.h
@@ -1,5 +1,5 @@
 /*
- * $Id: lexer.h,v 1.12 1999/11/23 03:11:08 grubba Exp $
+ * $Id: lexer.h,v 1.13 1999/12/17 21:09:49 hubbe Exp $
  *
  * Lexical analyzer template.
  * Based on lex.c 1.62
@@ -746,6 +746,9 @@ static int low_yylex(YYSTYPE *yylval)
 	  case TWO_CHAR('o','b'):
 	    if(ISWORD("object")) return F_OBJECT_ID;
 	  break;
+	  case TWO_CHAR('o','p'):
+	    if(ISWORD("optional")) return F_OPTIONAL;
+	  break;
 	  case TWO_CHAR('p','r'):
 	    if(ISWORD("program")) return F_PROGRAM_ID;
 	    if(ISWORD("predef")) return F_PREDEF;
diff --git a/src/program.c b/src/program.c
index 5406e931df59080ddbf814de4aeae251587c3283..e7be63fcc83d259e253e44075e4f6fe8916acd8e 100644
--- a/src/program.c
+++ b/src/program.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: program.c,v 1.186 1999/12/15 19:42:11 hubbe Exp $");
+RCSID("$Id: program.c,v 1.187 1999/12/17 21:09:51 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -3498,6 +3498,8 @@ static int low_implements(struct program *a, struct program *b)
     if(s == bid->name) continue;	/* Skip __INIT */
     i = find_shared_string_identifier(bid->name,a);
     if (i == -1) {
+      if (b->identifier_references[e].id_flags & (ID_OPTIONAL))
+	continue;		/* It's ok... */
 #if 0
       fprintf(stderr, "Missing identifier \"%s\"\n", bid->name->str);
 #endif /* 0 */
@@ -3559,6 +3561,8 @@ int yyexplain_not_implements(struct program *a, struct program *b)
     if(s == bid->name) continue;	/* Skip __INIT */
     i = find_shared_string_identifier(bid->name,a);
     if (i == -1) {
+      if (b->identifier_references[e].id_flags & (ID_OPTIONAL))
+	continue;		/* It's ok... */
       my_yyerror("Missing identifier \"%s\".", bid->name->str);
       return 0;
     }
diff --git a/src/program.h b/src/program.h
index 908087633a6b02897b6a4b14d25e8adfafe94e4f..75d578c7290e8a651b489827f056244afcf64e82 100644
--- a/src/program.h
+++ b/src/program.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: program.h,v 1.72 1999/12/15 19:42:12 hubbe Exp $
+ * $Id: program.h,v 1.73 1999/12/17 21:09:52 hubbe Exp $
  */
 #ifndef PROGRAM_H
 #define PROGRAM_H
@@ -162,8 +162,9 @@ struct program_constant
 #define ID_INLINE          0x20
 #define ID_HIDDEN          0x40 /* needed? */
 #define ID_INHERITED       0x80
+#define ID_OPTIONAL       0x100
 
-#define ID_MODIFIER_MASK 0x00ff
+#define ID_MODIFIER_MASK 0x01ff
 
 #define ID_STRICT_TYPES	 0x8000
 
diff --git a/src/testsuite.in b/src/testsuite.in
index 6dd5480e86a48384a0243e3a4401058320002f4a..4dc5d24a04c0ec6f0cdda975558ea750af62df2b 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,4 @@
-test_true([["$Id: testsuite.in,v 1.253 1999/12/14 12:58:19 hubbe Exp $"]]);
+test_true([["$Id: testsuite.in,v 1.254 1999/12/17 21:09:53 hubbe Exp $"]]);
 
 cond([[all_constants()->_verify_internals]],
 [[
@@ -847,9 +847,12 @@ test_true(clone(class c { constant i=1; })->i)
 test_true(clone(class c { constant i=0; mixed `->(string s) { if(s=="i") return 1; }})->i)
 test_true(clone(class c { constant i=1; mixed `->(string s) { return 0; }})["i"])
 test_true(clone(class c { constant i=0; mixed `[](string s) { if(s=="i") return 1; }})["i"])
+test_true(clone(class c { optional constant i=0; mixed `[](string s) { if(s=="i") return 1; }})["i"])
 test_true(clone(class c { mixed `[]=(mixed a, mixed b) { if(a!=b) throw(1); }})[1]=1)
 test_true(clone(class c { mixed `->=(mixed a, mixed b) { if(a!=b) throw(1); }})->i="i")
 
+test_eq((["static":42])->static,42)
+
 test_compile_any(class A {}; class B { inherit A; })
 
 test_any_equal(array a = ({({1,0,0}),({1,1,0}),({0,1,1})}); return map(a,`[],1);,
@@ -4165,8 +4168,8 @@ test_compile_any(class A {int v;} class B {inherit A; int v;})
 test_compile_error_low(class A {int v;} class B {inherit A; float v;})
 test_compile_error_low(class A {int v;} class B {inherit A; mixed v;})
 test_compile_error_low(class A {mixed v;} class B {inherit A; int v;})
-test_compile_error_low(class A {public int v;} class B {inherit A; float v;})
 test_compile_error_low(class A {public int v;} class B {inherit A; mixed v;})
+test_compile_error_low(class A { public { int v; } } class B {inherit A; mixed v;})
 test_compile_error_low(class A {public mixed v;} class B {inherit A; int v;})
 test_compile_error_low(class A {static int v;} class B {inherit A; float v;})
 test_compile_error_low(class A {static int v;} class B {inherit A; mixed v;})