progs/pprint/tree.sc
changeset 742 b5b5583a3a08
child 873 a25da86f7c8c
equal deleted inserted replaced
741:e66bd5c563eb 742:b5b5583a3a08
       
     1 // scalatags 
       
     2 import ammonite.ops._
       
     3 
       
     4 import $ivy.`com.lihaoyi::scalatags:0.8.2` 
       
     5 import scalatags.Text.all._
       
     6 import scalatags.Text._
       
     7 
       
     8 // regular expressions including records
       
     9 abstract class Rexp 
       
    10 case object ZERO extends Rexp
       
    11 case object ONE extends Rexp
       
    12 case class CHAR(c: Char) extends Rexp
       
    13 case class ALT(r1: Rexp, r2: Rexp) extends Rexp 
       
    14 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp 
       
    15 case class STAR(r: Rexp) extends Rexp 
       
    16 case class SPECIAL(s: String) extends Rexp
       
    17 
       
    18 def nullable (r: Rexp) : Boolean = r match {
       
    19   case ZERO => false
       
    20   case ONE => true
       
    21   case CHAR(_) => false
       
    22   case ALT(r1, r2) => nullable(r1) || nullable(r2)
       
    23   case SEQ(r1, r2) => nullable(r1) && nullable(r2)
       
    24   case STAR(_) => true
       
    25 }
       
    26 
       
    27 def der(c: Char, r: Rexp) : Rexp = r match {
       
    28   case ZERO => ZERO
       
    29   case ONE => ZERO
       
    30   case CHAR(d) => if (c == d) ONE else ZERO
       
    31   case ALT(r1, r2) => ALT(der(c, r1), der(c, r2))
       
    32   case SEQ(r1, r2) => 
       
    33     if (nullable(r1)) ALT(SEQ(der(c, r1), r2), der(c, r2))
       
    34     else SEQ(der(c, r1), r2)
       
    35   case STAR(r1) => SEQ(der(c, r1), STAR(r1))
       
    36 }
       
    37 
       
    38 def ders(s: List[Char], r: Rexp) : Rexp = s match {
       
    39   case Nil => r
       
    40   case c::s => ders(s, der(c, r))
       
    41 }
       
    42 
       
    43 def simp(r: Rexp) : Rexp = r match {
       
    44   case ALT(r1, r2) => (simp(r1), simp(r2)) match {
       
    45     case (ZERO, r2s) => r2s
       
    46     case (r1s, ZERO) => r1s
       
    47     case (r1s, r2s) => if (r1s == r2s) r1s else ALT (r1s, r2s)
       
    48   }
       
    49   case SEQ(r1, r2) =>  (simp(r1), simp(r2)) match {
       
    50     case (ZERO, _) => ZERO
       
    51     case (_, ZERO) => ZERO
       
    52     case (ONE, r2s) => r2s
       
    53     case (r1s, ONE) => r1s
       
    54     case (r1s, r2s) => SEQ(r1s, r2s)
       
    55   }
       
    56   case r => r
       
    57 }
       
    58 
       
    59 def ders_simp(s: List[Char], r: Rexp) : Rexp = s match {
       
    60   case Nil => r
       
    61   case c::s => ders_simp(s, simp(der(c, r)))
       
    62 }
       
    63 
       
    64 
       
    65 def pp(r: Rexp) : TypedTag[String] = r match {
       
    66   case CHAR(c) => li(code(c.toString))
       
    67   case ALT(r1, r2) => li(code("+"), ul(pp(r1), pp(r2)))
       
    68   case SEQ(r1, r2) => li(code(raw("&middot")), ul(pp(r1), pp(r2)))
       
    69   case STAR(r1) => li(code("*"), ul(pp(r1)))
       
    70   case ZERO => li(code("0"))
       
    71   case ONE => li(code("1"))
       
    72   case SPECIAL(s) => li(code(raw(s)))
       
    73 } 
       
    74 
       
    75 def mktree(r: Rexp) = 
       
    76    ul(cls := "tree")(pp(r))
       
    77 
       
    78 
       
    79 def index(rs: List[Rexp]) = 
       
    80   html(
       
    81     head(link(rel := "stylesheet", href := "./style.css")),
       
    82     body(rs.map(mktree))
       
    83   )
       
    84 
       
    85 
       
    86 
       
    87 /*
       
    88 println(index(List(simple, test, evil2)))
       
    89 
       
    90 val simple = CHAR('a')
       
    91 val test = ALT(CHAR('a'), CHAR('b'))
       
    92 
       
    93 
       
    94 write.over(pwd/"t1.html", 
       
    95     index(List(evil2, 
       
    96                ders("a".toList, evil2),
       
    97                ders("aa".toList, evil2),
       
    98                ders("aaa".toList, evil2))))
       
    99 */
       
   100 
       
   101 val evil2 = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
       
   102 val r1 = STAR(ALT(SPECIAL("<i>r<sub>1</sub></i>"), SPECIAL("<i>r<sub>2</sub></i>")))
       
   103 val r2 = ALT(SPECIAL("<i>r<sub>1</sub></i>"), STAR(SPECIAL("<i>r<sub>2</sub></i>")))
       
   104 
       
   105 @main
       
   106 def main(fname: String) = {
       
   107   val content = index(List(r1))
       
   108   write.over(pwd / fname, content)
       
   109 }