New syntax: semicolons, continue statement.
For the latter we must keep track of the current block's type.
(We can't continue through a try statement, sigh.()
diff --git a/Python/compile.c b/Python/compile.c
index 71d13bc..4dc3d9f 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -129,6 +129,9 @@
 
 
 /* Data structure used internally */
+
+#define MAXBLOCKS 20 /* Max static block nesting within a function */
+
 struct compiling {
 	object *c_code;		/* string */
 	object *c_consts;	/* list of objects */
@@ -137,10 +140,45 @@
 	int c_errors;		/* counts errors occurred */
 	int c_infunction;	/* set when compiling a function */
 	int c_loops;		/* counts nested loops */
+	int c_begin;		/* begin of current loop, for 'continue' */
+	int c_block[MAXBLOCKS];	/* stack of block types */
+	int c_nblocks;		/* current block stack level */
 	char *c_filename;	/* filename of current node */
 };
 
+
+/* Interface to the block stack */
+
+static void
+block_push(c, type)
+	struct compiling *c;
+	int type;
+{
+	if (c->c_nblocks >= MAXBLOCKS) {
+		err_setstr(TypeError, "too many statically nested blocks");
+		c->c_errors++;
+	}
+	else {
+		c->c_block[c->c_nblocks++] = type;
+	}
+}
+
+static void
+block_pop(c, type)
+	struct compiling *c;
+	int type;
+{
+	if (c->c_nblocks > 0)
+		c->c_nblocks--;
+	if (c->c_block[c->c_nblocks] != type && c->c_errors == 0) {
+		err_setstr(SystemError, "bad block pop");
+		c->c_errors++;
+	}
+}
+
+
 /* Prototypes */
+
 static int com_init PROTO((struct compiling *, char *));
 static void com_free PROTO((struct compiling *));
 static void com_done PROTO((struct compiling *));
@@ -170,6 +208,8 @@
 	c->c_errors = 0;
 	c->c_infunction = 0;
 	c->c_loops = 0;
+	c->c_begin = 0;
+	c->c_nblocks = 0;
 	c->c_filename = filename;
 	return 1;
 	
@@ -463,6 +503,24 @@
 }
 
 static void
+com_dictmaker(c, n)
+	struct compiling *c;
+	node *n;
+{
+	int i;
+	/* dictmaker: test ':' test (',' test ':' value)* [','] */
+	for (i = 0; i+2 < NCH(n); i += 4) {
+		/* We must arrange things just right for STORE_SUBSCR.
+		   It wants the stack to look like (value) (dict) (key) */
+		com_addbyte(c, DUP_TOP);
+		com_node(c, CHILD(n, i+2)); /* value */
+		com_addbyte(c, ROT_TWO);
+		com_node(c, CHILD(n, i)); /* key */
+		com_addbyte(c, STORE_SUBSCR);
+	}
+}
+
+static void
 com_atom(c, n)
 	struct compiling *c;
 	node *n;
@@ -485,8 +543,10 @@
 		else
 			com_list_constructor(c, CHILD(n, 1));
 		break;
-	case LBRACE:
+	case LBRACE: /* '{' [dictmaker] '}' */
 		com_addoparg(c, BUILD_MAP, 0);
+		if (TYPE(CHILD(n, 1)) != RBRACE)
+			com_dictmaker(c, CHILD(n, 1));
 		break;
 	case BACKQUOTE:
 		com_node(c, CHILD(n, 1));
@@ -1111,15 +1171,15 @@
 	struct compiling *c;
 	node *n;
 {
-	REQ(n, expr_stmt); /* exprlist ('=' exprlist)* NEWLINE */
-	com_node(c, CHILD(n, NCH(n)-2));
-	if (NCH(n) == 2) {
+	REQ(n, expr_stmt); /* exprlist ('=' exprlist)* */
+	com_node(c, CHILD(n, NCH(n)-1));
+	if (NCH(n) == 1) {
 		com_addbyte(c, PRINT_EXPR);
 	}
 	else {
 		int i;
-		for (i = 0; i < NCH(n)-3; i+=2) {
-			if (i+2 < NCH(n)-3)
+		for (i = 0; i < NCH(n)-2; i+=2) {
+			if (i+2 < NCH(n)-2)
 				com_addbyte(c, DUP_TOP);
 			com_assign(c, CHILD(n, i), 1/*assign*/);
 		}
@@ -1132,12 +1192,12 @@
 	node *n;
 {
 	int i;
-	REQ(n, print_stmt); /* 'print' (test ',')* [test] NEWLINE */
-	for (i = 1; i+1 < NCH(n); i += 2) {
+	REQ(n, print_stmt); /* 'print' (test ',')* [test] */
+	for (i = 1; i < NCH(n); i += 2) {
 		com_node(c, CHILD(n, i));
 		com_addbyte(c, PRINT_ITEM);
 	}
-	if (TYPE(CHILD(n, NCH(n)-2)) != COMMA)
+	if (TYPE(CHILD(n, NCH(n)-1)) != COMMA)
 		com_addbyte(c, PRINT_NEWLINE);
 		/* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */
 }
@@ -1147,12 +1207,12 @@
 	struct compiling *c;
 	node *n;
 {
-	REQ(n, return_stmt); /* 'return' [testlist] NEWLINE */
+	REQ(n, return_stmt); /* 'return' [testlist] */
 	if (!c->c_infunction) {
 		err_setstr(TypeError, "'return' outside function");
 		c->c_errors++;
 	}
-	if (NCH(n) == 2)
+	if (NCH(n) < 2)
 		com_addoparg(c, LOAD_CONST, com_addconst(c, None));
 	else
 		com_node(c, CHILD(n, 1));
@@ -1164,7 +1224,7 @@
 	struct compiling *c;
 	node *n;
 {
-	REQ(n, raise_stmt); /* 'raise' expr [',' expr] NEWLINE */
+	REQ(n, raise_stmt); /* 'raise' test [',' test] */
 	com_node(c, CHILD(n, 1));
 	if (NCH(n) > 3)
 		com_node(c, CHILD(n, 3));
@@ -1180,8 +1240,8 @@
 {
 	int i;
 	REQ(n, import_stmt);
-	/* 'import' NAME (',' NAME)* NEWLINE |
-	   'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE */
+	/* 'import' NAME (',' NAME)* |
+	   'from' NAME 'import' ('*' | NAME (',' NAME)*) */
 	if (STR(CHILD(n, 0))[0] == 'f') {
 		/* 'from' NAME 'import' ... */
 		REQ(CHILD(n, 1), NAME);
@@ -1233,10 +1293,11 @@
 {
 	int break_anchor = 0;
 	int anchor = 0;
-	int begin;
+	int save_begin = c->c_begin;
 	REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */
 	com_addfwref(c, SETUP_LOOP, &break_anchor);
-	begin = c->c_nexti;
+	block_push(c, SETUP_LOOP);
+	c->c_begin = c->c_nexti;
 	com_addoparg(c, SET_LINENO, n->n_lineno);
 	com_node(c, CHILD(n, 1));
 	com_addfwref(c, JUMP_IF_FALSE, &anchor);
@@ -1244,10 +1305,12 @@
 	c->c_loops++;
 	com_node(c, CHILD(n, 3));
 	c->c_loops--;
-	com_addoparg(c, JUMP_ABSOLUTE, begin);
+	com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
+	c->c_begin = save_begin;
 	com_backpatch(c, anchor);
 	com_addbyte(c, POP_TOP);
 	com_addbyte(c, POP_BLOCK);
+	block_pop(c, SETUP_LOOP);
 	if (NCH(n) > 4)
 		com_node(c, CHILD(n, 6));
 	com_backpatch(c, break_anchor);
@@ -1261,26 +1324,29 @@
 	object *v;
 	int break_anchor = 0;
 	int anchor = 0;
-	int begin;
+	int save_begin = c->c_begin;
 	REQ(n, for_stmt);
 	/* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */
 	com_addfwref(c, SETUP_LOOP, &break_anchor);
+	block_push(c, SETUP_LOOP);
 	com_node(c, CHILD(n, 3));
 	v = newintobject(0L);
 	if (v == NULL)
 		c->c_errors++;
 	com_addoparg(c, LOAD_CONST, com_addconst(c, v));
 	XDECREF(v);
-	begin = c->c_nexti;
+	c->c_begin = c->c_nexti;
 	com_addoparg(c, SET_LINENO, n->n_lineno);
 	com_addfwref(c, FOR_LOOP, &anchor);
 	com_assign(c, CHILD(n, 1), 1/*assigning*/);
 	c->c_loops++;
 	com_node(c, CHILD(n, 5));
 	c->c_loops--;
-	com_addoparg(c, JUMP_ABSOLUTE, begin);
+	com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
+	c->c_begin = save_begin;
 	com_backpatch(c, anchor);
 	com_addbyte(c, POP_BLOCK);
+	block_pop(c, SETUP_LOOP);
 	if (NCH(n) > 8)
 		com_node(c, CHILD(n, 8));
 	com_backpatch(c, break_anchor);
@@ -1383,10 +1449,12 @@
 	if (NCH(n) > 3 && TYPE(CHILD(n, NCH(n)-3)) != except_clause) {
 		/* Have a 'finally' clause */
 		com_addfwref(c, SETUP_FINALLY, &finally_anchor);
+		block_push(c, SETUP_FINALLY);
 	}
 	if (NCH(n) > 3 && TYPE(CHILD(n, 3)) == except_clause) {
 		/* Have an 'except' clause */
 		com_addfwref(c, SETUP_EXCEPT, &except_anchor);
+		block_push(c, SETUP_EXCEPT);
 	}
 	com_node(c, CHILD(n, 2));
 	if (except_anchor) {
@@ -1394,6 +1462,7 @@
 		int i;
 		node *ch;
 		com_addbyte(c, POP_BLOCK);
+		block_pop(c, SETUP_EXCEPT);
 		com_addfwref(c, JUMP_FORWARD, &end_anchor);
 		com_backpatch(c, except_anchor);
 		for (i = 3;
@@ -1434,12 +1503,15 @@
 	if (finally_anchor) {
 		node *ch;
 		com_addbyte(c, POP_BLOCK);
+		block_pop(c, SETUP_FINALLY);
+		block_push(c, END_FINALLY);
 		com_addoparg(c, LOAD_CONST, com_addconst(c, None));
 		com_backpatch(c, finally_anchor);
 		ch = CHILD(n, NCH(n)-1);
 		com_addoparg(c, SET_LINENO, ch->n_lineno);
 		com_node(c, ch);
 		com_addbyte(c, END_FINALLY);
+		block_pop(c, END_FINALLY);
 	}
 }
 
@@ -1464,6 +1536,23 @@
 }
 
 static void
+com_continue_stmt(c, n)
+	struct compiling *c;
+	node *n;
+{
+	int i = c->c_nblocks;
+	if (i-- > 0 && c->c_block[i] == SETUP_LOOP) {
+		com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
+	}
+	else {
+		err_setstr(TypeError, "'continue' not properly in loop");
+		c->c_errors++;
+	}
+	/* XXX Could allow it inside a 'finally' clause
+	   XXX if we could pop the exception still on the stack */
+}
+
+static void
 com_funcdef(c, n)
 	struct compiling *c;
 	node *n;
@@ -1547,11 +1636,21 @@
 	/* Trivial parse tree nodes */
 	
 	case stmt:
+	case small_stmt:
 	case flow_stmt:
 		com_node(c, CHILD(n, 0));
 		break;
 
 	case simple_stmt:
+		/* small_stmt (';' small_stmt)* [';'] NEWLINE */
+		com_addoparg(c, SET_LINENO, n->n_lineno);
+		{
+			int i;
+			for (i = 0; i < NCH(n)-1; i += 2)
+				com_node(c, CHILD(n, i));
+		}
+		break;
+	
 	case compound_stmt:
 		com_addoparg(c, SET_LINENO, n->n_lineno);
 		com_node(c, CHILD(n, 0));
@@ -1565,7 +1664,7 @@
 	case print_stmt:
 		com_print_stmt(c, n);
 		break;
-	case del_stmt: /* 'del' exprlist NEWLINE */
+	case del_stmt: /* 'del' exprlist */
 		com_assign(c, CHILD(n, 1), 0/*delete*/);
 		break;
 	case pass_stmt:
@@ -1577,6 +1676,9 @@
 		}
 		com_addbyte(c, BREAK_LOOP);
 		break;
+	case continue_stmt:
+		com_continue_stmt(c, n);
+		break;
 	case return_stmt:
 		com_return_stmt(c, n);
 		break;