From a99ca0a1c4df83638d888d316a453b6516477a08 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 4 Nov 2014 22:13:05 -0800 Subject: Narrowed it down to a problem in parboiled2??? It seem like if "f" gets printed, "B" should get printed too... --- .../src/main/scala/scalatex/stages/Compiler.scala | 17 +++ .../src/main/scala/scalatex/stages/Parser.scala | 19 ++-- .../src/test/scala/scalatex/BasicTests.scala | 30 +++--- .../src/test/scala/scalatex/ParserTests.scala | 119 ++++++++++++--------- 4 files changed, 110 insertions(+), 75 deletions(-) (limited to 'scalatexApi/src') diff --git a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala index 0ac9844..8bb203a 100644 --- a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala @@ -17,6 +17,7 @@ object Compiler{ println(template) def compileChain(code: String, parts: Seq[Ast.Chain.Sub], offset: Int): c.Tree = { + println("CODE " + code) parts.foldLeft(c.parse(code)){ case (curr, Ast.Chain.Prop(str, offset2)) => q"$curr.${TermName(str)}" case (curr, Ast.Chain.Args(str, offset2)) => @@ -37,6 +38,22 @@ object Compiler{ case Ast.Block.Text(str, _) => q"$str" case Ast.Chain(code, parts, offset) => compileChain(code, parts, offset) case Ast.Header(header, block, offset) => compileHeader(header, block, offset) + case Ast.Block.For(generators, Ast.Block(parts2, offset2), offset) => + val fresh = c.fresh() + + val tree = c.parse(s"$generators yield $fresh" ) + def rec(t: Tree): Tree = t match { + case a @ Apply(fun, List(f @ Function(vparams, body))) => + val f2 = Function(vparams, rec(body)) + val a2 = Apply(fun, List(f2)) + a2 + case Ident(x: TermName) if x.decoded == fresh => + q"Seq[$fragType](..${compileBlock(parts2, offset2)})" + } + + val out = rec(tree) + println(out) + out } } def compileHeader(header: String, block: Ast.Block, offset: Int): c.Tree = { diff --git a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala index 3b75d54..48138af 100644 --- a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala @@ -73,17 +73,21 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) { def IfElse = rule{ (IfElse1 | IfElse2) ~> (Ast.Block.IfElse(_, _, _)) } + + def ForHead = rule{ + "@" ~ capture("for" ~ '(' ~ Enumerators ~ ')'~ run(println("f"))) + } def ForLoop = rule{ - "@" ~ - capture("for" ~ ('(' ~ Enumerators ~ ')' | '{' ~ Enumerators ~ '}')) ~ - BraceBlock ~> (Ast.Block.For(_, _)) + run(println("A")) ~ ForHead ~ run(println("B")) ~ + BraceBlock ~ run(println("C")) ~> (Ast.Block.For(_, _)) } def LoneForLoop = rule{ - "@" ~ - capture("for" ~ ('(' ~ Enumerators ~ ')' | '{' ~ Enumerators ~ '}')) ~ + (capture(Indent) ~> (Ast.Block.Text(_))) ~ + ForHead ~ IndentBlock ~> (Ast.Block.For(_, _)) } + def ScalaChain = rule { Code ~ zeroOrMore(Extension) ~> {Ast.Chain(_, _)} } @@ -103,10 +107,11 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) { def BraceBlock: Rule1[Ast.Block] = rule{ '{' ~ Body ~ '}' } def BodyItem: Rule1[Seq[Ast.Block.Sub]] = rule{ + ForLoop ~> (Seq(_)) | + LoneForLoop ~> (Seq(_, _)) | + IfElse ~> (Seq(_)) | LoneScalaChain ~> (Seq(_, _)) | HeaderBlock ~> (Seq(_)) | - ForLoop ~> (Seq(_)) | - LoneForLoop ~> (Seq(_)) | TextNot("@}") ~> (Seq(_)) | (capture(Indent) ~> (x => Seq(Ast.Block.Text(x)))) | (capture(BlankLine) ~> (x => Seq(Ast.Block.Text(x)))) | diff --git a/scalatexApi/src/test/scala/scalatex/BasicTests.scala b/scalatexApi/src/test/scala/scalatex/BasicTests.scala index f0ee4f8..2412456 100644 --- a/scalatexApi/src/test/scala/scalatex/BasicTests.scala +++ b/scalatexApi/src/test/scala/scalatex/BasicTests.scala @@ -298,24 +298,18 @@ object BasicTests extends TestSuite{ // // 'loops { // -// * - check( -// tw(""" -// @for(x <- 0 until 3) -// lol -// """), -// tw(""" -// @for(x <- 0 until 3){ -// lol -// } -// """), -// tw( -// """ -// @for(x <- 0 until 3) { -// lol -// } -// """), -// "lollollol" -// ) + * - check( + tw(""" + @for(x <- 0 until 3) + lol + """), + tw(""" + @for(x <- 0 until 3){ + lol + } + """), + "lollollol" + ) // // // * - check( diff --git a/scalatexApi/src/test/scala/scalatex/ParserTests.scala b/scalatexApi/src/test/scala/scalatex/ParserTests.scala index c012328..5cefa67 100644 --- a/scalatexApi/src/test/scala/scalatex/ParserTests.scala +++ b/scalatexApi/src/test/scala/scalatex/ParserTests.scala @@ -4,7 +4,7 @@ package scalatex import org.parboiled2._ import torimatomeru.ScalaSyntax -import scalatex.stages.{Parser, Ast} +import scalatex.stages.{Trim, Parser, Ast} import scalatex.stages.Ast.Block.{IfElse, For, Text} import Ast.Chain.Args @@ -149,57 +149,76 @@ object ParserTests extends utest.TestSuite{ ) } 'ControlFlow{ - 'for - check( - "@for(x <- 0 until 3){lol}", - _.ForLoop.run(), - For("for(x <- 0 until 3)", Block(Seq(Text("lol")))) - ) - 'forBlock - check( - """@for(x <- 0 until 3) - | lol""".stripMargin, - _.LoneForLoop.run(), - For("for(x <- 0 until 3)", Block(Seq(Text("\n "), Text("lol")))) - ) - 'if - check( - "@if(true){lol}", - _.IfElse.run(), - IfElse("if(true)", Block(Seq(Text("lol"))), None) - ) - 'ifElse - check( - "@if(true){lol}else{ omg }", - _.IfElse.run(), - IfElse("if(true)", Block(Seq(Text("lol"))), Some(Block(Seq(Text(" omg "))))) - ) - 'ifBlock- check( - """@if(true) - | omg""".stripMargin, - _.IfElse.run(), - IfElse("if(true)", Block(Seq(Text("\n "), Text("omg"))), None) - ) - 'ifBlockElseBlock - check( - """@if(true) - | omg - |@else - | wtf""".stripMargin, - _.IfElse.run(), - IfElse( - "if(true)", - Block(Seq(Text("\n "), Text("omg"))), - Some(Block(Seq(Text("\n "), Text("wtf")))) + 'for { + 'for - check( + "@for(x <- 0 until 3){lol}", + _.ForLoop.run(), + For("for(x <- 0 until 3)", Block(Seq(Text("lol")))) ) - ) - 'ifElseBlock - check( - """@if(true){ - | omg - |}else - | wtf""".stripMargin, - _.IfElse.run(), - IfElse( - "if(true)", - Block(Seq(Text("\n "), Text("omg"), Text("\n"))), - Some(Block(Seq(Text("\n "), Text("wtf")))) + 'forBlock - check( + """ + |@for(x <- 0 until 3) + | lol""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + For("for(x <- 0 until 3)", Block(Seq(Text("\n "), Text("lol")))) + )) ) - ) + 'forBlockBraces - check( + """ + |@for(x <- 0 until 3){ + | lol + |}""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + For("for(x <- 0 until 3)", Block(Seq(Text("\n "), Text("lol")))) + )) + ) + } + 'ifElse { + 'if - check( + "@if(true){lol}", + _.IfElse.run(), + IfElse("if(true)", Block(Seq(Text("lol"))), None) + ) + 'ifElse - check( + "@if(true){lol}else{ omg }", + _.IfElse.run(), + IfElse("if(true)", Block(Seq(Text("lol"))), Some(Block(Seq(Text(" omg "))))) + ) + 'ifBlock - check( + """@if(true) + | omg""".stripMargin, + _.IfElse.run(), + IfElse("if(true)", Block(Seq(Text("\n "), Text("omg"))), None) + ) + 'ifBlockElseBlock - check( + """@if(true) + | omg + |@else + | wtf""".stripMargin, + _.IfElse.run(), + IfElse( + "if(true)", + Block(Seq(Text("\n "), Text("omg"))), + Some(Block(Seq(Text("\n "), Text("wtf")))) + ) + ) + 'ifElseBlock - check( + """@if(true){ + | omg + |}else + | wtf""".stripMargin, + _.IfElse.run(), + IfElse( + "if(true)", + Block(Seq(Text("\n "), Text("omg"), Text("\n"))), + Some(Block(Seq(Text("\n "), Text("wtf")))) + ) + ) + } } 'Body{ 'indents - check( -- cgit v1.2.3