summaryrefslogblamecommitdiff
path: root/scalatexApi/src/main/scala/scalatex/ScalatexParser.scala
blob: 406f4cd599c3b95b69e880ec4478f89fc5417303 (plain) (tree)




































                                                                                                                               
package scalatex

import org.parboiled2._
import torimatomeru.ScalaSyntax

trait Ast{
  def offset: Int
}
object Ast{
  case class Block(parts: Seq[Block.Sub], offset: Int = 0) extends Chain.Sub
  object Block{
    trait Sub
    case class Text(txt: String, offset: Int = 0) extends Block.Sub
  }
  case class Code(code: String, offset: Int = 0)
  case class Chain(lhs: Code, parts: Seq[Chain.Sub], offset: Int = 0) extends Block.Sub
  object Chain{
    trait Sub
    case class Prop(str: String, offset: Int = 0) extends Sub
    case class Args(str: String, offset: Int = 0) extends Sub
  }
}
class ScalatexParser(input: ParserInput) extends ScalaSyntax(input) {
  def TextNot(chars: String) = rule { capture(oneOrMore(noneOf(chars) | "@@")) ~> (x => Ast.Block.Text(x.replace("@@", "@"))) }
  def Text = TextNot("@")
  def Code = rule {
    "@" ~ capture(Id | BlockExpr | ('(' ~ optional(Exprs) ~ ')')) ~> (Ast.Code(_))
  }
  def ScalaChain = rule { Code ~ zeroOrMore(Extension) ~> (Ast.Chain(_, _)) }
  def Extension: Rule1[Ast.Chain.Sub] = rule {
    (capture(('.' ~ Id) ~ optional(TypeArgs)) ~> (Ast.Chain.Prop(_))) |
      (capture(!BlockExpr ~ ArgumentExprs) ~> (Ast.Chain.Args(_))) |
      TBlock
  }
  def TBlock = rule{ '{' ~ Body ~ '}' }
  def Body = rule{ zeroOrMore(TextNot("@}") | ScalaChain) ~> (x => Ast.Block(x)) }
}