| author | Christian Urban <urbanc@in.tum.de> | 
| Tue, 09 Oct 2018 08:16:25 +0100 | |
| changeset 574 | 6e19ad25309b | 
| parent 93 | 4794759139ea | 
| permissions | -rw-r--r-- | 
| 
90
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
1  | 
trait RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
2  | 
def nullable: Boolean  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
3  | 
def derive(c: Char): RegExp  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
4  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
5  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
6  | 
case object Empty extends RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
7  | 
def nullable = false  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
8  | 
def derive(c: Char) = Empty  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
9  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
10  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
11  | 
case object Eps extends RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
12  | 
def nullable = true  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
13  | 
def derive(c: Char) = Empty  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
14  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
15  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
16  | 
case class Str(s: String) extends RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
17  | 
def nullable = s.isEmpty  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
18  | 
def derive(c: Char) =  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
19  | 
if (s.isEmpty || s.head != c) Empty  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
20  | 
else Str(s.tail)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
21  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
22  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
23  | 
case class Cat(r: RegExp, s: RegExp) extends RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
24  | 
def nullable = r.nullable && s.nullable  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
25  | 
def derive(c: Char) =  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
26  | 
if (r.nullable) Or(Cat(r.derive(c), s), s.derive(c))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
27  | 
else Cat(r.derive(c), s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
28  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
29  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
30  | 
case class Star(r: RegExp) extends RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
31  | 
def nullable = true  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
32  | 
def derive(c: Char) = Cat(r.derive(c), this)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
33  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
34  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
35  | 
case class Or(r: RegExp, s: RegExp) extends RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
36  | 
def nullable = r.nullable || s.nullable  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
37  | 
def derive(c: Char) = Or(r.derive(c), s.derive(c))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
38  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
39  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
40  | 
case class And(r: RegExp, s: RegExp) extends RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
41  | 
def nullable = r.nullable && s.nullable  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
42  | 
def derive(c: Char) = And(r.derive(c), s.derive(c))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
43  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
44  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
45  | 
case class Not(r: RegExp) extends RegExp {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
46  | 
def nullable = !r.nullable  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
47  | 
def derive(c: Char) = Not(r.derive(c))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
48  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
49  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
50  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
51  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
52  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
53  | 
object Matcher {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
54  | 
  def matches(r: RegExp, s: String): Boolean = {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
55  | 
if (s.isEmpty) r.nullable  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
56  | 
else matches(r.derive(s.head), s.tail)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
57  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
58  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
59  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
60  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
61  | 
object Pimps {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
62  | 
implicit def string2RegExp(s: String) = Str(s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
63  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
64  | 
  implicit def regExpOps(r: RegExp) = new {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
65  | 
def | (s: RegExp) = Or(r, s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
66  | 
def & (s: RegExp) = And(r, s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
67  | 
def % = Star(r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
68  | 
def %(n: Int) = rep(r, n)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
69  | 
def ? = Or(Eps, r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
70  | 
def ! = Not(r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
71  | 
def ++ (s: RegExp) = Cat(r, s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
72  | 
def ~ (s: String) = Matcher.matches(r, s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
73  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
74  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
75  | 
  implicit def stringOps(s: String) = new {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
76  | 
def | (r: RegExp) = Or(s, r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
77  | 
def | (r: String) = Or(s, r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
78  | 
def & (r: RegExp) = And(s, r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
79  | 
def & (r: String) = And(s, r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
80  | 
def % = Star(s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
81  | 
def % (n: Int) = rep(Str(s), n)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
82  | 
def ? = Or(Eps, s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
83  | 
def ! = Not(s)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
84  | 
def ++ (r: RegExp) = Cat(s, r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
85  | 
def ++ (r: String) = Cat(s, r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
86  | 
def ~ (t: String) = Matcher.matches(s, t)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
87  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
88  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
89  | 
def rep(r: RegExp, n: Int): RegExp =  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
90  | 
if (n <= 0) Star(r)  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
91  | 
else Cat(r, rep(r, n - 1))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
92  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
93  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
94  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
95  | 
object Test {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
96  | 
import Pimps._  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
97  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
98  | 
val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
99  | 
  val int = ("+" | "-").? ++ digit.%(1)
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
100  | 
  val real = ("+" | "-").? ++ digit.%(1) ++ ("." ++ digit.%(1)).? ++ (("e" | "E") ++ ("+" | "-").? ++ digit.%(1)).?
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
101  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
102  | 
  def main(args: Array[String]) {
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
103  | 
    val ints = List("0", "-4534", "+049", "99")
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
104  | 
    val reals = List("0.9", "-12.8", "+91.0", "9e12", "+9.21E-12", "-512E+01")
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
105  | 
    val errs = List("", "-", "+", "+-1", "-+2", "2-")
 | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
106  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
107  | 
ints.foreach(s => assert(int ~ s))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
108  | 
reals.foreach(s => assert(!(int ~ s)))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
109  | 
errs.foreach(s => assert(!(int ~ s)))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
110  | 
|
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
111  | 
ints.foreach(s => assert(real ~ s))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
112  | 
reals.foreach(s => assert(real ~ s))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
113  | 
errs.foreach(s => assert(!(real ~ s)))  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
114  | 
}  | 
| 
 
e1f94216f39d
added
 
Christian Urban <christian dot urban at kcl dot ac dot uk> 
parents:  
diff
changeset
 | 
115  | 
}  |