From 850863eeb7a44e3fa367d4088330fdcb556929bd Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Wed, 5 Nov 2014 21:26:02 -0800 Subject: Text nodes have positions, more error tests pass --- .../src/main/scala/scalatex/stages/Compiler.scala | 24 ++++---- .../src/main/scala/scalatex/stages/Parser.scala | 12 ++-- .../src/test/scala/scalatex/ErrorTests.scala | 14 ++--- .../src/test/scala/scalatex/ParserTests.scala | 68 +++++++++++----------- 4 files changed, 61 insertions(+), 57 deletions(-) diff --git a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala index 5021540..5a3f38b 100644 --- a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala @@ -44,10 +44,10 @@ object Compiler{ case (curr, Ast.Chain.TypeArgs(str, offset2)) => val TypeApply(fun, args) = c.parse(s"omg$str") incPos(TypeApply(curr, args.map(incPosRec(_, offset2 - 2))), offset2) - case (curr, Ast.Block(parts, offset)) => - q"$curr(${compileBlock(parts, offset)})" - case (curr, Ast.Header(header, block, offset)) => - q"$curr(${compileHeader(header, block, offset)})" + case (curr, Ast.Block(parts, offset1)) => + incPos(q"$curr(${compileBlock(parts, offset1)})", offset1) + case (curr, Ast.Header(header, block, offset1)) => + incPos(q"$curr(${compileHeader(header, block, offset1)})", offset1) } out.foreach(o => println(o.pos + "\t" + o)) @@ -55,19 +55,23 @@ object Compiler{ } def compileBlock(parts: Seq[Ast.Block.Sub], offset: Int): c.Tree = { val res = parts.map{ - 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 b @ Ast.Block.IfElse(condString, Ast.Block(parts2, offset2), elseBlock, offset) => - println("AST " + b) + case Ast.Block.Text(str, offset1) => + incPos(q"$str", offset1) + case Ast.Chain(code, parts, offset1) => + compileChain(code, parts, offset1) + case Ast.Header(header, block, offset1) => + compileHeader(header, block, offset1) + case Ast.Block.IfElse(condString, Ast.Block(parts2, offset2), elseBlock, offset1) => val If(cond, _, _) = c.parse(condString + "{}") val elseCompiled = elseBlock match{ case Some(Ast.Block(parts3, offset3)) => compileBlock(parts3, offset3) case None => EmptyTree } - val res = If(cond, compileBlock(parts2, offset2), elseCompiled) + val res = If(incPosRec(cond, offset1), compileBlock(parts2, offset2), elseCompiled) + println("Tree " + res) + incPos(res, offset1) res case Ast.Block.For(generators, Ast.Block(parts2, offset2), offset) => val fresh = c.fresh() diff --git a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala index 9f41dd8..8432f96 100644 --- a/scalatexApi/src/main/scala/scalatex/stages/Parser.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala @@ -33,8 +33,8 @@ class Parser(input: ParserInput, indent: Int = 0, offset: Int = 0) extends Scala } def TextNot(chars: String) = rule { - capture(oneOrMore(noneOf(chars + "\n") | "@@")) ~> { - x => Ast.Block.Text(x.replace("@@", "@")) + push(offsetCursor) ~ capture(oneOrMore(noneOf(chars + "\n") | "@@")) ~> { + (i, x) => Ast.Block.Text(x.replace("@@", "@"), i) } } def Text = TextNot("@") @@ -55,7 +55,7 @@ class Parser(input: ParserInput, indent: Int = 0, offset: Int = 0) extends Scala def IndentSpaces = rule{ indent.times(' ') ~ zeroOrMore(' ') } def Indent = rule{ '\n' ~ IndentSpaces } def LoneScalaChain: Rule2[Ast.Block.Text, Ast.Chain] = rule { - (capture(Indent) ~> (Ast.Block.Text(_))) ~ + (push(offsetCursor) ~ capture(Indent) ~> ((i, x) => Ast.Block.Text(x, i))) ~ ScalaChain ~ IndentBlock ~> { (chain: Ast.Chain, body: Ast.Block) => chain.copy(parts = chain.parts :+ body) @@ -85,7 +85,7 @@ class Parser(input: ParserInput, indent: Int = 0, offset: Int = 0) extends Scala BraceBlock ~> (Ast.Block.For(_, _)) } def LoneForLoop = rule{ - (capture(Indent) ~> (Ast.Block.Text(_))) ~ + (push(offsetCursor) ~ capture(Indent) ~> ((i, t) => Ast.Block.Text(t, i))) ~ ForHead ~ IndentBlock ~> (Ast.Block.For(_, _)) @@ -116,8 +116,8 @@ class Parser(input: ParserInput, indent: Int = 0, offset: Int = 0) extends Scala LoneScalaChain ~> (Seq(_, _)) | HeaderBlock ~> (Seq(_)) | TextNot("@}") ~> (Seq(_)) | - (capture(Indent) ~> (x => Seq(Ast.Block.Text(x)))) | - (capture(BlankLine) ~> (x => Seq(Ast.Block.Text(x)))) | + (push(offsetCursor) ~ capture(Indent) ~> ((i, x) => Seq(Ast.Block.Text(x, i)))) | + (push(offsetCursor) ~ capture(BlankLine) ~> ((i, x) => Seq(Ast.Block.Text(x, i)))) | ScalaChain ~> (Seq(_: Ast.Block.Sub)) } def Body = rule{ diff --git a/scalatexApi/src/test/scala/scalatex/ErrorTests.scala b/scalatexApi/src/test/scala/scalatex/ErrorTests.scala index 82976eb..0935337 100644 --- a/scalatexApi/src/test/scala/scalatex/ErrorTests.scala +++ b/scalatexApi/src/test/scala/scalatex/ErrorTests.scala @@ -161,7 +161,7 @@ object ErrorTests extends TestSuite{ """ ) } -// 'curlies{ + 'curlies{ * - check( twRuntimeErrors("@p{@Seq(1, 2, 3).foldLeft(0)}"), "missing arguments for method foldLeft", @@ -170,21 +170,21 @@ object ErrorTests extends TestSuite{ ^ """ ) -// + * - check( twRuntimeErrors("@Nil.foldLeft{XY}"), "missing arguments for method foldLeft", """ twRuntimeErrors("@Nil.foldLeft{XY}"), - ^ + ^ """ ) -// + // * - check( -// twRuntimeErrors("@Nil.map{(x: Int, y: String) => omg}"), +// twRuntimeErrors("@Seq(1).map{(y: String) => omg}"), // "type mismatch", // """ -// twRuntimeErrors("@Nil.map{(x: Int, y: String) => omg}"), +// twRuntimeErrors("@Seq(1).map{(y: String) => omg}"), // ^ // """ // ) @@ -368,6 +368,6 @@ object ErrorTests extends TestSuite{ // ^ // """ // ) -// } + } } } diff --git a/scalatexApi/src/test/scala/scalatex/ParserTests.scala b/scalatexApi/src/test/scala/scalatex/ParserTests.scala index 7cd5002..7de01ed 100644 --- a/scalatexApi/src/test/scala/scalatex/ParserTests.scala +++ b/scalatexApi/src/test/scala/scalatex/ParserTests.scala @@ -103,7 +103,7 @@ object ParserTests extends utest.TestSuite{ Ast.Header( "import math.abs\nimport math.sin", Ast.Block( - Seq(Text("\n"), Text("\n"), Text("hello world"), Text("\n")), + Seq(Text("\n", 33), Text("\n", 34), Text("hello world", 35), Text("\n", 46)), 33 ) ) @@ -120,12 +120,12 @@ object ParserTests extends utest.TestSuite{ } 'Block{ - * - check("{i am a cow}", _.BraceBlock.run(), Block(Seq(Block.Text("i am a cow")), 1)) + * - check("{i am a cow}", _.BraceBlock.run(), Block(Seq(Block.Text("i am a cow", 1)), 1)) * - check("{i @am a @cow}", _.BraceBlock.run(), Block(Seq( - Block.Text("i "), + Block.Text("i ", 1), Chain("am",Seq(), 3), - Block.Text(" a "), + Block.Text(" a ", 6), Chain("cow",Seq(), 9) ), 1) ) @@ -142,10 +142,10 @@ object ParserTests extends utest.TestSuite{ ) * - check("@omg{bbq}.cow(moo){a @b}\n", _.ScalaChain.run(), Chain("omg",Seq( - Block(Seq(Block.Text("bbq")), 5), + Block(Seq(Text("bbq", 5)), 5), Chain.Prop("cow", 9), Chain.Args("(moo)", 13), - Block(Seq(Block.Text("a "), Chain("b", Nil, 21)), 19) + Block(Seq(Text("a ", 19), Chain("b", Nil, 21)), 19) )) ) } @@ -154,7 +154,7 @@ object ParserTests extends utest.TestSuite{ 'for - check( "@for(x <- 0 until 3){lol}", _.ForLoop.run(), - For("for(x <- 0 until 3)", Block(Seq(Text("lol")), 21)) + For("for(x <- 0 until 3)", Block(Seq(Text("lol", 21)), 21)) ) 'forBlock - check( """ @@ -163,7 +163,7 @@ object ParserTests extends utest.TestSuite{ _.Body.run(), Block(Seq( Text("\n"), - For("for(x <- 0 until 3)", Block(Seq(Text("\n "), Text("lol")), 21)) + For("for(x <- 0 until 3)", Block(Seq(Text("\n ", 21), Text("lol", 24)), 21)) )) ) 'forBlockBraces - check( @@ -174,7 +174,7 @@ object ParserTests extends utest.TestSuite{ _.Body.run(), Block(Seq( Text("\n"), - For("for(x <- 0 until 3)", Block(Seq(Text("\n "), Text("lol"), Text("\n")), 22)) + For("for(x <- 0 until 3)", Block(Seq(Text("\n ", 22), Text("lol", 25), Text("\n", 28)), 22)) )) ) } @@ -182,19 +182,19 @@ object ParserTests extends utest.TestSuite{ 'if - check( "@if(true){lol}", _.IfElse.run(), - IfElse("if(true)", Block(Seq(Text("lol")), 10), None) + IfElse("if(true)", Block(Seq(Text("lol", 10)), 10), None) ) 'ifElse - check( "@if(true){lol}else{ omg }", _.IfElse.run(), - IfElse("if(true)", Block(Seq(Text("lol")), 10), Some(Block(Seq(Text(" omg ")), 19))) + IfElse("if(true)", Block(Seq(Text("lol", 10)), 10), Some(Block(Seq(Text(" omg ", 19)), 19))) ) 'ifBlock - check( """ |@if(true) | omg""".stripMargin, _.IfElse.run(), - IfElse("if(true)", Block(Seq(Text("\n "), Text("omg")), 10), None) + IfElse("if(true)", Block(Seq(Text("\n ", 10), Text("omg", 13)), 10), None) ) 'ifBlockElseBlock - check( """ @@ -205,8 +205,8 @@ object ParserTests extends utest.TestSuite{ _.IfElse.run(), IfElse( "if(true)", - Block(Seq(Text("\n "), Text("omg")), 10), - Some(Block(Seq(Text("\n "), Text("wtf")), 22)) + Block(Seq(Text("\n ", 10), Text("omg", 13)), 10), + Some(Block(Seq(Text("\n ", 22), Text("wtf", 25)), 22)) ) ) 'ifBlockElseBraceBlock - check( @@ -218,8 +218,8 @@ object ParserTests extends utest.TestSuite{ _.IfElse.run(), IfElse( "if(true)", - Block(Seq(Text("\n "), Text("omg"), Text("\n")), 10), - Some(Block(Seq(Text("\n "), Text("wtf"), Text("\n")), 23)) + Block(Seq(Text("\n ", 10), Text("omg", 13), Text("\n", 16)), 10), + Some(Block(Seq(Text("\n ", 23), Text("wtf", 26), Text("\n", 29)), 23)) ) ) 'ifBlockElseBraceBlockNested - { @@ -236,16 +236,16 @@ object ParserTests extends utest.TestSuite{ Block(Vector( Text("\n"), Chain("p",Vector(Block(Vector( - Text("\n "), + Text("\n ", 3), IfElse("if(true)", Block(Vector( - Text("\n "), Text("Hello"), Text("\n ") + Text("\n ", 16), Text("Hello", 21), Text("\n ", 26) ), 16), Some(Block(Vector( - Text("\n "), Text("lols"), Text("\n ") + Text("\n ", 35), Text("lols", 40), Text("\n ", 44) ), 35)) )), 3)), 1), - Text("\n") + Text("\n", 48) )) assert(res == expected) } @@ -257,8 +257,8 @@ object ParserTests extends utest.TestSuite{ _.IfElse.run(), IfElse( "if(true)", - Block(Seq(Text("\n "), Text("omg"), Text("\n")), 10), - Some(Block(Seq(Text("\n "), Text("wtf")), 22)) + Block(Seq(Text("\n ", 10), Text("omg", 13), Text("\n", 16)), 10), + Some(Block(Seq(Text("\n ", 22), Text("wtf", 25)), 22)) ) ) } @@ -275,11 +275,11 @@ object ParserTests extends utest.TestSuite{ Block(Seq( Text("\n"), Chain("omg",Seq(Block(Seq( - Text("\n "), + Text("\n ", 5), Chain("wtf",Seq(Block(Seq( - Text("\n "), + Text("\n ", 7), Chain("bbq",Seq(Block(Seq( - Text("\n "), + Text("\n ", 9), Chain("lol",Seq(), 16) ), 9)), 12) ), 7)), 8) @@ -296,12 +296,12 @@ object ParserTests extends utest.TestSuite{ Text("\n"), Chain("omg",Seq(Block( Seq( - Text("\n "), + Text("\n ", 5), Chain("wtf",Seq(), 8) ), 5 )), 1), - Text("\n"), + Text("\n", 12), Chain("bbq", Seq(), 13) )) ) @@ -316,13 +316,13 @@ object ParserTests extends utest.TestSuite{ Text("\n"), Chain("omg",Seq(Block( Seq( - Text("\n "), + Text("\n ", 6), Chain("wtf",Seq(), 9), - Text("\n") + Text("\n", 13) ), 6 )), 1), - Text("\n"), + Text("\n", 15), Chain("bbq", Seq(), 16) )) ) @@ -337,12 +337,12 @@ object ParserTests extends utest.TestSuite{ Chain("omg",Seq( Args("""("lol", 1, 2)""", 5), Block(Seq( - Text("\n "), + Text("\n ", 18), Chain("wtf",Seq(), 21) ), 18) ), 1), - Text("\n"), - Text("bbq") + Text("\n", 25), + Text("bbq", 26) )) ) // * - check( @@ -376,7 +376,7 @@ object ParserTests extends utest.TestSuite{ Block(Seq( Text("\n"), Chain("{\"lol\" * 3}", Seq(), 1), - Text("\n"), + Text("\n", 13), Chain("""{ | val omg = "omg" | omg * 2 -- cgit v1.2.3