@@ -75,23 +75,23 @@ export function concat(left: ExtRegex, right: ExtRegex): ExtRegex {
75
75
if ( equal ( empty , left ) )
76
76
// ∅ · r ≈ ∅
77
77
return empty
78
- else if ( equal ( empty , right ) )
78
+ if ( equal ( empty , right ) )
79
79
// r · ∅ ≈ ∅
80
80
return empty
81
- else if ( left . type === "concat" )
81
+ if ( left . type === "concat" )
82
82
// (r · s) · t ≈ r · (s · t)
83
83
return concat ( left . left , concat ( left . right , right ) )
84
- else if ( left . type === "epsilon" )
84
+ if ( left . type === "epsilon" )
85
85
// ε · r ≈ r
86
86
return right
87
- else if ( right . type === "epsilon" )
87
+ if ( right . type === "epsilon" )
88
88
// r · ε ≈ r
89
89
return left
90
- else if ( left . type === 'union' && equal ( left . right , epsilon ) ) {
90
+ if ( left . type === 'union' && equal ( left . right , epsilon ) ) {
91
91
if ( equal ( left . left , right ) )
92
92
// (r + ε) · r ≈ r · (r + ε)
93
93
return concat ( right , left )
94
- else if ( right . type === 'concat' && equal ( left . left , right . left ) )
94
+ if ( right . type === 'concat' && equal ( left . left , right . left ) )
95
95
// (r + ε) · (r · s) ≈ r · ((r + ε) · s)
96
96
return concat ( right . left , concat ( left , right . right ) )
97
97
}
@@ -102,78 +102,116 @@ export function concat(left: ExtRegex, right: ExtRegex): ExtRegex {
102
102
if ( equal ( left . inner , right ) )
103
103
// r* · r ≈ r · r*
104
104
return concat ( right , left )
105
- else if ( right . type === 'concat' && equal ( left . inner , right . left ) )
105
+ if ( right . type === 'concat' && equal ( left . inner , right . left ) )
106
106
// r* · (r · s) ≈ r · (r* · s)
107
107
return concat ( left . inner , concat ( left , right . right ) )
108
- else if ( right . type === 'star' && equal ( left . inner , right . inner ) )
108
+ if ( right . type === 'star' && equal ( left . inner , right . inner ) )
109
109
// r* · r* ≈ r*
110
110
return left
111
- else if ( right . type === 'concat' && right . left . type === 'star' && equal ( left , right . left ) )
111
+ if ( right . type === 'concat' && right . left . type === 'star' && equal ( left , right . left ) )
112
112
// r* · (r* · s) ≈ r* · s
113
113
return concat ( left , right . right )
114
114
}
115
115
116
116
return withHash ( { type : 'concat' , left, right } )
117
117
}
118
118
119
+ function extractFront ( regex : StdRegex ) : [ StdRegex , StdRegex ]
120
+ function extractFront ( regex : ExtRegex ) : [ ExtRegex , ExtRegex ]
121
+ function extractFront ( regex : ExtRegex ) : [ ExtRegex , ExtRegex ] {
122
+ switch ( regex . type ) {
123
+ case 'epsilon' : return [ regex , epsilon ]
124
+ case 'literal' : return [ regex , epsilon ]
125
+ case 'concat' : return [ regex . left , regex . right ]
126
+ case 'union' : return [ regex , epsilon ]
127
+ case 'star' : return [ regex . inner , regex ]
128
+ case 'intersection' : return [ regex , epsilon ]
129
+ case 'complement' : return [ regex , epsilon ]
130
+ }
131
+ checkedAllCases ( regex )
132
+ }
133
+
134
+ function extractBack ( regex : StdRegex ) : [ StdRegex , StdRegex ]
135
+ function extractBack ( regex : ExtRegex ) : [ ExtRegex , ExtRegex ]
136
+ function extractBack ( regex : ExtRegex ) : [ ExtRegex , ExtRegex ] {
137
+ switch ( regex . type ) {
138
+ case 'epsilon' : return [ epsilon , epsilon ]
139
+ case 'literal' : return [ epsilon , regex ]
140
+ case 'concat' : return [ regex . left , regex . right ]
141
+ case 'union' : return [ epsilon , regex ]
142
+ case 'star' : return [ regex , regex . inner ]
143
+ case 'intersection' : return [ epsilon , regex ]
144
+ case 'complement' : return [ epsilon , regex ]
145
+ }
146
+ checkedAllCases ( regex )
147
+ }
148
+
119
149
export function union ( left : StdRegex , right : StdRegex ) : StdRegex
120
150
export function union ( left : ExtRegex , right : ExtRegex ) : ExtRegex
121
151
export function union ( left : ExtRegex , right : ExtRegex ) : ExtRegex {
122
152
if ( left . type === 'union' )
123
153
// (r + s) + t ≈ r + (s + t)
124
154
return union ( left . left , union ( left . right , right ) )
125
- else if ( equal ( left , right ) )
155
+ if ( equal ( left , right ) )
126
156
// r + r ≈ r
127
157
return left
128
- else if ( equal ( left , empty ) )
158
+ if ( equal ( left , empty ) )
129
159
// ∅ + r ≈ r
130
160
return right
131
- else if ( left . type === 'epsilon' )
161
+ if ( left . type === 'epsilon' )
132
162
// ε + r ≈ r + ε
133
163
return union ( right , left )
134
- else if ( equal ( empty , right ) )
164
+ if ( equal ( empty , right ) )
135
165
// r + ∅ ≈ r
136
166
return left
137
- else if ( equal ( left , complement ( empty ) ) )
167
+ if ( equal ( left , complement ( empty ) ) )
138
168
// ¬∅ + r ≈ ¬∅
139
169
return complement ( empty )
140
- else if ( equal ( complement ( empty ) , right ) )
170
+ if ( equal ( complement ( empty ) , right ) )
141
171
// r + ¬∅ ≈ ¬∅
142
172
return complement ( empty )
143
- else if ( left . type === 'literal' && right . type === 'literal' )
173
+ if ( left . type === 'literal' && right . type === 'literal' )
144
174
// R + S ≈ R ∪ S
145
175
return literal ( CharSet . union ( left . charset , right . charset ) )
146
- else if ( right . type === 'union' && equal ( left , right . left ) )
147
- // r + (r + s) = r + s
148
- return union ( left , right . right )
149
- else if ( right . type === 'union' && equal ( left , right . right ) )
150
- // r + (s + r) = r + s
151
- return union ( left , right . left )
152
-
153
- else if ( left . type === 'concat' ) {
154
- if ( right . type === 'concat' ) {
155
- if ( equal ( left . left , right . left ) )
156
- // (r · s) + (r · t) = r · (s + t)
157
- return concat ( left . left , union ( left . right , right . right ) )
158
- else if ( equal ( left . right , right . right ) )
159
- // (s · r) + (t · r) = (s + t) · r
160
- return concat ( union ( left . left , right . left ) , left . right )
161
- } else if ( equal ( left . left , right ) ) {
162
- // (r · s) + r = r · (s + ε)
163
- return concat ( left . left , optional ( left . right ) )
164
- } else if ( equal ( right , left . right ) ) {
165
- // (s · r) + r = (s + ε) · r
166
- return concat ( optional ( left . left ) , left . right )
167
- }
168
- } else if ( right . type === 'concat' ) {
169
- if ( equal ( right . left , left ) )
170
- // r + (r · s) = r · (ε + s)
171
- return concat ( right . left , optional ( right . right ) )
172
- else if ( right . right . hash === left . hash )
173
- // r + (s · r) = (s + ε) · r
174
- return concat ( optional ( right . left ) , right . right )
176
+ if ( left . type === 'star' && right . type === 'epsilon' )
177
+ // r* + ε = r*
178
+ return left
179
+
180
+ if ( right . type == 'union' ) {
181
+ if ( equal ( left , right . left ) )
182
+ // r + (r + s) = r + s
183
+ return union ( left , right . right )
184
+ if ( equal ( left , right . right ) )
185
+ // r + (s + r) = r + s
186
+ return union ( left , right . left )
187
+
188
+ // const [leftHead, leftTail] = extractFront(left)
189
+ // const [rightHead, rightTail] = extractFront(right.left)
190
+ // if (equal(leftHead, rightHead))
191
+ // // (r · s) + ((r · t) + u) = (r · (s + t)) + u
192
+ // return union(concat(left, union(leftTail, rightTail)), right.right)
193
+ // // return concat(left, optional(union(leftTail, right.right)))
175
194
}
176
195
196
+ const [ leftHead , leftTail ] = extractFront ( left )
197
+ const [ rightHead , rightTail ] = extractFront ( right )
198
+
199
+ if ( equal ( leftHead , rightHead ) )
200
+ // (r · s) + (r · t) = r · (s + t)
201
+ // (r · s) + r = r · (s + ε)
202
+ // r + (r · s) = r · (ε + s)
203
+ // r + r* = r · (ε + r*)
204
+ return concat ( leftHead , union ( leftTail , rightTail ) )
205
+
206
+ const [ leftInit , leftLast ] = extractBack ( left )
207
+ const [ rightInit , rightLast ] = extractBack ( right )
208
+
209
+ if ( equal ( leftLast , rightLast ) )
210
+ // (s · r) + (t · r) = (s + t) · r
211
+ // (s · r) + r = (s + ε) · r
212
+ // r + (s · r) = (s + ε) · r
213
+ return concat ( union ( leftInit , rightInit ) , leftLast )
214
+
177
215
return withHash ( { type : 'union' , left, right } )
178
216
}
179
217
@@ -189,6 +227,9 @@ export function star(inner: ExtRegex): ExtRegex {
189
227
else if ( equal ( empty , inner ) )
190
228
// ∅∗ ≈ ε
191
229
return epsilon
230
+ else if ( inner . type === 'concat' && inner . left . type === 'star' && inner . right . type === 'star' )
231
+ // (r∗ · s∗)∗ = (r + s)∗
232
+ return star ( union ( inner . left . inner , inner . right . inner ) )
192
233
else
193
234
return withHash ( { type : "star" , inner } )
194
235
}
0 commit comments