compiler/PEGFsa.st
changeset 503 ff58cd9f1f3c
parent 502 1e45d3c96ec5
child 504 0fb1f0799fc1
equal deleted inserted replaced
501:e29bd90f388e 503:ff58cd9f1f3c
       
     1 "{ Package: 'stx:goodies/petitparser/compiler' }"
       
     2 
       
     3 "{ NameSpace: Smalltalk }"
       
     4 
       
     5 Object subclass:#PEGFsa
       
     6 	instanceVariableNames:'states startState name distances priorities'
       
     7 	classVariableNames:''
       
     8 	poolDictionaries:''
       
     9 	category:'PetitCompiler-FSA'
       
    10 !
       
    11 
       
    12 !PEGFsa methodsFor:'accessing'!
       
    13 
       
    14 allTransitions
       
    15     ^ self allTransitions: IdentitySet new
       
    16 !
       
    17 
       
    18 allTransitions: collection
       
    19     self states do: [ :s | collection addAll: s transitions  ].
       
    20     ^ collection
       
    21 !
       
    22 
       
    23 forwardTransitions
       
    24     | backTransitions |
       
    25     backTransitions := self backTransitions.
       
    26     ^ self allTransitions reject: [ :t | backTransitions includes: t ]
       
    27 !
       
    28 
       
    29 minPriority
       
    30     "this is the worst estimate"
       
    31     ^ (self states size) negated
       
    32 !
       
    33 
       
    34 name
       
    35     ^ name 
       
    36 !
       
    37 
       
    38 name: anObject
       
    39     
       
    40     name := anObject
       
    41 !
       
    42 
       
    43 prefix
       
    44     ^ 'fsa_'
       
    45 !
       
    46 
       
    47 startState
       
    48     ^ startState
       
    49 !
       
    50 
       
    51 stateNamed: name
       
    52     ^ states detect: [ :e | e name = name ]
       
    53 !
       
    54 
       
    55 states
       
    56     ^ states
       
    57 !
       
    58 
       
    59 suffix
       
    60     ^ ''
       
    61 !
       
    62 
       
    63 transitionFrom: from to: to
       
    64     ^ from transitions detect: [ :t | t destination = to ]
       
    65 !
       
    66 
       
    67 transitionsFor: state
       
    68     self assert: (states includes: state).
       
    69     ^ state transitions
       
    70 ! !
       
    71 
       
    72 !PEGFsa methodsFor:'analysis'!
       
    73 
       
    74 backTransitions
       
    75     |  transitionSet |
       
    76     transitionSet := IdentitySet new.
       
    77     self computeDistances.
       
    78     
       
    79     self backTransitionsFrom: startState openSet: IdentitySet new transitionSet: transitionSet.
       
    80     ^ transitionSet
       
    81 !
       
    82 
       
    83 backTransitionsFrom: state openSet: openSet transitionSet: transitionSet
       
    84     (openSet includes: state) ifTrue: [  
       
    85         ^ self
       
    86     ].
       
    87     openSet add: state.
       
    88     
       
    89     state transitions do: [ :t | 
       
    90         ((openSet includes: t destination) and: [self is: state furtherThan: t destination]) ifTrue: [  
       
    91             transitionSet add: t		
       
    92         ].
       
    93         self backTransitionsFrom: t destination openSet: openSet copy transitionSet: transitionSet
       
    94     ]
       
    95 !
       
    96 
       
    97 computeDistances
       
    98     | queue openSet |
       
    99     distances := IdentityDictionary new.
       
   100     queue := OrderedCollection with: startState.
       
   101     openSet := IdentitySet new.
       
   102 
       
   103     distances at: startState put: 0.
       
   104     
       
   105     [ queue isEmpty not ] whileTrue: [ 
       
   106         | state |
       
   107         state := queue removeFirst.
       
   108         openSet add: state.
       
   109         
       
   110         state transitions do: [ :t |
       
   111             (openSet includes: (t destination)) ifFalse: [ 
       
   112                 distances at: (t destination ) put: ((distances at: state) + 1).
       
   113                 queue addLast: (t destination)
       
   114             ]
       
   115         ]
       
   116     ].
       
   117 
       
   118     ^ distances
       
   119 !
       
   120 
       
   121 computePriorities
       
   122     | queue openSet |
       
   123     self flag: 'not working...'.
       
   124     priorities := IdentityDictionary new.
       
   125     queue := OrderedCollection with: startState.
       
   126     openSet := IdentitySet new.
       
   127 
       
   128     priorities at: startState put: (startState priorityIfNone: 0).
       
   129     
       
   130     [ queue isEmpty not ] whileTrue: [ 
       
   131         | state |
       
   132         state := queue removeFirst.
       
   133         openSet add: state.
       
   134         
       
   135         state transitions do: [ :t |
       
   136             (openSet includes: (t destination)) ifFalse: [ 
       
   137                 priorities at: (t destination ) put: ((priorities at: state) + t priority).
       
   138                 queue addLast: (t destination)
       
   139             ]
       
   140         ]
       
   141     ].
       
   142 
       
   143     ^ priorities
       
   144 !
       
   145 
       
   146 epsilonDestinationsFrom: state
       
   147     | openSet |
       
   148     openSet := IdentitySet new.
       
   149     self epsilonDestinationsFrom: state openSet: openSet.
       
   150     ^ openSet
       
   151 !
       
   152 
       
   153 epsilonDestinationsFrom: state openSet: openSet
       
   154     (openSet includes: state) ifTrue: [ 
       
   155         ^ self 
       
   156     ].
       
   157 
       
   158     openSet add: state.
       
   159     
       
   160     ((self transitionsFor: state) select: [ :t | t isEpsilon ]) do: [ :t |
       
   161         self epsilonDestinationsFrom: t destination openSet: openSet
       
   162     ]
       
   163     
       
   164 !
       
   165 
       
   166 finalStates
       
   167     ^ self reachableStates select: [ :s | s isFinal ]
       
   168 !
       
   169 
       
   170 is: state furtherThan: anotherState
       
   171 
       
   172     ^ (distances at: state) >= (distances at: anotherState)
       
   173 !
       
   174 
       
   175 isBackTransition: t
       
   176     ^ self backTransitions includes: t
       
   177 !
       
   178 
       
   179 joinPoints
       
   180     ^ self joinTransitions collect: [ :t | t destination ]
       
   181 !
       
   182 
       
   183 joinTransitions
       
   184     | joinTransitions transitions  size |
       
   185     joinTransitions := IdentitySet new.
       
   186 
       
   187     transitions := self allTransitions asOrderedCollection.
       
   188     size := transitions size.
       
   189 
       
   190     
       
   191     (1 to: size - 1) do: [ :index1 |
       
   192         (index1 + 1 to: size)  do: [ :index2 | 
       
   193             ((transitions at: index1) destination == (transitions at: index2) destination) ifTrue: [ 
       
   194                 joinTransitions add: (transitions at: index1).
       
   195                 joinTransitions add: (transitions at: index2).
       
   196             ]
       
   197         ]
       
   198     ].
       
   199 
       
   200     ^ joinTransitions
       
   201 !
       
   202 
       
   203 minimumPriority
       
   204 !
       
   205 
       
   206 nonFinalStates
       
   207     ^ self states reject: [ :s | s isFinal ]
       
   208 !
       
   209 
       
   210 reachableStates
       
   211     ^ self statesReachableFrom: startState
       
   212 !
       
   213 
       
   214 statePairs
       
   215     |  pairs ordered |
       
   216     pairs := OrderedCollection new.
       
   217     ordered := self topologicalOrder.
       
   218     1 to: (ordered size - 1) do: [ :index1 |
       
   219         (index1 + 1) to: ordered size do: [ :index2 |
       
   220             pairs add: (PEGFsaPair with: (ordered at: index1) with: (ordered at: index2))
       
   221  		]
       
   222     ].
       
   223 
       
   224     self assert: (pairs allSatisfy: [ :e | e class == PEGFsaPair ]).
       
   225     ^ pairs
       
   226 !
       
   227 
       
   228 statesReachableFrom: state
       
   229     | openSet |
       
   230     self assert: state isNil not.
       
   231     
       
   232     openSet := IdentitySet new.
       
   233     self statesReachableFrom: state openSet: openSet.
       
   234     ^ openSet
       
   235 !
       
   236 
       
   237 statesReachableFrom: state openSet: openSet
       
   238     (openSet contains: [:e | e == state]) ifTrue: [ 
       
   239         ^ self 
       
   240     ].
       
   241 
       
   242     openSet add: state.
       
   243     
       
   244     (self transitionsFor: state) do: [ :t |
       
   245         self statesReachableFrom: t destination openSet: openSet
       
   246     ]
       
   247     
       
   248 !
       
   249 
       
   250 topologicalOrder
       
   251     | collection |
       
   252     collection := OrderedCollection new.
       
   253     self statesReachableFrom: startState openSet: collection.
       
   254     ^ collection
       
   255 ! !
       
   256 
       
   257 !PEGFsa methodsFor:'comparing'!
       
   258 
       
   259 = anotherFsa
       
   260     "
       
   261         Please note what the compare does. IMO nothing useful for no.
       
   262         
       
   263         For comparing if two FSA's are equivalent, use isIsomorphicTo:
       
   264     "
       
   265 
       
   266     (self == anotherFsa)  ifTrue: [ ^ true ].
       
   267     (self class == anotherFsa class) ifFalse: [ ^ false ].
       
   268     
       
   269     (startState = anotherFsa startState) ifFalse: [ ^ false ].
       
   270     (name = anotherFsa name) ifFalse: [ ^ false ].
       
   271     
       
   272     (states size = anotherFsa states size) ifFalse: [ ^ false ].
       
   273     states do: [:s |
       
   274         (anotherFsa states contains: [ :e | e = s ]) ifFalse: [ ^ false ].
       
   275     ].
       
   276     ^ true
       
   277 !
       
   278 
       
   279 hash
       
   280     ^ states hash bitXor: (startState bitXor: name)
       
   281 !
       
   282 
       
   283 isIsomorphicTo: anotherFsa
       
   284     | topologicalOrder anotherTopologicalOrder  |
       
   285     
       
   286     "
       
   287         Please not that this version of comparison is sensitive to the order
       
   288         in which the transitions in state are ordered.
       
   289     "
       
   290     
       
   291     topologicalOrder := self topologicalOrder.
       
   292     anotherTopologicalOrder := anotherFsa topologicalOrder.
       
   293     
       
   294     topologicalOrder size == anotherTopologicalOrder size ifFalse: [ ^ false ].
       
   295     
       
   296     topologicalOrder with: anotherTopologicalOrder do: [ :s1 :s2 |
       
   297         (s1 canBeIsomorphicTo: s2) ifFalse: [ ^ false ]
       
   298     ].
       
   299     
       
   300     ^ true
       
   301 "	
       
   302     transitions := topologicalOrder flatCollect: [ :s | s transitions ].
       
   303     anotherTransitions := anotherTopologicalOrder flatCollect: [ :s | s transitions ].
       
   304 "	
       
   305 ! !
       
   306 
       
   307 !PEGFsa methodsFor:'copying'!
       
   308 
       
   309 postCopy
       
   310     | map |
       
   311     super postCopy.
       
   312     
       
   313     map := IdentityDictionary new.
       
   314     states do: [ :s |
       
   315         map at: s put: s copy.
       
   316     ].
       
   317     
       
   318     states := map values asIdentitySet.
       
   319     startState := map at: startState.
       
   320     
       
   321     states do: [ :s |
       
   322         s transitions do: [:t |
       
   323             t destination: (map at: t destination)
       
   324         ]
       
   325     ]
       
   326 ! !
       
   327 
       
   328 !PEGFsa methodsFor:'gt'!
       
   329 
       
   330 gtGraphViewIn: composite
       
   331     <gtInspectorPresentationOrder: 41>
       
   332     composite roassal2
       
   333         title: 'Graph'; 
       
   334         initializeView: [ RTMondrian new ];
       
   335         painting: [ :view |
       
   336             self viewGraphOn: view.	
       
   337         ].
       
   338 !
       
   339 
       
   340 gtStringViewIn: composite
       
   341     <gtInspectorPresentationOrder: 40>
       
   342 
       
   343     composite text
       
   344             title: 'Textual Representation';
       
   345             display: [ :fsa | fsa asString  ]
       
   346 !
       
   347 
       
   348 viewGraphOn: b
       
   349     b shape circle size: 50.
       
   350     b shape color: Color gray muchLighter muchLighter.
       
   351     b shape withText: #gtName.
       
   352     b nodes: (self nonFinalStates).
       
   353 
       
   354     b shape circle size: 50.
       
   355     b shape color: Color gray muchLighter.
       
   356     b shape withText: #gtName.
       
   357     b nodes: (self finalStates).
       
   358 
       
   359     b shape arrowedLine.
       
   360     b edges 
       
   361         connectToAll: [ :state | 
       
   362             state transitions 	select: [:t | (self isBackTransition:t)  not] 
       
   363                                     thenCollect: #destination ]
       
   364         labelled: [ :t | (self transitionFrom: t key to: t value) gtName  ].		
       
   365 
       
   366     b shape arrowedLine.
       
   367     b shape color: Color red.
       
   368     b edges 
       
   369         connectToAll: [ :state | 
       
   370             state transitions 	select: [:t | (self isBackTransition: t) ] 
       
   371                                 thenCollect: #destination ]
       
   372         labelled: [ :t | (self transitionFrom: t key to: t value) gtName  ].
       
   373 
       
   374 
       
   375     b layout horizontalTree  .
       
   376     b layout layout horizontalGap: 30.
       
   377 
       
   378     ^ b
       
   379 ! !
       
   380 
       
   381 !PEGFsa methodsFor:'initialization'!
       
   382 
       
   383 initialize
       
   384     states := IdentitySet new.
       
   385 ! !
       
   386 
       
   387 !PEGFsa methodsFor:'modifications'!
       
   388 
       
   389 addState: state
       
   390     self assert: (states includes: state) not.
       
   391     states add: state
       
   392 !
       
   393 
       
   394 addTransitionFrom: fromState to: toState 
       
   395     ^ self addTransitionFrom: fromState to: toState priority: 0 
       
   396 !
       
   397 
       
   398 addTransitionFrom: fromState to: toState on: character
       
   399     self addTransitionFrom: fromState to: toState on: character priority: 0
       
   400 !
       
   401 
       
   402 addTransitionFrom: fromState to: toState on: character priority: priority
       
   403     | transition |
       
   404     transition := PEGFsaTransition new 
       
   405         addCharacter: character;
       
   406         destination: toState;
       
   407         priority: priority;
       
   408         yourself.
       
   409         
       
   410     fromState addTransition: transition
       
   411 !
       
   412 
       
   413 addTransitionFrom: fromState to: toState onCharacterSet: characterSet
       
   414     self addTransitionFrom: fromState to: toState onCharacterSet: characterSet priority: 0
       
   415 !
       
   416 
       
   417 addTransitionFrom: fromState to: toState onCharacterSet: characterSet priority: priority
       
   418     | transition |
       
   419     transition := PEGFsaTransition new 
       
   420         characterSet: characterSet;
       
   421         destination: toState;
       
   422         priority: priority;
       
   423         yourself.
       
   424 
       
   425     fromState addTransition: transition
       
   426 !
       
   427 
       
   428 addTransitionFrom: fromState to: toState priority: priority
       
   429     | transition |
       
   430     self assert: (states includes: fromState).
       
   431     self assert: (states includes: toState).
       
   432     
       
   433     transition := PEGFsaTransition new 
       
   434         destination: toState;
       
   435         priority: priority;
       
   436         yourself.
       
   437         
       
   438     fromState addTransition: transition.
       
   439 !
       
   440 
       
   441 adopt: fsa
       
   442     states addAll: fsa reachableStates.
       
   443 !
       
   444 
       
   445 finalState: state
       
   446     self assert: state isFinal not.
       
   447     state final: true.
       
   448 !
       
   449 
       
   450 fixFinalStatePriorities
       
   451     self finalStates do: [ :s |
       
   452         s hasPriority ifFalse: [ s priority: 0 ]
       
   453     ]
       
   454 !
       
   455 
       
   456 removeState: state
       
   457     self assert: (states includes: state).
       
   458     states remove: state.
       
   459 !
       
   460 
       
   461 replace: state with: anotherState
       
   462     | transitions  |
       
   463     self assert: (state class == PEGFsaState).
       
   464     self assert: (anotherState class == PEGFsaState).
       
   465     
       
   466     transitions := self allTransitions.
       
   467 
       
   468     transitions do: [ :t |
       
   469         (t destination == state) ifTrue: [ 
       
   470             t destination: anotherState.
       
   471         ]
       
   472     ].
       
   473     states := startState reachableStates.	
       
   474 !
       
   475 
       
   476 startState: state
       
   477     self assert: (states includes: state).
       
   478     
       
   479     startState := state
       
   480 ! !
       
   481 
       
   482 !PEGFsa methodsFor:'printing'!
       
   483 
       
   484 asString
       
   485     | stream  |
       
   486     stream := WriteStream on: ''.
       
   487     
       
   488     self topologicalOrder do: [ :state |
       
   489         state printOn: stream.
       
   490         stream nextPutAll: '> '.
       
   491         
       
   492         (self transitionsFor: state) do: [ :transition |
       
   493             stream nextPut: (Character codePoint: 13).
       
   494             stream nextPut: (Character codePoint: 9).
       
   495             transition printOn: stream.
       
   496         ].
       
   497         stream nextPut: (Character codePoint: 13).
       
   498     ].
       
   499     
       
   500 "	stream nextPutAll: 'finals: '.
       
   501     (states select: [:s | s isFinal ]) do: [:e | e printOn: stream ].
       
   502     stream nextPut: (Character codePoint: 13).
       
   503 "
       
   504     ^ stream contents.
       
   505 ! !
       
   506 
       
   507 !PEGFsa methodsFor:'testing'!
       
   508 
       
   509 canHavePPCId
       
   510     ^ true
       
   511 !
       
   512 
       
   513 checkConsistency
       
   514     self assert: (states includes: startState).
       
   515     states do: [ :s | s transitions do: [ :t |
       
   516         self assert: (states includes: t destination).
       
   517     ] ].
       
   518     ^ true
       
   519 !
       
   520 
       
   521 checkFinalStatesPriorities
       
   522     self assert: (self finalStates allSatisfy: #hasPriority)
       
   523 !
       
   524 
       
   525 checkSanity
       
   526     self checkConsistency.
       
   527     self checkTransitionsIdentity.
       
   528     self checkFinalStatesPriorities.
       
   529 !
       
   530 
       
   531 checkTransitionsIdentity
       
   532     | bag set |
       
   533     bag := IdentityBag new.
       
   534     set := IdentitySet new.
       
   535     bag := self allTransitions: bag.
       
   536     set := self allTransitions: set.	
       
   537     
       
   538     self assert: bag size == set size.
       
   539 !
       
   540 
       
   541 isDeterministic
       
   542     self reachableStates do: [ :state |
       
   543         state transitionPairs do: [ :pair | 
       
   544             ((pair first intersection: pair second) includes: true) ifTrue: [ 					
       
   545                 ^ false
       
   546             ] 
       
   547         ]
       
   548     ].
       
   549     ^ true
       
   550 !
       
   551 
       
   552 isReachableState: state
       
   553     ^ self reachableStates includes: state
       
   554 !
       
   555 
       
   556 isStartState: state
       
   557     ^ startState == state
       
   558 !
       
   559 
       
   560 isWithoutEpsilons
       
   561     self reachableStates do: [ :state | 
       
   562         state transitions do: [ :t | 
       
   563             t isEpsilon ifTrue: [ ^ false ]
       
   564         ]
       
   565     ].
       
   566     ^ true
       
   567 ! !
       
   568 
       
   569 !PEGFsa methodsFor:'transformations'!
       
   570 
       
   571 compact
       
   572     self fixFinalStatePriorities.
       
   573     self determinize.
       
   574     self minimize.
       
   575     
       
   576     self checkSanity.
       
   577 !
       
   578 
       
   579 determinize
       
   580     | joinDictionary |
       
   581     self removeEpsilons.
       
   582 
       
   583     self removeUnreachableStates.
       
   584     self removeLowPriorityTransitions.
       
   585     self mergeTransitions.
       
   586     
       
   587     joinDictionary := Dictionary new.
       
   588     self topologicalOrder do: [:state | state determinize: joinDictionary ].
       
   589     
       
   590     states	 := startState reachableStates.
       
   591 
       
   592     self removeUnreachableStates.
       
   593     self removeLowPriorityTransitions.
       
   594     self mergeTransitions.
       
   595     
       
   596 !
       
   597 
       
   598 mergeTransitions
       
   599     | toRemove |
       
   600     self reachableStates do: [ :state |
       
   601         toRemove := OrderedCollection new.
       
   602         state transitionPairs do:[ :pair | 
       
   603             (pair first destination = pair second destination) ifTrue: [ 
       
   604                 pair first mergeWith: pair second.
       
   605                 toRemove add: pair second.
       
   606             ]
       
   607         ].
       
   608         toRemove do: [ :t |
       
   609             state removeTransition: t
       
   610         ]
       
   611     ]
       
   612 !
       
   613 
       
   614 minimize
       
   615     | pair |
       
   616     pair := self statePairs detect:  [ :p | p first equals: p second ] ifNone: [ nil ].
       
   617     [ pair isNil not ] whileTrue: [ 
       
   618         "Join priorities, because equivalency of priorities does not imply from the equeality of states"
       
   619         pair first joinPriority: pair second newState: pair first.
       
   620         pair first joinName: pair second newState: pair first.
       
   621         self replace: pair second with: pair first.
       
   622         self mergeTransitions.
       
   623         pair := self statePairs detect:  [ :p | p first equals: p second ] ifNone: [ nil ].
       
   624  	].
       
   625 !
       
   626 
       
   627 removeEpsilonTransition: transition source: state
       
   628     ^ self removeEpsilonTransition: transition source: state openSet: IdentitySet new
       
   629 !
       
   630 
       
   631 removeEpsilonTransition: transition source: source openSet: openSet
       
   632     | destination |
       
   633     (openSet includes: transition) ifTrue: [ self error: 'loop in epsilons?!!' ].
       
   634     openSet add: transition.
       
   635     
       
   636     destination := transition destination.
       
   637     
       
   638     "First Remove Recursively"
       
   639     ((self transitionsFor: destination ) select: [ :t | t isEpsilon  ]) do: [ :t |
       
   640         self removeEpsilonTransition: t source: destination openSet: openSet
       
   641     ].
       
   642     
       
   643     (transition priority abs) timesRepeat: [ 
       
   644         (self statesReachableFrom: destination) do: [ :s |
       
   645             s decreasePriority.
       
   646             s transitions do: [ :t | t decreasePriority  ]
       
   647         ]
       
   648     ].
       
   649 
       
   650     (destination transitions) do: [ :t |
       
   651         source addTransition: (t copy)
       
   652     ].
       
   653 
       
   654     destination hasPriority ifTrue: [ 
       
   655         source hasPriority ifTrue: [ 
       
   656             "self assert: source priority == destination priority"
       
   657             self flag: 'I am not 100% sure about this case'
       
   658         ].
       
   659         source priority: destination priority
       
   660     ].
       
   661 
       
   662     destination isFinal ifTrue: [ 
       
   663         source final: true.
       
   664         source retval: destination retval.
       
   665     ].
       
   666 
       
   667     source removeTransition: transition.
       
   668 !
       
   669 
       
   670 removeEpsilons
       
   671     states do: [ :state |
       
   672         self removeEpsilonsFor: state
       
   673     ]
       
   674 !
       
   675 
       
   676 removeEpsilonsFor: state
       
   677     (self transitionsFor: state) copy do: [ :t |
       
   678         t isEpsilon ifTrue: [ 
       
   679             self removeEpsilonTransition: t source: state
       
   680         ]
       
   681     ]
       
   682 !
       
   683 
       
   684 removeLowPriorityTransitions
       
   685     states do: [ :state |
       
   686         self removeLowPriorityTransitionsFor: state
       
   687     ]
       
   688 !
       
   689 
       
   690 removeLowPriorityTransitionsFor: state
       
   691     state hasPriority ifFalse: [ ^ self ].
       
   692     state isFinal ifFalse: [ ^ self ].
       
   693     
       
   694     state transitions do: [ :t |
       
   695         (t priority < state priority) ifTrue: [ 
       
   696             state removeTransition: t
       
   697         ]
       
   698     ]
       
   699 !
       
   700 
       
   701 removeUnreachableStates
       
   702     | reachable toRemove |
       
   703     reachable := self reachableStates.
       
   704     toRemove := OrderedCollection new.
       
   705 
       
   706     states do: [ :s |
       
   707         (reachable includes: s) ifFalse: [ 
       
   708             toRemove add: s		
       
   709         ]
       
   710     ].
       
   711 
       
   712     toRemove do: [ :s | states remove: s ]
       
   713 ! !
       
   714