Index: parse.y
===================================================================
--- parse.y	(revision 24243)
+++ parse.y	(working copy)
@@ -91,6 +91,7 @@
     EXPR_FNAME,			/* ignore newline, no reserved words. */
     EXPR_DOT,			/* right after `.' or `::', no reserved words. */
     EXPR_CLASS,			/* immediate after `class', no here document. */
+    EXPR_VALUE			/* alike EXPR_BEG but label is disallowed. */
 } lex_state;
 static NODE *lex_strterm;
 
@@ -267,7 +268,7 @@
 	k__LINE__
 	k__FILE__
 
-%token <id>   tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR
+%token <id>   tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
 %token <node> tINTEGER tFLOAT tSTRING_CONTENT
 %token <node> tNTH_REF tBACK_REF
 %token <num>  tREGEXP_END
@@ -2504,6 +2505,14 @@
 		    {
 			$$ = list_append(NEW_LIST($1), $3);
 		    }
+		| tLABEL arg_value
+		    {
+		    /*%%%*/
+			$$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2);
+		    /*%
+			$$ = dispatch2(assoc_new, $1, $2);
+		    %*/
+		    }
 		;
 
 operation	: tIDENTIFIER
@@ -3434,7 +3443,8 @@
 }
 
 #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG)
-#define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || lex_state == EXPR_CLASS)
+#define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || \
+                  lex_state == EXPR_VALUE || lex_state == EXPR_CLASS)
 
 static int
 yylex()
@@ -3491,6 +3501,7 @@
 	  case EXPR_FNAME:
 	  case EXPR_DOT:
 	  case EXPR_CLASS:
+          case EXPR_VALUE:
 	    goto retry;
 	  default:
 	    break;
@@ -3673,7 +3684,7 @@
 
       case '?':
 	if (lex_state == EXPR_END || lex_state == EXPR_ENDARG) {
-	    lex_state = EXPR_BEG;
+	    lex_state = EXPR_VALUE;
 	    return '?';
 	}
 	c = nextc();
@@ -4526,6 +4537,16 @@
 		}
 	    }
 
+	    if ((lex_state == EXPR_BEG && !cmd_state) ||
+		lex_state == EXPR_ARG ||
+		lex_state == EXPR_CMDARG) {
+		if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) {
+		    lex_state = EXPR_BEG;
+		    nextc();
+		    yylval.id = rb_intern(tok());
+		    return tLABEL;
+		}
+	    }
 	    if (lex_state != EXPR_DOT) {
 		const struct kwtable *kw;
 
@@ -4547,7 +4568,7 @@
 			    return kDO_BLOCK;
 			return kDO;
 		    }
-		    if (state == EXPR_BEG)
+		    if (state == EXPR_BEG || state == EXPR_VALUE)
 			return kw->id[0];
 		    else {
 			if (kw->id[0] != kw->id[1])
@@ -4562,6 +4583,7 @@
 		lex_state == EXPR_DOT ||
 		lex_state == EXPR_ARG ||
 		lex_state == EXPR_CLASS ||
+                lex_state == EXPR_VALUE ||
 		lex_state == EXPR_CMDARG) {
 		if (cmd_state) {
 		    lex_state = EXPR_CMDARG;
Index: keywords
===================================================================
--- keywords	(revision 24243)
+++ keywords	(working copy)
@@ -5,27 +5,27 @@
 BEGIN, {klBEGIN, klBEGIN}, EXPR_END
 END, {klEND, klEND}, EXPR_END
 alias, {kALIAS, kALIAS}, EXPR_FNAME
-and, {kAND, kAND}, EXPR_BEG
+and, {kAND, kAND}, EXPR_VALUE
 begin, {kBEGIN, kBEGIN}, EXPR_BEG
 break, {kBREAK, kBREAK}, EXPR_MID
-case, {kCASE, kCASE}, EXPR_BEG
+case, {kCASE, kCASE}, EXPR_VALUE
 class, {kCLASS, kCLASS}, EXPR_CLASS
 def, {kDEF, kDEF}, EXPR_FNAME
 defined?, {kDEFINED, kDEFINED}, EXPR_ARG
 do, {kDO, kDO}, EXPR_BEG
 else, {kELSE, kELSE}, EXPR_BEG
-elsif, {kELSIF, kELSIF}, EXPR_BEG
+elsif, {kELSIF, kELSIF}, EXPR_VALUE
 end, {kEND, kEND}, EXPR_END
 ensure, {kENSURE, kENSURE}, EXPR_BEG
 false, {kFALSE, kFALSE}, EXPR_END
-for, {kFOR, kFOR}, EXPR_BEG
-if, {kIF, kIF_MOD}, EXPR_BEG
-in, {kIN, kIN}, EXPR_BEG
-module, {kMODULE, kMODULE}, EXPR_BEG
+for, {kFOR, kFOR}, EXPR_VALUE
+if, {kIF, kIF_MOD}, EXPR_VALUE
+in, {kIN, kIN}, EXPR_VALUE
+module, {kMODULE, kMODULE}, EXPR_VALUE
 next, {kNEXT, kNEXT}, EXPR_MID
 nil, {kNIL, kNIL}, EXPR_END
 not, {kNOT, kNOT}, EXPR_BEG
-or, {kOR, kOR}, EXPR_BEG
+or, {kOR, kOR}, EXPR_VALUE
 redo, {kREDO, kREDO}, EXPR_END
 rescue, {kRESCUE, kRESCUE_MOD}, EXPR_MID
 retry, {kRETRY, kRETRY}, EXPR_END
@@ -35,8 +35,8 @@
 then, {kTHEN, kTHEN}, EXPR_BEG
 true, {kTRUE, kTRUE}, EXPR_END
 undef, {kUNDEF, kUNDEF}, EXPR_FNAME
-unless, {kUNLESS, kUNLESS_MOD}, EXPR_BEG
-until, {kUNTIL, kUNTIL_MOD}, EXPR_BEG
-when, {kWHEN, kWHEN}, EXPR_BEG
-while, {kWHILE, kWHILE_MOD}, EXPR_BEG
+unless, {kUNLESS, kUNLESS_MOD}, EXPR_VALUE
+until, {kUNTIL, kUNTIL_MOD}, EXPR_VALUE
+when, {kWHEN, kWHEN}, EXPR_VALUE
+while, {kWHILE, kWHILE_MOD}, EXPR_VALUE
 yield, {kYIELD, kYIELD}, EXPR_ARG
