Advertisement
Guest User

Untitled

a guest
May 9th, 2015
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.23 KB | None | 0 0
  1. package ch.epfl.data.sc.pardis.utils
  2.  
  3. import Document._
  4.  
  5. /**
  6.  * Doc formatter using string interpolation.
  7.  * Markers " #{ ", " #} " (including the space character) are used to express nesting
  8.  * Marker " # " expresses document break, just like "\n".
  9.  *
  10.  * For example:
  11.  * {{{
  12.  *   doc"class A { #{  # $decl #}  # }"
  13.  * }}}
  14.  * instead of:
  15.  * {{{
  16.  *   "class A {" :: Document.nest(2, DocBreak :: decl) :/: "}"
  17.  * }}}
  18.  */
  19. class DocumentContext(ctx: StringContext) {
  20.   val NEST_COUNT = 2
  21.  
  22.   object doc {
  23.     def apply(docs: Document*): Document = {
  24.  
  25.       case object Nest extends Document
  26.       case object UnNest extends Document
  27.       case object Insert extends Document
  28.  
  29.       assert(ctx.parts.size == docs.size + 1 && ctx.parts.size > 0)
  30.  
  31.       def interleave(arr: Seq[Document], interleaved: Document) =
  32.         arr(0) +: arr.tail.map { List(interleaved, _) }.flatten
  33.  
  34.       def splitOn(mark: String, interleaved: Document) = (ds: Seq[Document]) => ds flatMap {
  35.         case DocText(str) => interleave(str.split(mark, -1) map DocText, interleaved)
  36.         case d            => Seq(d)
  37.       }
  38.  
  39.       // Makes a sequence of the parts separated with Nest, UnNest and Insert (for positions where docs are to be inserted)
  40.       val parts = (
  41.         splitOn(" #\\{ ", Nest) andThen
  42.         splitOn(" #\\} ", UnNest) andThen
  43.         splitOn(" # ", DocBreak) andThen
  44.         splitOn("\n", DocBreak)
  45.       )(interleave(ctx.parts map DocText, Insert))
  46.  
  47.       // println(parts)
  48.  
  49.       val diter = docs.iterator
  50.       val allDocs = parts map { case Insert => diter.next() case d => d }
  51.  
  52.       // Processes the sequence, replacing ..Nest..UnNest.. by a nest(..) operation
  53.       def proc(xs: Seq[Document]): Document = xs match {
  54.         case Seq(Nest)               => throw new IllegalArgumentException("Unmatched opening nesting marker")
  55.         case Seq(UnNest)             => throw new IllegalArgumentException("Closing nesting marker closes nothing")
  56.         case Nest +: rest :+ UnNest  => nest(NEST_COUNT, proc(rest))
  57.         case (n @ Nest +: rest) :+ d => proc(n) :: d
  58.         case d +: rest               => d :: proc(rest)
  59.         case Seq()                   => empty
  60.       }
  61.       proc(allDocs)
  62.  
  63.     }
  64.   }
  65.  
  66. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement