progs/re-sulzmann-partial.scala
changeset 95 dbe49327b6c5
parent 94 9ea667baf097
equal deleted inserted replaced
94:9ea667baf097 95:dbe49327b6c5
       
     1 import scala.language.implicitConversions
       
     2 import scala.language.reflectiveCalls
       
     3 
       
     4 abstract class Rexp
       
     5 
       
     6 case object NULL extends Rexp
       
     7 case object EMPTY extends Rexp
       
     8 case class CHAR(c: Char) extends Rexp
       
     9 case class ALT(r1: Rexp, r2: Rexp) extends Rexp 
       
    10 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp 
       
    11 case class STAR(r: Rexp) extends Rexp 
       
    12 
       
    13 abstract class Pat
       
    14 
       
    15 case class VAR(x: String, r: Rexp) extends Pat
       
    16 case class GRP(x: String, p: Pat) extends Pat
       
    17 case class PSEQ(p1: Pat, p2: Pat) extends Pat
       
    18 case class PALT(p1: Pat, p2: Pat) extends Pat
       
    19 case class PSTAR(p: Pat) extends Pat
       
    20 
       
    21 
       
    22 def nullable (r: Rexp) : Boolean = r match {
       
    23   case NULL => false
       
    24   case EMPTY => true
       
    25   case CHAR(_) => false
       
    26   case ALT(r1, r2) => nullable(r1) || nullable(r2)
       
    27   case SEQ(r1, r2) => nullable(r1) && nullable(r2)
       
    28   case STAR(_) => true
       
    29 }
       
    30 
       
    31 def down (p: Pat) : Rexp = p match {
       
    32   case VAR(x: String, w: String, r: Rexp) => r
       
    33   case GRP(x: String, w: String, p: Pat) => down(p)
       
    34   case PSEQ(p1: Pat, p2: Pat) => SEQ(down(p1), down(p2))
       
    35   case PALT(p1: Pat, p2: Pat) => ALT(down(p1), down(p2))
       
    36   case PSTAR(p: Pat) => STAR(down(p))
       
    37 }
       
    38 
       
    39 def patnullable (p: Pat) : Boolean = p match {
       
    40   case PVar(_, r) => nullable(r)
       
    41   case PSEQ(p1, p2) => patnullable(p1) && patnullable(p2)
       
    42   case PCHOICE(p1, p2) => patnullable(p1) || patnullable(p2)
       
    43   case PSTAR(p) => true
       
    44   case PatVar(_, p) => patnullable(p)
       
    45 }
       
    46 
       
    47 //type Env = Set[List[(String, String)]]
       
    48 type Env = Map[Int, String]
       
    49 
       
    50 def update(n: Int, c: Char) (env: Env) = 
       
    51   env + (n -> (env.getOrElse(n, "") + c.toString))
       
    52 
       
    53 def pderivPat (p: Pat, c: Char) : Set[(Pat, Env => Env)] = p match {
       
    54   case PVar(n: Int, r: Rexp) => {
       
    55     val pds = pderiv(r, c)
       
    56     if (pds.isEmpty) Set()
       
    57     else Set((PVar(n, toRexp(pds.toList)), update(n, c)))
       
    58   }
       
    59   case PSEQ(p1: Pat, p2: Pat) => {
       
    60     val pats : Set[(Pat, Env => Env)] = 
       
    61       for ((p, f) <- pderivPat(p1, c)) yield (PSEQ(p, p2), f)
       
    62     if (nullable(strip(p1))) pats ++ pderivPat(p2, c)  
       
    63     else pats
       
    64   }
       
    65   case PCHOICE(p1: Pat, p2: Pat) => pderivPat(p1, c) ++ pderivPat(p2, c)
       
    66   case PSTAR(p1: Pat) => 
       
    67     for ((p, f) <- pderivPat(p1, c)) yield (PSEQ(p, PSTAR(p1)), f)
       
    68   case PatVar(n: Int, p1: Pat) => 
       
    69     for ((p, f) <- pderivPat(p1, c)) yield (PatVar(n, p), f compose (update (n, c)))
       
    70 }
       
    71 
       
    72 
       
    73 val p2 = PSEQ(PVar(1, STAR("A")), PVar(2, STAR("A")))
       
    74 pderivPat(p2, 'A').mkString("\n")
       
    75 
       
    76 
       
    77 def greedy_aux(env: Set[(Pat, Env)], w: List[Char]) : Set[Env] = w match {
       
    78   case Nil => 
       
    79     for ((p, e) <- env if patnullable(p)) yield e
       
    80   case c::cs => {
       
    81     val env2 = for ((p, e) <- env; (p1, f) <- pderivPat(p, c)) yield (p1, f(e))
       
    82     greedy_aux(env2, cs)
       
    83   }
       
    84 }
       
    85 
       
    86 def greedy(p: Pat, w: String) = {
       
    87   val res = greedy_aux(Set((p, Map())), w.toList)
       
    88   if (res.isEmpty) None else Some(res)
       
    89 }
       
    90 
       
    91 // some convenience for typing in regular expressions
       
    92 def charlist2rexp (s : List[Char]) : Rexp = s match {
       
    93   case Nil => EMPTY
       
    94   case c::Nil => CHAR(c)
       
    95   case c::s => SEQ(CHAR(c), charlist2rexp(s))
       
    96 }
       
    97 implicit def string2rexp (s : String) : Rexp = charlist2rexp(s.toList)
       
    98 
       
    99 implicit def RexpOps (r: Rexp) = new {
       
   100   def | (s: Rexp) = ALT(r, s)
       
   101   def % = STAR(r)
       
   102   def ~ (s: Rexp) = SEQ(r, s)
       
   103 }
       
   104 
       
   105 implicit def stringOps (s: String) = new {
       
   106   def | (r: Rexp) = ALT(s, r)
       
   107   def | (r: String) = ALT(s, r)
       
   108   def % = STAR(s)
       
   109   def ~ (r: Rexp) = SEQ(s, r)
       
   110   def ~ (r: String) = SEQ(s, r)
       
   111 }
       
   112 
       
   113 implicit def PatOps (p: Pat) = new {
       
   114   def | (q: Pat) = PALT(p, q)
       
   115   def % = PSTAR(p)
       
   116   def ~ (q: Pat) = PSEQ(p, q)
       
   117 }
       
   118 
       
   119 val p3 = PSTAR(PSEQ(PVar(1, "A"), PVar(2, "B")))
       
   120 
       
   121 greedy2(Set((p3, Map())), "ABAB".toList)
       
   122 
       
   123 
       
   124 val p4 = PVar(1, "A")
       
   125 greedy2(Set((p4, Map())), "A".toList)
       
   126 
       
   127 val p5 = PSEQ(PVar(1, "A"), PVar(1, "B"))
       
   128 greedy2(Set((p5, Map())), "AB".toList)
       
   129 
       
   130 val res = pderivPat(p5, 'A')
       
   131 for ((_, f) <- res) yield f(Map())
       
   132 
       
   133 
       
   134 val p6 = PatVar(4,PSTAR(PCHOICE(PCHOICE(PVar(1, "A"), PVar(2, "AB")), PVar(3, "B"))))
       
   135 
       
   136 greedy(p6, "ABA")