diff options
Diffstat (limited to 'scalatexApi/src/main')
-rw-r--r-- | scalatexApi/src/main/scala/scalatex/package.scala | 15 | ||||
-rw-r--r-- | scalatexApi/src/main/scala/scalatex/stages/Compiler.scala | 150 | ||||
-rw-r--r-- | scalatexApi/src/main/scala/scalatex/stages/Parser.scala (renamed from scalatexApi/src/main/scala/scalatex/ScalatexParser.scala) | 34 | ||||
-rw-r--r-- | scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala | 2 |
4 files changed, 41 insertions, 160 deletions
diff --git a/scalatexApi/src/main/scala/scalatex/package.scala b/scalatexApi/src/main/scala/scalatex/package.scala index a55f3e3..eb3ba6e 100644 --- a/scalatexApi/src/main/scala/scalatex/package.scala +++ b/scalatexApi/src/main/scala/scalatex/package.scala @@ -2,7 +2,7 @@ import scala.reflect.internal.util.{BatchSourceFile, SourceFile, OffsetPosition} import scala.reflect.io.{PlainFile, AbstractFile} import scala.reflect.macros.{TypecheckException, Context} import scalatags.Text.all._ -import scalatex.stages.Compiler +import scalatex.stages.{Parser, Compiler} import scala.language.experimental.macros import acyclic.file @@ -69,7 +69,7 @@ package object scalatex { } def compileThing(c: Context) - (s: String, + (scalatexSource: String, source: SourceFile, point: Int, runtimeErrors: Boolean, @@ -78,12 +78,17 @@ package object scalatex { def compile(s: String): c.Tree = { val realPos = new OffsetPosition(source, point).asInstanceOf[c.universe.Position] - Compiler(c)(realPos, new ScalatexParser(s).Body.run().get) + Compiler(c)(realPos, new Parser(s).Body.run().get) } - + def normalize(str: String) = { + val lines = str.split("\n") + val offset = lines.iterator.map(_.takeWhile(_ == ' ').length).min + lines.iterator.map(_.drop(offset)).mkString("\n") + } + import c.Position try { - val compiled = compile(s) + val compiled = compile(scalatexSource) if (debug) println(compiled) c.Expr[Frag](c.typeCheck(compiled)) } catch { diff --git a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala index 5127945..a305199 100644 --- a/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/Compiler.scala @@ -2,7 +2,7 @@ package scalatex package stages import acyclic.file -import scala.reflect.macros.Context +import scala.reflect.macros.whitebox.Context import scala.reflect.internal.util.{Position, OffsetPosition} /** @@ -27,150 +27,20 @@ object Compiler{ case (curr, Ast.Chain.TypeArgs(str, offset2)) => val TypeApply(fun, args) = c.parse(s"omg$str") TypeApply(curr, args) + case (curr, Ast.Block(parts, offset)) => + q"$curr(..${compileBlock(parts, offset)})" } - } - def compileBlock(parts: Seq[Ast.Block.Sub], offset: Int): c.Tree = { - val compiledParts = parts.map{ + def compileBlock(parts: Seq[Ast.Block.Sub], offset: Int): Seq[c.Tree] = { + parts.map{ case Ast.Block.Text(str, offset2) => q"$str" case Ast.Chain(code, parts, offset) => compileChain(code, parts, offset) } - q"Seq[$fragType](..$compiledParts)" } - ??? -// def compileTree(frag: Ast): Tree = frag match{ -// case Ast.Block(parts, offset) -// -//// println(s"${frag.offset}\n${literalPos.point}\n${pos.point}\n$frag\n") -// -// val f: Tree = frag match { -// case Ast.Block.Text(text, offset) => fragPos.at(q"$text", 0) -// case WN.Display(exp, offset) => compileTree(exp) -// case WN.Comment(msg, offset) => q"" -// case WN.ScalaExp(Seq(WN.Simple(first, _), WN.Block(ws, args, content, _)), offset) -// if first.startsWith("for(") => -// val fresh = c.fresh() -// val skeleton: Tree = c.parse(first + s"{$fresh}").asInstanceOf[Apply] -//// println("FIRST " + first) -// skeleton.foreach{x => -// x -// if (x.pos != NoPosition) fragPos.set(x, x.pos.point + 1) -// } -// val b = content.map(compileTree(_)) -// 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)) -// atPos(a.pos)(a2) -// atPos(f.pos)(f2) -// a2 -// case Ident(x: TermName) if x.decoded == fresh => -// q"Seq[$fragType](..$b)" -// } -// rec(skeleton) -// -// case WN.ScalaExp(WN.Simple(first, _) +: WN.Block(_, None, content1, _) +: rest, offset) -// if first.startsWith("if(") => -// -// val b1 = content1.map(compileTree(_)) -// val tree = c.parse(first + "{}").asInstanceOf[If] -// tree.foreach{x => -// fragPos.set(x, x.pos.point + 1) -// } -// val If(cond, _, _) = tree -// val b2 = rest match{ -// case Seq(WN.Simple(next, _), WN.Block(_, None, content2, _)) => -// content2.map(compileTree(_)) -// case Seq() => Nil -// } -// q"if($cond){ Seq[$fragType](..$b1): $fragType } else { Seq[$fragType](..$b2): $fragType }" -// -// case xx @ WN.ScalaExp(WN.Simple(first, _) +: rest, offset) => -// -// val firstTree = c.parse(first) -// -// firstTree.foreach{x => -// fragPos.set(x, x.pos.point) -// } -// -// val s = rest.foldLeft[Tree](firstTree) { -// case (l, WN.Simple(code, _)) => -// -// val fresh = c.fresh() -// -// val snippet = s"$fresh$code" -// val skeleton = c.parse(snippet) -// -// def rec(t: Tree): Tree = { -// -// val res = t match { -// case Apply(fun, args) => -// for(arg <- args; tree <- arg if tree.pos != NoPosition){ -// fragPos.set(tree, tree.pos.point + first.length - fresh.length) -// } -// -// Apply(rec(fun), args) -// case Select(qualifier, name) => Select(rec(qualifier), name) -// case Ident(x: TermName) if x.decoded == fresh => l -// } -// fragPos.at(res, t.pos.point + first.length - fresh.length) -//// println(Position.formatMessage(newPos.asInstanceOf[scala.reflect.internal.util.Position], "", true)) -// res -// } -// rec(skeleton) -// -// case (l, WN.Block(ws, None, content, offset)) => -// val contentTrees = content.map(compileTree(_)) -// fragPos.at(q"$l(..$contentTrees)", offset) -// -// case (l, WN.Block(ws, Some(args), content, offset)) => -// -// val snippet = s"{$args ()}" -// val skeleton = c.parse(snippet) -// -// val Function(vparams, body) = skeleton -// -// vparams.map(_.foreach { t => -// if (t.pos != NoPosition) -// fragPos.set(t, t.pos.point) -// }) -// val contentTrees = content.map{compileTree(_)} -// -// val func = Function(vparams, q"Seq[$fragType](..$contentTrees)") -// fragPos.at(func, skeleton.pos.point) -// val res = q"$l($func)" -// fragPos.at(res, offset) -// res -// } -// -// s -// } -// f -// } -// -// def compileTemplate(tmpl: WN.Template): Tree = { -// val WN.Template(name, comment, params, topImports, imports, subs, content, offset) = tmpl -// val fullName = if (name.toString == "") c.fresh("outer") else name -// -// val DefDef(mods, realName, tparams, vparamss, tpt, rhs) = { -// val snippet = s"def $fullName$params = {}" -// val z = c.parse(snippet).asInstanceOf[DefDef] -// z -// } -// -// val innerDefs = subs.map(compileTemplate(_)) -// -// val body = atPos(literalPos)(q"""{ -// ..${topImports.map(i => c.parse(i.code))} -// ..$innerDefs -// -// Seq[scalatags.Text.all.Frag](..${content.map(compileTree(_))}) -// }""") -// -// if (name.toString == "") body -// else DefDef(mods, realName, tparams, vparamss, tpt, body) -// } -// -// atPos(literalPos)(q"${compileTemplate(template)}") + val res = q"Seq[$fragType](..${compileBlock(template.parts, template.offset)})" + println("::::::::::::::::::::::::::::::::::::::::::::::::") + println(res) + println("::::::::::::::::::::::::::::::::::::::::::::::::") + res } }
\ No newline at end of file diff --git a/scalatexApi/src/main/scala/scalatex/ScalatexParser.scala b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala index a36d2d8..d8878de 100644 --- a/scalatexApi/src/main/scala/scalatex/ScalatexParser.scala +++ b/scalatexApi/src/main/scala/scalatex/stages/Parser.scala @@ -1,8 +1,9 @@ package scalatex +package stages import org.parboiled2._ import torimatomeru.ScalaSyntax - +import Util._ trait Ast{ def offset: Int } @@ -21,7 +22,12 @@ object Ast{ case class Args(str: String, offset: Int = 0) extends Sub } } -class ScalatexParser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) { +object Parser{ + def parse(input: String): Ast.Block = { + new Parser(input).Body.run().get + } +} +class Parser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(input) { val txt = input.sliceString(0, input.length) val indentTable = txt.split('\n').map{ s => if (s.trim == "") -1 @@ -35,7 +41,7 @@ class ScalatexParser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(in def cursorNextIndent() = { nextIndentTable(txt.take(cursor).count(_ == '\n')) } - println("INDENT " + indent) + def TextNot(chars: String) = rule { capture(oneOrMore(noneOf(chars + "\n") | "@@")) ~> { x => Ast.Block.Text(x.replace("@@", "@")) @@ -47,13 +53,13 @@ class ScalatexParser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(in } def BlankLine = rule{ '\n' ~ zeroOrMore(' ') ~ &('\n') } def Indent = rule{ '\n' ~ indent.times(' ') ~ zeroOrMore(' ') } - def LoneScalaChain: Rule1[Ast.Chain] = rule { - Indent ~ + def LoneScalaChain: Rule2[Ast.Block.Text, Ast.Chain] = rule { + (capture(Indent) ~> (Ast.Block.Text(_))) ~ ScalaChain ~ zeroOrMore(BlankLine) ~ test(cursorNextIndent() > indent) ~ runSubParser { - new ScalatexParser(_, cursorNextIndent()).Body + new Parser(_, cursorNextIndent()).Body } ~> { (chain: Ast.Chain, body: Ast.Block) => chain.copy(parts = chain.parts :+ body) } @@ -63,7 +69,7 @@ class ScalatexParser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(in Code ~ zeroOrMore(Extension) ~> {Ast.Chain(_, _)} } def Extension: Rule1[Ast.Chain.Sub] = rule { - (capture('.' ~ Id) ~> (Ast.Chain.Prop(_))) | + ('.' ~ capture(Id) ~> (Ast.Chain.Prop(_))) | (capture(TypeArgs2) ~> (Ast.Chain.TypeArgs(_))) | (capture(ArgumentExprs2) ~> (Ast.Chain.Args(_))) | TBlock @@ -78,14 +84,14 @@ class ScalatexParser(input: ParserInput, indent: Int = 0) extends ScalaSyntax(in def TBlock = rule{ '{' ~ Body ~ '}' } def Body = rule{ - zeroOrMore( - LoneScalaChain | - TextNot("@}") | - (capture(Indent) ~> (Ast.Block.Text(_))) | - (capture(BlankLine) ~> (Ast.Block.Text(_))) | - ScalaChain + oneOrMore( + LoneScalaChain ~> (Seq(_, _)) | + TextNot("@}") ~> (Seq(_)) | + (capture(Indent) ~> (x => Seq(Ast.Block.Text(x)))) | + (capture(BlankLine) ~> (x => Seq(Ast.Block.Text(x)))) | + ScalaChain ~> (Seq(_)) ) ~> {x => - Ast.Block(x) + Ast.Block(x.flatten) } } } diff --git a/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala b/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala index 4b94033..5bbd0af 100644 --- a/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala +++ b/scalatexApi/src/main/scala/torimatomeru/ScalaSyntax.scala @@ -6,7 +6,7 @@ import org.parboiled2._ class ScalaSyntax(val input: ParserInput) extends Parser with Basic with Identifiers with Literals { - def Whitespace = rule { zeroOrMore(WhitespaceChar | Comment | Newline) } + def Whitespace = rule { zeroOrMore(WhitespaceChar | Comment) } /** * Every token handles space at the end. |