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