compiler/PEGFsaTransition.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 24 Jul 2015 15:06:54 +0100
changeset 502 1e45d3c96ec5
child 504 0fb1f0799fc1
child 515 b5316ef15274
permissions -rw-r--r--
Updated to PetitCompiler-JanVrany.135, PetitCompiler-Tests-JanKurs.93, PetitCompiler-Extras-Tests-JanVrany.16, PetitCompiler-Benchmarks-JanKurs.12 Name: PetitCompiler-JanVrany.135 Author: JanVrany Time: 22-07-2015, 06:53:29.127 PM UUID: 890178b5-275d-46af-a2ad-1738998f07cb Ancestors: PetitCompiler-JanVrany.134 Name: PetitCompiler-Tests-JanKurs.93 Author: JanKurs Time: 20-07-2015, 11:30:10.283 PM UUID: 6473e671-ad70-42ca-b6c3-654b78edc531 Ancestors: PetitCompiler-Tests-JanKurs.92 Name: PetitCompiler-Extras-Tests-JanVrany.16 Author: JanVrany Time: 22-07-2015, 05:18:22.387 PM UUID: 8f6f9129-dbba-49b1-9402-038470742f98 Ancestors: PetitCompiler-Extras-Tests-JanKurs.15 Name: PetitCompiler-Benchmarks-JanKurs.12 Author: JanKurs Time: 06-07-2015, 02:10:06.901 PM UUID: cb24f1ac-46a4-494d-9780-64576f0f0dba Ancestors: PetitCompiler-Benchmarks-JanKurs.11, PetitCompiler-Benchmarks-JanVrany.e29bd90f388e.20150619081300

"{ Package: 'stx:goodies/petitparser/compiler' }"

"{ NameSpace: Smalltalk }"

Object subclass:#PEGFsaTransition
	instanceVariableNames:'characterSet destination priority'
	classVariableNames:''
	poolDictionaries:''
	category:'PetitCompiler-FSA'
!

!PEGFsaTransition methodsFor:'accessing'!

characterSet
    ^ characterSet
!

characterSet: anObject
    characterSet := anObject
!

destination
    ^ destination
!

destination: anObject
    destination := anObject
!

priority
    ^ priority
!

priority: anObject
    priority := anObject
! !

!PEGFsaTransition methodsFor:'comparing'!

= anotherTransition
    "
    Please note the identity comparison on destination
    If you use equality instead of identy, you will get infinite loop.

    So much for comparison by now :)	
    "
    (self == anotherTransition) ifTrue: [ ^ true ].
    (self class == anotherTransition class) ifFalse: [ ^ false ].

    (destination == anotherTransition destination) ifFalse: [ ^ false ].
    (priority == anotherTransition priority) ifFalse: [ ^ false ].
    (characterSet = anotherTransition characterSet) ifFalse: [ ^ false ].
    
    ^ true
!

canBeIsomorphicTo: anotherTransition
    (priority == anotherTransition priority) ifFalse: [ ^ false ].
    (characterSet = anotherTransition characterSet) ifFalse: [ ^ false ].
    
    ^ true
!

equals: anotherTransition
    "this method is used for minimization of the FSA"
    
    (self == anotherTransition) ifTrue: [ ^ true ].

    (destination == anotherTransition destination) ifFalse: [ ^ false ].
    (characterSet = anotherTransition characterSet) ifFalse: [ ^ false ].

    "JK: If character set and destination are the same, priority does not really matter"
    ^ true
!

hash
    ^ destination hash bitXor: (priority hash bitXor: characterSet hash)
!

isIsomorphicTo: object resolvedSet: set
    (set includes: (PEGFsaPair with: self with: object)) ifTrue: [ 
        ^ true
    ].
    set add: (PEGFsaPair with: self with: object).

    (self == object) ifTrue: [ ^ true ].
    (self class == object class) ifFalse: [ ^ false ].

    (priority == object priority) ifFalse: [ ^ false ].
    (characterSet = object characterSet) ifFalse: [ ^ false ].
    (destination isIsomorphicTo: object destination resolvedSet: set) ifFalse: [ ^ false ].
    
    ^ true
! !

!PEGFsaTransition methodsFor:'copying'!

postCopy
    super postCopy.
    characterSet := characterSet copy.
! !

!PEGFsaTransition methodsFor:'gt'!

gtName
    | gtName |
    gtName := self characterSetAsString.
    priority < 0 ifTrue: [ gtName := gtName, ',', priority asString ].
    ^ gtName
! !

!PEGFsaTransition methodsFor:'initialization'!

initialize
    super initialize.
    characterSet := Array new: 255 withAll: false.
    priority := 0.
! !

!PEGFsaTransition methodsFor:'modifications'!

addCharacter: character
    characterSet at: character codePoint put: true
!

decreasePriority
    priority := priority - 1
! !

!PEGFsaTransition methodsFor:'printing'!

characterSetAsString
    | stream |
    stream := WriteStream on: ''.
    self printCharacterSetOn: stream.
    ^ stream contents
!

printCharacterSetOn: stream
    self isEpsilon ifTrue: [ 
        stream nextPutAll: '<epsilon>'.
        ^ self
    ].

    stream nextPut: $[.
    32 to: 127 do: [ :index |
        (characterSet at: index) ifTrue: [ 
            stream nextPut: (Character codePoint: index)
        ]
    ].
    stream nextPut: $].
!

printOn: stream
    self printCharacterSetOn: stream.
    stream nextPutAll: ' ('.
    priority printOn: stream.
    stream nextPutAll: ')'.		
    stream nextPutAll: '-->'.
    destination printOn: stream.
    stream nextPutAll: '(ID: '.
    stream nextPutAll: self identityHash asString.
    stream nextPutAll: ')'.
! !

!PEGFsaTransition methodsFor:'set operations'!

complement: transition
    | complement |
    complement := Array new: 255.
    
    1 to: 255 do: [ :index |
        complement
            at: index 
            put: ((self characterSet at: index) and: [(transition characterSet at: index) not])
    ].

    ^ complement
!

disjunction: transition
    | disjunction |
    disjunction := Array new: 255.
    
    1 to: 255 do: [ :index |
        disjunction
            at: index 
            put: ((self characterSet at: index) xor: [transition characterSet at: index])
    ].

    ^ disjunction
!

intersection: transition
    | intersection |
    intersection := Array new: 255.
    
    1 to: 255 do: [ :index |
        intersection
            at: index 
            put: ((self characterSet at: index) and: [transition characterSet at: index])
    ].

    ^ intersection
!

union: transition
    | union |
    union := Array new: 255.
    
    1 to: 255 do: [ :index |
        union
            at: index 
            put: ((self characterSet at: index) or: [transition characterSet at: index])
    ].

    ^ union
! !

!PEGFsaTransition methodsFor:'testing'!

accepts: character
    ^ characterSet at: character codePoint
!

isEpsilon
    ^ characterSet allSatisfy: [ :e | e not ]
!

overlapsWith: transition
    ^ (self intersection: transition) anySatisfy: [ :bool | bool ]
! !

!PEGFsaTransition methodsFor:'transformation'!

join: transition
    ^ self join: transition joinDictionary: Dictionary new.
!

join: transition joinDictionary: dictionary
    | newDestination newTransition |
"	pair := PEGFsaPair with: self with: transition.
    (dictionary includesKey: pair) ifTrue: [ ^ dictionary at: pair ].
    dictionary at: pair put: nil.
"	
    newDestination := self destination join: transition destination joinDictionary: dictionary.
    newDestination isNil ifTrue: [ self error: 'What a cycle!! I wonder, how does this happened!!' ].
    
    newTransition := PEGFsaTransition new.
    newTransition destination: newDestination.
    newTransition characterSet: (self intersection: transition).
    newTransition priority: (self priority min: transition priority).
    
"	^ dictionary at: pair put: newTransition"
    ^ newTransition 
!

mergeWith: transition
    | union |
    self assert: destination = transition destination.
    
    union := self union: transition.
    self characterSet: union
! !