author | Jan Vrany <jan.vrany@fit.cvut.cz> |
Fri, 03 Oct 2014 02:45:16 +0100 | |
changeset 378 | 53d66ecfeb1b |
parent 376 | a2656b27cace |
child 381 | 0bbbcf5da2d4 |
permissions | -rw-r--r-- |
262 | 1 |
"{ Package: 'stx:goodies/petitparser/analyzer' }"! |
2 |
||
3 |
!PPActionParser methodsFor:'*petitanalyzer-matching'! |
|
4 |
||
5 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
6 |
^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self block = aParser block ] |
|
7 |
! ! |
|
8 |
||
9 |
!PPDelegateParser methodsFor:'*petitanalyzer-transforming'! |
|
10 |
||
11 |
replace: aParser with: anotherParser |
|
12 |
super replace: aParser with: anotherParser. |
|
13 |
parser == aParser ifTrue: [ parser := anotherParser ] |
|
14 |
! ! |
|
15 |
||
16 |
!PPEpsilonParser methodsFor:'*petitanalyzer-testing'! |
|
17 |
||
18 |
isNullable |
|
19 |
^ true |
|
20 |
! ! |
|
21 |
||
22 |
!PPFailingParser methodsFor:'*petitanalyzer-matching'! |
|
23 |
||
24 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
25 |
^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self message = aParser message ] |
|
26 |
! ! |
|
27 |
||
28 |
!PPLimitedRepeatingParser methodsFor:'*petitanalyzer-transforming'! |
|
29 |
||
378
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
30 |
replace: aParser with: anotherParser |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
31 |
super replace: aParser with: anotherParser. |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
32 |
limit == aParser ifTrue: [ limit := anotherParser ] |
262 | 33 |
! ! |
34 |
||
35 |
!PPListParser methodsFor:'*petitanalyzer-matching'! |
|
36 |
||
37 |
copyInContext: aDictionary seen: aSeenDictionary |
|
38 |
| copy copies | |
|
39 |
aSeenDictionary at: self ifPresent: [ :value | ^ value ]. |
|
40 |
copy := aSeenDictionary at: self put: self copy. |
|
41 |
copies := OrderedCollection new. |
|
42 |
parsers do: [ :each | |
|
43 |
| result | |
|
44 |
result := each |
|
45 |
copyInContext: aDictionary |
|
46 |
seen: aSeenDictionary. |
|
47 |
result isCollection |
|
48 |
ifTrue: [ copies addAll: result ] |
|
49 |
ifFalse: [ copies add: result ] ]. |
|
50 |
^ copy |
|
51 |
setParsers: copies; |
|
52 |
yourself |
|
53 |
! ! |
|
54 |
||
55 |
!PPListParser methodsFor:'*petitanalyzer-transforming'! |
|
56 |
||
57 |
replace: aParser with: anotherParser |
|
58 |
super replace: aParser with: anotherParser. |
|
59 |
parsers keysAndValuesDo: [ :index :parser | |
|
60 |
parser == aParser |
|
61 |
ifTrue: [ parsers at: index put: anotherParser ] ] |
|
62 |
! ! |
|
63 |
||
64 |
!PPLiteralParser methodsFor:'*petitanalyzer-matching'! |
|
65 |
||
66 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
67 |
^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self literal = aParser literal and: [ self message = aParser message ] ] |
|
68 |
! ! |
|
69 |
||
378
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
70 |
!PPNotParser methodsFor:'*petitanalyzer-private'! |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
71 |
|
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
72 |
firstSets: aFirstDictionary into: aSet |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
73 |
|
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
74 |
! ! |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
75 |
|
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
76 |
!PPNotParser methodsFor:'*petitanalyzer-testing'! |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
77 |
|
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
78 |
isFirstSetTerminal |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
79 |
^ true |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
80 |
! ! |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
81 |
|
262 | 82 |
!PPOptionalParser methodsFor:'*petitanalyzer-testing'! |
83 |
||
84 |
isNullable |
|
85 |
^ true |
|
86 |
! ! |
|
87 |
||
88 |
!PPParser methodsFor:'*petitanalyzer-named'! |
|
89 |
||
90 |
allNamedParsers |
|
91 |
"Answer all the named parse nodes of the receiver." |
|
92 |
||
93 |
| result | |
|
94 |
result := OrderedCollection new. |
|
95 |
self allNamedParsersDo: [ :parser | result addLast: parser ]. |
|
96 |
^ result |
|
97 |
! ! |
|
98 |
||
99 |
!PPParser methodsFor:'*petitanalyzer-named'! |
|
100 |
||
101 |
allNamedParsersDo: aBlock |
|
102 |
"Iterate over all the named parse nodes of the receiver." |
|
103 |
||
104 |
self allParsersDo: [ :each | |
|
105 |
each name notNil |
|
106 |
ifTrue: [ aBlock value: each ] ] |
|
107 |
! ! |
|
108 |
||
109 |
!PPParser methodsFor:'*petitanalyzer-enumerating'! |
|
110 |
||
111 |
allParsers |
|
112 |
"Answer all the parse nodes of the receiver." |
|
113 |
||
114 |
| result | |
|
115 |
result := OrderedCollection new. |
|
116 |
self allParsersDo: [ :parser | result addLast: parser ]. |
|
117 |
^ result |
|
118 |
! ! |
|
119 |
||
120 |
!PPParser methodsFor:'*petitanalyzer-enumerating'! |
|
121 |
||
122 |
allParsersDo: aBlock |
|
123 |
"Iterate over all the parse nodes of the receiver." |
|
124 |
||
125 |
self allParsersDo: aBlock seen: IdentitySet new |
|
126 |
! ! |
|
127 |
||
128 |
!PPParser methodsFor:'*petitanalyzer-enumerating'! |
|
129 |
||
130 |
allParsersDo: aBlock seen: aSet |
|
131 |
"Iterate over all the parse nodes of the receiver, do not visit and follow the ones contained in aSet." |
|
132 |
||
133 |
(aSet includes: self) |
|
134 |
ifTrue: [ ^ self ]. |
|
135 |
aSet add: self. |
|
136 |
aBlock value: self. |
|
137 |
self children |
|
138 |
do: [ :each | each allParsersDo: aBlock seen: aSet ] |
|
139 |
! ! |
|
140 |
||
141 |
!PPParser methodsFor:'*petitanalyzer-matching'! |
|
142 |
||
143 |
copyInContext: aDictionary |
|
144 |
^ self copyInContext: aDictionary seen: IdentityDictionary new |
|
145 |
! ! |
|
146 |
||
147 |
!PPParser methodsFor:'*petitanalyzer-matching'! |
|
148 |
||
149 |
copyInContext: aDictionary seen: aSeenDictionary |
|
150 |
| copy | |
|
151 |
aSeenDictionary |
|
152 |
at: self |
|
153 |
ifPresent: [ :value | ^ value ]. |
|
154 |
copy := aSeenDictionary |
|
155 |
at: self |
|
156 |
put: self copy. |
|
157 |
copy children do: [ :each | |
|
158 |
copy |
|
159 |
replace: each |
|
160 |
with: (each copyInContext: aDictionary seen: aSeenDictionary) ]. |
|
161 |
^ copy |
|
162 |
! ! |
|
163 |
||
164 |
!PPParser methodsFor:'*petitanalyzer-querying'! |
|
165 |
||
166 |
cycleSet |
|
167 |
"Answer a set of all nodes that are within one or more cycles of left-recursion. This is generally not a problem if at least one of the nodes is memoized, but it might make the grammar very inefficient and should be avoided if possible." |
|
168 |
||
169 |
| cycles | |
|
170 |
cycles := IdentitySet new. |
|
171 |
self cycleSet: OrderedCollection new firstSets: self firstSets into: cycles. |
|
172 |
^ cycles |
|
173 |
! ! |
|
174 |
||
175 |
!PPParser methodsFor:'*petitanalyzer-private'! |
|
176 |
||
177 |
cycleSet: aDictionary |
|
178 |
"PRIVATE: Answer the children that could be part of a cycle-set with the receiver, subclasses might restrict the number of children returned. aDictionary is pre-calcualted first-sets." |
|
179 |
||
180 |
^ self children |
|
181 |
! ! |
|
182 |
||
183 |
!PPParser methodsFor:'*petitanalyzer-private'! |
|
184 |
||
185 |
cycleSet: aStack firstSets: aDictionary into: aSet |
|
186 |
"PRIVATE: Try to find a cycle, where aStack contains the previously visited parsers. The method returns quickly when the receiver is a terminal, terminals cannot be part of a cycle. If aStack already contains the receiver, then we are in a cycle. In this case we don't process the children further and add the nodes to aSet." |
|
187 |
||
188 |
| index | |
|
189 |
self isTerminal |
|
190 |
ifTrue: [ ^ self ]. |
|
191 |
(index := aStack indexOf: self) > 0 |
|
192 |
ifTrue: [ ^ aSet addAll: (aStack copyFrom: index to: aStack size) ]. |
|
193 |
aStack addLast: self. |
|
194 |
(self cycleSet: aDictionary) |
|
195 |
do: [ :each | each cycleSet: aStack firstSets: aDictionary into: aSet ]. |
|
196 |
aStack removeLast |
|
197 |
! ! |
|
198 |
||
199 |
!PPParser methodsFor:'*petitanalyzer-querying'! |
|
200 |
||
201 |
firstSet |
|
202 |
"Answer the first-set of the receiver. Note, this implementation is inefficient when called on different receivers of the same grammar, instead use #firstSets to calculate the first-sets at once." |
|
203 |
||
204 |
^ self firstSets at: self |
|
205 |
! ! |
|
206 |
||
207 |
!PPParser methodsFor:'*petitanalyzer-querying'! |
|
208 |
||
209 |
firstSets |
|
210 |
"Answer a dictionary with all the parsers reachable from the receiver as key and their first-set as value. The first-set of a parser is the list of terminal parsers that begin the parser derivable from that parser." |
|
211 |
||
212 |
| firstSets | |
|
213 |
firstSets := IdentityDictionary new. |
|
214 |
self allParsersDo: [ :each | |
|
378
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
215 |
firstSets at: each put: (each isFirstSetTerminal |
262 | 216 |
ifTrue: [ IdentitySet with: each ] |
217 |
ifFalse: [ IdentitySet new ]). |
|
218 |
each isNullable |
|
219 |
ifTrue: [ (firstSets at: each) add: PPSentinel instance ] ]. |
|
220 |
[ | changed tally | |
|
221 |
changed := false. |
|
222 |
firstSets keysAndValuesDo: [ :parser :first | |
|
223 |
tally := first size. |
|
224 |
parser firstSets: firstSets into: first. |
|
225 |
changed := changed or: [ tally ~= first size ] ]. |
|
226 |
changed ] whileTrue. |
|
227 |
^ firstSets |
|
228 |
! ! |
|
229 |
||
230 |
!PPParser methodsFor:'*petitanalyzer-private'! |
|
231 |
||
232 |
firstSets: aFirstDictionary into: aSet |
|
233 |
"PRIVATE: Try to add additional elements to the first-set aSet of the receiver, use the incomplete aFirstDictionary." |
|
234 |
||
235 |
self children do: [ :parser | aSet addAll: (aFirstDictionary at: parser) ] |
|
236 |
! ! |
|
237 |
||
238 |
!PPParser methodsFor:'*petitanalyzer-querying'! |
|
239 |
||
240 |
followSet |
|
241 |
"Answer the follow-set of the receiver starting at the receiver. Note, this implementation is inefficient when called on different receivers of the same grammar, instead use #followSets to calculate the follow-sets at once." |
|
242 |
||
243 |
^ self followSets at: self |
|
244 |
! ! |
|
245 |
||
246 |
!PPParser methodsFor:'*petitanalyzer-querying'! |
|
247 |
||
248 |
followSets |
|
249 |
"Answer a dictionary with all the parsers reachable from the receiver as key and their follow-set as value. The follow-set of a parser is the list of terminal parsers that can appear immediately to the right of that parser." |
|
250 |
||
251 |
| current previous continue firstSets followSets | |
|
252 |
current := previous := 0. |
|
253 |
firstSets := self firstSets. |
|
254 |
followSets := IdentityDictionary new. |
|
255 |
self allParsersDo: [ :each | followSets at: each put: IdentitySet new ]. |
|
256 |
(followSets at: self) add: PPSentinel instance. |
|
257 |
[ followSets keysAndValuesDo: [ :parser :follow | |
|
258 |
parser |
|
259 |
followSets: followSets |
|
260 |
firstSets: firstSets |
|
261 |
into: follow ]. |
|
262 |
current := followSets |
|
263 |
inject: 0 |
|
264 |
into: [ :result :each | result + each size ]. |
|
265 |
continue := previous < current. |
|
266 |
previous := current. |
|
267 |
continue ] whileTrue. |
|
268 |
^ followSets |
|
269 |
! ! |
|
270 |
||
271 |
!PPParser methodsFor:'*petitanalyzer-private'! |
|
272 |
||
273 |
followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet |
|
274 |
"PRIVATE: Try to add additional elements to the follow-set aSet of the receiver, use the incomplete aFollowDictionary and the complete aFirstDictionary." |
|
275 |
||
276 |
self children do: [ :parser | (aFollowDictionary at: parser) addAll: aSet ] |
|
277 |
! ! |
|
278 |
||
279 |
!PPParser methodsFor:'*petitanalyzer-named'! |
|
280 |
||
281 |
innerChildren |
|
282 |
"Answer the inner children of the receiver." |
|
283 |
||
284 |
| result | |
|
285 |
result := OrderedCollection new. |
|
286 |
self innerChildrenDo: [ :parser | result addLast: parser ]. |
|
287 |
^ result |
|
288 |
! ! |
|
289 |
||
290 |
!PPParser methodsFor:'*petitanalyzer-named'! |
|
291 |
||
292 |
innerChildrenDo: aBlock |
|
293 |
"Iterate over the inner children of the receiver." |
|
294 |
||
295 |
self innerChildrenDo: aBlock seen: IdentitySet new |
|
296 |
! ! |
|
297 |
||
298 |
!PPParser methodsFor:'*petitanalyzer-named'! |
|
299 |
||
300 |
innerChildrenDo: aBlock seen: aSet |
|
301 |
"Iterate over the inner children of the receiver." |
|
302 |
||
303 |
self children do: [ :each | |
|
304 |
(aSet includes: each) |
|
305 |
ifTrue: [ ^ self ]. |
|
306 |
aSet add: each. |
|
307 |
each name isNil ifTrue: [ |
|
308 |
aBlock value: each. |
|
309 |
each innerChildrenDo: aBlock seen: aSet ] ] |
|
310 |
! ! |
|
311 |
||
312 |
!PPParser methodsFor:'*petitanalyzer-testing'! |
|
313 |
||
378
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
314 |
isFirstSetTerminal |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
315 |
"Answer true if the receiver is a terminal or leaf parser, that means it does not delegate to any other parser." |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
316 |
|
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
317 |
^ self children isEmpty |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
318 |
! ! |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
319 |
|
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
320 |
!PPParser methodsFor:'*petitanalyzer-testing'! |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
321 |
|
262 | 322 |
isNullable |
323 |
"Answer true if the receiver is a nullable parser, e.g. it can successfully parse nothing." |
|
324 |
||
325 |
^ false |
|
326 |
! ! |
|
327 |
||
328 |
!PPParser methodsFor:'*petitanalyzer-testing'! |
|
329 |
||
330 |
isTerminal |
|
331 |
"Answer true if the receiver is a terminal or leaf parser, that means it does not delegate to any other parser." |
|
332 |
||
333 |
^ self children isEmpty |
|
334 |
! ! |
|
335 |
||
336 |
!PPParser methodsFor:'*petitanalyzer-matching'! |
|
337 |
||
338 |
match: aParser inContext: aDictionary |
|
339 |
^ self match: aParser inContext: aDictionary seen: IdentitySet new |
|
340 |
! ! |
|
341 |
||
342 |
!PPParser methodsFor:'*petitanalyzer-matching'! |
|
343 |
||
344 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
345 |
"This is the default implementation to match two parsers. This code can properly handle recursion. This is code is supposed to be overridden in subclasses that add new state." |
|
346 |
||
347 |
(self == aParser or: [ anIdentitySet includes: self ]) |
|
348 |
ifTrue: [ ^ true ]. |
|
349 |
anIdentitySet add: self. |
|
350 |
^ self class = aParser class and: [ self matchList: self children against: aParser children inContext: aDictionary seen: anIdentitySet ] |
|
351 |
! ! |
|
352 |
||
353 |
!PPParser methodsFor:'*petitanalyzer-matching'! |
|
354 |
||
355 |
matchList: matchList against: parserList inContext: aDictionary seen: aSet |
|
356 |
^ self matchList: matchList index: 1 against: parserList index: 1 inContext: aDictionary seen: aSet |
|
357 |
! ! |
|
358 |
||
359 |
!PPParser methodsFor:'*petitanalyzer-matching'! |
|
360 |
||
361 |
matchList: matchList index: matchIndex against: parserList index: parserIndex inContext: aDictionary seen: aSet |
|
362 |
| parser currentIndex currentDictionary currentSeen parsers | |
|
363 |
matchList size < matchIndex |
|
364 |
ifTrue: [ ^ parserList size < parserIndex ]. |
|
365 |
parser := matchList at: matchIndex. |
|
366 |
parser class = PPListPattern ifTrue: [ |
|
367 |
currentIndex := parserIndex - 1. |
|
368 |
[ currentDictionary := aDictionary copy. |
|
369 |
currentSeen := aSet copy. |
|
370 |
parserList size < currentIndex or: [ |
|
371 |
parsers := parserList copyFrom: parserIndex to: currentIndex. |
|
372 |
(currentDictionary at: parser ifAbsentPut: [ parsers ]) = parsers and: [ |
|
373 |
(self |
|
374 |
matchList: matchList |
|
375 |
index: matchIndex + 1 |
|
376 |
against: parserList |
|
377 |
index: currentIndex + 1 |
|
378 |
inContext: currentDictionary |
|
379 |
seen: currentSeen) |
|
380 |
ifTrue: [ |
|
381 |
currentDictionary keysAndValuesDo: [ :key :value | aDictionary at: key put: value ]. |
|
382 |
^ true ]. |
|
383 |
false ] ] ] whileFalse: [ currentIndex := currentIndex + 1 ]. |
|
384 |
^ false ]. |
|
385 |
parserList size < parserIndex |
|
386 |
ifTrue: [ ^ false ]. |
|
387 |
(parser match: (parserList at: parserIndex) inContext: aDictionary seen: aSet) |
|
388 |
ifFalse: [ ^ false ]. |
|
389 |
^ self |
|
390 |
matchList: matchList |
|
391 |
index: matchIndex + 1 |
|
392 |
against: parserList |
|
393 |
index: parserIndex + 1 |
|
394 |
inContext: aDictionary |
|
395 |
seen: aSet |
|
396 |
! ! |
|
397 |
||
398 |
!PPParser methodsFor:'*petitanalyzer-named'! |
|
399 |
||
400 |
namedChildren |
|
401 |
"Answer the named children of the receiver." |
|
402 |
||
403 |
| result | |
|
404 |
result := OrderedCollection new. |
|
405 |
self namedChildrenDo: [ :parser | result addLast: parser ]. |
|
406 |
^ result |
|
407 |
! ! |
|
408 |
||
409 |
!PPParser methodsFor:'*petitanalyzer-named'! |
|
410 |
||
411 |
namedChildrenDo: aBlock |
|
412 |
"Iterate over the named children of the receiver." |
|
413 |
||
414 |
self namedChildrenDo: aBlock seen: IdentitySet new |
|
415 |
! ! |
|
416 |
||
417 |
!PPParser methodsFor:'*petitanalyzer-named'! |
|
418 |
||
419 |
namedChildrenDo: aBlock seen: aSet |
|
420 |
"Iterate over the named children of the receiver." |
|
421 |
||
422 |
self children do: [ :each | |
|
423 |
(aSet includes: each) |
|
424 |
ifTrue: [ ^ self ]. |
|
425 |
aSet add: each. |
|
426 |
each name isNil |
|
427 |
ifTrue: [ each namedChildrenDo: aBlock seen: aSet ] |
|
428 |
ifFalse: [ aBlock value: each ] ] |
|
429 |
! ! |
|
430 |
||
431 |
!PPParser methodsFor:'*petitanalyzer-transforming'! |
|
432 |
||
433 |
replace: aParser with: anotherParser |
|
434 |
"Replace the references of the receiver pointing to aParser with anotherParser." |
|
435 |
! ! |
|
436 |
||
437 |
!PPParser methodsFor:'*petitanalyzer-transforming'! |
|
438 |
||
439 |
transform: aBlock |
|
440 |
"Answer a copy of all parsers reachable from the receiver transformed using aBlock." |
|
441 |
||
442 |
| mapping root | |
|
443 |
mapping := IdentityDictionary new. |
|
444 |
self allParsersDo: [ :each | |
|
445 |
mapping |
|
446 |
at: each |
|
447 |
put: (aBlock value: each copy) ]. |
|
448 |
root := mapping at: self. |
|
449 |
[ | changed | |
|
450 |
changed := false. |
|
451 |
root allParsersDo: [ :each | |
|
452 |
each children do: [ :old | |
|
453 |
mapping at: old ifPresent: [ :new | |
|
454 |
each replace: old with: new. |
|
455 |
changed := true ] ] ]. |
|
456 |
changed ] whileTrue. |
|
457 |
^ root |
|
458 |
! ! |
|
459 |
||
460 |
!PPPluggableParser methodsFor:'*petitanalyzer-matching'! |
|
461 |
||
462 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
463 |
^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self block = aParser block ] |
|
464 |
! ! |
|
465 |
||
466 |
!PPPredicateParser methodsFor:'*petitanalyzer-matching'! |
|
467 |
||
468 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
469 |
^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self block = aParser block and: [ self message = aParser message ] ] |
|
470 |
! ! |
|
471 |
||
472 |
!PPPredicateSequenceParser methodsFor:'*petitanalyzer-matching'! |
|
473 |
||
474 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
475 |
^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self size = aParser size ] |
|
476 |
! ! |
|
477 |
||
378
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
478 |
!PPRepeatingParser methodsFor:'*petitanalyzer-private'! |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
479 |
|
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
480 |
followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
481 |
| firstSet | |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
482 |
super followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet. |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
483 |
|
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
484 |
firstSet := aFirstDictionary at: self. |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
485 |
self children do: [:p | (aFollowDictionary at: p) addAll: (firstSet reject: [:each | each isNullable]) ] |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
486 |
! ! |
53d66ecfeb1b
Merged in latest version from Moose repository
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
376
diff
changeset
|
487 |
|
262 | 488 |
!PPRepeatingParser methodsFor:'*petitanalyzer-testing'! |
489 |
||
490 |
isNullable |
|
491 |
^ min = 0 |
|
492 |
! ! |
|
493 |
||
494 |
!PPRepeatingParser methodsFor:'*petitanalyzer-matching'! |
|
495 |
||
496 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
497 |
^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self min = aParser min and: [ self max = aParser max ] ] |
|
498 |
! ! |
|
499 |
||
500 |
!PPSequenceParser methodsFor:'*petitanalyzer-private'! |
|
501 |
||
502 |
cycleSet: aDictionary |
|
503 |
| firstSet | |
|
504 |
1 to: parsers size do: [ :index | |
|
505 |
firstSet := aDictionary at: (parsers at: index). |
|
506 |
(firstSet anySatisfy: [ :each | each isNullable ]) |
|
507 |
ifFalse: [ ^ parsers copyFrom: 1 to: index ] ]. |
|
508 |
^ parsers |
|
509 |
! ! |
|
510 |
||
511 |
!PPSequenceParser methodsFor:'*petitanalyzer-private'! |
|
512 |
||
513 |
firstSets: aFirstDictionary into: aSet |
|
514 |
| nullable | |
|
515 |
parsers do: [ :parser | |
|
516 |
nullable := false. |
|
517 |
(aFirstDictionary at: parser) do: [ :each | |
|
518 |
each isNullable |
|
519 |
ifTrue: [ nullable := true ] |
|
520 |
ifFalse: [ aSet add: each ] ]. |
|
521 |
nullable |
|
522 |
ifFalse: [ ^ self ] ]. |
|
523 |
aSet add: PPSentinel instance |
|
524 |
! ! |
|
525 |
||
526 |
!PPSequenceParser methodsFor:'*petitanalyzer-private'! |
|
527 |
||
528 |
followSets: aFollowDictionary firstSets: aFirstDictionary into: aSet |
|
529 |
parsers keysAndValuesDo: [ :index :parser | |
|
530 |
| followSet firstSet | |
|
531 |
followSet := aFollowDictionary at: parser. |
|
532 |
index = parsers size |
|
533 |
ifTrue: [ followSet addAll: aSet ] |
|
534 |
ifFalse: [ |
|
535 |
(self class withAll: (parsers |
|
536 |
copyFrom: index + 1 to: parsers size)) |
|
537 |
firstSets: aFirstDictionary |
|
538 |
into: (firstSet := IdentitySet new). |
|
539 |
(firstSet anySatisfy: [ :each | each isNullable ]) |
|
540 |
ifTrue: [ followSet addAll: aSet ]. |
|
541 |
followSet addAll: (firstSet |
|
542 |
reject: [ :each | each isNullable ]) ] ] |
|
543 |
! ! |
|
544 |
||
545 |
!PPTokenParser methodsFor:'*petitanalyzer-matching'! |
|
546 |
||
547 |
match: aParser inContext: aDictionary seen: anIdentitySet |
|
548 |
^ (super match: aParser inContext: aDictionary seen: anIdentitySet) and: [ self tokenClass = aParser tokenClass ] |
|
549 |
! ! |
|
550 |
||
551 |
!stx_goodies_petitparser_analyzer class methodsFor:'documentation'! |
|
552 |
||
376
a2656b27cace
Added monticelloName to package definition to ease export to .mcz
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
284
diff
changeset
|
553 |
extensionsVersion_HG |
a2656b27cace
Added monticelloName to package definition to ease export to .mcz
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
284
diff
changeset
|
554 |
|
a2656b27cace
Added monticelloName to package definition to ease export to .mcz
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
284
diff
changeset
|
555 |
^ '$Changeset: <not expanded> $' |
262 | 556 |
! ! |