summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Haoyi <haoyi@dropbox.com>2014-11-16 16:40:51 -0800
committerLi Haoyi <haoyi@dropbox.com>2014-11-16 16:40:51 -0800
commitba96a85378fd7fb24cf386ced21a3427112c3610 (patch)
tree5e995c9eb0d886051f96d3dd5573a5b6115ecc64
parent857c620357775c8ee79de2c53dbdc39456332c4b (diff)
downloadhands-on-scala-js-ba96a85378fd7fb24cf386ced21a3427112c3610.tar.gz
hands-on-scala-js-ba96a85378fd7fb24cf386ced21a3427112c3610.tar.bz2
hands-on-scala-js-ba96a85378fd7fb24cf386ced21a3427112c3610.zip
Fixed more things, added "macro" keyword
-rw-r--r--scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala69
-rw-r--r--scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala129
2 files changed, 144 insertions, 54 deletions
diff --git a/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala b/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala
index d0a9b0e..d2dd29d 100644
--- a/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala
+++ b/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala
@@ -34,7 +34,7 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
/**
* helper printing function
*/
- def pr(s: String) = rule { run(print(s)) }
+ def pr(s: String) = rule { run(println(s"LOGGING $cursor: $s")) }
//////////////////////////////////////////////////
// Override rules from dependencies
@@ -123,7 +123,9 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def PrefixExpr(G: B = true) = rule { optional(anyOf("-+~!")) ~ SimpleExpr(G) }
def SimpleExpr(G: B = true): Rule0 = rule {
- SimpleExpr1(G) ~ zeroOrMore('.' ~ IdS() | TypeArgs | ArgumentExprs(G)) ~ optional('_')
+ SimpleExpr1(G) ~
+ zeroOrMore('.' ~ IdS() | TypeArgs | ArgumentExprs(G)) ~
+ optional('_')
}
def SimpleExpr1(G: B = true) = rule{
@@ -138,11 +140,15 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def Exprs: Rule0 = rule { oneOrMore(Expr()).separatedBy(',') }
def ArgumentExprs(G: B = true): Rule0 = rule {
- '(' ~ (optional(Exprs ~ ',') ~ PostfixExpr() ~ ':' ~ '_' ~ '*' | optional(Exprs)) ~ ')' |
- optional(NewlineS) ~ BlockExpr(G)
+ '(' ~ (optional(Exprs ~ ',') ~ PostfixExpr() ~ ':' ~ '_' ~ '*' | optional(Exprs)) ~ wspStrG(")", G) |
+ optional(NewlineS) ~ BlockExpr(G)
}
+
def BlockExpr(G: B = true): Rule0 = rule { '{' ~ (CaseClauses | Block) ~ wspStrG("}", G) }
- def Block: Rule0 = rule { zeroOrMore(BlockStat ~ SemiS) ~ optional(ResultExpr()) }
+ def Block: Rule0 = rule {
+ zeroOrMore(BlockStat ~ SemiS) ~ optional(ResultExpr())
+ }
+
def BlockStat: Rule0 = rule {
SemiS |
Import(false) |
@@ -162,10 +168,10 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def Pattern3: Rule0 = rule { SimplePattern ~ zeroOrMore(IdS() ~ optional(NewlineS) ~ SimplePattern) } // this pattern doesn't make sense to me...
def SimplePattern: Rule0 = rule {
'_' |
- LiteralS() ~ drop[String] | //literal currently captures, so it can be used outside. but since all our rules lack AST, we drop its value in order to be able to compose them
- '(' ~ optional(Patterns) ~ ')' |
- StableId() ~ '(' ~ (optional(Patterns ~ ',') ~ optional(VarIdS() ~ '@') ~ '_' ~ '*' | optional(Patterns)) ~ ')' |
- VarIdS() /*|
+ LiteralS() ~ drop[String] | //literal currently captures, so it can be used outside. but since all our rules lack AST, we drop its value in order to be able to compose them
+ '(' ~ optional(Patterns) ~ ')' |
+ StableId() ~ '(' ~ (optional(Patterns ~ ',') ~ optional(VarIdS() ~ '@') ~ '_' ~ '*' | optional(Patterns)) ~ ')' |
+ VarIdS() /*|
XmlPattern*/
}
def Patterns: Rule0 = rule { '_' ~ '*' | oneOrMore(Pattern).separatedBy(',') }
@@ -194,7 +200,15 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def Annotation: Rule0 = rule { '@' ~ SimpleType ~ zeroOrMore(ArgumentExprs()) }
def ConstrAnnotation: Rule0 = rule { '@' ~ SimpleType ~ ArgumentExprs() }
- def TemplateBody(G: B = true): Rule0 = rule { optional(NewlineS) ~ '{' ~ optional(SelfType) ~ TemplateStat(false) ~ zeroOrMore(SemiS ~ TemplateStat(false)) ~ wspStrG("}", G) }
+ def TemplateBody(G: B = true): Rule0 = rule {
+ WhiteLines ~
+ '{' ~
+ optional(SelfType) ~
+ TemplateStat(false) ~
+ zeroOrMore(SemiS ~ TemplateStat(false)) ~
+ WhiteLines ~
+ wspStrG("}", G)
+ }
def TemplateStat(G: B = true): Rule0 = rule {
Import(false) |
zeroOrMore(Annotation ~ optional(NewlineS)) ~ zeroOrMore(Modifier) ~ (Def(G) | Dcl) |
@@ -213,9 +227,9 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def Dcl: Rule0 = rule {
"val" ~ ValDcl |
- "var" ~ VarDcl |
- "def" ~ FunDcl |
- "type" ~ zeroOrMore(NewlineS) ~ TypeDcl
+ "var" ~ VarDcl |
+ "def" ~ FunDcl |
+ "type" ~ zeroOrMore(NewlineS) ~ TypeDcl
}
def ValDcl: Rule0 = rule { Ids ~ ':' ~ Type }
def VarDcl: Rule0 = rule { Ids ~ ':' ~ Type }
@@ -229,22 +243,39 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def VarDef(G: B = true): Rule0 = rule { Ids ~ ':' ~ Type ~ '=' ~ '_' | PatDef(G) }
def FunDef(G: B = true): Rule0 = rule {
"this" ~ ParamClause ~ ParamClauses ~ ('=' ~ ConstrExpr | optional(NewlineS) ~ ConstrBlock) |
- FunSig ~ (optional(':' ~ Type) ~ '=' ~ Expr(G) | optional(NewlineS) ~ '{' ~ Block ~ '}')
+ FunSig ~ (optional(':' ~ Type) ~ '=' ~ optional("macro") ~ Expr(G) | optional(NewlineS) ~ '{' ~ Block ~ '}')
}
def TypeDef: Rule0 = rule { IdS() ~ optional(TypeParamClause) ~ '=' ~ Type }
def TmplDef(G: B = true): Rule0 = rule { "trait" ~ TraitDef(G) | optional("case") ~ ("class" ~ ClassDef(G) | "object" ~ ObjectDef(G)) }
- def ClassDef(G: B = true): Rule0 = rule { IdS() ~ optional(TypeParamClause) ~ zeroOrMore(ConstrAnnotation) ~ optional(AccessModifier) ~ ClassParamClauses(G) ~ ClassTemplateOpt(G) }
+ def ClassDef(G: B = true): Rule0 = rule {
+ IdS() ~
+ optional(TypeParamClause) ~
+ zeroOrMore(ConstrAnnotation) ~
+ optional(AccessModifier) ~
+ ClassParamClauses(G) ~
+ ClassTemplateOpt(G)
+ }
def TraitDef(G: B = true): Rule0 = rule { IdS() ~ optional(TypeParamClause) ~ TraitTemplateOpt(G) }
def ObjectDef(G: B = true): Rule0 = rule { IdS() ~ ClassTemplateOpt(G) }
- def ClassTemplateOpt(G: B = true): Rule0 = rule { "extends" ~ ClassTemplate(G) | optional(optional("extends") ~ TemplateBody(G)) }
+ def ClassTemplateOpt(G: B = true): Rule0 = rule {
+ "extends" ~ ClassTemplate(G) |
+ optional(optional("extends") ~ TemplateBody(G))
+ }
def TraitTemplateOpt(G: B = true): Rule0 = rule { "extends" ~ TraitTemplate(G) | optional(optional("extends") ~ TemplateBody(G)) }
- def ClassTemplate(G: B = true): Rule0 = rule { optional(EarlyDefs) ~ ClassParents ~ optional(TemplateBody(G)) }
+ def ClassTemplate(G: B = true): Rule0 = rule {
+ optional(EarlyDefs) ~
+ ClassParents ~
+ optional(TemplateBody(G))
+ }
+
def TraitTemplate(G: B = true): Rule0 = rule { optional(EarlyDefs) ~ TraitParents ~ optional(TemplateBody(G)) }
def ClassParents: Rule0 = rule { Constr ~ zeroOrMore("with" ~ AnnotType) }
def TraitParents: Rule0 = rule { AnnotType ~ zeroOrMore("with" ~ AnnotType) }
def Constr: Rule0 = rule { AnnotType ~ zeroOrMore(ArgumentExprs()) }
- def EarlyDefs: Rule0 = rule { '{' ~ optional(oneOrMore(EarlyDef).separatedBy(SemiS)) ~ '}' ~ "with" }
+ def EarlyDefs: Rule0 = rule {
+ '{' ~ optional(oneOrMore(EarlyDef).separatedBy(SemiS)) ~ '}' ~ "with"
+ }
def EarlyDef: Rule0 = rule { zeroOrMore(Annotation ~ optional(NewlineS)) ~ zeroOrMore(Modifier) ~ PatVarDef(false) }
def ConstrExpr: Rule0 = rule { ConstrBlock | SelfInvocation }
def ConstrBlock: Rule0 = rule { '{' ~ SelfInvocation ~ zeroOrMore(SemiS ~ BlockStat) ~ '}' }
@@ -254,5 +285,5 @@ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identif
def TopStat: Rule0 = rule { Packaging | PackageObject(false) | Import(false) | zeroOrMore(Annotation ~ optional(NewlineS)) ~ zeroOrMore(Modifier) ~ TmplDef(false) | MATCH }
def Packaging: Rule0 = rule { "package" ~ QualId ~ optional(NewlineS) ~ '{' ~ TopStatSeq ~ '}' }
def PackageObject(G: B = true): Rule0 = rule { "package" ~ "object" ~ ObjectDef(G) }
- def CompilationUnit: Rule1[String] = rule { capture(zeroOrMore(SemiS) ~ zeroOrMore("package" ~ QualId).separatedBy(SemiS) ~ TopStatSeq) }
+ def CompilationUnit: Rule1[String] = rule { capture(zeroOrMore(SemiS) ~ zeroOrMore("package" ~ QualId).separatedBy(SemiS) ~ TopStatSeq ~ EOI) }
}
diff --git a/scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala b/scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala
index 4562dbd..f872ec6 100644
--- a/scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala
+++ b/scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala
@@ -11,6 +11,8 @@ 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) =>
@@ -18,43 +20,100 @@ object SyntaxTest extends TestSuite{
}
}
def tests = TestSuite{
+ 'unit {
+ * - check(
+ "package torimatomeru"
- * - check(
- "package torimatomeru"
+ )
+ * - check(
+ """
+ |package torimatomeru
+ |
+ |import org.parboiled2.ParseError
+ |import utest._
+ |import utest.framework.Test
+ """.stripMargin
- )
- * - check(
- """
- |package torimatomeru
- |
- |import org.parboiled2.ParseError
- |import utest._
- |import utest.framework.Test
- """.stripMargin
+ )
+ * - check(
+ """
+ |package torimatomeru
+ |
+ |import org.parboiled2.ParseError
+ |import utest._
+ |import utest.framework.Test
+ |import utest.util.Tree
+ |
+ |import scala.util.{Failure, Success}
+ |
+ |object SyntaxTest extends TestSuite
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object SyntaxTest extends TestSuite{
+ | def check[T](input: String) = {
+ |
+ | }
+ |}
+ """.stripMargin
+ )
+ * - check(
+ """
+ |object SyntaxTest{
+ | a()
+ | throw 1
+ |}
+ """.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
+ )
+ * - check(
+ """package scalatex
+ |
+ |
+ |import org.parboiled2._
+ |import torimatomeru.ScalaSyntax
+ |
+ |import scalatex.stages.{Trim, Parser, Ast}
+ |import scalatex.stages.Ast.Block.{IfElse, For, Text}
+ |import Ast.Chain.Args
+ |
+ |object ParserTests extends utest.TestSuite{
+ | import Ast._
+ | import utest._
+ | def check[T](input: String, parse: Parser => scala.util.Try[T], expected: T) = {
+ | val parsed = parse(new Parser(input)).get
+ | assert(parsed == expected)
+ | }
+ | def tests = TestSuite{}
+ |}
+ """.stripMargin
+ )
+ }
+ 'file{
+ * - check(io.Source.fromFile("scalatexApi/src/test/scala/torimatomeru/SyntaxTest.scala").mkString)
+ * - check(io.Source.fromFile("scalatexApi/src/test/scala/scalatex/TestUtil.scala").mkString)
+
+// Seems to run forever? Maybe exponential performance
+// * - check(io.Source.fromFile("scalatexApi/src/test/scala/scalatex/ParserTests.scala").mkString)
- )
- * - check(
- """
- |package torimatomeru
- |
- |import org.parboiled2.ParseError
- |import utest._
- |import utest.framework.Test
- |import utest.util.Tree
- |
- |import scala.util.{Failure, Success}
- |
- |object SyntaxTest extends TestSuite
- """.stripMargin
- )
- * - check(
- """
- |object SyntaxTest extends TestSuite{
- | def check[T](input: String) = {
- |
- | }
- |}
- """.stripMargin
- )
+ * - check(io.Source.fromFile("scalatexApi/src/main/scala/scalatex/package.scala").mkString)
+ }
}
}