89 lines
2.5 KiB
Smalltalk
89 lines
2.5 KiB
Smalltalk
|
"
|
||
|
I can recognize the deterministic choices, i.e. the choices, where based on the first token, one can decide if to take the choice or not.
|
||
|
|
||
|
This simplifies the generated code and this migth improve performance as well (not yet implemented, as far as I know..)
|
||
|
|
||
|
I need to be revisited and reimplemented...
|
||
|
"
|
||
|
Class {
|
||
|
#name : 'PPCDeterministicChoiceVisitor',
|
||
|
#superclass : 'PPCRewritingVisitor',
|
||
|
#category : 'PetitCompiler-Visitors'
|
||
|
}
|
||
|
|
||
|
{ #category : 'as yet unclassified' }
|
||
|
PPCDeterministicChoiceVisitor >> isDeterministicChoice: node [
|
||
|
| predicates firstIndexes |
|
||
|
|
||
|
predicates := self predicates: node.
|
||
|
firstIndexes := OrderedCollection new.
|
||
|
predicates do: [ :predicate |
|
||
|
predicate classification withIndexDo: [ :bool :index |
|
||
|
bool ifTrue: [firstIndexes add: index]
|
||
|
]
|
||
|
].
|
||
|
|
||
|
|
||
|
^ firstIndexes size = firstIndexes asIdentitySet size
|
||
|
]
|
||
|
|
||
|
{ #category : 'as yet unclassified' }
|
||
|
PPCDeterministicChoiceVisitor >> mergeFirstCharSets: firstSet [
|
||
|
| firstCharSetsOfFirstSet blocks mergedBlock |
|
||
|
firstCharSetsOfFirstSet := firstSet collect: [:e | e firstCharSet ].
|
||
|
blocks := firstCharSetsOfFirstSet collect: [ :e | e block ].
|
||
|
mergedBlock := [ :input | blocks anySatisfy: [ :block | block value: input ] ].
|
||
|
|
||
|
|
||
|
^ PPCharSetPredicate on: mergedBlock.
|
||
|
]
|
||
|
|
||
|
{ #category : 'as yet unclassified' }
|
||
|
PPCDeterministicChoiceVisitor >> predicates: node [
|
||
|
| firstSets mergedSets |
|
||
|
|
||
|
(node startsWithTrimmingTokens) ifTrue: [
|
||
|
| tokensPerChild |
|
||
|
tokensPerChild := node children collect: [:child | child firstSetWithTokens "firstSet" ].
|
||
|
|
||
|
firstSets := tokensPerChild collect: [ :childTokensOrTerminal |
|
||
|
| firstSet |
|
||
|
firstSet := IdentitySet new.
|
||
|
childTokensOrTerminal do: [ :tokenOrTerminal |
|
||
|
tokenOrTerminal isTokenNode ifTrue: [
|
||
|
firstSet addAll: tokenOrTerminal child firstSet
|
||
|
] ifFalse: [
|
||
|
firstSet addAll: tokenOrTerminal firstSet.
|
||
|
]
|
||
|
].
|
||
|
firstSet
|
||
|
].
|
||
|
] ifFalse: [
|
||
|
firstSets := node children collect: [:child | child firstSet ].
|
||
|
].
|
||
|
|
||
|
mergedSets := firstSets collect: [ :fs | self mergeFirstCharSets: fs ].
|
||
|
node children with: mergedSets do: [ :child :merged |
|
||
|
child mergedFirstCharSet: merged
|
||
|
].
|
||
|
^ mergedSets
|
||
|
]
|
||
|
|
||
|
{ #category : 'as yet unclassified' }
|
||
|
PPCDeterministicChoiceVisitor >> visitChoiceNode: node [
|
||
|
self visitChildren: node.
|
||
|
|
||
|
(self isDeterministicChoice: node) ifTrue: [
|
||
|
^ PPCDeterministicChoiceNode new
|
||
|
children: node children;
|
||
|
name: node name;
|
||
|
firstFollowCache: node firstFollowCache;
|
||
|
properties: node properties;
|
||
|
yourself.
|
||
|
].
|
||
|
|
||
|
^ super visitChoiceNode: node.
|
||
|
|
||
|
|
||
|
]
|