compiler/PPCGuard.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Thu, 21 May 2015 14:12:22 +0100
changeset 464 f6d77fee9811
parent 459 4751c407bb40
child 515 b5316ef15274
permissions -rw-r--r--
Updated to PetitCompiler-JanKurs.118, PetitCompiler-Tests-JanKurs.46, PetitCompiler-Extras-Tests-JanKurs.11, and PetitCompiler-Benchmarks-JanKurs.11 Name: PetitCompiler-JanKurs.118 Author: JanKurs Time: 13-05-2015, 03:59:01.292 PM UUID: 4a8ccd94-3131-4cc7-9098-528f8e5ea0b5 Name: PetitCompiler-Tests-JanKurs.46 Author: JanKurs Time: 04-05-2015, 04:25:06.162 PM UUID: 9f4cf8b7-876e-4a13-9579-b833f016db66 Name: PetitCompiler-Extras-Tests-JanKurs.11 Author: JanKurs Time: 13-05-2015, 04:27:27.940 PM UUID: e9f30c31-fbd0-4e96-ad2a-868f88d20ea8 Name: PetitCompiler-Benchmarks-JanKurs.11 Author: JanKurs Time: 13-05-2015, 02:21:49.932 PM UUID: 6a23fd1e-a86f-46db-8221-cc41b778d32c

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

"{ NameSpace: Smalltalk }"

Object subclass:#PPCGuard
	instanceVariableNames:'classification id message'
	classVariableNames:''
	poolDictionaries:''
	category:'PetitCompiler-Guards'
!

!PPCGuard class methodsFor:'as yet unclassified'!

on: aPPCNode
    ^ self new
        initializeFor: aPPCNode;
        yourself
!

on: aPPCNode id: id
    ^ self new
        initializeFor: aPPCNode;
        id: id;
        yourself
! !

!PPCGuard methodsFor:'accessing'!

classification
    ^ classification
!

id
    
    ^ id
!

id: anObject
    
    id := anObject
!

message
    (message == #unknown) ifTrue: [ 
        (self testMessage: #isLetter) ifTrue: [ ^ message := #isLetter ].
        (self testMessage: #isAlphaNumeric) ifTrue: [ ^ message := #isAlphaNumeric ].
        (self testMessage: #isDigit) ifTrue: [ ^ message := #isDigit ].
        
        ^ message := nil.
    ].
    ^ message
! !

!PPCGuard methodsFor:'as yet unclassified'!

classificationOn: aBlock
    classification := Array new: 255.
    1 to: classification size do: [ :index |
        classification at: index put: (aBlock
            value: (Character value: index)) ].
!

compileAny: compiler
    compiler add: '(context atEnd not)'.
!

compileCharacter: compiler
    self assert: (classification select: [ :e | e ]) size = 1.
    
    classification keysAndValuesDo: [ :index :value | value ifTrue: [  
        (index > 32 and: [ index < 127 ]) ifTrue: [ 
            compiler add: '(context peek == ', (Character value: index) storeString, ')'
        ] ifFalse: [ 
            id := compiler idFor: (Character value: index) prefixed: #character.
            compiler addConstant: (Character value: index) as: id.
            compiler add: '(context peek = ', id, ')'.
     		] 
    ] ].
!

compileGuard: compiler id: symbol
    self id: symbol.
    ^ self compileGuard: compiler
!

compileMessage: compiler
    compiler add: '(context peek ', message, ')'
!

testAny
    ^ classification allSatisfy: [ :e | e ].
!

testMessage: selector
 		classification keysAndValuesDo: [:index :element |
				(element = ((Character value: index) perform: selector)) ifFalse: [ 
						^ false 
				]
		].
		^ true
!

testSingleCharacter
    ^ (classification select: [ :e | e ]) size = 1
! !

!PPCGuard methodsFor:'code generation'!

compileArray: compiler
    | array |
    self assert: id isNotNil.

    array := ((classification asOrderedCollection) addLast: false; yourself) asArray.
    compiler addConstant: array as: id.
    compiler add: '(', id, ' at: context peek asInteger)'.
!

compileGuard: compiler
    self assert: self makesSense description: 'No Guard could be compiled'.
    self assert: id notNil.
    
    self message ifNotNil: [ ^ self compileMessage: compiler ].
    self testAny ifTrue: [ ^ self compileAny: compiler ].
    self testSingleCharacter ifTrue: [ ^ self compileCharacter: compiler ].
    
    ^ self compileArray: compiler
!

makesSense
    ^ classification isNil not
! !

!PPCGuard methodsFor:'initialization'!

initializeFor: node
    message := #unknown.
    id := nil.
    
    "No Guards for trimming parser so far"
"	((node firstSetSuchThat: [ :e | e isKindOf: PPCTrimNode ]) isEmpty) ifFalse: [ 
        ^ self initializeForNoGuard 
    ]."
    (node acceptsEpsilon) ifTrue: [  
        ^ self initializeForEpsilon
    ].

    self classificationOn: [:char | node firstSet anySatisfy: [:e | (e firstCharSetCached value: char) ]]

"	self classificationOn: [ :char | node firstSet anySatisfy: [ :e |  (e firstCharParser parse: char asString) isPetitFailure not ] ]"
!

initializeForEpsilon
    classification := nil
    
!

initializeForNoGuard
    classification := nil
    
! !