166 lines
4.4 KiB
Smalltalk
166 lines
4.4 KiB
Smalltalk
|
Class {
|
||
|
#name : 'PEGFsaAbstractDeterminizator',
|
||
|
#superclass : 'Object',
|
||
|
#instVars : [
|
||
|
'fsa',
|
||
|
'joinDictionary'
|
||
|
],
|
||
|
#category : 'PetitCompiler-FSA'
|
||
|
}
|
||
|
|
||
|
{ #category : 'as yet unclassified' }
|
||
|
PEGFsaAbstractDeterminizator class >> new [
|
||
|
^ self basicNew initialize
|
||
|
]
|
||
|
|
||
|
{ #category : 'determinization' }
|
||
|
PEGFsaAbstractDeterminizator >> determinize [
|
||
|
| states |
|
||
|
" fsa checkSanity."
|
||
|
fsa removeEpsilons.
|
||
|
fsa removeUnreachableStates.
|
||
|
fsa mergeTransitions.
|
||
|
|
||
|
states := fsa topologicalOrder asOrderedCollection.
|
||
|
states do: [ :state |
|
||
|
self determinizeState: state
|
||
|
].
|
||
|
|
||
|
fsa states: fsa startState reachableStates.
|
||
|
|
||
|
fsa removeUnreachableStates.
|
||
|
fsa mergeTransitions.
|
||
|
]
|
||
|
|
||
|
{ #category : 'determinization' }
|
||
|
PEGFsaAbstractDeterminizator >> determinize: anFsa [
|
||
|
fsa := anFsa.
|
||
|
joinDictionary := Dictionary new.
|
||
|
|
||
|
self determinize.
|
||
|
^ fsa
|
||
|
]
|
||
|
|
||
|
{ #category : 'determinization' }
|
||
|
PEGFsaAbstractDeterminizator >> determinizeOverlap: t1 second: t2 state: state [
|
||
|
| t1Prime t2Prime tIntersection |
|
||
|
self assert: (state transitions includes: t1).
|
||
|
self assert: (state transitions includes: t2).
|
||
|
|
||
|
tIntersection := self joinTransition: t1 with: t2.
|
||
|
|
||
|
t1Prime := PEGFsaCharacterTransition new
|
||
|
destination: t1 destination;
|
||
|
characterSet: (t1 complement: t2);
|
||
|
yourself.
|
||
|
t2Prime := PEGFsaCharacterTransition new
|
||
|
destination: t2 destination;
|
||
|
characterSet: (t2 complement: t1);
|
||
|
yourself.
|
||
|
|
||
|
|
||
|
state removeTransition: t1.
|
||
|
state removeTransition: t2.
|
||
|
|
||
|
tIntersection isEmpty ifFalse: [ state addTransition: tIntersection ].
|
||
|
t1Prime isEmpty ifFalse: [ state addTransition: t1Prime ].
|
||
|
t2Prime isEmpty ifFalse: [ state addTransition: t2Prime ].
|
||
|
]
|
||
|
|
||
|
{ #category : 'determinization' }
|
||
|
PEGFsaAbstractDeterminizator >> determinizeState: state [
|
||
|
| pairs |
|
||
|
|
||
|
pairs := state transitionPairs asOrderedCollection.
|
||
|
|
||
|
[pairs isEmpty] whileFalse: [
|
||
|
| pair |
|
||
|
|
||
|
(joinDictionary size > 100) ifTrue: [ self error: 'Oh man, this is really big FSA. Are you sure you want to continue?' ].
|
||
|
|
||
|
pair := pairs removeFirst.
|
||
|
self assert:((pair first destination = pair second destination) not
|
||
|
or: [pair first isPredicateTransition not
|
||
|
or: [pair second isPredicateTransition not ] ]).
|
||
|
|
||
|
self assert: (pair contains: #isEpsilon) not.
|
||
|
|
||
|
(pair first overlapsWith: pair second) ifTrue: [
|
||
|
self determinizeOverlap: pair first second: pair second state: state.
|
||
|
"recompute pairs after the determinization"
|
||
|
pairs := state transitionPairs asOrderedCollection.
|
||
|
]
|
||
|
].
|
||
|
]
|
||
|
|
||
|
{ #category : 'initialization' }
|
||
|
PEGFsaAbstractDeterminizator >> initialize [
|
||
|
super initialize.
|
||
|
joinDictionary := Dictionary new
|
||
|
]
|
||
|
|
||
|
{ #category : 'accessing - keys' }
|
||
|
PEGFsaAbstractDeterminizator >> joinKey: key with: anotherKey [
|
||
|
^ Set new
|
||
|
addAll: key;
|
||
|
addAll: anotherKey;
|
||
|
yourself.
|
||
|
|
||
|
]
|
||
|
|
||
|
{ #category : 'joining' }
|
||
|
PEGFsaAbstractDeterminizator >> joinName: state with: anotherState into: newState [
|
||
|
newState name: state name asString, '_', anotherState name asString.
|
||
|
|
||
|
]
|
||
|
|
||
|
{ #category : 'joining' }
|
||
|
PEGFsaAbstractDeterminizator >> joinState: state with: anotherState [
|
||
|
| key newState |
|
||
|
key := self keyFor: state and: anotherState.
|
||
|
(joinDictionary includesKey: key) ifTrue: [ ^ joinDictionary at: key ].
|
||
|
|
||
|
newState := PEGFsaState new.
|
||
|
joinDictionary at: key put: newState.
|
||
|
|
||
|
self joinRetval: state with: anotherState into: newState.
|
||
|
self joinInfo: state with: anotherState into: newState.
|
||
|
self joinName: state with: anotherState into: newState.
|
||
|
self joinTransitions: state with: anotherState into: newState.
|
||
|
|
||
|
self determinizeState: newState.
|
||
|
|
||
|
self assert: ((joinDictionary at: key) == newState).
|
||
|
^ newState
|
||
|
]
|
||
|
|
||
|
{ #category : 'joining' }
|
||
|
PEGFsaAbstractDeterminizator >> joinTransition: t1 with: t2 [
|
||
|
| newDestination newTransition |
|
||
|
self assert: t1 isCharacterTransition.
|
||
|
self assert: t2 isCharacterTransition.
|
||
|
|
||
|
newDestination := self joinState: t1 destination with: t2 destination.
|
||
|
|
||
|
newTransition := PEGFsaCharacterTransition new.
|
||
|
newTransition destination: newDestination.
|
||
|
newTransition characterSet: (t1 intersection: t2).
|
||
|
newTransition priority: (t1 priority max: t2 priority).
|
||
|
|
||
|
^ newTransition
|
||
|
]
|
||
|
|
||
|
{ #category : 'accessing - keys' }
|
||
|
PEGFsaAbstractDeterminizator >> keyFor: state [
|
||
|
^ joinDictionary keyAtIdentityValue: state ifAbsent: [ Set with: state ]
|
||
|
]
|
||
|
|
||
|
{ #category : 'accessing - keys' }
|
||
|
PEGFsaAbstractDeterminizator >> keyFor: state and: anotherState [
|
||
|
| key anotherKey |
|
||
|
key := self keyFor: state.
|
||
|
anotherKey := self keyFor: anotherState.
|
||
|
|
||
|
^ self joinKey: key with: anotherKey
|
||
|
]
|