diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 509422675001e25ee7f3a2a2b52988473bf8874b..c41f1b512f6b3a1da605bcfce37583c98aad6512 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -401,7 +401,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <node>	columnDef columnOptions
 %type <defelt>	def_elem reloption_elem old_aggr_elem
 %type <node>	def_arg columnElem where_clause where_or_current_clause
-				a_expr b_expr c_expr func_expr AexprConst indirection_el
+				a_expr b_expr c_expr AexprConst indirection_el
 				columnref in_expr having_clause func_table array_expr
 				ExclusionWhereClause
 %type <list>	ExclusionConstraintList ExclusionConstraintElem
@@ -481,6 +481,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <ival>	document_or_content
 %type <boolean> xml_whitespace_option
 
+%type <node>	func_application func_expr_common_subexpr
+%type <node>	func_expr func_expr_windowless
 %type <node>	common_table_expr
 %type <with>	with_clause opt_with_clause
 %type <list>	cte_list
@@ -6132,7 +6134,7 @@ index_elem:	ColId opt_collate opt_class opt_asc_desc opt_nulls_order
 					$$->ordering = $4;
 					$$->nulls_ordering = $5;
 				}
-			| func_expr opt_collate opt_class opt_asc_desc opt_nulls_order
+			| func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order
 				{
 					$$ = makeNode(IndexElem);
 					$$->name = NULL;
@@ -9894,8 +9896,7 @@ relation_expr_opt_alias: relation_expr					%prec UMINUS
 				}
 		;
 
-
-func_table: func_expr								{ $$ = $1; }
+func_table: func_expr_windowless					{ $$ = $1; }
 		;
 
 
@@ -11079,15 +11080,7 @@ c_expr:		columnref								{ $$ = $1; }
 				}
 		;
 
-/*
- * func_expr is split out from c_expr just so that we have a classification
- * for "everything that is a function call or looks like one".  This isn't
- * very important, but it saves us having to document which variants are
- * legal in the backwards-compatible functional-index syntax for CREATE INDEX.
- * (Note that many of the special SQL functions wouldn't actually make any
- * sense as functional index entries, but we ignore that consideration here.)
- */
-func_expr:	func_name '(' ')' over_clause
+func_application: func_name '(' ')'
 				{
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = $1;
@@ -11096,11 +11089,11 @@ func_expr:	func_name '(' ')' over_clause
 					n->agg_star = FALSE;
 					n->agg_distinct = FALSE;
 					n->func_variadic = FALSE;
-					n->over = $4;
+					n->over = NULL;
 					n->location = @1;
 					$$ = (Node *)n;
 				}
-			| func_name '(' func_arg_list ')' over_clause
+			| func_name '(' func_arg_list ')'
 				{
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = $1;
@@ -11109,11 +11102,11 @@ func_expr:	func_name '(' ')' over_clause
 					n->agg_star = FALSE;
 					n->agg_distinct = FALSE;
 					n->func_variadic = FALSE;
-					n->over = $5;
+					n->over = NULL;
 					n->location = @1;
 					$$ = (Node *)n;
 				}
-			| func_name '(' VARIADIC func_arg_expr ')' over_clause
+			| func_name '(' VARIADIC func_arg_expr ')'
 				{
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = $1;
@@ -11122,11 +11115,11 @@ func_expr:	func_name '(' ')' over_clause
 					n->agg_star = FALSE;
 					n->agg_distinct = FALSE;
 					n->func_variadic = TRUE;
-					n->over = $6;
+					n->over = NULL;
 					n->location = @1;
 					$$ = (Node *)n;
 				}
-			| func_name '(' func_arg_list ',' VARIADIC func_arg_expr ')' over_clause
+			| func_name '(' func_arg_list ',' VARIADIC func_arg_expr ')'
 				{
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = $1;
@@ -11135,11 +11128,11 @@ func_expr:	func_name '(' ')' over_clause
 					n->agg_star = FALSE;
 					n->agg_distinct = FALSE;
 					n->func_variadic = TRUE;
-					n->over = $8;
+					n->over = NULL;
 					n->location = @1;
 					$$ = (Node *)n;
 				}
-			| func_name '(' func_arg_list sort_clause ')' over_clause
+			| func_name '(' func_arg_list sort_clause ')'
 				{
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = $1;
@@ -11148,11 +11141,11 @@ func_expr:	func_name '(' ')' over_clause
 					n->agg_star = FALSE;
 					n->agg_distinct = FALSE;
 					n->func_variadic = FALSE;
-					n->over = $6;
+					n->over = NULL;
 					n->location = @1;
 					$$ = (Node *)n;
 				}
-			| func_name '(' ALL func_arg_list opt_sort_clause ')' over_clause
+			| func_name '(' ALL func_arg_list opt_sort_clause ')'
 				{
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = $1;
@@ -11165,11 +11158,11 @@ func_expr:	func_name '(' ')' over_clause
 					 * for that in FuncCall at the moment.
 					 */
 					n->func_variadic = FALSE;
-					n->over = $7;
+					n->over = NULL;
 					n->location = @1;
 					$$ = (Node *)n;
 				}
-			| func_name '(' DISTINCT func_arg_list opt_sort_clause ')' over_clause
+			| func_name '(' DISTINCT func_arg_list opt_sort_clause ')'
 				{
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = $1;
@@ -11178,11 +11171,11 @@ func_expr:	func_name '(' ')' over_clause
 					n->agg_star = FALSE;
 					n->agg_distinct = TRUE;
 					n->func_variadic = FALSE;
-					n->over = $7;
+					n->over = NULL;
 					n->location = @1;
 					$$ = (Node *)n;
 				}
-			| func_name '(' '*' ')' over_clause
+			| func_name '(' '*' ')'
 				{
 					/*
 					 * We consider AGGREGATE(*) to invoke a parameterless
@@ -11201,11 +11194,48 @@ func_expr:	func_name '(' ')' over_clause
 					n->agg_star = TRUE;
 					n->agg_distinct = FALSE;
 					n->func_variadic = FALSE;
-					n->over = $5;
+					n->over = NULL;
 					n->location = @1;
 					$$ = (Node *)n;
 				}
-			| COLLATION FOR '(' a_expr ')'
+        ;
+
+
+/*
+ * func_expr and its cousin func_expr_windowless is split out from c_expr just 
+ * so that we have classifications for "everything that is a function call or 
+ * looks like one".  This isn't very important, but it saves us having to document 
+ * which variants are legal in the backwards-compatible functional-index syntax 
+ * for CREATE INDEX.
+ * (Note that many of the special SQL functions wouldn't actually make any
+ * sense as functional index entries, but we ignore that consideration here.)
+ */
+func_expr: func_application over_clause 
+				{
+              		FuncCall *n = (FuncCall*)$1;
+					n->over = $2;
+					$$ = (Node*)n;
+				} 
+			| func_expr_common_subexpr
+				{ $$ = $1; }
+		;
+
+/* 
+ * As func_expr but does not accept WINDOW functions directly (they
+ * can still be contained in arguments for functions etc.)
+ * Use this when window expressions are not allowed, so to disambiguate 
+ * the grammar. (e.g. in CREATE INDEX)
+ */
+func_expr_windowless: 
+			func_application						{ $$ = $1; }
+			| func_expr_common_subexpr 				{ $$ = $1; }
+		;
+
+/*
+ * Special expression 
+ */
+func_expr_common_subexpr:	
+			COLLATION FOR '(' a_expr ')'
 				{
 					FuncCall *n = makeNode(FuncCall);
 					n->funcname = SystemFuncName("pg_collation_for");
@@ -12794,6 +12824,7 @@ unreserved_keyword:
 			| OPERATOR
 			| OPTION
 			| OPTIONS
+			| OVER
 			| OWNED
 			| OWNER
 			| PARSER
@@ -12992,7 +13023,6 @@ type_func_name_keyword:
 			| NATURAL
 			| NOTNULL
 			| OUTER_P
-			| OVER
 			| OVERLAPS
 			| RIGHT
 			| SIMILAR
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 68a13b7a7ba7fb77fabec033f39df98c5592a503..b3d72a9ae3b0082965c0c78a56477a40f8f1cd6c 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -270,7 +270,7 @@ PG_KEYWORD("or", OR, RESERVED_KEYWORD)
 PG_KEYWORD("order", ORDER, RESERVED_KEYWORD)
 PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD)
 PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD)
-PG_KEYWORD("over", OVER, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("over", OVER, UNRESERVED_KEYWORD)
 PG_KEYWORD("overlaps", OVERLAPS, TYPE_FUNC_NAME_KEYWORD)
 PG_KEYWORD("overlay", OVERLAY, COL_NAME_KEYWORD)
 PG_KEYWORD("owned", OWNED, UNRESERVED_KEYWORD)
diff --git a/src/test/regress/expected/window.out b/src/test/regress/expected/window.out
index 752c7b42ff341bf895405e5f3f558dedb1986e63..ecc1c2c6113da89bc625ac3b2def9cce7fa3b15f 100644
--- a/src/test/regress/expected/window.out
+++ b/src/test/regress/expected/window.out
@@ -989,9 +989,9 @@ ERROR:  window functions are not allowed in GROUP BY
 LINE 1: SELECT rank() OVER (ORDER BY 1), count(*) FROM empsalary GRO...
                ^
 SELECT * FROM rank() OVER (ORDER BY random());
-ERROR:  window functions are not allowed in functions in FROM
+ERROR:  syntax error at or near "ORDER"
 LINE 1: SELECT * FROM rank() OVER (ORDER BY random());
-                      ^
+                                   ^
 DELETE FROM empsalary WHERE (rank() OVER (ORDER BY random())) > 10;
 ERROR:  window functions are not allowed in WHERE
 LINE 1: DELETE FROM empsalary WHERE (rank() OVER (ORDER BY random())...