From f9f749398874120e93eb5bc15eaffbe21462b398 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Mon, 17 Nov 2014 00:00:09 -0800 Subject: Fixed type patterns to use CompoundType to not collide with with `=>` in pattern matches --- .../src/main/scala/scalaparser/ScalaSyntax.scala | 29 ++++++--- .../src/test/scala/scalaparser/SyntaxTest.scala | 76 +++++++++++++++++++++- 2 files changed, 92 insertions(+), 13 deletions(-) diff --git a/scalatexApi/src/main/scala/scalaparser/ScalaSyntax.scala b/scalatexApi/src/main/scala/scalaparser/ScalaSyntax.scala index b7501a1..f88a532 100644 --- a/scalatexApi/src/main/scala/scalaparser/ScalaSyntax.scala +++ b/scalatexApi/src/main/scala/scalaparser/ScalaSyntax.scala @@ -97,7 +97,9 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif def ExistentialDcl = rule { "type" ~ TypeDcl | "val" ~ ValDcl } def InfixType = rule { CompoundType ~ zeroOrMore(Id() ~ optional(Newline) ~ CompoundType) } - def CompoundType = rule { oneOrMore(AnnotType(false)).separatedBy(WL ~ "with") ~ optional(Refinement) } + def CompoundType = rule { + oneOrMore(AnnotType(false)).separatedBy(WL ~ "with") ~ optional(Refinement) + } def AnnotType(G: B = t) = rule { SimpleType(false) ~ zeroOrMore(WL ~ Annotation) ~ W(G) } @@ -116,7 +118,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif def Types = rule { oneOrMore(Type).separatedBy(',') } def Refinement = rule { optional(Newline) ~ '{' ~ oneOrMore(RefineStat).separatedBy(Semi) ~ '}' } def RefineStat = rule { "type" ~ TypeDef | Dcl | MATCH } - def TypePat = rule { Type } + def TypePat = rule { CompoundType } def Ascription(G: B = t) = rule { ":" ~ (InfixType | oneOrMore(Annotation) | "_" ~ StrW("*", G)) } def ParamType = rule { "=>" ~ Type | Type ~ "*" | Type } @@ -135,7 +137,13 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif } def IfCFlow(G: B = t) = rule { "if" ~ '(' ~ Expr() ~ ')' ~ zeroOrMore(Newline) ~ Expr(G) ~ optional(optional(Semi) ~ "else" ~ Expr(G)) } def WhileCFlow(G: B = t) = rule { "while" ~ '(' ~ Expr() ~ ')' ~ zeroOrMore(Newline) ~ Expr(G) } - def TryCFlow(G: B = t) = rule { "try" ~ '{' ~ Block ~ StrW("}", G) ~ optional("catch" ~ '{' ~ CaseClauses ~ StrW("}", G)) ~ optional("finally" ~ Expr(G)) } + def TryCFlow(G: B = t) = rule { + "try" ~ Expr(false) ~ + optional(WL ~ "catch" ~ Expr(false)) ~ + optional(WL ~ "finally" ~ Expr(false)) ~ + W(G) + } + def DoWhileCFlow(G: B = t) = rule { "do" ~ Expr() ~ optional(Semi) ~ "while" ~ '(' ~ Expr() ~ StrW(")", G) } def ForCFlow(G: B = t) = rule { "for" ~ ('(' ~ Enumerators ~ ')' | '{' ~ Enumerators ~ '}') ~ zeroOrMore(Newline) ~ optional("yield") ~ Expr(G) } def PostfixExpr(G: B = t): R0 = rule { InfixExpr(G) ~ optional(Id() ~ optional(Newline)) } @@ -177,17 +185,17 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif Expr1(false) } def ResultExpr(G: B = t): R0 = rule { (Bindings | optional("implicit") ~ Id() | "_") ~ "=>" ~ Block | Expr1(t) } - def Enumerators: R0 = rule { Generator ~ zeroOrMore(Semi ~ Enumerator) } - def Enumerator: R0 = rule { Generator | Guard | Pattern1 ~ '=' ~ Expr() } - def Generator: R0 = rule { Pattern1 ~ "<-" ~ Expr() ~ optional(Guard) } + def Enumerators: R0 = rule { Generator(false) ~ zeroOrMore(Semi ~ Enumerator(false)) ~ WL } + def Enumerator(G: B = t): R0 = rule { Generator(G) | Guard(G) | Pattern1 ~ '=' ~ Expr(G) } + def Generator(G: B = t): R0 = rule { Pattern1 ~ "<-" ~ Expr(false) ~ optional(WL ~ Guard(false)) ~ W(G) } def CaseClauses: R0 = rule { oneOrMore(CaseClause) } - def CaseClause: R0 = rule { "case" ~ Pattern ~ optional(Guard) ~ "=>" ~ Block } - def Guard: R0 = rule { "if" ~ PostfixExpr() } + def CaseClause: R0 = rule { "case" ~ Pattern ~ optional(Guard(true)) ~ "=>" ~ Block } + def Guard(G: B = t): R0 = rule { "if" ~ PostfixExpr(G) } def Pattern: R0 = rule { - oneOrMore(Pattern1 ).separatedBy('|') + oneOrMore(Pattern1).separatedBy('|') } def Pattern1: R0 = rule { '_' ~ ':' ~ TypePat | VarId() ~ ':' ~ TypePat | Pattern2 } - def Pattern2: R0 = rule { VarId() ~ optional("@" ~ Pattern3) | Pattern3 } + def Pattern2: R0 = rule { VarId() ~ optional("@" ~ Pattern3) | Pattern3 } def Pattern3: R0 = rule { SimplePattern ~ zeroOrMore(Id() ~ SimplePattern) } @@ -329,6 +337,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif def PackageObject(G: B = t): R0 = rule { "package" ~ "object" ~ ObjectDef(G) } def CompilationUnit: Rule1[String] = rule { capture( + WL ~ zeroOrMore(Semi) ~ zeroOrMore("package" ~ QualId(false)).separatedBy(Semi) ~ TopStatSeq ~ diff --git a/scalatexApi/src/test/scala/scalaparser/SyntaxTest.scala b/scalatexApi/src/test/scala/scalaparser/SyntaxTest.scala index 2c16962..4e69bc2 100644 --- a/scalatexApi/src/test/scala/scalaparser/SyntaxTest.scala +++ b/scalatexApi/src/test/scala/scalaparser/SyntaxTest.scala @@ -218,10 +218,69 @@ object SyntaxTest extends TestSuite{ |} """.stripMargin ) + * - check( + """/* __ *\ + |** ________ ___ / / ___ __ ____ Scala.js CLI ** + |** / __/ __// _ | / / / _ | __ / // __/ (c) 2013-2014, LAMP/EPFL ** + |** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** + |** /____/\___/_/ |_/____/_/ | |__/ /____/ ** + |** |/____/ ** + |\* */ + | + |package scala.scalajs.cli + | + """.stripMargin + ) + * - check( + """ + |object O{ + | for { + | a <- b + | c <- d + | } { + | 1 + | } + |} + """.stripMargin + ) + * - check( + """ + |object O{ + | val jarFile = + | try { 1 } + | catch { case _: F => G } + |} + """.stripMargin + ) + * - check( + """ + |object F{ + | func{ case _: F => fail } + |} + """.stripMargin + ) + * - check( + """ + |object SyntaxTest extends TestSuite{ + | def check[T](input: String) = { + | new ScalaSyntax(input).CompilationUnit.run() match{ + | case Failure(f: ParseError) => + | println(f.position) + | println(f.formatExpectedAsString) + | println(f.formatTraces) + | throw new Exception(f.position + "\t" + f.formatTraces) + | case Success(parsed) => + | assert(parsed == input) + | } + | } + |} + """.stripMargin + ) + } - println("Checking") + def checkFile(path: String) = check(io.Source.fromFile(path).mkString) 'file{ - def checkFile(path: String) = check(io.Source.fromFile(path).mkString) + * - checkFile("scalatexApi/src/main/scala/scalaparser/syntax/Basic.scala") * - checkFile("scalatexApi/src/main/scala/scalaparser/syntax/Identifiers.scala") @@ -243,6 +302,17 @@ object SyntaxTest extends TestSuite{ * - checkFile("scalatexPlugin/src/main/scala/scalatex/ScalaTexPlugin.scala") } - } + 'omg{ + val root = new java.io.File("../scala-js/") + def listFiles(s: java.io.File): Iterator[String] = { + val (dirs, files) = s.listFiles().toIterator.partition(_.isDirectory) + files.map(_.getPath) ++ dirs.flatMap(listFiles) + } + for(f <- listFiles(root).filter(_.endsWith(".scala"))){ + println("CHECKING " + f) + checkFile(f) + } + } + } } -- cgit v1.2.3