PetitCommonMark/software/petitcompiler/PEGFsaAbstractDeterminizato...

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
]