129 lines
3.5 KiB
Smalltalk
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
|
|
|
|
]
|