author | Chengsong |
Thu, 16 Apr 2020 09:14:15 +0100 | |
changeset 149 | 6c5920fd02a7 |
parent 148 | c8ef391dd6f7 |
child 150 | b51d34113d47 |
permissions | -rw-r--r-- |
0 | 1 |
package RexpRelated |
2 |
import scala.language.implicitConversions |
|
3 |
import scala.language.reflectiveCalls |
|
4 |
import scala.annotation.tailrec |
|
5 |
import scala.util.Try |
|
6 |
||
7 |
abstract class Bit |
|
8 |
case object Z extends Bit |
|
9 |
case object S extends Bit |
|
12
768b833d6230
removed C(c) The retrieve and code in the previous version is still not correct and will crash. no prob now.
Chengsong
parents:
11
diff
changeset
|
10 |
//case class C(c: Char) extends Bit |
0 | 11 |
|
12 |
||
13 |
abstract class Rexp |
|
14 |
case object ZERO extends Rexp |
|
15 |
case object ONE extends Rexp |
|
16 |
case class CHAR(c: Char) extends Rexp |
|
17 |
case class ALTS(rs: List[Rexp]) extends Rexp |
|
18 |
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp |
|
19 |
case class STAR(r: Rexp) extends Rexp |
|
20 |
case class RECD(x: String, r: Rexp) extends Rexp |
|
21 |
||
22 |
||
23 |
||
24 |
object Rexp{ |
|
25 |
type Bits = List[Bit] |
|
26 |
// abbreviations |
|
27 |
type Mon = (Char, Rexp) |
|
28 |
type Lin = Set[Mon] |
|
29 |
def ALT(r1: Rexp, r2: Rexp) = ALTS(List(r1, r2)) |
|
30 |
def PLUS(r: Rexp) = SEQ(r, STAR(r)) |
|
31 |
def AALT(bs: Bits, r1: ARexp, r2: ARexp) = AALTS(bs, List(r1, r2)) |
|
32 |
||
33 |
||
34 |
def distinctBy[B, C](xs: List[B], f: B => C, acc: List[C] = Nil): List[B] = xs match { |
|
35 |
case Nil => Nil |
|
36 |
case (x::xs) => { |
|
37 |
val res = f(x) |
|
38 |
if (acc.contains(res)) distinctBy(xs, f, acc) |
|
39 |
else x::distinctBy(xs, f, res::acc) |
|
40 |
} |
|
41 |
} |
|
42 |
// some convenience for typing in regular expressions |
|
43 |
def charlist2rexp(s : List[Char]): Rexp = s match { |
|
44 |
case Nil => ONE |
|
45 |
case c::Nil => CHAR(c) |
|
46 |
case c::s => SEQ(CHAR(c), charlist2rexp(s)) |
|
47 |
} |
|
48 |
implicit def string2rexp(s : String) : Rexp = charlist2rexp(s.toList) |
|
49 |
||
50 |
implicit def RexpOps(r: Rexp) = new { |
|
51 |
def | (s: Rexp) = ALT(r, s) |
|
52 |
def % = STAR(r) |
|
53 |
def ~ (s: Rexp) = SEQ(r, s) |
|
54 |
} |
|
55 |
||
56 |
implicit def stringOps(s: String) = new { |
|
57 |
def | (r: Rexp) = ALT(s, r) |
|
58 |
def | (r: String) = ALT(s, r) |
|
59 |
def % = STAR(s) |
|
60 |
def ~ (r: Rexp) = SEQ(s, r) |
|
61 |
def ~ (r: String) = SEQ(s, r) |
|
62 |
def $ (r: Rexp) = RECD(s, r) |
|
63 |
} |
|
64 |
||
65 |
// translation into ARexps |
|
66 |
def fuse(bs: Bits, r: ARexp) : ARexp = r match { |
|
67 |
case AZERO => AZERO |
|
68 |
case AONE(cs) => AONE(bs ++ cs) |
|
69 |
case ACHAR(cs, f) => ACHAR(bs ++ cs, f) |
|
70 |
case AALTS(cs, rs) => AALTS(bs ++ cs, rs) |
|
71 |
case ASEQ(cs, r1, r2) => ASEQ(bs ++ cs, r1, r2) |
|
72 |
case ASTAR(cs, r) => ASTAR(bs ++ cs, r) |
|
73 |
} |
|
74 |
||
75 |
def internalise(r: Rexp) : ARexp = r match { |
|
76 |
case ZERO => AZERO |
|
77 |
case ONE => AONE(Nil) |
|
78 |
case CHAR(c) => ACHAR(Nil, c) |
|
79 |
case ALTS(List(r1, r2)) => |
|
80 |
AALTS(Nil, List(fuse(List(Z), internalise(r1)), fuse(List(S), internalise(r2)))) |
|
81 |
case ALTS(r1::rs) => { |
|
82 |
val AALTS(Nil, rs2) = internalise(ALTS(rs)) |
|
83 |
AALTS(Nil, fuse(List(Z), internalise(r1)) :: rs2.map(fuse(List(S), _))) |
|
84 |
} |
|
85 |
case SEQ(r1, r2) => ASEQ(Nil, internalise(r1), internalise(r2)) |
|
86 |
case STAR(r) => ASTAR(Nil, internalise(r)) |
|
87 |
case RECD(x, r) => internalise(r) |
|
88 |
} |
|
89 |
||
90 |
internalise(("a" | "ab") ~ ("b" | "")) |
|
5 | 91 |
|
0 | 92 |
def decode_aux(r: Rexp, bs: Bits) : (Val, Bits) = (r, bs) match { |
93 |
case (ONE, bs) => (Empty, bs) |
|
12
768b833d6230
removed C(c) The retrieve and code in the previous version is still not correct and will crash. no prob now.
Chengsong
parents:
11
diff
changeset
|
94 |
case (CHAR(f), bs) => (Chr(f), bs) |
768b833d6230
removed C(c) The retrieve and code in the previous version is still not correct and will crash. no prob now.
Chengsong
parents:
11
diff
changeset
|
95 |
case (ALTS(r::Nil), bs) => decode_aux(r, bs)//this case seems only used when we simp a regex before derivatives and it contains things like alt("a") |
0 | 96 |
case (ALTS(rs), bs) => bs match { |
97 |
case Z::bs1 => { |
|
98 |
val (v, bs2) = decode_aux(rs.head, bs1) |
|
99 |
(Left(v), bs2) |
|
100 |
} |
|
101 |
case S::bs1 => { |
|
102 |
val (v, bs2) = decode_aux(ALTS(rs.tail), bs1) |
|
103 |
(Right(v), bs2) |
|
104 |
} |
|
105 |
} |
|
106 |
case (SEQ(r1, r2), bs) => { |
|
107 |
val (v1, bs1) = decode_aux(r1, bs) |
|
108 |
val (v2, bs2) = decode_aux(r2, bs1) |
|
109 |
(Sequ(v1, v2), bs2) |
|
110 |
} |
|
111 |
case (STAR(r1), S::bs) => { |
|
112 |
val (v, bs1) = decode_aux(r1, bs) |
|
113 |
//println(v) |
|
114 |
val (Stars(vs), bs2) = decode_aux(STAR(r1), bs1) |
|
115 |
(Stars(v::vs), bs2) |
|
116 |
} |
|
117 |
case (STAR(_), Z::bs) => (Stars(Nil), bs) |
|
118 |
case (RECD(x, r1), bs) => { |
|
119 |
val (v, bs1) = decode_aux(r1, bs) |
|
120 |
(Rec(x, v), bs1) |
|
121 |
} |
|
109 | 122 |
case (r, Nil) => (Stars(Nil), Nil) |
0 | 123 |
} |
124 |
||
125 |
def decode(r: Rexp, bs: Bits) = decode_aux(r, bs) match { |
|
126 |
case (v, Nil) => v |
|
127 |
case _ => throw new Exception("Not decodable") |
|
128 |
} |
|
5 | 129 |
|
11
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
130 |
def code(v: Val): Bits = v match { |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
131 |
case Empty => Nil |
12
768b833d6230
removed C(c) The retrieve and code in the previous version is still not correct and will crash. no prob now.
Chengsong
parents:
11
diff
changeset
|
132 |
case Chr(a) => Nil |
11
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
133 |
case Left(v) => Z :: code(v) |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
134 |
case Right(v) => S :: code(v) |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
135 |
case Sequ(v1, v2) => code(v1) ::: code(v2) |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
136 |
case Stars(Nil) => Z::Nil |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
137 |
case Stars(v::vs) => S::code(v) ::: code(Stars(vs)) |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
138 |
} |
0 | 139 |
|
148 | 140 |
//note that left and right are not recorded |
141 |
//although they guide the retrival |
|
142 |
//in contrast with stars |
|
11
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
143 |
def retrieve(r: ARexp, v: Val): Bits = (r,v) match { |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
144 |
case (AONE(bs), Empty) => bs |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
145 |
case (ACHAR(bs, c), Chr(d)) => bs |
14 | 146 |
case (AALTS(bs, a::Nil), v) => bs ++ retrieve(a, v) |
11
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
147 |
case (AALTS(bs, as), Left(v)) => bs ++ retrieve(as.head,v) |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
148 |
case (AALTS(bs, as), Right(v)) => bs ++ retrieve(AALTS(Nil,as.tail),v) |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
149 |
case (ASEQ(bs, a1, a2), Sequ(v1, v2)) => bs ++ retrieve(a1, v1) ++ retrieve(a2, v2) |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
150 |
case (ASTAR(bs, a), Stars(Nil)) => bs ++ List(Z) |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
151 |
case (ASTAR(bs, a), Stars(v::vs)) => bs ++ List(S) ++ retrieve(a, v) ++ retrieve(ASTAR(Nil, a), Stars(vs)) |
59 | 152 |
}//bug here last clause should not add list(S) |
0 | 153 |
//erase function: extracts the regx from Aregex |
154 |
def erase(r:ARexp): Rexp = r match{ |
|
155 |
case AZERO => ZERO |
|
156 |
case AONE(_) => ONE |
|
157 |
case ACHAR(bs, f) => CHAR(f) |
|
158 |
case AALTS(bs, rs) => ALTS(rs.map(erase(_))) |
|
159 |
case ASEQ(bs, r1, r2) => SEQ (erase(r1), erase(r2)) |
|
160 |
case ASTAR(cs, r)=> STAR(erase(r)) |
|
161 |
} |
|
162 |
||
163 |
//--------------------------------------------------------------------------------------------------------START OF NON-BITCODE PART |
|
164 |
// nullable function: tests whether the regular |
|
165 |
// expression can recognise the empty string |
|
166 |
def nullable (r: Rexp) : Boolean = r match { |
|
167 |
case ZERO => false |
|
168 |
case ONE => true |
|
169 |
case CHAR(_) => false |
|
170 |
case ALTS(rs) => rs.exists(nullable) |
|
171 |
case SEQ(r1, r2) => nullable(r1) && nullable(r2) |
|
172 |
case STAR(_) => true |
|
173 |
case RECD(_, r) => nullable(r) |
|
174 |
//case PLUS(r) => nullable(r) |
|
175 |
} |
|
176 |
||
177 |
// derivative of a regular expression w.r.t. a character |
|
178 |
def der (c: Char, r: Rexp) : Rexp = r match { |
|
179 |
case ZERO => ZERO |
|
180 |
case ONE => ZERO |
|
181 |
case CHAR(f) => if (c == f) ONE else ZERO |
|
182 |
case ALTS(List(r1, r2)) => ALTS(List(der(c, r1), der(c, r2))) |
|
183 |
case SEQ(r1, r2) => |
|
184 |
if (nullable(r1)) ALTS(List(SEQ(der(c, r1), r2), der(c, r2))) |
|
185 |
else SEQ(der(c, r1), r2) |
|
186 |
case STAR(r) => SEQ(der(c, r), STAR(r)) |
|
187 |
case RECD(_, r1) => der(c, r1) |
|
188 |
//case PLUS(r) => SEQ(der(c, r), STAR(r)) |
|
189 |
} |
|
190 |
||
92 | 191 |
def ders (s: List[Char], r: Rexp) : Rexp = s match { |
192 |
case Nil => r |
|
193 |
case c::s => ders(s, der(c, r)) |
|
194 |
} |
|
195 |
||
196 |
def der_seqo(r:Rexp, s: List[Char],acc: List[Rexp]) : List[Rexp] = s match{ |
|
197 |
case Nil => acc ::: List(r) |
|
198 |
case c::cs => der_seqo(der(c, r), cs, acc ::: List(r)) |
|
199 |
} |
|
200 |
def der_seq_revo(r:Rexp, s: List[Char], acc: List[Rexp]): List[Rexp] = s match{ |
|
201 |
case Nil => r::acc |
|
202 |
case c::cs =>der_seq_revo(r, cs, ders(s, r) :: acc ) |
|
203 |
} |
|
204 |
def re_closeo(l1: List[Rexp], l2: List[Rexp], re_init: Rexp): Rexp = l1 match { |
|
205 |
case Nil => re_init |
|
206 |
case c::cs => if(nullable(c)) re_closeo(cs, l2.tail, ALT(re_init, l2.head) ) |
|
207 |
else re_closeo(cs, l2.tail, re_init) |
|
208 |
} |
|
93 | 209 |
|
92 | 210 |
//HERE |
211 |
def closed_string_dero(r1: Rexp, r2: Rexp, s: List[Char]): Rexp = { |
|
212 |
val l1 = der_seqo(r1, s, Nil) |
|
213 |
val l2 = der_seq_revo(r2, s, Nil) |
|
214 |
val Re = re_closeo((l1.reverse).tail, l2.tail, SEQ(l1.last, l2.head)) |
|
215 |
Re |
|
216 |
} |
|
217 |
//derivative w.r.t string |
|
218 |
def ders2(s: List[Char], r: Rexp) : Rexp = (s, r) match { |
|
219 |
case (Nil, r) => r |
|
220 |
case (s, ZERO) => ZERO |
|
221 |
case (s, ONE) => if (s == Nil) ONE else ZERO |
|
222 |
case (s, CHAR(c)) => if (s == List(c)) ONE else |
|
223 |
if (s == Nil) CHAR(c) else ZERO |
|
224 |
case (s, ALTS(List(r1, r2))) => ALT(ders2(s, r1), ders2(s, r2)) |
|
225 |
case (s, SEQ(r1, r2)) => closed_string_dero(r1, r2, s) |
|
226 |
case (c::cs, STAR(r)) => closed_string_dero(der(c, r), STAR(r), cs) |
|
227 |
} |
|
228 |
||
0 | 229 |
def flatten(v: Val) : String = v match { |
230 |
case Empty => "" |
|
231 |
case Chr(c) => c.toString |
|
232 |
case Left(v) => flatten(v) |
|
233 |
case Right(v) => flatten(v) |
|
234 |
case Sequ(v1, v2) => flatten(v1) + flatten(v2) |
|
235 |
case Stars(vs) => vs.map(flatten).mkString |
|
236 |
case Rec(_, v) => flatten(v) |
|
237 |
} |
|
238 |
||
239 |
// extracts an environment from a value |
|
240 |
def env(v: Val) : List[(String, String)] = v match { |
|
241 |
case Empty => Nil |
|
242 |
case Chr(c) => Nil |
|
243 |
case Left(v) => env(v) |
|
244 |
case Right(v) => env(v) |
|
245 |
case Sequ(v1, v2) => env(v1) ::: env(v2) |
|
246 |
case Stars(vs) => vs.flatMap(env) |
|
247 |
case Rec(x, v) => (x, flatten(v))::env(v) |
|
248 |
} |
|
249 |
||
250 |
||
251 |
// injection part |
|
252 |
def mkeps(r: Rexp) : Val = r match { |
|
253 |
case ONE => Empty |
|
254 |
case ALTS(List(r1, r2)) => |
|
255 |
if (nullable(r1)) Left(mkeps(r1)) else Right(mkeps(r2)) |
|
256 |
case SEQ(r1, r2) => Sequ(mkeps(r1), mkeps(r2)) |
|
257 |
case STAR(r) => Stars(Nil) |
|
258 |
case RECD(x, r) => Rec(x, mkeps(r)) |
|
259 |
//case PLUS(r) => Stars(List(mkeps(r))) |
|
260 |
} |
|
148 | 261 |
def haschr(r: Rexp) : Boolean = r match { |
262 |
case CHAR(c) => true |
|
263 |
case STAR(r0) => haschr(r0) |
|
264 |
case SEQ(r1, r2) => haschr(r1) && nullable(r2) || haschr(r2) && nullable(r1) |
|
265 |
case ALTS(List(r1, r2)) => haschr(r1) || haschr(r2) |
|
266 |
case ONE => false |
|
267 |
case ZERO => false |
|
268 |
} |
|
269 |
def haschar(r: Rexp, c: Char) : Boolean = r match { |
|
270 |
case CHAR(d) => if(c == d) true else false |
|
271 |
case SEQ(r1, r2) => if(haschar(r1, c) && nullable(r2)) true else if(haschar(r2, c) && nullable(r1) ) true else false |
|
272 |
case STAR(r) => if(haschar(r, c)) true else false |
|
273 |
case ALTS(List(r1, r2)) => if(haschar(r1, c) || haschar(r2, c)) true else false |
|
274 |
case ONE => false |
|
275 |
case ZERO => false |
|
276 |
} |
|
277 |
def mkchr(r: Rexp) : Val = r match { |
|
278 |
case SEQ(r1, r2) => |
|
279 |
if(haschr(r1) && nullable(r2)) Sequ(mkchr(r1), mkeps(r2)) |
|
280 |
else if(nullable(r1) && haschr(r2)) Sequ(mkeps(r1), mkchr(r2)) |
|
281 |
else throw new Exception(r.toString) |
|
282 |
case ALTS(List(r1, r2)) => if (haschr(r1)) Left(mkchr(r1)) else Right(mkchr(r2)) |
|
283 |
case STAR(r0) => Stars(List(mkchr(r0))) |
|
284 |
case CHAR(c) => Chr(c) |
|
285 |
case _ => throw new Exception("the regex you gave me can't make a char") |
|
286 |
} |
|
287 |
def mkchar(r: Rexp, c: Char) : Val = r match { |
|
288 |
case CHAR(d) => Chr(c)//if(c == d) Chr(c) else error |
|
289 |
case ALTS(List(r1, r2)) => |
|
290 |
if (haschar(r1, c)) Left(mkchar(r1, c)) else Right(mkchar(r2, c)) |
|
0 | 291 |
|
148 | 292 |
case SEQ(r1, r2) => {if(haschar(r1, c)) Sequ(mkchar(r1, c), mkeps(r2)) else Sequ(mkeps(r1), mkchar(r2, c))} |
293 |
case STAR(r) =>Stars(List(mkchar(r, c))) |
|
294 |
} |
|
0 | 295 |
def inj(r: Rexp, c: Char, v: Val) : Val = (r, v) match { |
296 |
case (STAR(r), Sequ(v1, Stars(vs))) => Stars(inj(r, c, v1)::vs) |
|
297 |
case (SEQ(r1, r2), Sequ(v1, v2)) => Sequ(inj(r1, c, v1), v2) |
|
298 |
case (SEQ(r1, r2), Left(Sequ(v1, v2))) => Sequ(inj(r1, c, v1), v2) |
|
299 |
case (SEQ(r1, r2), Right(v2)) => Sequ(mkeps(r1), inj(r2, c, v2)) |
|
300 |
case (ALTS(List(r1, r2)), Left(v1)) => Left(inj(r1, c, v1)) |
|
301 |
case (ALTS(List(r1, r2)), Right(v2)) => Right(inj(r2, c, v2)) |
|
302 |
case (CHAR(_), Empty) => Chr(c) |
|
303 |
case (RECD(x, r1), _) => Rec(x, inj(r1, c, v)) |
|
304 |
//case (PLUS(r), Sequ(v1, Stars(vs))) => Stars(inj(r, c, v1)::vs) |
|
305 |
} |
|
148 | 306 |
def fuzzy_inj(r: ARexp, c: Char, v: Val) : Val = v match { |
307 |
case Stars(vs) => r match {//vs |
|
308 |
case ASTAR(bs, r0) => inj( erase(r), c, Sequ(mkeps(erase(bder(c, r0))), v) ) |
|
309 |
case ASEQ(bs, r1, r2) => inj(erase(r), c, Sequ(mkeps(erase(bder(c, r1))), v) ) |
|
310 |
} |
|
311 |
case Sequ(v1, v2) => r match { |
|
312 |
case ASTAR(bs, r0) => inj(erase(r), c, Sequ(mkchar(erase(bder(c, r0)), c), v2)) |
|
313 |
case _ => v |
|
314 |
} |
|
315 |
case _ => v |
|
316 |
} |
|
317 |
/*def gen_rect(r: Rexp) : Val => Val = { |
|
318 |
//lingqi |
|
319 |
//buyao sanle |
|
320 |
val r1 = bsimp(r) |
|
321 |
||
322 |
} |
|
323 |
def fuzzy_inj(r: ARexp, c: Char, v: Val) : Val = { |
|
324 |
val f = gen_rect(r) |
|
325 |
val vo = f(v) |
|
326 |
inj(r, c, vo) |
|
327 |
}*/ |
|
0 | 328 |
def lex(r: Rexp, s: List[Char]) : Val = s match { |
329 |
case Nil => if (nullable(r)) mkeps(r) else throw new Exception("Not matched") |
|
330 |
case c::cs => inj(r, c, lex(der(c, r), cs)) |
|
331 |
} |
|
332 |
||
333 |
def lexing(r: Rexp, s: String) : Val = lex(r, s.toList) |
|
334 |
||
335 |
// some "rectification" functions for simplification |
|
336 |
def F_ID(v: Val): Val = v |
|
337 |
def F_RIGHT(f: Val => Val) = (v:Val) => Right(f(v)) |
|
338 |
def F_LEFT(f: Val => Val) = (v:Val) => Left(f(v)) |
|
339 |
def F_ALT(f1: Val => Val, f2: Val => Val) = (v:Val) => v match { |
|
340 |
case Right(v) => Right(f2(v)) |
|
341 |
case Left(v) => Left(f1(v)) |
|
342 |
} |
|
343 |
def F_SEQ(f1: Val => Val, f2: Val => Val) = (v:Val) => v match { |
|
344 |
case Sequ(v1, v2) => Sequ(f1(v1), f2(v2)) |
|
345 |
} |
|
346 |
def F_SEQ_Empty1(f1: Val => Val, f2: Val => Val) = |
|
347 |
(v:Val) => Sequ(f1(Empty), f2(v)) |
|
348 |
def F_SEQ_Empty2(f1: Val => Val, f2: Val => Val) = |
|
349 |
(v:Val) => Sequ(f1(v), f2(Empty)) |
|
350 |
def F_RECD(f: Val => Val) = (v:Val) => v match { |
|
351 |
case Rec(x, v) => Rec(x, f(v)) |
|
352 |
} |
|
353 |
def F_ERROR(v: Val): Val = throw new Exception("error") |
|
354 |
||
355 |
// simplification of regular expressions returning also an |
|
356 |
// rectification function; no simplification under STAR |
|
357 |
def simp(r: Rexp): (Rexp, Val => Val) = r match { |
|
358 |
case ALTS(List(r1, r2)) => { |
|
359 |
val (r1s, f1s) = simp(r1) |
|
360 |
val (r2s, f2s) = simp(r2) |
|
361 |
(r1s, r2s) match { |
|
362 |
case (ZERO, _) => (r2s, F_RIGHT(f2s)) |
|
363 |
case (_, ZERO) => (r1s, F_LEFT(f1s)) |
|
364 |
case _ => if (r1s == r2s) (r1s, F_LEFT(f1s)) |
|
365 |
else (ALTS(List(r1s, r2s)), F_ALT(f1s, f2s)) |
|
366 |
} |
|
367 |
} |
|
368 |
case SEQ(r1, r2) => { |
|
369 |
val (r1s, f1s) = simp(r1) |
|
370 |
val (r2s, f2s) = simp(r2) |
|
371 |
(r1s, r2s) match { |
|
372 |
case (ZERO, _) => (ZERO, F_ERROR) |
|
373 |
case (_, ZERO) => (ZERO, F_ERROR) |
|
374 |
case (ONE, _) => (r2s, F_SEQ_Empty1(f1s, f2s)) |
|
375 |
case (_, ONE) => (r1s, F_SEQ_Empty2(f1s, f2s)) |
|
376 |
case _ => (SEQ(r1s,r2s), F_SEQ(f1s, f2s)) |
|
377 |
} |
|
378 |
} |
|
379 |
case RECD(x, r1) => { |
|
380 |
val (r1s, f1s) = simp(r1) |
|
381 |
(RECD(x, r1s), F_RECD(f1s)) |
|
382 |
} |
|
383 |
case r => (r, F_ID) |
|
384 |
} |
|
385 |
/* |
|
386 |
val each_simp_time = scala.collection.mutable.ArrayBuffer.empty[Long] |
|
387 |
val each_simp_timeb = scala.collection.mutable.ArrayBuffer.empty[Long] |
|
388 |
*/ |
|
389 |
def lex_simp(r: Rexp, s: List[Char]) : Val = s match { |
|
390 |
case Nil => { |
|
391 |
if (nullable(r)) { |
|
392 |
mkeps(r) |
|
393 |
} |
|
394 |
else throw new Exception("Not matched") |
|
395 |
} |
|
396 |
case c::cs => { |
|
397 |
val (r_simp, f_simp) = simp(der(c, r)) |
|
398 |
inj(r, c, f_simp(lex_simp(r_simp, cs))) |
|
399 |
} |
|
400 |
} |
|
401 |
||
402 |
def lexing_simp(r: Rexp, s: String) : Val = lex_simp(r, s.toList) |
|
403 |
||
404 |
//println(lexing_simp(("a" | "ab") ~ ("b" | ""), "ab")) |
|
405 |
||
406 |
// filters out all white spaces |
|
407 |
def tokenise(r: Rexp, s: String) = |
|
408 |
env(lexing_simp(r, s)).filterNot { _._1 == "w"} |
|
409 |
||
410 |
||
411 |
//reads the string from a file |
|
412 |
def fromFile(name: String) : String = |
|
413 |
io.Source.fromFile(name).mkString |
|
414 |
||
415 |
def tokenise_file(r: Rexp, name: String) = |
|
416 |
tokenise(r, fromFile(name)) |
|
417 |
||
418 |
// Testing |
|
419 |
//============ |
|
420 |
||
421 |
def time[T](code: => T) = { |
|
422 |
val start = System.nanoTime() |
|
423 |
val result = code |
|
424 |
val end = System.nanoTime() |
|
425 |
println((end - start)/1.0e9) |
|
426 |
result |
|
427 |
} |
|
428 |
||
429 |
//--------------------------------------------------------------------------------------------------------END OF NON-BITCODE PART |
|
430 |
||
431 |
// bnullable function: tests whether the aregular |
|
432 |
// expression can recognise the empty string |
|
433 |
def bnullable (r: ARexp) : Boolean = r match { |
|
434 |
case AZERO => false |
|
435 |
case AONE(_) => true |
|
436 |
case ACHAR(_,_) => false |
|
437 |
case AALTS(_, rs) => rs.exists(bnullable) |
|
438 |
case ASEQ(_, r1, r2) => bnullable(r1) && bnullable(r2) |
|
439 |
case ASTAR(_, _) => true |
|
440 |
} |
|
441 |
||
442 |
def mkepsBC(r: ARexp) : Bits = r match { |
|
443 |
case AONE(bs) => bs |
|
444 |
case AALTS(bs, rs) => { |
|
445 |
val n = rs.indexWhere(bnullable) |
|
446 |
bs ++ mkepsBC(rs(n)) |
|
447 |
} |
|
448 |
case ASEQ(bs, r1, r2) => bs ++ mkepsBC(r1) ++ mkepsBC(r2) |
|
449 |
case ASTAR(bs, r) => bs ++ List(Z) |
|
450 |
} |
|
451 |
||
452 |
// derivative of a regular expression w.r.t. a character |
|
453 |
def bder(c: Char, r: ARexp) : ARexp = r match { |
|
454 |
case AZERO => AZERO |
|
455 |
case AONE(_) => AZERO |
|
12
768b833d6230
removed C(c) The retrieve and code in the previous version is still not correct and will crash. no prob now.
Chengsong
parents:
11
diff
changeset
|
456 |
case ACHAR(bs, f) => if (c == f) AONE(bs) else AZERO |
0 | 457 |
case AALTS(bs, rs) => AALTS(bs, rs.map(bder(c, _))) |
458 |
case ASEQ(bs, r1, r2) => |
|
459 |
if (bnullable(r1)) AALT(bs, ASEQ(Nil, bder(c, r1), r2), fuse(mkepsBC(r1), bder(c, r2))) |
|
460 |
else ASEQ(bs, bder(c, r1), r2) |
|
461 |
case ASTAR(bs, r) => ASEQ(bs, fuse(List(S), bder(c, r)), ASTAR(Nil, r)) |
|
462 |
} |
|
107 | 463 |
def bder_rf(c: Char, r: ARexp) : ARexp = r match { |
464 |
case AZERO => AZERO |
|
465 |
case AONE(_) => AZERO |
|
466 |
case ACHAR(bs, f) => if (c == f) AONE(bs) else AZERO |
|
467 |
case AALTS(bs, rs) => AALTS(bs, rs.map(bder_rf(c, _))) |
|
468 |
case ASEQ(bs, r1, r2) => |
|
469 |
if (bnullable(r1)) AALT(bs, ASEQ(Nil, bder_rf(c, r1), r2), fuse(mkepsBC(r1), bder_rf(c, r2))) |
|
470 |
else ASEQ(bs, bder_rf(c, r1), r2) |
|
471 |
case ASTAR(bs, r) => ASEQ(bs, fuse(List(S), bder_rf(c, r)), ASTAR(Nil, r)) |
|
472 |
} |
|
0 | 473 |
// derivative w.r.t. a string (iterates bder) |
474 |
@tailrec |
|
475 |
def bders (s: List[Char], r: ARexp) : ARexp = s match { |
|
476 |
case Nil => r |
|
477 |
case c::s => bders(s, bder(c, r)) |
|
478 |
} |
|
107 | 479 |
|
480 |
def bders_rf(s: List[Char], r: ARexp) : ARexp = s match { |
|
481 |
case Nil => r |
|
482 |
case c::s => bders_rf(s, bder_rf(c, r)) |
|
483 |
} |
|
484 |
def all_zero_except_alt(rs: List[ARexp], a: ARexp): ARexp = rs match{ |
|
485 |
case Nil => a |
|
486 |
case AZERO :: rs1 => all_zero_except_alt(rs1, a) |
|
487 |
case AALTS(bs, rs1) :: rs2 => { |
|
488 |
if (a == AZERO) |
|
489 |
all_zero_except_alt(rs2, AALTS(bs, rs1)) |
|
490 |
else |
|
491 |
AZERO |
|
492 |
} |
|
493 |
case r1 :: rs2 => AZERO |
|
494 |
} |
|
0 | 495 |
def flats(rs: List[ARexp]): List[ARexp] = rs match { |
496 |
case Nil => Nil |
|
497 |
case AZERO :: rs1 => flats(rs1) |
|
498 |
case AALTS(bs, rs1) :: rs2 => rs1.map(fuse(bs, _)) ::: flats(rs2) |
|
499 |
case r1 :: rs2 => r1 :: flats(rs2) |
|
15 | 500 |
} |
17 | 501 |
/* |
15 | 502 |
def remove(v: Val): Val = v match{ |
503 |
case Right(v1) => v1 |
|
504 |
case Left(v1) => v1 |
|
505 |
case _ => throw new Exception("Not removable") |
|
17 | 506 |
}*/ |
15 | 507 |
def augment(v: Val, i: Int): Val = if(i > 1) augment(Right(v), i - 1) else Right(v) |
508 |
//an overly complex version |
|
509 |
/* |
|
510 |
if(rel_dist >0){//the regex we are dealing with is not what v points at |
|
511 |
rs match{ |
|
512 |
case Nil => throw new Exception("Trying to simplify a non-existent value") |
|
148 | 513 |
case AZERO :: rs1 => right_shift(rs1, rel_dist - 1, remove(v)) |
514 |
case AALTS(bs, rs1) :: rs2 => right_shift(rs2, rel_dist - 1, augment(v, rs1.length - 1))//rs1 is guaranteed to have a len geq 2 |
|
515 |
case r1 :: rs2 => right_shift(rs2, rel_dist - 1, v) |
|
15 | 516 |
} |
0 | 517 |
} |
15 | 518 |
else if(rel_dist == 0){//we are dealing with regex v is pointing to -- "v->r itself" |
519 |
rs match{//r1 cannot be zero |
|
148 | 520 |
AALTS(bs, rs1) :: rs2 => right_shift( ) |
15 | 521 |
AZERO::rs2 => throw new Exception("Value corresponds to zero") |
148 | 522 |
r1::rs2 => right_shift(rs2, rel_dist - 1, v) |
15 | 523 |
} |
524 |
||
525 |
} |
|
526 |
else{ |
|
527 |
||
528 |
} |
|
529 |
*/ |
|
148 | 530 |
//gives how much the regex at i has shifted right after flatten(on a list of simplified regexes) |
531 |
def right_shift(rs: List[ARexp], i: Int): Int = (rs, i) match { |
|
15 | 532 |
case (_, 0) => 0 |
533 |
case (Nil, _) => 0 |
|
148 | 534 |
case (AZERO :: rs1, _) => right_shift(rs1, i - 1) - 1 |
535 |
case (AALTS(bs, rs1) :: rs2, _) => rs1.length - 1 + right_shift(rs2, i - 1) |
|
536 |
case (r1 :: rs2, _) => right_shift(rs2, i - 1) |
|
15 | 537 |
} |
0 | 538 |
def rflats(rs: List[Rexp]): List[Rexp] = rs match { |
539 |
case Nil => Nil |
|
540 |
case ZERO :: rs1 => rflats(rs1) |
|
541 |
case ALTS(rs1) :: rs2 => rs1 ::: rflats(rs2) |
|
542 |
case r1 :: rs2 => r1 :: rflats(rs2) |
|
543 |
} |
|
544 |
var flats_time = 0L |
|
545 |
var dist_time = 0L |
|
546 |
||
547 |
def bsimp(r: ARexp): ARexp = r match { |
|
548 |
case ASEQ(bs1, r1, r2) => (bsimp(r1), bsimp(r2)) match { |
|
549 |
case (AZERO, _) => AZERO |
|
550 |
case (_, AZERO) => AZERO |
|
551 |
case (AONE(bs2), r2s) => fuse(bs1 ++ bs2, r2s) |
|
552 |
case (r1s, r2s) => ASEQ(bs1, r1s, r2s) |
|
553 |
} |
|
554 |
case AALTS(bs1, rs) => { |
|
555 |
val rs_simp = rs.map(bsimp) |
|
556 |
val flat_res = flats(rs_simp) |
|
557 |
val dist_res = distinctBy(flat_res, erase) |
|
558 |
dist_res match { |
|
559 |
case Nil => AZERO |
|
93 | 560 |
case r :: Nil => fuse(bs1, r) |
0 | 561 |
case rs => AALTS(bs1, rs) |
562 |
} |
|
563 |
} |
|
5 | 564 |
//case ASTAR(bs, r) => ASTAR(bs, bsimp(r)) |
0 | 565 |
case r => r |
566 |
} |
|
107 | 567 |
//minimise fuse operation if possible |
568 |
def bsimp_rf(r: ARexp):ARexp = r match { |
|
569 |
case ASEQ(bs1, r1, r2) => (bsimp_rf(r1), bsimp_rf(r2)) match { |
|
570 |
case (AZERO, _) => AZERO |
|
571 |
case (_, AZERO) => AZERO |
|
572 |
case (AONE(bs2), r2s) => fuse(bs1 ++ bs2, r2s) |
|
573 |
case (r1s, r2s) => ASEQ(bs1, r1s, r2s) |
|
574 |
} |
|
575 |
case AALTS(bs1, rs) => { |
|
576 |
//after map simp, before flats, check if all others simplify to 0s, if yes, do not fuse |
|
577 |
val rs_simp = rs.map(bsimp_rf) |
|
578 |
//prevent fuse from happening |
|
579 |
val fuse_alts = all_zero_except_alt(rs_simp, AZERO)//returns AZERO if not the case, return AALTS if yes |
|
580 |
if(fuse_alts == AZERO){ |
|
581 |
val flat_res = flats(rs_simp) |
|
582 |
val dist_res = distinctBy(flat_res, erase) |
|
583 |
dist_res match { |
|
584 |
case Nil => AZERO |
|
585 |
case r :: Nil => fuse(bs1, r) |
|
586 |
case rs => AALTS(bs1, rs) |
|
587 |
} |
|
588 |
} |
|
589 |
else{ |
|
590 |
fuse(bs1, fuse_alts) |
|
591 |
} |
|
592 |
} |
|
593 |
//case ASTAR(bs, r) => ASTAR(bs, bsimp(r)) |
|
594 |
case r => r |
|
595 |
} |
|
93 | 596 |
//only print at the top level |
597 |
||
148 | 598 |
//find_pos returns the index of a certain regex in a list of regex |
599 |
//the leftmost regex is given the index 0 and the regex next to it |
|
600 |
//is given 1 and so on |
|
601 |
//it needs the value to point out which regex it wants to get index of |
|
602 |
//find_pos_aux does essentially the same thing as find_pos, except that |
|
603 |
//it receives an alts instead of a list of regular expressions |
|
17 | 604 |
def find_pos(v: Val, rs: List[ARexp]): Int = (v, rs) match{ |
605 |
case (v, r::Nil) => 0 |
|
15 | 606 |
case (Right(v), r::rs) => find_pos(v, rs) + 1 |
17 | 607 |
case (Left(v), r::rs) => 0 |
608 |
//case (v, _) => 0 |
|
609 |
} |
|
610 |
def find_pos_aux(v: Val, r: ARexp): Int = r match { |
|
611 |
case AALTS(bs, rs) => find_pos(v, rs) |
|
612 |
case r => 0 |
|
15 | 613 |
} |
17 | 614 |
def remove(v: Val, rs: List[ARexp]) : Val = (v,rs) match {//remove the outmost layer of ALTS's Left and Right |
615 |
//we have to use r to detect the bound of nested L/Rs |
|
616 |
case (v, r::Nil) => v |
|
617 |
case (Right(v), r::rs) => remove(v, rs) |
|
15 | 618 |
case (Left(v), r::rs) => v |
17 | 619 |
//case (v, r::Nil) => v |
15 | 620 |
} |
16 | 621 |
def simple_end(v: Val): Boolean = v match { |
15 | 622 |
case Left(v) => return false |
623 |
case Right(v) => return simple_end(v) |
|
624 |
case v => return true |
|
625 |
} |
|
148 | 626 |
|
627 |
//tells if rs[i] after flatten is at the right end |
|
628 |
def isend(v: Val, rs: List[ARexp], i: Int): Boolean = {//TODO: here the slice api i am not familiar with so this call might be incorrect and crash the bsimp2 |
|
629 |
val rsbh = rs.slice(i + 1, rs.length) |
|
15 | 630 |
val out_end = if(flats(rsbh) == Nil) true else false |
631 |
val inner_end = simple_end(v) |
|
632 |
inner_end && out_end |
|
633 |
} |
|
148 | 634 |
//get the coat of v and wears it on vs |
16 | 635 |
def get_coat(v: Val, rs: List[Rexp], vs: Val): Val = (v, rs) match{//the dual operation of remove(so-called by myself) |
15 | 636 |
case (Right(v), r::Nil) => Right(vs) |
637 |
case (Left(v), r::rs) => Left(vs) |
|
638 |
case (Right(v), r::rs) => Right(get_coat(v, rs, vs)) |
|
639 |
} |
|
148 | 640 |
//coat does the job of "coating" a value |
641 |
//given the number of right outside it |
|
15 | 642 |
def coat(v: Val, i: Int) : Val = i match { |
643 |
case 0 => v |
|
644 |
case i => coat(Right(v), i - 1) |
|
645 |
} |
|
148 | 646 |
def decoat(v:Val, i: Int) : Val = i match { |
647 |
case 0 => v |
|
648 |
case i => v match { |
|
649 |
case Right(v0) => decoat(v0, i - 1) |
|
650 |
case _ => throw new Exception("bad args decoat") |
|
651 |
} |
|
652 |
} |
|
653 |
//given a regex, and a value, return the rectification function for how to rebuild the original value from the simplified value |
|
654 |
||
655 |
def vunsimp(r: ARexp, v: Val) : Val => Val = (r, v) match { |
|
656 |
case (ASEQ(bs1, r1, r2), Sequ(v1, v2)) => (bsimp2(r1, v1), bsimp2(r2, v2)) match { |
|
657 |
case ((AZERO, _), (_, _) )=> throw new Exception("bad arguments") |
|
658 |
case ((_, _), (AZERO, _)) => throw new Exception("bad arguments") |
|
659 |
case ((AONE(bs2), v1s) , (r2s, v2s)) => (vtails => Sequ(v1, vunsimp(r2, v2)(vtails))) //(fuse(bs1 ++ bs2, r2s), v2s )//v2 tells how to retrieve bits in r2s, which is enough as the bits of the first part of the sequence has already been integrated to the top level of the second regx. |
|
660 |
case ((r1s, v1s), (r2s, v2s)) => (vsmall => vsmall match { |
|
661 |
case Sequ(v1small, v2small) => Sequ(vunsimp(r1, v1)(v1small), vunsimp(r2, v2)(v2small)) |
|
662 |
case _ => { |
|
663 |
println(vsmall) ; |
|
664 |
throw new Exception("bad arguments sequ") |
|
665 |
} |
|
666 |
//(ASEQ(bs1, r1s, r2s), Sequ(v1s, v2s)) |
|
667 |
}) |
|
668 |
} |
|
669 |
case (AALTS(bs1, rs), v) => { |
|
670 |
val init_ind = find_pos(v, rs) |
|
671 |
val rightend1 = if(init_ind + 1 == rs.length) true else false |
|
672 |
val inner_rectfunct = vunsimp(rs(init_ind), remove(v, rs))//remove all the outer layers of left and right in v to match the regx rs[i] |
|
673 |
val vpointr = bsimp2(rs(init_ind), remove(v, rs)) |
|
674 |
val target_vs = vpointr._2 |
|
675 |
val target_rs = vpointr._1 |
|
676 |
||
677 |
val rs_simp = rs.map(bsimp) |
|
678 |
val target_vs_kernel = target_rs match { |
|
679 |
case AALTS(bs2, rs2) => remove(target_vs, rs2)//remove the secondary layer of left and right |
|
680 |
case r => target_vs |
|
681 |
} |
|
682 |
val target_vs_outerlayers = target_rs match { |
|
683 |
case AALTS(bs2, rs2) => find_pos(target_vs, rs2)//remove the secondary layer of left and right |
|
684 |
case r => 0 |
|
685 |
} |
|
686 |
val rightend2 = target_rs match { |
|
687 |
case AALTS(bs2, rs2) => if(find_pos(target_vs, rs2) == rs2.length - 1) true else false |
|
688 |
case r => false |
|
689 |
} |
|
690 |
val isalts = target_rs match { |
|
691 |
case AALTS(bs2, rs2) => true |
|
692 |
case r => false |
|
693 |
} |
|
694 |
||
695 |
||
696 |
val flat_res = flats(rs_simp) |
|
697 |
val flats_shit1 = right_shift(rs_simp, init_ind) |
|
698 |
val flats_shift2 = find_pos_aux(target_vs, target_rs) |
|
699 |
val flats_shift = flats_shit1 + flats_shift2//right_shift used to be called flats_vsimp |
|
700 |
val new_ind = init_ind + flats_shift |
|
701 |
||
702 |
val dist_res = distinctBy(flat_res, erase) |
|
703 |
val front_part = distinctBy(flat_res.slice(0, new_ind + 1), erase) |
|
704 |
||
705 |
val vdb = if(dist_res.length == front_part.length )//that means the regex we are interested in is at the end of the list |
|
706 |
{ |
|
707 |
coat(target_vs_kernel, front_part.length - 1) |
|
708 |
} |
|
709 |
else{ |
|
710 |
coat(Left(target_vs_kernel), front_part.length - 1) |
|
711 |
} |
|
712 |
if(rightend1){ |
|
713 |
if(rightend2){ |
|
714 |
kernel_coated: Val => |
|
715 |
decoat(kernel_coated, front_part.length - 1) match { |
|
716 |
case Left(vk) => coat(inner_rectfunct(coat(vk, target_vs_outerlayers)), init_ind)//add clause: if rs_simp(init_ind) is an alts |
|
717 |
case vk => coat(inner_rectfunct(coat(vk, target_vs_outerlayers)), init_ind) |
|
718 |
} |
|
719 |
} |
|
720 |
else{ |
|
721 |
kernel_coated: Val => |
|
722 |
decoat(kernel_coated, front_part.length - 1) match { |
|
723 |
case Left(vk) => if(isalts) coat(inner_rectfunct(coat(Left(vk), target_vs_outerlayers)), init_ind) |
|
724 |
else coat(inner_rectfunct(coat((vk), target_vs_outerlayers)), init_ind)//add clause: if rs_simp(init_ind) is an alts |
|
725 |
case vk => if(isalts) coat(inner_rectfunct(coat(Left(vk), target_vs_outerlayers)), init_ind) |
|
726 |
else coat(inner_rectfunct(coat((vk), target_vs_outerlayers)), init_ind) |
|
727 |
} |
|
728 |
} |
|
729 |
} |
|
730 |
else{ |
|
731 |
if(rightend2){ |
|
732 |
kernel_coated: Val => |
|
733 |
decoat(kernel_coated, front_part.length - 1) match { |
|
734 |
case Left(vk) => coat(Left(inner_rectfunct(coat(vk, target_vs_outerlayers))), init_ind)//add clause: if rs_simp(init_ind) is an alts |
|
735 |
case vk => coat(Left(inner_rectfunct(coat(vk, target_vs_outerlayers))), init_ind) |
|
736 |
} |
|
737 |
} |
|
738 |
else{ |
|
739 |
kernel_coated: Val => |
|
740 |
decoat(kernel_coated, front_part.length - 1) match { |
|
741 |
case Left(vk) => if(isalts) coat(Left(inner_rectfunct(coat(Left(vk), target_vs_outerlayers))), init_ind) |
|
742 |
else coat(Left(inner_rectfunct(coat(vk, target_vs_outerlayers))), init_ind)//add clause: if rs_simp(init_ind) is an alts |
|
743 |
case vk => if(isalts) coat(Left(inner_rectfunct(coat(Left(vk), target_vs_outerlayers))), init_ind) |
|
744 |
else coat(Left(inner_rectfunct(coat(vk, target_vs_outerlayers))), init_ind) |
|
745 |
} |
|
746 |
} |
|
747 |
||
748 |
} |
|
749 |
||
750 |
} |
|
751 |
//case ASTAR(bs, r) => ASTAR(bs, bsimp(r)) |
|
752 |
case (r, v) => (v => v) |
|
753 |
} |
|
17 | 754 |
//This version takes a regex and a value, return a simplified regex and its corresponding simplified value |
755 |
def bsimp2(r: ARexp, v: Val): (ARexp, Val) = (r,v) match{ |
|
756 |
case (ASEQ(bs1, r1, r2), Sequ(v1, v2)) => (bsimp2(r1, v1), bsimp2(r2, v2)) match { |
|
757 |
case ((AZERO, _), (_, _) )=> (AZERO, undefined) |
|
758 |
case ((_, _), (AZERO, _)) => (AZERO, undefined) |
|
759 |
case ((AONE(bs2), v1s) , (r2s, v2s)) => (fuse(bs1 ++ bs2, r2s), v2s )//v2 tells how to retrieve bits in r2s, which is enough as the bits of the first part of the sequence has already been integrated to the top level of the second regx. |
|
760 |
case ((r1s, v1s), (r2s, v2s)) => (ASEQ(bs1, r1s, r2s), Sequ(v1s, v2s)) |
|
761 |
} |
|
762 |
case (AALTS(bs1, rs), v) => { |
|
763 |
val init_ind = find_pos(v, rs) |
|
148 | 764 |
val vpointr = bsimp2(rs(init_ind), remove(v, rs))//remove all the outer layers of left and right in v to match the regx rs[i] |
765 |
val target_sv = vpointr._2 |
|
766 |
val target_sr = vpointr._1 |
|
767 |
||
17 | 768 |
val rs_simp = rs.map(bsimp) |
148 | 769 |
val target_vs_kernel = target_sr match { |
770 |
case AALTS(bs2, rs2) => remove(target_sv, rs2)//if rs(init_ind) after simp is also an alts, we remove the R(....L(v)) outside v |
|
771 |
case r => target_sv |
|
17 | 772 |
} |
773 |
val flat_res = flats(rs_simp) |
|
148 | 774 |
val flats_shift1 = right_shift(rs_simp, init_ind) |
775 |
val flats_base = find_pos_aux(target_sv, target_sr) |
|
776 |
val flats_shift = flats_shift1 + flats_base//right_shift used to be called flats_vsimp |
|
777 |
val new_ind = init_ind + flats_shift |
|
778 |
||
17 | 779 |
val dist_res = distinctBy(flat_res, erase) |
780 |
val front_part = distinctBy(flat_res.slice(0, new_ind + 1), erase) |
|
148 | 781 |
|
17 | 782 |
val vdb = if(dist_res.length == front_part.length )//that means the regex we are interested in is at the end of the list |
783 |
{ |
|
148 | 784 |
coat(target_vs_kernel, front_part.length - 1) |
17 | 785 |
} |
786 |
else{ |
|
148 | 787 |
coat(Left(target_vs_kernel), front_part.length - 1) |
17 | 788 |
} |
789 |
dist_res match { |
|
790 |
case Nil => (AZERO, undefined) |
|
791 |
case s :: Nil => (fuse(bs1, s), vdb) |
|
792 |
case rs => (AALTS(bs1, rs), vdb) |
|
793 |
} |
|
794 |
} |
|
795 |
//case ASTAR(bs, r) => ASTAR(bs, bsimp(r)) |
|
796 |
case (r, v) => (r, v) |
|
797 |
} |
|
148 | 798 |
//the below are all residuals from the bsimp2 function |
799 |
//val vs_for_coating = if(isend(vs._2, rs_simp, init_ind)||flat_res.length == 1) vs_kernel else Left(vs_kernel) |
|
800 |
//val vf = coat(vs_for_coating, new_ind) |
|
801 |
//flats2 returns a list of regex and a single v |
|
802 |
//now |- vf: ALTS(bs1, flat_res) |
|
803 |
//phase 2 transformation so that aalts(bs1, rsf) => aalts(bs, rsdb) and vf => vdb |
|
804 |
//val size_reduction = new_ind + 1 - front_part.length |
|
17 | 805 |
def vsimp(r: ARexp, v: Val): Val = bsimp2(r, v)._2 |
806 |
/*This version was first intended for returning a function however a value would be simpler. |
|
15 | 807 |
def bsimp2(r: ARexp, v: Val): (ARexp, Val => Val) = (r,v) match{ |
808 |
case (ASEQ(bs1, r1, r2), v) => (bsimp2(r1), bsimp2(r2)) match { |
|
809 |
case ((AZERO, _), (_, _) )=> (AZERO, undefined) |
|
810 |
case ((_, _), (AZERO, _)) => (AZERO, undefined) |
|
811 |
case ((AONE(bs2), f1) , (r2s, f2)) => (fuse(bs1 ++ bs2, r2s), lambda v => v match { case Sequ(_, v) => f2(v) } ) |
|
812 |
case ((r1s, f1), (r2s, f2)) => (ASEQ(bs1, r1s, r2s), lambda v => v match {case Sequ(v1, v2) => Sequ(f1(v1), f2(v2))} |
|
813 |
} |
|
814 |
case AALTS(bs1, rs) => { |
|
815 |
val init_ind = find_pos(v, rs) |
|
816 |
val vs = bsimp2(rs[init_ind], remove(v, rs))//remove all the outer layers of left and right in v to match the regx rs[i] |
|
817 |
val rs_simp = rs.map(bsimp) |
|
818 |
val vs_kernel = rs_simp[init_ind] match { |
|
819 |
case AALTS(bs2, rs2) => remove(vs, rs_simp[init_ind])//remove the secondary layer of left and right |
|
820 |
case r => vs |
|
821 |
} |
|
822 |
val vs_for_coating = if(isend(vs, rs_simp, init_ind)) vs_kernel else Left(vs_kernel) |
|
823 |
||
824 |
val r_s = rs_simp[init_ind] |
|
148 | 825 |
val shift = right_shift(vs, rs_simp, init_ind) + find_pos(vs, rs_simp[init_ind]) |
15 | 826 |
val vf = coat(vs_for_coating, shift + init_ind) |
827 |
||
828 |
val flat_res = flats(rs_simp)//flats2 returns a list of regex and a single v |
|
829 |
val dist_res = distinctBy(flat_res, erase) |
|
830 |
dist_res match { |
|
831 |
case Nil => AZERO |
|
832 |
case s :: Nil => fuse(bs1, s) |
|
833 |
case rs => AALTS(bs1, rs) |
|
834 |
} |
|
835 |
} |
|
836 |
//case ASTAR(bs, r) => ASTAR(bs, bsimp(r)) |
|
837 |
case r => r |
|
16 | 838 |
}*/ |
5 | 839 |
def super_bsimp(r: ARexp): ARexp = r match { |
840 |
case ASEQ(bs1, r1, r2) => (super_bsimp(r1), super_bsimp(r2)) match { |
|
0 | 841 |
case (AZERO, _) => AZERO |
842 |
case (_, AZERO) => AZERO |
|
11
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
843 |
case (AONE(bs2), r2s) => fuse(bs1 ++ bs2, r2s)//万一是(r1, alts(rs))这种形式呢 |
9c1ca6d6e190
The C(Char) construct is incompatible with the code and retrieve in Fahad's thesis.
Chengsong
parents:
5
diff
changeset
|
844 |
case (AALTS(bs2, rs), r2) => AALTS(bs1 ++ bs2, rs.map(r => r match {case AONE(bs3) => fuse(bs3, r2) case r => ASEQ(Nil, r, r2)} ) ) |
0 | 845 |
case (r1s, r2s) => ASEQ(bs1, r1s, r2s) |
846 |
} |
|
847 |
case AALTS(bs1, rs) => { |
|
5 | 848 |
val rs_simp = rs.map(super_bsimp) |
0 | 849 |
val flat_res = flats(rs_simp) |
850 |
val dist_res = distinctBy(flat_res, erase) |
|
851 |
dist_res match { |
|
852 |
case Nil => AZERO |
|
853 |
case s :: Nil => fuse(bs1, s) |
|
854 |
case rs => AALTS(bs1, rs) |
|
855 |
} |
|
856 |
} |
|
5 | 857 |
//case ASTAR(bs, r) => ASTAR(bs, bsimp(r)) |
0 | 858 |
case r => r |
859 |
} |
|
860 |
||
5 | 861 |
|
0 | 862 |
def simp_weakened(r: Rexp): Rexp = r match { |
863 |
case SEQ(r1, r2) => (simp_weakened(r1), r2) match { |
|
864 |
case (ZERO, _) => ZERO |
|
865 |
case (_, ZERO) => ZERO |
|
866 |
case (ONE, r2s) => r2s |
|
867 |
case (r1s, r2s) => SEQ(r1s, r2s) |
|
868 |
} |
|
869 |
case ALTS(rs) => { |
|
870 |
val rs_simp = rs.map(simp_weakened) |
|
871 |
val flat_res = rflats(rs_simp) |
|
872 |
val dist_res = rs_simp.distinct |
|
873 |
dist_res match { |
|
874 |
case Nil => ZERO |
|
875 |
case s :: Nil => s |
|
876 |
case rs => ALTS(rs) |
|
877 |
} |
|
878 |
} |
|
879 |
case STAR(r) => STAR(simp_weakened(r)) |
|
880 |
case r => r |
|
881 |
} |
|
882 |
||
883 |
def bders_simp (s: List[Char], r: ARexp) : ARexp = s match { |
|
884 |
case Nil => r |
|
885 |
case c::s => bders_simp(s, bsimp(bder(c, r))) |
|
886 |
} |
|
107 | 887 |
def bders_simp_rf (s: List[Char], r: ARexp) : ARexp = s match { |
888 |
case Nil => r |
|
889 |
case c::s => bders_simp_rf(s, bsimp_rf(bder(c, r))) |
|
890 |
} |
|
891 |
||
14 | 892 |
//----------------------------------------------------------------------------experiment bsimp |
893 |
/* |
|
894 |
||
0 | 895 |
*/ |
896 |
/* |
|
897 |
def time[T](code: => T) = { |
|
898 |
val start = System.nanoTime() |
|
899 |
val result = code |
|
900 |
val end = System.nanoTime() |
|
901 |
println((end - start)/1.0e9) |
|
902 |
result |
|
903 |
} |
|
904 |
*/ |
|
905 |
// main unsimplified lexing function (produces a value) |
|
148 | 906 |
def blex(s: List[Char], r: ARexp) : Bits = s match { |
0 | 907 |
case Nil => if (bnullable(r)) mkepsBC(r) else throw new Exception("Not matched") |
908 |
case c::cs => { |
|
909 |
val der_res = bder(c,r) |
|
148 | 910 |
blex(cs, der_res) |
0 | 911 |
} |
912 |
} |
|
913 |
||
148 | 914 |
def bpre_lexing(r: Rexp, s: String) = blex( s.toList, internalise(r) ) |
915 |
def blexing(s: String, r: Rexp) : Val = decode(r, blex( s.toList, internalise(r) ) ) |
|
0 | 916 |
|
917 |
var bder_time = 0L |
|
918 |
var bsimp_time = 0L |
|
919 |
var mkepsBC_time = 0L |
|
920 |
var small_de = 2 |
|
921 |
var big_de = 5 |
|
922 |
var usual_de = 3 |
|
923 |
||
924 |
def blex_simp(r: ARexp, s: List[Char]) : Bits = s match { |
|
925 |
case Nil => { |
|
926 |
if (bnullable(r)) { |
|
927 |
//println(asize(r)) |
|
5 | 928 |
mkepsBC(r) |
0 | 929 |
} |
930 |
else throw new Exception("Not matched") |
|
931 |
} |
|
932 |
case c::cs => { |
|
933 |
val der_res = bder(c,r) |
|
934 |
val simp_res = bsimp(der_res) |
|
935 |
blex_simp(simp_res, cs) |
|
936 |
} |
|
937 |
} |
|
5 | 938 |
def super_blex_simp(r: ARexp, s: List[Char]): Bits = s match { |
939 |
case Nil => { |
|
940 |
if (bnullable(r)) { |
|
941 |
mkepsBC(r) |
|
942 |
} |
|
943 |
else throw new Exception("Not matched") |
|
944 |
} |
|
945 |
case c::cs => { |
|
946 |
super_blex_simp(super_bsimp(bder(c,r)), cs) |
|
947 |
} |
|
948 |
} |
|
0 | 949 |
def blex_real_simp(r: ARexp, s: List[Char]): ARexp = s match{ |
950 |
case Nil => r |
|
951 |
case c::cs => blex_real_simp(bsimp(bder(c, r)), cs) |
|
952 |
} |
|
953 |
||
954 |
||
955 |
//size: of a Aregx for testing purposes |
|
956 |
def size(r: Rexp) : Int = r match { |
|
957 |
case ZERO => 1 |
|
958 |
case ONE => 1 |
|
959 |
case CHAR(_) => 1 |
|
960 |
case SEQ(r1, r2) => 1 + size(r1) + size(r2) |
|
961 |
case ALTS(rs) => 1 + rs.map(size).sum |
|
962 |
case STAR(r) => 1 + size(r) |
|
963 |
} |
|
964 |
||
965 |
def asize(a: ARexp) = size(erase(a)) |
|
966 |
||
967 |
||
968 |
// decoding does not work yet |
|
969 |
def blexing_simp(r: Rexp, s: String) = { |
|
970 |
val bit_code = blex_simp(internalise(r), s.toList) |
|
5 | 971 |
decode(r, bit_code) |
972 |
} |
|
973 |
def super_blexing_simp(r: Rexp, s: String) = { |
|
974 |
decode(r, super_blex_simp(internalise(r), s.toList)) |
|
0 | 975 |
} |
976 |
||
977 |
||
978 |
||
979 |
||
980 |
||
981 |
// Lexing Rules for a Small While Language |
|
982 |
||
983 |
//symbols |
|
984 |
/* |
|
985 |
val SYM = PRED("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(_)) |
|
986 |
||
987 |
//digits |
|
988 |
val DIGIT = PRED("0123456789".contains(_)) |
|
989 |
//identifiers |
|
990 |
val ID = SYM ~ (SYM | DIGIT).% |
|
991 |
//numbers |
|
992 |
val NUM = STAR(DIGIT) |
|
993 |
//keywords |
|
994 |
val KEYWORD : Rexp = "skip" | "while" | "do" | "if" | "then" | "else" | "read" | "write" | "true" | "false" |
|
995 |
val AKEYWORD: Rexp = ALTS(List("skip" , "while" , "do" , "if" , "then" , "else" , "read" , "write" , "true" , "false")) |
|
996 |
//semicolons |
|
997 |
val SEMI: Rexp = ";" |
|
998 |
//operators |
|
999 |
val OP: Rexp = ":=" | "==" | "-" | "+" | "*" | "!=" | "<" | ">" | "<=" | ">=" | "%" | "/" |
|
1000 |
val AOP: Rexp = ALTS(List(":=" , "==" , "-" , "+" , "*" , "!=" , "<" , ">" , "<=" , ">=" , "%" , "/")) |
|
1001 |
//whitespaces |
|
1002 |
val WHITESPACE = PLUS(" " | "\n" | "\t") |
|
1003 |
//parentheses |
|
1004 |
val RPAREN: Rexp = ")" |
|
1005 |
val LPAREN: Rexp = "(" |
|
1006 |
val BEGIN: Rexp = "{" |
|
1007 |
val END: Rexp = "}" |
|
1008 |
//strings...but probably needs not |
|
1009 |
val STRING: Rexp = "\"" ~ SYM.% ~ "\"" |
|
1010 |
||
1011 |
||
1012 |
||
1013 |
val WHILE_REGS = (("k" $ KEYWORD) | |
|
1014 |
("i" $ ID) | |
|
1015 |
("o" $ OP) | |
|
1016 |
("n" $ NUM) | |
|
1017 |
("s" $ SEMI) | |
|
1018 |
("str" $ STRING) | |
|
1019 |
("p" $ (LPAREN | RPAREN)) | |
|
1020 |
("b" $ (BEGIN | END)) | |
|
1021 |
("w" $ WHITESPACE)).% |
|
1022 |
||
1023 |
val AWHILE_REGS = ( |
|
1024 |
ALTS( |
|
1025 |
List( |
|
1026 |
("k" $ AKEYWORD), |
|
1027 |
("i" $ ID), |
|
1028 |
("o" $ AOP) , |
|
1029 |
("n" $ NUM) , |
|
1030 |
("s" $ SEMI) , |
|
1031 |
("str" $ STRING), |
|
1032 |
("p" $ (LPAREN | RPAREN)), |
|
1033 |
("b" $ (BEGIN | END)), |
|
1034 |
("w" $ WHITESPACE) |
|
1035 |
) |
|
1036 |
) |
|
1037 |
).% |
|
1038 |
||
1039 |
*/ |
|
1040 |
||
1041 |
||
1042 |
//--------------------------------------------------------------------------------------------------------START OF NON-BITCODE PART (TESTING) |
|
1043 |
/* |
|
1044 |
// Two Simple While programs |
|
1045 |
//======================== |
|
1046 |
println("prog0 test") |
|
1047 |
||
1048 |
val prog0 = """read n""" |
|
1049 |
println(env(lexing_simp(WHILE_REGS, prog0))) |
|
1050 |
println(tokenise(WHILE_REGS, prog0)) |
|
1051 |
||
1052 |
println("prog1 test") |
|
1053 |
||
1054 |
val prog1 = """read n; write (n)""" |
|
1055 |
println(tokenise(WHILE_REGS, prog1)) |
|
1056 |
||
1057 |
*/ |
|
1058 |
// Bigger Tests |
|
1059 |
//============== |
|
1060 |
||
1061 |
def escape(raw: String): String = { |
|
1062 |
import scala.reflect.runtime.universe._ |
|
1063 |
Literal(Constant(raw)).toString |
|
1064 |
} |
|
1065 |
||
1066 |
val prog2 = """ |
|
1067 |
write "Fib"; |
|
1068 |
read n; |
|
1069 |
minus1 := 0; |
|
1070 |
minus2 := 1; |
|
1071 |
while n > 0 do { |
|
1072 |
temp := minus2; |
|
1073 |
minus2 := minus1 + minus2; |
|
1074 |
minus1 := temp; |
|
1075 |
n := n - 1 |
|
1076 |
}; |
|
1077 |
write "Result"; |
|
1078 |
write minus2 |
|
1079 |
""" |
|
1080 |
||
1081 |
val prog3 = """ |
|
1082 |
start := 1000; |
|
1083 |
x := start; |
|
1084 |
y := start; |
|
1085 |
z := start; |
|
1086 |
while 0 < x do { |
|
1087 |
while 0 < y do { |
|
1088 |
while 0 < z do { |
|
1089 |
z := z - 1 |
|
1090 |
}; |
|
1091 |
z := start; |
|
1092 |
y := y - 1 |
|
1093 |
}; |
|
1094 |
y := start; |
|
1095 |
x := x - 1 |
|
1096 |
} |
|
1097 |
""" |
|
1098 |
/* |
|
1099 |
for(i <- 400 to 400 by 1){ |
|
1100 |
println(i+":") |
|
1101 |
blexing_simp(WHILE_REGS, prog2 * i) |
|
1102 |
} */ |
|
1103 |
||
1104 |
/* |
|
1105 |
for (i <- 2 to 5){ |
|
1106 |
for(j <- 1 to 3){ |
|
1107 |
println(i,j) |
|
1108 |
small_de = i |
|
1109 |
usual_de = i + j |
|
1110 |
big_de = i + 2*j |
|
1111 |
blexing_simp(AWHILE_REGS, prog2 * 100) |
|
1112 |
} |
|
1113 |
}*/ |
|
1114 |
||
1115 |
/* |
|
1116 |
println("Tokens of prog2") |
|
1117 |
println(tokenise(WHILE_REGS, prog2).mkString("\n")) |
|
1118 |
||
1119 |
val fib_tokens = tokenise(WHILE_REGS, prog2) |
|
1120 |
fib_tokens.map{case (s1, s2) => (escape(s1), escape(s2))}.mkString(",\n") |
|
1121 |
||
1122 |
||
1123 |
val test_tokens = tokenise(WHILE_REGS, prog3) |
|
1124 |
test_tokens.map{case (s1, s2) => (escape(s1), escape(s2))}.mkString(",\n") |
|
1125 |
*/ |
|
1126 |
||
1127 |
/* |
|
1128 |
println("time test for blexing_simp") |
|
1129 |
for (i <- 1 to 1 by 1) { |
|
1130 |
lexing_simp(WHILE_REGS, prog2 * i) |
|
1131 |
blexing_simp(WHILE_REGS, prog2 * i) |
|
1132 |
for( j <- 0 to each_simp_timeb.length - 1){ |
|
1133 |
if( each_simp_timeb(j)/each_simp_time(j) >= 10.0 ) |
|
1134 |
println(j, each_simp_timeb(j), each_simp_time(j)) |
|
1135 |
} |
|
1136 |
} |
|
1137 |
*/ |
|
1138 |
||
1139 |
||
1140 |
//--------------------------------------------------------------------------------------------------------END OF NON-BITCODE PART (TESTING) |
|
1141 |
||
1142 |
||
1143 |
||
1144 |
def clear() = { |
|
1145 |
print("") |
|
1146 |
//print("\33[H\33[2J") |
|
1147 |
} |
|
1148 |
||
1149 |
//testing the two lexings produce the same value |
|
1150 |
//enumerates strings of length n over alphabet cs |
|
1151 |
def strs(n: Int, cs: String) : Set[String] = { |
|
1152 |
if (n == 0) Set("") |
|
1153 |
else { |
|
1154 |
val ss = strs(n - 1, cs) |
|
1155 |
ss ++ |
|
1156 |
(for (s <- ss; c <- cs.toList) yield c + s) |
|
1157 |
} |
|
1158 |
} |
|
1159 |
def enum(n: Int, s: String) : Stream[Rexp] = n match { |
|
1160 |
case 0 => ZERO #:: ONE #:: s.toStream.map(CHAR) |
|
1161 |
case n => { |
|
1162 |
val rs = enum(n - 1, s) |
|
1163 |
rs #::: |
|
1164 |
(for (r1 <- rs; r2 <- rs) yield ALT(r1, r2)) #::: |
|
1165 |
(for (r1 <- rs; r2 <- rs) yield SEQ(r1, r2)) #::: |
|
1166 |
(for (r1 <- rs) yield STAR(r1)) |
|
1167 |
} |
|
1168 |
} |
|
1169 |
||
1170 |
//tests blexing and lexing |
|
1171 |
def tests_blexer_simp(ss: Set[String])(r: Rexp) = { |
|
1172 |
clear() |
|
1173 |
//println(s"Testing ${r}") |
|
1174 |
for (s <- ss.par) yield { |
|
1175 |
val res1 = Try(Some(lexing_simp(r, s))).getOrElse(None) |
|
5 | 1176 |
val res2 = Try(Some(super_blexing_simp(r, s))).getOrElse(None) |
0 | 1177 |
if (res1 != res2) println(s"Disagree on ${r} and ${s}") |
1178 |
if (res1 != res2) println(s" ${res1} != ${res2}") |
|
1179 |
if (res1 != res2) Some((r, s)) else None |
|
1180 |
} |
|
1181 |
} |
|
1182 |
||
1183 |
||
1184 |
||
5 | 1185 |
|
0 | 1186 |
/* |
1187 |
def single_expression_explorer(ar: ARexp, ss: Set[String]): Unit = { |
|
1188 |
for (s <- ss){ |
|
1189 |
||
1190 |
val der_res = bder(c, ar) |
|
1191 |
val simp_res = bsimp(der_res) |
|
1192 |
println(asize(der_res)) |
|
1193 |
println(asize(simp_res)) |
|
1194 |
single_expression_explorer(simp_res, (sc - c)) |
|
1195 |
} |
|
1196 |
}*/ |
|
1197 |
||
1198 |
//single_expression_explorer(internalise(("c"~("a"+"b"))%) , Set('a','b','c')) |
|
1199 |
||
1200 |
||
1201 |
} |
|
1202 |
||
1203 |
import Rexp.Bits |
|
1204 |
abstract class ARexp |
|
1205 |
case object AZERO extends ARexp |
|
1206 |
case class AONE(bs: Bits) extends ARexp |
|
1207 |
case class ACHAR(bs: Bits, f: Char) extends ARexp |
|
1208 |
case class AALTS(bs: Bits, rs: List[ARexp]) extends ARexp |
|
1209 |
case class ASEQ(bs: Bits, r1: ARexp, r2: ARexp) extends ARexp |
|
1210 |
case class ASTAR(bs: Bits, r: ARexp) extends ARexp |
|
1211 |
||
1212 |
||
1213 |
||
1214 |
abstract class Val |
|
1215 |
case object Empty extends Val |
|
1216 |
case class Chr(c: Char) extends Val |
|
1217 |
case class Sequ(v1: Val, v2: Val) extends Val |
|
1218 |
case class Left(v: Val) extends Val |
|
1219 |
case class Right(v: Val) extends Val |
|
1220 |
case class Stars(vs: List[Val]) extends Val |
|
1221 |
case class Rec(x: String, v: Val) extends Val |
|
17 | 1222 |
case object undefined extends Val |
0 | 1223 |
//case class Pos(i: Int, v: Val) extends Val |
1224 |
case object Prd extends Val |