| 784 |      1 | // Another automaton construction
 | 
|  |      2 | //================================
 | 
| 733 |      3 | 
 | 
|  |      4 | import $file.dfa, dfa._ 
 | 
| 487 |      5 | 
 | 
|  |      6 | // regular expressions
 | 
|  |      7 | abstract class Rexp
 | 
|  |      8 | case object ZERO extends Rexp                    // matches nothing
 | 
|  |      9 | case object ONE extends Rexp                     // matches the empty string
 | 
|  |     10 | case class CHAR(c: Char) extends Rexp            // matches a character c
 | 
|  |     11 | case class ALT(r1: Rexp, r2: Rexp) extends Rexp  // alternative
 | 
|  |     12 | case class SEQ(r1: Rexp, r2: Rexp) extends Rexp  // sequence
 | 
|  |     13 | case class STAR(r: Rexp) extends Rexp            // star
 | 
|  |     14 | 
 | 
| 784 |     15 | // the nullable function: tests whether the regular 
 | 
|  |     16 | // expression can recognise the empty string
 | 
|  |     17 | def nullable (r: Rexp) : Boolean = r match {
 | 
|  |     18 |   case ZERO => false
 | 
|  |     19 |   case ONE => true
 | 
|  |     20 |   case CHAR(_) => false
 | 
|  |     21 |   case ALT(r1, r2) => nullable(r1) || nullable(r2)
 | 
|  |     22 |   case SEQ(r1, r2) => nullable(r1) && nullable(r2)
 | 
|  |     23 |   case STAR(_) => true
 | 
| 486 |     24 | }
 | 
| 487 |     25 | 
 | 
| 784 |     26 | // the derivative of a regular expression w.r.t. a character
 | 
|  |     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))
 | 
| 487 |     36 | }
 | 
|  |     37 | 
 | 
|  |     38 | 
 | 
| 784 |     39 | def flaw(r: Rexp) : DFA[Rexp, Char] = {
 | 
|  |     40 |   DFA(r, 
 | 
|  |     41 |       { case (r, c) => der(c, r) }, 
 | 
|  |     42 |       nullable(_))
 | 
| 488 |     43 | }
 | 
| 487 |     44 | 
 | 
| 784 |     45 | val r = STAR(CHAR('a'))
 | 
|  |     46 | val pseudo = flaw(r)
 | 
|  |     47 | println(pseudo.accepts("".toList))    // true
 | 
|  |     48 | println(pseudo.accepts("a".toList))   // true
 | 
|  |     49 | println(pseudo.accepts("aa".toList))  // true
 | 
|  |     50 | println(pseudo.accepts("bb".toList))  // false
 |