diff options
Diffstat (limited to 'scalatexApi/src')
-rw-r--r-- | scalatexApi/src/main/scala/scalatex/stages/Parser.scala | 45 | ||||
-rw-r--r-- | scalatexApi/src/test/scala/scalatex/BasicTests.scala | 51 | ||||
-rw-r--r-- | scalatexApi/src/test/scala/scalatex/ParserTests.scala | 48 |
3 files changed, 105 insertions, 39 deletions
diff --git a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala index e54cb6b..3a5fb97 100644 --- a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala @@ -55,15 +55,30 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) { def LoneScalaChain: Rule2[Ast.Block.Text, Ast.Chain] = rule { (capture(Indent) ~> (Ast.Block.Text(_))) ~ ScalaChain ~ - zeroOrMore(BlankLine) ~ test(cursorNextIndent() > indent) ~ - runSubParser { - new Parser(_, cursorNextIndent()).Body - } ~> { (chain: Ast.Chain, body: Ast.Block) => - chain.copy(parts = chain.parts :+ body) + runSubParser(new Parser(_, cursorNextIndent()).Body) ~> { + (chain: Ast.Chain, body: Ast.Block) => chain.copy(parts = chain.parts :+ body) } } + def IfElse = rule{ + "@" ~ capture("if" ~ "(" ~ Expr ~ ")") ~ TBlock ~ optional("else" ~ TBlock) ~>{ + Ast.Block.IfElse(_, _, _) + } + } + def ForLoop = rule{ + "@" ~ + capture("for" ~ ('(' ~ Enumerators ~ ')' | '{' ~ Enumerators ~ '}')) ~ + TBlock ~> (Ast.Block.For(_, _)) + } + def LoneForLoop = rule{ + "@" ~ + capture("for" ~ ('(' ~ Enumerators ~ ')' | '{' ~ Enumerators ~ '}')) ~ + test(cursorNextIndent() > indent) ~ + runSubParser(new Parser(_, cursorNextIndent()).Body) ~> + (Ast.Block.For(_, _)) + } + def ScalaChain = rule { Code ~ zeroOrMore(Extension) ~> {Ast.Chain(_, _)} } @@ -80,15 +95,17 @@ class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) { '(' ~ Ws ~ (optional(Exprs ~ ',' ~ Ws) ~ PostfixExpr ~ ':' ~ Ws ~ '_' ~ Ws ~ '*' ~ Ws | optional(Exprs)) ~ ')' } def BlockExpr2: Rule0 = rule { '{' ~ Ws ~ (CaseClauses | Block) ~ '}' } - def TBlock = rule{ '{' ~ Body ~ '}' } + def TBlock: Rule1[Ast.Block] = rule{ '{' ~ Body ~ '}' } - def BodyItem = rule{ + def BodyItem: Rule1[Seq[Ast.Block.Sub]] = rule{ LoneScalaChain ~> (Seq(_, _)) | - HeaderBlock ~> (Seq(_)) | - TextNot("@}") ~> (Seq(_)) | - (capture(Indent) ~> (x => Seq(Ast.Block.Text(x)))) | - (capture(BlankLine) ~> (x => Seq(Ast.Block.Text(x)))) | - ScalaChain ~> (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)))) | + ScalaChain ~> (Seq(_: Ast.Block.Sub)) } def Body = rule{ oneOrMore(BodyItem) ~> {x => @@ -117,9 +134,11 @@ object Ast{ object Block{ trait Sub extends Ast case class Text(txt: String, offset: Int = 0) extends Block.Sub - + case class For(generators: String, block: Block, offset: Int = 0) extends Block.Sub + case class IfElse(condition: String, block: Block, elseBlock: Option[Block], offset: Int = 0) extends Block.Sub } case class Header(front: String, block: Block, offset: Int = 0) extends Block.Sub with Chain.Sub + /** * @param lhs The first expression in this method-chain * @param parts A list of follow-on items chained to the first diff --git a/scalatexApi/src/test/scala/scalatex/BasicTests.scala b/scalatexApi/src/test/scala/scalatex/BasicTests.scala index 8acb9b7..f0ee4f8 100644 --- a/scalatexApi/src/test/scala/scalatex/BasicTests.scala +++ b/scalatexApi/src/test/scala/scalatex/BasicTests.scala @@ -1,5 +1,6 @@ package scalatex import utest._ +import scala.collection.mutable.ArrayBuffer import scalatex.stages._ import scalatags.Text.all._ @@ -241,30 +242,31 @@ object BasicTests extends TestSuite{ ) } } -// 'mixed{ -// check( -// tw(""" -// @div{ -// Hello -// @div -// @h1 WORLD @b{!!!} -// lol -// @p{ -// @h2{Header 2} -// } -// } -// """), -// """ -// <div> -// Hello -// <div> -// <h1></h1>WORLD<b>!!!</b>lol -// <p><h2>Header2</h2></p> -// </div> -// </div> -// """ -// ) -// } + 'mixed{ + check( + tw(""" + @div{ + Hello + @div + @h1 + WORLD @b{!!!} + lol + @p{ + @h2{Header 2} + } + } + """), + """ + <div> + Hello + <div> + <h1>WORLD<b>!!!</b>lol</h1> + <p><h2>Header2</h2></p> + </div> + </div> + """ + ) + } // // 'args{ // val things = Seq(1, 2, 3) @@ -468,4 +470,5 @@ object BasicTests extends TestSuite{ // } } } + } diff --git a/scalatexApi/src/test/scala/scalatex/ParserTests.scala b/scalatexApi/src/test/scala/scalatex/ParserTests.scala index 9301755..c2f35cc 100644 --- a/scalatexApi/src/test/scala/scalatex/ParserTests.scala +++ b/scalatexApi/src/test/scala/scalatex/ParserTests.scala @@ -5,7 +5,7 @@ import org.parboiled2._ import torimatomeru.ScalaSyntax import scalatex.stages.{Parser, Ast} -import Ast.Block.Text +import scalatex.stages.Ast.Block.{IfElse, For, Text} import Ast.Chain.Args object ParserTests extends utest.TestSuite{ @@ -148,6 +148,29 @@ 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 "))))) + ) + } 'Body{ 'indents - check( """ @@ -181,7 +204,28 @@ object ParserTests extends utest.TestSuite{ Chain("omg",Seq(Block( Seq( Text("\n "), - Chain("wtf",Seq())) + Chain("wtf",Seq()) + ) + ))), + Text("\n"), + Chain("bbq", Seq()) + )) + ) + 'braces - check( + """ + |@omg{ + | @wtf + |} + |@bbq""".stripMargin, + _.Body.run(), + Block(Seq( + Text("\n"), + Chain("omg",Seq(Block( + Seq( + Text("\n "), + Chain("wtf",Seq()), + Text("\n") + ) ))), Text("\n"), Chain("bbq", Seq()) |