From 6dc8a6a5df5e2dc30d78a4f0fd637eed417b08a1 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Tue, 3 Jun 2014 07:00:17 +0100 Subject: [PATCH] Allow primes at the end of identifiers. --- .../scala/tools/nsc/ast/parser/Scanners.scala | 11 +++++ .../scala/reflect/NameTransformer.scala | 1 + test/files/neg/primed-identifiers.check | 7 +++ test/files/neg/primed-identifiers.scala | 13 +++++ test/files/pos/primed-identifiers.scala | 48 +++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 test/files/neg/primed-identifiers.check create mode 100644 test/files/neg/primed-identifiers.scala create mode 100644 test/files/pos/primed-identifiers.scala diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 328c10448b2..a5fa90bacac 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -637,6 +637,10 @@ trait Scanners extends ScannersCommon { putChar(ch) nextChar() getIdentOrOperatorRest() + case '\'' => + putChar(ch) + nextChar() + getPrimeRest() case SU => // strangely enough, Character.isUnicodeIdentifierPart(SU) returns true! finishNamed() case _ => @@ -649,6 +653,13 @@ trait Scanners extends ScannersCommon { } } + private def getPrimeRest(): Unit = + if (ch == '\'') { + putChar(ch) + nextChar() + getPrimeRest() + } else finishNamed() + private def getOperatorRest(): Unit = (ch: @switch) match { case '~' | '!' | '@' | '#' | '%' | '^' | '*' | '+' | '-' | '<' | diff --git a/src/library/scala/reflect/NameTransformer.scala b/src/library/scala/reflect/NameTransformer.scala index a8430548f5c..864ac3cfc72 100755 --- a/src/library/scala/reflect/NameTransformer.scala +++ b/src/library/scala/reflect/NameTransformer.scala @@ -54,6 +54,7 @@ object NameTransformer { enterOp('\\', "$bslash") enterOp('?', "$qmark") enterOp('@', "$at") + enterOp('\'', "$prime") /** Replace operator symbols by corresponding `\$opname`. * diff --git a/test/files/neg/primed-identifiers.check b/test/files/neg/primed-identifiers.check new file mode 100644 index 00000000000..fa4fb81daf6 --- /dev/null +++ b/test/files/neg/primed-identifiers.check @@ -0,0 +1,7 @@ +primed-identifiers.scala:4: error: value b' is not a member of object a1 + a1 b'c' // parses as a1 b' c' + ^ +primed-identifiers.scala:4: error: not found: value c' + a1 b'c' // parses as a1 b' c' + ^ +two errors found diff --git a/test/files/neg/primed-identifiers.scala b/test/files/neg/primed-identifiers.scala new file mode 100644 index 00000000000..68c2876bfe9 --- /dev/null +++ b/test/files/neg/primed-identifiers.scala @@ -0,0 +1,13 @@ +object a1 { + def b(c: Char) = ??? + + a1 b'c' // parses as a1 b' c' +} + +object a2 { + def b'(c: Int) = ??? + def b(c: Char) = ??? + + val c' = 23 + a2 b'c' // parses as a2 b' c' +} diff --git a/test/files/pos/primed-identifiers.scala b/test/files/pos/primed-identifiers.scala new file mode 100644 index 00000000000..348ff4aca20 --- /dev/null +++ b/test/files/pos/primed-identifiers.scala @@ -0,0 +1,48 @@ +object Test { + val l = List("Identifiers", "with", "primes", "!") + + val l' = l map(_.length) + + val l'' = l zip l' + + val l''' = l''.reverse + + object a1 { + def b(c: Char) = ??? + + a1 b 'c' + } + + object a2 { + def b'(c: Int) = ??? + def b(c: Char) = ??? + + a2 b' 23 + a2 b'23 + + val i = 23 + a2 b'i + + val c' = 23 + a2 b'c' // parses as a2 b' c' + + a2 b 'c' + } + + case object Foo' + case class Bar'(i: Int) + + ((): Any) match { + case foo': String => ??? + case Foo' => ??? + case Bar'(foo') => ??? + } + + val (x', y') = (13, 23) + + for (z' <- List(x', y')) x'*2 + + type T' = Int + def foo[U', F'[_]](ft: F'[T'], fu: F'[U']) = (ft, fu) +} +