compiler/PEGFsaInterpret.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:#PEGFsaInterpret
	instanceVariableNames:'fsa debug retvals stream maxPriority'
	classVariableNames:''
	poolDictionaries:''
	category:'PetitCompiler-FSA'
!

!PEGFsaInterpret methodsFor:'accessing'!

debug
    ^ debug
!

debug: anObject
    debug := anObject
!

fsa
    ^ fsa
! !

!PEGFsaInterpret methodsFor:'debugging'!

reportFsa: anFsa
    debug ifTrue: [ 
        Transcript show: anFsa asString; cr.
    ]
!

reportStart
    debug ifTrue: [ 
        Transcript show: '============================'; cr.
    ]
!

reportStates: states
    debug ifTrue: [ 
        Transcript show: 'states: '; show: states asString; cr
    ]
! !

!PEGFsaInterpret methodsFor:'initialization'!

initialize
    super initialize.
    debug := true
! !

!PEGFsaInterpret methodsFor:'running'!

interpret
    | states newStates character run  |
    maxPriority := SmallInteger minVal.
    newStates := IdentitySet with: fsa startState.
    retvals := IdentityDictionary new.
    
    self recordNewState: fsa startState position: 0.
    
    self reportStart.
    self reportFsa: fsa.
    
    run := stream atEnd not.
    
    [run] whileTrue: [  
        states := newStates.
        newStates := IdentitySet new.
        character := stream peek.

        self reportStates: states.

        states do: [ :state |
            self expand: state on: character into: newStates.
        ].
        
        newStates isEmpty ifFalse: [ stream next ].
        run := stream atEnd not and: [ newStates isEmpty not ].
    ].

    ^ self return: newStates
!

interpret: anFsa on: aStream
    fsa := anFsa.
    stream := aStream.
    
    ^ self interpret
! !

!PEGFsaInterpret methodsFor:'running support'!

allowsTransition: t from: state transitionsTaken: transitionsTaken
"	(state hasPriority) ifTrue: [ 
        ^ state priority <= t priority
    ].
"	
    "state hasPriority ifTrue: [ "
"		transitionsTaken isEmpty ifTrue: [ ^ true ].
        ^ transitionsTaken anyOne priority <= t priority.
"	"]."
    ^ true
!

expand: state on: character into: newStates "transitionsTaken: transitionsTaken"
    | transitions transitionsTaken |

    transitionsTaken := OrderedCollection new.
    transitions := self sortedTransitionsFor: state.
    transitions do: [ :t | 
        (self allowsTransition: t from: state transitionsTaken: transitionsTaken) ifTrue: [ 
            t isEpsilon ifTrue: [  
                (t destination isFinal) ifTrue: [ 
                    newStates add: t destination.
                    self recordNewState: t destination position: stream position.
                ].

                "Descent into the next state"
                self 	expand: t destination 
                        on: character 
                        into: newStates.

                newStates isEmpty ifFalse: [ 
                    transitionsTaken add: t.
                ].

            ] ifFalse: [  
                (t accepts: character) ifTrue: [ 
                    transitionsTaken add: t.
                    newStates add: t destination.
                    self recordNewState: t destination.
                ]
            ] 
        ]
    ]
!

recordNewState: state
    ^ self recordNewState: state position: stream position + 1
!

recordNewState: state position: position
    (state isFinal) ifFalse: [ ^ self ].
    (maxPriority > state priority) ifTrue: [ ^ true ].
        
    self assert: state hasPriority description: 'final state must have priority'.
    (maxPriority < state priority) ifTrue: [ 
        retvals := IdentityDictionary new.
        maxPriority := state priority.
    ].


    state retvalAsCollection do: [ :r |
        retvals at: r put: position
    ].
!

return: states
    | priority priorities |
    priorities := (states select: #hasPriority thenCollect: #priority).
    priorities isEmpty ifTrue: [  
        ^ retvals keysAndValuesRemove: [ :key :value | key class == PEGFsaFailure ] 
    ].
    
    priority := priorities max.
    
    (maxPriority < priority) ifTrue: [ ^ IdentityDictionary new ].
    ^ retvals keysAndValuesRemove: [ :key :value | key class == PEGFsaFailure ]
!

sortedTransitionsFor: state
    ^ (fsa transitionsFor: state) asOrderedCollection
        "Dear future me, enjoy this:"
"		sort: [ :e1 :e2 | (e1 isEpsilon not and: [e2 isEpsilon]) not ])"
        sort: [ :e1 :e2 | e1 priority > e2 priority ]
            
! !