From e65a5dde462be15d4fbb5db8e3be2d7365c99f08 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Fri, 28 Nov 2014 09:51:52 -0800 Subject: Goes all the way to scala / test / files / pos / dotless-targs.scala --- .../src/main/scala/scalaParser/ScalaSyntax.scala | 22 +++++++------ .../scala/scalaParser/syntax/Identifiers.scala | 19 ++++++++---- .../main/scala/scalaParser/syntax/Literals.scala | 2 +- scalaParser/src/test/resources/test.scala | 11 +++++-- .../src/test/scala/scalaParser/SyntaxTest.scala | 36 ++++++++++++++++++++-- 5 files changed, 68 insertions(+), 22 deletions(-) diff --git a/scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala b/scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala index 6e41654..11cff86 100644 --- a/scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala +++ b/scalaParser/src/main/scala/scalaParser/ScalaSyntax.scala @@ -142,7 +142,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif } } def AnnotType = rule { - SimpleType ~ optional(NotNewline ~ oneOrMore(Annotation)) + SimpleType ~ optional(NotNewline ~ oneOrMore(NotNewline ~ Annotation)) } def SimpleType: R0 = { def BasicType: R0 = rule { @@ -185,7 +185,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif } } def Enumerators(G: Boolean = false): R0 = { - def Generator: R0 = rule { Pattern1 ~ K.O("<-") ~ Expr0(G) ~ optional(Guard(G)) } + def Generator: R0 = rule { Pattern1 ~ (K.O("<-") | K.O("←"))~ Expr0(G) ~ optional(Guard(G)) } def Enumerator: R0 = rule { Generator | Guard(G) | Pattern1 ~ `=` ~ Expr0(G) } rule { Generator ~ zeroOrMore(Semis ~ Enumerator) ~ WL } } @@ -271,7 +271,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif OneNewlineMax ~ BlockExpr } - def BlockExpr: R0 = rule { '{' ~ (CaseClauses | Block) ~ "}" } + def BlockExpr: R0 = rule { '{' ~ (CaseClauses | Block) ~ optional(Semis) ~ "}" } def BlockStats: R0 = { @@ -313,26 +313,26 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif } def Pattern2: R0 = { def Pattern3: R0 = rule { - SimplePattern ~ zeroOrMore(Id ~ SimplePattern) + `_` ~ '*' | SimplePattern ~ zeroOrMore(Id ~ SimplePattern) } rule{ VarId ~ "@" ~ Pattern3 | Pattern3 | VarId } } def SimplePattern: R0 = { - def Patterns: R0 = rule { `_` ~ '*' | oneOrMore(Pattern).separatedBy(',') } + def ExtractorArgs = rule{ - optional(Patterns ~ ',') ~ optional(VarId ~ '@') ~ `_` ~ '*' + zeroOrMore(Pattern).separatedBy(',') } def Extractor: R0 = rule{ StableId ~ optional( - '(' ~ (ExtractorArgs | Patterns | MATCH) ~ ')' + '(' ~ ExtractorArgs ~ ')' ) } rule { `_` ~ optional(`:` ~ TypePat) ~ !("*") | Literal | - '(' ~ optional(Patterns) ~ ')' | + '(' ~ optional(ExtractorArgs) ~ ')' | Extractor | VarId } @@ -361,6 +361,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif } def ParamClause: R0 = rule { OneNewlineMax ~ '(' ~ optional(Params) ~ ')' } def Params: R0 = { + def Param: R0 = rule { zeroOrMore(Annotation) ~ Id ~ optional(`:` ~ ParamType) ~ optional(`=` ~ Expr) } rule { zeroOrMore(Param).separatedBy(',') } } @@ -387,6 +388,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif '{' ~ optional(SelfType) ~ zeroOrMore(TemplateStat).separatedBy(Semis) ~ + optional(Semis) ~ '}' } def TemplateStat: R0 = rule { @@ -460,7 +462,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif OneNewlineMax ~ '(' ~ `implicit` ~ - ClassParam ~ + oneOrMore(ClassParam).separatedBy(",") ~ ")" } @@ -545,7 +547,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif rule { capture( optional(Semis) ~ - (TopPackageSeq ~ optional(Semis ~ TopStatSeq) | TopStatSeq) ~ + (TopPackageSeq ~ optional(Semis ~ TopStatSeq) | TopStatSeq | MATCH) ~ optional(Semis) ~ WL ) diff --git a/scalaParser/src/main/scala/scalaParser/syntax/Identifiers.scala b/scalaParser/src/main/scala/scalaParser/syntax/Identifiers.scala index 5456d16..a95afac 100644 --- a/scalaParser/src/main/scala/scalaParser/syntax/Identifiers.scala +++ b/scalaParser/src/main/scala/scalaParser/syntax/Identifiers.scala @@ -8,15 +8,21 @@ trait Identifiers { self: Parser with Basic => import Basic._ def Operator = rule{!Keywords ~ oneOrMore(OperatorChar)} - def VarId = rule { !Keywords ~ Lower ~ IdRest } - def PlainId = rule { !Keywords ~ Upper ~ IdRest | VarId | Operator } + def VarId = VarId0(true) + def VarId0(dollar: Boolean) = rule { !Keywords ~ Lower ~ IdRest(dollar) } + def PlainId = rule { !Keywords ~ Upper ~ IdRest(true) | VarId | Operator } + def PlainIdNoDollar = rule { !Keywords ~ Upper ~ IdRest(false) | VarId0(false) | Operator } def Id = rule { !Keywords ~ PlainId | ("`" ~ oneOrMore(noneOf("`")) ~ "`") } - def IdRest = rule { - zeroOrMore(zeroOrMore("_") ~ oneOrMore(!"_" ~ Letter | Digit)) ~ - optional(oneOrMore("_") ~ zeroOrMore(OperatorChar)) + def IdRest(dollar: Boolean) = { + if (!dollar) rule { + zeroOrMore(zeroOrMore("_") ~ oneOrMore(!anyOf("_$") ~ Letter | Digit)) ~ + optional(oneOrMore("_") ~ zeroOrMore(OperatorChar)) + } else rule{ + zeroOrMore(zeroOrMore("_") ~ oneOrMore(!"_" ~ Letter | Digit)) ~ + optional(oneOrMore("_") ~ zeroOrMore(OperatorChar)) + } } - def AlphabetKeywords = rule { ( "abstract" | "case" | "catch" | "class" | "def" | "do" | "else" | "extends" | "false" | "finally" | "final" | "finally" | "forSome" | "for" | "if" | @@ -33,5 +39,6 @@ trait Identifiers { self: Parser with Basic => AlphabetKeywords | SymbolicKeywords } + } } diff --git a/scalaParser/src/main/scala/scalaParser/syntax/Literals.scala b/scalaParser/src/main/scala/scalaParser/syntax/Literals.scala index 703c793..e6dd54d 100644 --- a/scalaParser/src/main/scala/scalaParser/syntax/Literals.scala +++ b/scalaParser/src/main/scala/scalaParser/syntax/Literals.scala @@ -51,7 +51,7 @@ trait Literals { self: Parser with Basic with Identifiers => } def pr(s: String) = rule { run(println(s"LOGGING $cursor: $s")) } def Interpolation = rule{ - "$" ~ Identifiers.Id | "${" ~ Block ~ WL ~ "}" | "$$" + "$" ~ Identifiers.PlainIdNoDollar | "${" ~ Block ~ WL ~ "}" | "$$" } def StringLiteral = rule { (Identifiers.Id ~ "\"\"\"" ~ MultiLineChars ~ ("\"\"\"" ~ zeroOrMore('"'))) | diff --git a/scalaParser/src/test/resources/test.scala b/scalaParser/src/test/resources/test.scala index 5267441..191933e 100644 --- a/scalaParser/src/test/resources/test.scala +++ b/scalaParser/src/test/resources/test.scala @@ -1,3 +1,8 @@ -trait T{ - s match { case S(_, r @ _*) => 1 } -} \ No newline at end of file +class A { + def fn1 = List apply 1 + def fn2 = List apply[Int] 2 + + def g1: Char = "g1" toList 0 + def g2: Char = "g2" apply 1 + + def h1 = List apply[List[Int]] (List(1), List(2)) mapConserve[List[Any]] (x => x) \ No newline at end of file diff --git a/scalaParser/src/test/scala/scalaParser/SyntaxTest.scala b/scalaParser/src/test/scala/scalaParser/SyntaxTest.scala index 569c982..8a4affb 100644 --- a/scalaParser/src/test/scala/scalaParser/SyntaxTest.scala +++ b/scalaParser/src/test/scala/scalaParser/SyntaxTest.scala @@ -698,6 +698,32 @@ object SyntaxTest extends TestSuite{ """import java.util.concurrent.TimeUnit.{ NANOSECONDS => NANOS, MILLISECONDS ⇒ MILLIS } """.stripMargin ) + * - check( + """class FunFinder{ + | val targetName = s"$name${ if (isModule) "$" else "" }" + |} + """.stripMargin + ) + * - check( + """class AkkaException{ + | for (i ← 0 until trace.length) + | () + |} + """.stripMargin + ) + * - check( + """class FiniteDuration{ + | 1000. + |} + """.stripMargin + ) + * - check( + """object Test4 { + | type T = F @field + | @BeanProperty val x = 1 + |} + """.stripMargin + ) } 'neg{ @@ -776,14 +802,20 @@ object SyntaxTest extends TestSuite{ val (dirs, files) = s.listFiles().toIterator.partition(_.isDirectory) files.map(_.getPath) ++ dirs.flatMap(listFiles) } + // Things that we won't bother parsing, mainly because they use XML literals val blacklist = Seq( "dbuild-meta-json-gen.scala", - "genprod.scala" + "genprod.scala", + "doc/html/HtmlPage.scala", + "scala/src/scaladoc/scala/tools/nsc/doc/html", + "jvm/interpreter.scala", + "disabled", // don't bother parsing disabled tests + "neg" // or neg tests ) for{ f <- listFiles(root) if f.endsWith(".scala") - if !blacklist.exists(f.endsWith) + if !blacklist.exists(f.contains) }{ println("CHECKING " + f) checkFile(f) -- cgit v1.2.3