diff --git a/src/language.yacc b/src/language.yacc
index 66a63139e960b8ef368251a0e226ff91bea7497c..989f900a6fe8a4a846cc15d07fc4b7898e858720 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -171,7 +171,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.73 1998/04/10 23:23:08 grubba Exp $");
+RCSID("$Id: language.yacc,v 1.74 1998/04/13 12:51:09 grubba Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -195,7 +195,10 @@ RCSID("$Id: language.yacc,v 1.73 1998/04/10 23:23:08 grubba Exp $");
 #define YYMAXDEPTH	1000
 
 #ifdef DEBUG
+#ifndef YYDEBUG
+/* May also be defined by machine.h */
 #define YYDEBUG 1
+#endif /* YYDEBUG */
 #endif
 
 
@@ -285,10 +288,11 @@ int yylex(YYSTYPE *yylval);
 %type <number> modifier
 %type <number> modifier_list
 %type <number> modifiers
+%type <number> opt_string_type
 %type <number> optional_dot_dot_dot
 %type <number> optional_stars
 
-/* The following symbos return type information */
+/* The following symbols return type information */
 
 %type <n> cast
 %type <n> simple_type
@@ -355,9 +359,11 @@ int yylex(YYSTYPE *yylval);
 %type <n> low_program_ref
 %%
 
-all: program;
+all: program
+  ;
 
 program: program def optional_semi_colon
+  | error { yyerrok; }
   |  /* empty */
   ;
 
@@ -380,6 +386,7 @@ string_constant: string
   ;
 
 optional_rename_inherit: ':' F_IDENTIFIER { $$=$2; }
+  | ':' bad_identifier { $$=0; }
   | { $$=0; }
   ;
 
@@ -427,6 +434,11 @@ inheritance: modifiers F_INHERIT low_program_ref optional_rename_inherit ';'
     pop_n_elems(1);
     free_node($3);
   }
+  | modifiers F_INHERIT low_program_ref error ';'
+  {
+    free_node($3); yyerrok;
+  }
+  | modifiers F_INHERIT error ';' { yyerrok; }
   ;
 
 import: modifiers F_IMPORT idents ';'
@@ -436,6 +448,7 @@ import: modifiers F_IMPORT idents ';'
     use_module(sp-1);
     pop_stack();
   }
+  | modifiers F_IMPORT error ';' { yyerrok; }
   ;
 
 constant_name: F_IDENTIFIER '=' expr0
@@ -467,6 +480,7 @@ constant_name: F_IDENTIFIER '=' expr0
     if($3) free_node($3);
     free_node($1);
   }
+  | bad_identifier '=' expr0 { if ($3) free_node($3); }
   ;
 
 constant_list: constant_name
@@ -474,6 +488,7 @@ constant_list: constant_name
   ;
 
 constant: modifiers F_CONSTANT constant_list ';' {}
+  | modifiers F_CONSTANT error ';' { yyerrok; }
   ;
 
 block_or_semi: block
@@ -500,7 +515,7 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER
     if(!compiler_frame->previous ||
        !compiler_frame->previous->current_type)
     {
-      yyerror("Internal compiler fault");
+      yyerror("Internal compiler fault.");
       copy_shared_string(compiler_frame->current_type,
 			 mixed_type_string);
     }else{
@@ -564,7 +579,7 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER
 	if(!compiler_frame->variable[e].name ||
 	   !compiler_frame->variable[e].name->len)
 	  {
-	    my_yyerror("Missing name for argument %d",e);
+	    my_yyerror("Missing name for argument %d.",e);
 	  }
       }
 
@@ -578,14 +593,20 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER
     free_node($4);
     free_node($<n>9);
   }
+  | modifiers type_or_error optional_stars bad_identifier
+    '(' arguments ')' block_or_semi
+  {
+    free_string(pop_type());
+  }
   | modifiers type_or_error name_list ';' {}
   | inheritance {}
   | import {}
   | constant {}
   | class { free_node($1); }
-  | error ';' { yyerrok; }
+  | error ';'
   {
     reset_type_stack();
+    yyerrok;
 /*     if(num_parse_error>5) YYACCEPT; */
   }
   ;
@@ -595,6 +616,7 @@ optional_dot_dot_dot: F_DOT_DOT_DOT { $$=1; }
   ;
 
 optional_identifier: F_IDENTIFIER
+  | bad_identifier { $$=0 }
   | /* empty */ { $$=0; }
   ;
 
@@ -726,10 +748,10 @@ type2: type2 '|' type3 { push_type(T_OR); }
 
 type3: F_INT_ID      { push_type(T_INT); }
   | F_FLOAT_ID    { push_type(T_FLOAT); }
-  | F_STRING_ID   { push_type(T_STRING); }
   | F_PROGRAM_ID  { push_type(T_PROGRAM); }
   | F_VOID_ID     { push_type(T_VOID); }
   | F_MIXED_ID    { push_type(T_MIXED); }
+  | F_STRING_ID opt_string_type { push_type(T_STRING); }
   | F_OBJECT_ID   opt_object_type { push_type(T_OBJECT); }
   | F_MAPPING_ID opt_mapping_type { push_type(T_MAPPING); }
   | F_ARRAY_ID opt_array_type { push_type(T_ARRAY); }
@@ -737,6 +759,13 @@ type3: F_INT_ID      { push_type(T_INT); }
   | F_FUNCTION_ID opt_function_type { push_type(T_FUNCTION); }
   ;
 
+opt_string_type:  /* Empty */ { $$=1; }
+  | '(' F_NUMBER ')'
+  {
+    if ($2 != 1) yyerror("Wide strings are not supported.");
+    $$=1;
+  }
+
 opt_object_type:  /* Empty */ { push_type_int(0); push_type(0); }
   | '(' program_ref ')'
   {
@@ -745,7 +774,7 @@ opt_object_type:  /* Empty */ { push_type_int(0); push_type(0); }
     {
       push_type_int(p->id);
     }else{
-      yyerror("Not a valid program specifier");
+      yyerror("Not a valid program specifier.");
       push_type_int(0);
     }
     pop_n_elems(2);
@@ -840,6 +869,7 @@ new_name: optional_stars F_IDENTIFIER
     free_string(type);
     free_node($2);
   }
+  | optional_stars bad_identifier {}
   | optional_stars F_IDENTIFIER '='
   {
     struct pike_string *type;
@@ -857,6 +887,10 @@ new_name: optional_stars F_IDENTIFIER
 				       mkidentifiernode($<number>4))));
     free_node($2);
   }
+  | optional_stars bad_identifier '=' expr0
+  {
+    free_node($4);
+  }
   ;
 
 
@@ -868,6 +902,7 @@ new_local_name: optional_stars F_IDENTIFIER
     $$=mknode(F_ASSIGN,mkintnode(0),mklocalnode(islocal($2->u.sval.u.string)));
     free_node($2);
   }
+  | optional_stars bad_identifier {}
   | optional_stars F_IDENTIFIER '=' expr0
   {
     push_finished_type($<n>0->u.sval.u.string);
@@ -876,6 +911,15 @@ new_local_name: optional_stars F_IDENTIFIER
     $$=mknode(F_ASSIGN,$4,mklocalnode(islocal($2->u.sval.u.string)));
     free_node($2);
   }
+  | optional_stars bad_identifier '=' expr0
+  {
+    free_node($4);
+  }
+  | optional_stars F_IDENTIFIER '=' error
+  {
+    free_node($2);
+    /* No yyerok here since we aren't done yet. */
+  }
   ;
 
 new_local_name2: F_IDENTIFIER
@@ -884,12 +928,22 @@ new_local_name2: F_IDENTIFIER
     $$=mknode(F_ASSIGN,mkintnode(0),mklocalnode(islocal($1->u.sval.u.string)));
     free_node($1);
   }
+  | bad_identifier { $$=mkintnode(0); }
   | F_IDENTIFIER '=' expr0
   {
     add_local_name($1->u.sval.u.string, $<n>0->u.sval.u.string);
     $$=mknode(F_ASSIGN,$3, mklocalnode(islocal($1->u.sval.u.string)));
     free_node($1);
   }
+  | bad_identifier '=' expr0 { $$=$3; }
+  | F_IDENTIFIER '=' error
+  {
+    /* Just ignore the assignment */
+    add_local_name($1->u.sval.u.string, $<n>0->u.sval.u.string);
+    $$=mknode(F_ASSIGN,mkintnode(0),mklocalnode(islocal($1->u.sval.u.string)));
+    free_node($1);
+    yyerrok;
+  }
   ;
 
 
@@ -905,7 +959,7 @@ block:'{'
   ;
 
 failsafe_block: block
-              | error { $$=0; }
+              | error { $$=0; yyerrok }
               ;
   
 
@@ -1026,6 +1080,7 @@ class: modifiers F_CLASS optional_identifier
       free_string(s);
       $1|=ID_PRIVATE | ID_INLINE;
     }
+    /* fprintf(stderr, "LANGUAGE.YACC: CLASS start\n"); */
     if(compiler_pass==1)
     {
       low_start_new_program(0, $3->u.sval.u.string, $1);
@@ -1066,6 +1121,8 @@ class: modifiers F_CLASS optional_identifier
     else
       p=end_program();
 
+    /* fprintf(stderr, "LANGUAGE.YACC: CLASS end\n"); */
+
     $$=mkidentifiernode(isidentifier($3->u.sval.u.string));
 
     if(!p)
@@ -1075,7 +1132,6 @@ class: modifiers F_CLASS optional_identifier
 
     free_node($3);
     check_tree($$,0);
-
   }
   ;
 
@@ -1214,10 +1270,13 @@ expr00: expr0
 
 expr0: expr01
   | expr4 '=' expr0  { $$=mknode(F_ASSIGN,$3,$1); }
+  | expr4 '=' error { $$=$1; reset_type_stack(); yyerrok; }
   | '[' low_lvalue_list ']' '=' expr0  { $$=mknode(F_ASSIGN,$5,mknode(F_ARRAY_LVALUE,$2,0)); }
   | expr4 assign expr0  { $$=mknode($2,$1,$3); }
-  | '[' low_lvalue_list ']' assign expr0  { $$=mknode(F_ASSIGN,mknode(F_ARRAY_LVALUE,$2,0),$5); }
-  | error assign expr01 { $$=0; reset_type_stack(); yyerrok; }
+  | expr4 assign error { $$=$1; reset_type_stack(); yyerrok; }
+  | '[' low_lvalue_list ']' assign expr0  { $$=mknode($4,mknode(F_ARRAY_LVALUE,$2,0),$5); }
+  | '[' low_lvalue_list error ']' { $$=$2; reset_type_stack(); yyerrok; }
+/*  | error { $$=0; reset_type_stack(); } */
   ;
 
 expr01: expr1 { $$ = $1; }
@@ -1307,11 +1366,13 @@ expr4: string
   | class
   | idents
   | expr4 '(' expr_list ')' { $$=mkapplynode($1,$3); }
+  | expr4 '(' error ')' { $$=mkapplynode($1, NULL); yyerrok; }
   | expr4 '[' expr0 ']' { $$=mknode(F_INDEX,$1,$3); }
   | expr4 '['  comma_expr_or_zero F_DOT_DOT comma_expr_or_maxint ']'
   {
     $$=mknode(F_RANGE,$1,mknode(F_ARG_LIST,$3,$5));
   }
+  | expr4 '[' error ']' { $$=$1; yyerrok; }
   | '(' comma_expr2 ')' { $$=$2; }
   | '(' '{' expr_list '}' ')'
     { $$=mkefuncallnode("aggregate",$3); }
@@ -1319,10 +1380,12 @@ expr4: string
     { $$=mkefuncallnode("aggregate_mapping",$3); };
   | F_MULTISET_START expr_list F_MULTISET_END
     { $$=mkefuncallnode("aggregate_multiset",$2); }
+  | '(' error ')' { yyerrok; }
   | expr4 F_ARROW F_IDENTIFIER
   {
     $$=mknode(F_ARROW,$1,$3);
   }
+  | expr4 F_ARROW bad_identifier {}
   ;
 
 idents: low_idents
@@ -1334,6 +1397,7 @@ idents: low_idents
     copy_shared_string(last_identifier, $3->u.sval.u.string);
     free_node($3);
   }
+  | idents '.' bad_identifier {}
   ;
 
 low_idents: F_IDENTIFIER
@@ -1356,7 +1420,8 @@ low_idents: F_IDENTIFIER
 	     DECLARE_CYCLIC();
 	     if(BEGIN_CYCLIC(last_identifier, lex.current_file))
 	     {
-	       my_yyerror("Recursive module dependency in %s",last_identifier->str);
+	       my_yyerror("Recursive module dependency in %s.",
+			  last_identifier->str);
 	     }else{
 	       SET_CYCLIC_RET(1);
 	       ref_push_string(last_identifier);
@@ -1410,6 +1475,10 @@ low_idents: F_IDENTIFIER
     free_node(tmp2);
     free_node($3);
   }
+  | F_PREDEF F_COLON_COLON bad_identifier
+  {
+    $$=mkintnode(0);
+  }
   | F_IDENTIFIER F_COLON_COLON F_IDENTIFIER
   {
     $$=reference_inherited_identifier($1->u.sval.u.string,
@@ -1425,6 +1494,10 @@ low_idents: F_IDENTIFIER
     free_node($1);
     free_node($3);
   }
+  | F_IDENTIFIER F_COLON_COLON bad_identifier
+  {
+    $$=$1;
+  }
   | F_COLON_COLON F_IDENTIFIER
   {
     int e,i;
@@ -1450,6 +1523,10 @@ low_idents: F_IDENTIFIER
     }
     free_node($2);
   }
+  | F_COLON_COLON bad_identifier
+  {
+    $$=mkintnode(0);
+  }
   ;
 
 comma_expr_or_zero: /* empty */ { $$=mkintnode(0); }
@@ -1493,6 +1570,7 @@ typeof: F_TYPEOF '(' expr0 ')'
   } ;
  
 catch_arg: '(' comma_expr ')'  { $$=$2; }
+  | '(' error ')' { $$=mkintnode(0); yyerrok; }
   | block
   ; 
 
@@ -1543,6 +1621,90 @@ string: F_STRING
   }
   ;
 
+/*
+ * Some error-handling
+ */
+
+bad_identifier : bad_def_identifier
+  | F_INLINE
+  { yyerror("inline is a reserved word."); }
+  | F_LOCAL
+  { yyerror("local is a reserved word."); }
+  | F_NO_MASK
+  { yyerror("nomask is a reserved word."); }
+  | F_PREDEF
+  { yyerror("predef is a reserved word."); }
+  | F_PRIVATE
+  { yyerror("private is a reserved word."); }
+  | F_PROTECTED
+  { yyerror("protected is a reserved word."); }
+  | F_PUBLIC
+  { yyerror("public is a reserved word."); }
+  | F_STATIC
+  { yyerror("static is a reserved word."); }
+  | F_ARRAY_ID
+  { yyerror("array is a reserved word."); }
+  | F_FLOAT_ID
+  { yyerror("float is a reserved word.");}
+  | F_INT_ID
+  { yyerror("int is a reserved word."); }
+  | F_MAPPING_ID
+  { yyerror("mapping is a reserved word."); }
+  | F_MULTISET_ID
+  { yyerror("multiset is a reserved word."); }
+  | F_STRING_ID
+  { yyerror("string is a reserved word."); }
+  | F_VOID_ID
+  { yyerror("void is a reserved word."); }
+  ;
+
+bad_def_identifier
+  : F_DO
+  { yyerror("do is a reserved word."); }
+  | F_ELSE
+  { yyerror("else is a reserved word."); }
+  | F_RETURN
+  { yyerror("return is a reserved word."); }
+  | F_CONSTANT
+  { yyerror("constant is a reserved word."); }
+  | F_IMPORT
+  { yyerror("import is a reserved word."); }
+  | F_INHERIT
+  { yyerror("inherit is a reserved word."); }
+  | F_CLASS
+  { yyerror("class is a reserved word."); }
+  | F_CATCH
+  { yyerror("catch is a reserved word."); }
+  | F_GAUGE
+  { yyerror("gauge is a reserved word."); }
+  | F_LAMBDA
+  { yyerror("lambda is a reserved word."); }
+  | F_SSCANF
+  { yyerror("sscanf is a reserved word."); }
+  | F_SIZEOF
+  { yyerror("sizeof is a reserved word."); }
+  | F_SWITCH
+  { yyerror("switch is a reserved word."); }
+  | F_TYPEOF
+  { yyerror("typeof is a reserved word."); }
+  | F_BREAK
+  { yyerror("break is a reserved word."); }
+  | F_CASE
+  { yyerror("case is a reserved word."); }
+  | F_CONTINUE
+  { yyerror("continue is a reserved word."); }
+  | F_DEFAULT
+  { yyerror("default is a reserved word."); }
+  | F_FOR
+  { yyerror("for is a reserved word."); }
+  | F_FOREACH
+  { yyerror("foreach is a reserved word."); }
+  | F_IF
+  { yyerror("if is a reserved word."); }
+  ;
+
+
+
 %%
 
 void yyerror(char *str)
@@ -1555,7 +1717,7 @@ void yyerror(char *str)
     fatal("Stack error (underflow)\n");
 #endif
 
-  if (num_parse_error > 5) return;
+  if (num_parse_error > 10) return;
   num_parse_error++;
   cumulative_parse_error++;
 
@@ -1582,7 +1744,7 @@ void add_local_name(struct pike_string *str,
   reference_shared_string(str);
   if (compiler_frame->current_number_of_locals == MAX_LOCAL)
   {
-    yyerror("Too many local variables");
+    yyerror("Too many local variables.");
   }else {
     compiler_frame->variable[compiler_frame->current_number_of_locals].type = type;
     compiler_frame->variable[compiler_frame->current_number_of_locals].name = str;