PetitCommonMark/software/petitcompiler/PPCDeterministicChoiceVisit...

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.
]