compiler/PEGFsaAbstractDeterminizator.st
changeset 515 b5316ef15274
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/compiler/PEGFsaAbstractDeterminizator.st	Mon Aug 17 12:13:16 2015 +0100
@@ -0,0 +1,163 @@
+"{ Package: 'stx:goodies/petitparser/compiler' }"
+
+"{ NameSpace: Smalltalk }"
+
+Object subclass:#PEGFsaAbstractDeterminizator
+	instanceVariableNames:'fsa joinDictionary'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'PetitCompiler-FSA'
+!
+
+!PEGFsaAbstractDeterminizator class methodsFor:'as yet unclassified'!
+
+new
+    ^ self basicNew initialize
+! !
+
+!PEGFsaAbstractDeterminizator methodsFor:'accessing - keys'!
+
+joinKey: key with: anotherKey
+    ^ Set new
+        addAll: key;
+        addAll: anotherKey;
+        yourself.
+!
+
+keyFor: state
+    ^ joinDictionary keyAtIdentityValue: state ifAbsent: [ Set with: state ]
+!
+
+keyFor: state and: anotherState
+    | key anotherKey |
+    key := self keyFor: state.
+    anotherKey := self keyFor: anotherState.
+    
+    ^ self joinKey: key with: anotherKey
+! !
+
+!PEGFsaAbstractDeterminizator methodsFor:'determinization'!
+
+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.
+!
+
+determinize: anFsa
+    fsa := anFsa.
+    joinDictionary := Dictionary new.
+    
+    self determinize.
+    ^ fsa
+!
+
+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 ].
+!
+
+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.
+        ]
+    ].
+! !
+
+!PEGFsaAbstractDeterminizator methodsFor:'initialization'!
+
+initialize
+    super initialize.
+    joinDictionary := Dictionary new
+! !
+
+!PEGFsaAbstractDeterminizator methodsFor:'joining'!
+
+joinName: state with: anotherState into: newState
+    newState name: state name asString, '_', anotherState name asString.
+!
+
+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
+!
+
+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 
+! !
+