| 966 |      1 | // A template of the simple matcher with simplification 
 | 
|  |      2 | // of derivatives to be used in CW1
 | 
| 725 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      3 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      4 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      5 | abstract class Rexp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      6 | case object ZERO extends Rexp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      7 | case object ONE extends Rexp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      8 | case class CHAR(c: Char) extends Rexp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      9 | case class ALT(r1: Rexp, r2: Rexp) extends Rexp 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     10 | case class SEQ(r1: Rexp, r2: Rexp) extends Rexp 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     11 | case class STAR(r: Rexp) extends Rexp 
 | 
| 966 |     12 | 
 | 
|  |     13 | case class RANGE(cs: Set[Char]) extends Rexp             // set of characters
 | 
|  |     14 | case class PLUS(r: Rexp) extends Rexp                    // plus
 | 
|  |     15 | case class OPTIONAL(r: Rexp) extends Rexp                // optional
 | 
|  |     16 | case class INTER(r1: Rexp, r2: Rexp) extends Rexp        // intersection
 | 
|  |     17 | case class NTIMES(r: Rexp, n: Int) extends Rexp          // n-times
 | 
|  |     18 | case class UPTO(r: Rexp, n: Int) extends Rexp            // up n-times
 | 
|  |     19 | case class FROM(r: Rexp, n: Int) extends Rexp            // from n-times
 | 
|  |     20 | case class BETWEEN(r: Rexp, n: Int, m: Int) extends Rexp // between nm-times
 | 
|  |     21 | case class NOT(r: Rexp) extends Rexp                     // not
 | 
|  |     22 | case class CFUN(f: Char => Boolean) extends Rexp  
 | 
|  |     23 |  
 | 
| 725 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     24 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     25 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     26 | // the nullable function: tests whether the regular 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     27 | // expression can recognise the empty string
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     28 | def nullable (r: Rexp) : Boolean = r match {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     29 |   case ZERO => false
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     30 |   case ONE => true
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     31 |   case CHAR(_) => false
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     32 |   case ALT(r1, r2) => nullable(r1) || nullable(r2)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     33 |   case SEQ(r1, r2) => nullable(r1) && nullable(r2)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     34 |   case STAR(_) => true
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     35 |   case NTIMES(r, i) => if (i == 0) true else nullable(r)
 | 
| 966 |     36 |   // ??? other cases
 | 
| 725 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     37 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     38 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     39 | // the derivative of a regular expression w.r.t. a character
 | 
| 825 |     40 | def der(c: Char, r: Rexp) : Rexp = r match {
 | 
| 725 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     41 |   case ZERO => ZERO
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     42 |   case ONE => ZERO
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     43 |   case CHAR(d) => if (c == d) ONE else ZERO
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     44 |   case ALT(r1, r2) => ALT(der(c, r1), der(c, r2))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     45 |   case SEQ(r1, r2) => 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     46 |     if (nullable(r1)) ALT(SEQ(der(c, r1), r2), der(c, r2))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     47 |     else SEQ(der(c, r1), r2)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     48 |   case STAR(r1) => SEQ(der(c, r1), STAR(r1))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     49 |   case NTIMES(r, i) => 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     50 |     if (i == 0) ZERO else SEQ(der(c, r), NTIMES(r, i - 1))
 | 
| 966 |     51 |   // ??? other cases  
 | 
| 725 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     52 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     53 | 
 | 
| 919 |     54 | // simplification
 | 
| 725 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     55 | def simp(r: Rexp) : Rexp = r match {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     56 |   case ALT(r1, r2) => (simp(r1), simp(r2)) match {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     57 |     case (ZERO, r2s) => r2s
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     58 |     case (r1s, ZERO) => r1s
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     59 |     case (r1s, r2s) => if (r1s == r2s) r1s else ALT (r1s, r2s)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     60 |   }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     61 |   case SEQ(r1, r2) =>  (simp(r1), simp(r2)) match {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     62 |     case (ZERO, _) => ZERO
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     63 |     case (_, ZERO) => ZERO
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     64 |     case (ONE, r2s) => r2s
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     65 |     case (r1s, ONE) => r1s
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     66 |     case (r1s, r2s) => SEQ(r1s, r2s)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     67 |   }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     68 |   case r => r
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     69 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     70 | 
 | 
| 928 |     71 | // the derivative w.r.t. a string (iterates der and simp)
 | 
| 725 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     72 | def ders(s: List[Char], r: Rexp) : Rexp = s match {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     73 |   case Nil => r
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     74 |   case c::s => ders(s, simp(der(c, r)))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     75 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     76 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     77 | // the main matcher function
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     78 | def matcher(r: Rexp, s: String) : Boolean = 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     79 |   nullable(ders(s.toList, r))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     80 | 
 |