PetitCommonMark/software/petitcompiler/PPCRecognizerComponentDetec...

129 lines
3.5 KiB
Smalltalk

"
I do traverse the tree and locate recognizer components. I do start PPCRecognizerComponentVisitor, when a recognizer component is detected.
Recognizer component is a subgraph, that does not return a value, just returns true/false of an recognition attempt, therefore the recognizer component nodes can be further optimized.
"
Class {
#name : 'PPCRecognizerComponentDetector',
#superclass : 'PPCRewritingVisitor',
#category : 'PetitCompiler-Visitors'
}
{ #category : 'visiting' }
PPCRecognizerComponentDetector >> visitIslandNode: node [
| water newWater |
water := node water.
newWater := self visitWithRecognizingComponentVisitor: water.
self cache: water value: newWater ifPresent: [ :e | self assert: e == newWater ].
^ super visitIslandNode: node
]
{ #category : 'visiting' }
PPCRecognizerComponentDetector >> visitNotNode: node [
"We don't need result of the not,..."
| child newChild |
"
There might be some pretty complicated logic in the not not,
for example
'foo', 'bar' ==> [ :res | res isOK ] not
If recognizing component dos not create arrays, res will be nill
and thus such a parse will be invalid
"
true ifTrue: [ ^ super visitNotNode: node ].
child := node child.
newChild := self visitWithRecognizingComponentVisitor: child.
self cache: child value: newChild.
^ super visitNotNode: node
]
{ #category : 'visiting' }
PPCRecognizerComponentDetector >> visitTokenConsumeNode: node [
"Let the scanner handle this stuff"
^ node
]
{ #category : 'visiting' }
PPCRecognizerComponentDetector >> visitTokenNode: node [
| child newChild |
child := node child.
newChild := self visitWithRecognizingComponentVisitor: child.
self cache: child value: newChild ifPresent: [ :e | self assert: e == newChild ].
^ super visitTokenNode: node
]
{ #category : 'visiting' }
PPCRecognizerComponentDetector >> visitTokenWhitespaceNode: node [
| child newChild |
child := node child.
newChild := self visitWithRecognizingComponentVisitor: child.
self cache: child value: newChild ifPresent: [ :e | self assert: e == newChild ].
^ super visitTokenWhitespaceNode: node
]
{ #category : 'visiting' }
PPCRecognizerComponentDetector >> visitTokenizingParserNode: node [
| |
"Do not visit whitespace, it is tokenizer's job"
" self change.
newWhitespace := self visitWithRecognizingComponentVisitor: node whitespace.
node replace: node whitespace with: newWhitespace.
"
"Do not visit tokens, they will be handled by the scanner:"
"self visit: node tokens."
self visitChild: node parser of: node.
^ node
]
{ #category : 'visiting' }
PPCRecognizerComponentDetector >> visitTrimmingTokenNode: node [
| child newChild whitespace newWhitespace |
child := node child.
newChild := self visitWithRecognizingComponentVisitor: child.
self cache: child value: newChild ifPresent: [ :e | self assert: e == newChild ].
whitespace := node whitespace.
newWhitespace := self visitWithRecognizingComponentVisitor: whitespace.
self cache: whitespace value: newWhitespace ifPresent: [ :e | self assert: e == newWhitespace ].
^ super visitTrimmingTokenNode: node
]
{ #category : 'visiting' }
PPCRecognizerComponentDetector >> visitWithRecognizingComponentVisitor: node [
| retval forbiddenNodes copyVisitor tokenVisitor copy |
(self isCached: node) ifTrue: [
^ self cachedValue: node
].
copyVisitor := PPCCopyVisitor new.
tokenVisitor := PPCRecognizerComponentVisitor new.
forbiddenNodes := openSet copy.
copyVisitor forbiddenSet: openSet copy.
copy := copyVisitor visit: node.
retval := tokenVisitor visit: copy.
^ retval
]