Reviewers: marja, rossberg,

Description:
Allow yield expressions without a RHS.

[email protected], [email protected]
BUG=

Please review this at https://codereview.chromium.org/348893007/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+56, -14 lines):
  M src/ast.h
  M src/preparser.h
  M test/mjsunit/harmony/generators-parsing.js


Index: src/ast.h
diff --git a/src/ast.h b/src/ast.h
index 23f9eef477a9a318769ad67256b650e23ca11372..702eabd9263703711e6853ce9fc597bdb07f71f2 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -3375,6 +3375,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED {
                   Expression* expression,
                   Yield::Kind yield_kind,
                   int pos) {
+    if (!expression) expression = NewUndefinedLiteral(pos);
     Yield* yield = new(zone_) Yield(
         zone_, generator_object, expression, yield_kind, pos);
     VISIT_AND_RETURN(Yield, yield)
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index 499240e63acc6b43bdcefd74edc183113600f432..c64c8de95b69efa2bb46f53ae933e9a3b8a4f249 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -1792,15 +1792,29 @@ template <class Traits>
 typename ParserBase<Traits>::ExpressionT
 ParserBase<Traits>::ParseYieldExpression(bool* ok) {
   // YieldExpression ::
-  //   'yield' '*'? AssignmentExpression
+  //   'yield' ([no line terminator] '*'? AssignmentExpression)?
   int pos = peek_position();
   Expect(Token::YIELD, CHECK_OK);
-  Yield::Kind kind =
-      Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
   ExpressionT generator_object =
factory()->NewVariableProxy(function_state_->generator_object_variable());
-  ExpressionT expression =
-      ParseAssignmentExpression(false, CHECK_OK);
+  ExpressionT expression = Traits::EmptyExpression();
+  Yield::Kind kind = Yield::SUSPEND;
+  if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
+    if (Check(Token::MUL)) kind = Yield::DELEGATING;
+    switch (peek()) {
+      case Token::EOS:
+      case Token::SEMICOLON:
+      case Token::RBRACE:
+      case Token::RBRACK:
+      case Token::RPAREN:
+      case Token::COLON:
+      case Token::COMMA:
+        break;
+      default:
+        expression = ParseAssignmentExpression(false, CHECK_OK);
+        break;
+    }
+  }
   typename Traits::Type::YieldExpression yield =
       factory()->NewYield(generator_object, expression, kind, pos);
   if (kind == Yield::DELEGATING) {
Index: test/mjsunit/harmony/generators-parsing.js
diff --git a/test/mjsunit/harmony/generators-parsing.js b/test/mjsunit/harmony/generators-parsing.js index 2a4a68c37cd3f71089c280d8b52dbe507b0f6fda..21790b0e1383b0a67dac5774a605b4c8d9916fab 100644
--- a/test/mjsunit/harmony/generators-parsing.js
+++ b/test/mjsunit/harmony/generators-parsing.js
@@ -35,6 +35,40 @@ function* g() { yield 3; yield 4; }
 // Yield expressions.
 function* g() { (yield 3) + (yield 4); }

+// Yield without a RHS.
+function* g() { yield; }
+function* g() { yield }
+function* g() {
+  yield
+}
+function* g() { (yield) }
+function* g() { [yield] }
+function* g() { {yield} }
+function* g() { yield, yield }
+function* g() { yield; yield }
+function* g() { (yield) ? yield : yield }
+function* g() {
+  (yield)
+  ? yield
+  : yield
+}
+
+// If yield has a RHS, it needs to start on the same line.  The * in a
+// yield* counts as starting the RHS.
+function* g() {
+  yield *
+  foo
+}
+assertThrows("function* g() { yield\n* foo }", SyntaxError);
+assertEquals(undefined,
+             (function*(){
+               yield
+               3
+             })().next().value);
+
+// A YieldExpression is not a LogicalORExpression.
+assertThrows("function* g() { yield ? yield : yield }", SyntaxError);
+
 // You can have a generator in strict mode.
 function* g() { "use strict"; yield 3; yield 4; }

@@ -50,14 +84,10 @@ function* g() { yield 1; return 2; yield "dead"; }
 // Named generator expression.
 (function* g() { yield 3; });

-// A generator without a yield is specified as causing an early error. This
-// behavior is currently unimplemented.  See
-// https://bugs.ecmascript.org/show_bug.cgi?id=1283.
+// You can have a generator without a yield.
 function* g() { }

-// A YieldExpression in the RHS of a YieldExpression is currently specified as
-// causing an early error.  This behavior is currently unimplemented.  See
-// https://bugs.ecmascript.org/show_bug.cgi?id=1283.
+// A YieldExpression is valid as the RHS of a YieldExpression.
 function* g() { yield yield 1; }
 function* g() { yield 3 + (yield 4); }

@@ -86,9 +116,6 @@ assertThrows("function* g() { yield: 1 }", SyntaxError)
 // functions.
 function* g() { function f() { yield (yield + yield (0)); } }

-// Yield needs a RHS.
-assertThrows("function* g() { yield; }", SyntaxError);
-
 // Yield in a generator is not an identifier.
 assertThrows("function* g() { yield = 10; }", SyntaxError);



--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to