From 36b0e8178f74a2986bce5c9027b9a2b22a4e7527 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 18 Feb 2009 19:59:28 +0000 Subject: Fix and test case for #1565; an anonymous funct... Fix and test case for #1565; an anonymous function can now be used as a statement (primarily for use in the interpreter) unless it cannot be distinguished from a self-type declaration. --- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 16 ++++++++++++---- test/files/neg/xmltruncated6.check | 2 +- test/files/pos/bug1565.scala | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 test/files/pos/bug1565.scala diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index f08b08b3d7..b8b8d1bffb 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1075,9 +1075,17 @@ trait Parsers extends NewScanners with MarkupParsers { Match(stripParens(t), cases) } } - if (inToken == ARROW && location != InTemplate) { + // in order to allow anonymous functions as statements (as opposed to expressions) inside + // templates, we have to disambiguate them from self type declarations - bug #1565 + // The case still missed is unparenthesized single argument, like "x: Int => x + 1", which + // may be impossible to distinguish from a self-type and so remains an error. (See #1564) + def lhsIsTypedParamList() = t match { + case Parens(xs) if xs forall (_.isInstanceOf[Typed]) => true + case _ => false + } + if (inToken == ARROW && (location != InTemplate || lhsIsTypedParamList)) { t = atPos(inSkipToken) { - Function(convertToParams(t), if (location == Local) expr() else block()) + Function(convertToParams(t), if (location != InBlock) expr() else block()) } } stripParens(t) @@ -2501,10 +2509,10 @@ trait Parsers extends NewScanners with MarkupParsers { acceptStatSep() } else if (isExprIntro) { stats += statement(InBlock) - if (inToken != RBRACE && inToken != CASE) acceptStatSep() + if (inToken != RBRACE && inToken != CASE && inToken != EOF) acceptStatSep() } else if (isDefIntro || isLocalModifier || in.token == AT) { stats ++= localDef - if (inToken == RBRACE || inToken == CASE) { + if (inToken == RBRACE || inToken == CASE || inToken == EOF) { syntaxError("block must end in result expression, not in definition", false) stats += Literal(()).setPos(inCurrentPos) } else acceptStatSep() diff --git a/test/files/neg/xmltruncated6.check b/test/files/neg/xmltruncated6.check index 6123114560..f638f2f090 100644 --- a/test/files/neg/xmltruncated6.check +++ b/test/files/neg/xmltruncated6.check @@ -1,4 +1,4 @@ -xmltruncated6.scala:2: error: ';' expected but eof found. +xmltruncated6.scala:2: error: in XML literal: expected end of Scala block val stuff = { "no closing brace" ^ one error found diff --git a/test/files/pos/bug1565.scala b/test/files/pos/bug1565.scala new file mode 100644 index 0000000000..9a5bfd0882 --- /dev/null +++ b/test/files/pos/bug1565.scala @@ -0,0 +1,18 @@ +object Bug1565 { + object X0 { 0; (a : Int, b : Int, c : Int) => println(List(a, b)) } + def x() = { 0; (a : Int, b : Int) => println(List(a, b)) ; 0 } + + (a : Int, b : Int) => println(List(a, b)) + + // various function syntaxes to exercise the parser + val xs = List(1,2,3) + xs.filter(x => x < 2) + xs.filter((x) => x < 2) + xs.filter { x => x < 2 } + xs.filter { _ < 2 } + xs.filter (_ < 2) + xs.foreach { e => + val buf0 = e + 1 + buf0 + } +} \ No newline at end of file -- cgit v1.2.3