271 lines
5.8 KiB
Smalltalk
271 lines
5.8 KiB
Smalltalk
"
|
|
I do specialize some nodes, so that they can emit optimized code for them.
|
|
|
|
e.g. #any star can be optimized to simple jump to the end of the input.
|
|
"
|
|
Class {
|
|
#name : 'PPCSpecializingVisitor',
|
|
#superclass : 'PPCRewritingVisitor',
|
|
#category : 'PetitCompiler-Visitors'
|
|
}
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> rejectDuplicateChildren: node [
|
|
| seen newChildren |
|
|
seen := IdentitySet new.
|
|
newChildren := OrderedCollection new.
|
|
node children do: [ :child |
|
|
(seen includes: child) ifFalse: [
|
|
newChildren add: child
|
|
].
|
|
seen add: child
|
|
].
|
|
^ newChildren
|
|
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitActionNode: node [
|
|
(node block isSymbol) ifTrue: [
|
|
| newNode |
|
|
newNode := PPCSymbolActionNode new
|
|
block: node block;
|
|
name: node name;
|
|
child: node child;
|
|
properties: node properties copy;
|
|
yourself.
|
|
|
|
^ super visitActionNode: newNode
|
|
].
|
|
|
|
^ super visitActionNode: node
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitChoiceNode: node [
|
|
self visitChildren: node.
|
|
|
|
(node children size = 1) ifTrue: [
|
|
^ node "firstChild "
|
|
|
|
].
|
|
|
|
"Remove the identical children"
|
|
"node children: (self rejectDuplicateChildren: node)."
|
|
^ node
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitForwardNode: node [
|
|
node name ifNil: [
|
|
self cache: node value: node child.
|
|
^ self visit: node child.
|
|
].
|
|
|
|
node child name ifNil: [
|
|
node child name: node name.
|
|
|
|
self cache: node value: node child.
|
|
^ self visit: node child.
|
|
].
|
|
|
|
(node child name = node name) ifTrue: [
|
|
self cache: node value: node child.
|
|
^ self visit: node child.
|
|
].
|
|
|
|
^ super visitForwardNode: node
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitIslandNode: node [
|
|
(context options useContextFreeSeas and: [ node island isContextFree ]) ifTrue: [
|
|
node parser: node parser asLightweightMemoizingSea
|
|
].
|
|
|
|
^ super visitIslandNode: node
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitNonEmptyNode: node [
|
|
self visitChildren: node.
|
|
|
|
(node child alwaysConsumes) ifTrue: [
|
|
^ node child
|
|
].
|
|
|
|
^ node
|
|
|
|
"Modified: / 23-04-2015 / 12:02:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitNotNode: node [
|
|
self visitChildren: node.
|
|
|
|
(node child isKindOf: PPCAbstractLiteralNode) ifTrue: [
|
|
^ PPCNotLiteralNode new
|
|
name: node name;
|
|
literal: node child literal;
|
|
yourself
|
|
].
|
|
|
|
(node child isKindOf: PPCMessagePredicateNode) ifTrue: [
|
|
^ PPCNotMessagePredicateNode new
|
|
name: node name;
|
|
predicate: node child predicate;
|
|
message: node child message;
|
|
yourself
|
|
].
|
|
|
|
(node child isKindOf: PPCCharSetPredicateNode) ifTrue: [
|
|
^ PPCNotCharSetPredicateNode new
|
|
name: node name;
|
|
predicate: node child predicate;
|
|
yourself
|
|
].
|
|
|
|
(node child isKindOf: PPCCharacterNode) ifTrue: [
|
|
^ PPCNotCharacterNode new
|
|
name: node name;
|
|
character: node child character;
|
|
yourself
|
|
].
|
|
|
|
^ node
|
|
|
|
"Modified: / 23-04-2015 / 12:02:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitPlusNode: node [
|
|
self visitChildren: node.
|
|
|
|
(node child isKindOf: PPCMessagePredicateNode) ifTrue: [
|
|
^ PPCPlusMessagePredicateNode new
|
|
name: node name;
|
|
child: node child;
|
|
message: node child message;
|
|
yourself
|
|
].
|
|
|
|
^ node
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitPredicateNode: node [
|
|
| charSet |
|
|
|
|
(node predicate class == PPCharSetPredicate) ifTrue: [
|
|
charSet := node predicate.
|
|
].
|
|
charSet := PPCharSetPredicate on: node predicate.
|
|
|
|
|
|
(charSet equals: (PPCharSetPredicate on: [ :char | char isLetter])) ifTrue: [
|
|
^ PPCMessagePredicateNode new
|
|
name: node name;
|
|
message: #isLetter;
|
|
predicate: node predicate;
|
|
yourself
|
|
].
|
|
|
|
|
|
(charSet equals: (PPCharSetPredicate on: [ :char | char isDigit])) ifTrue: [
|
|
^ PPCMessagePredicateNode new
|
|
name: node name;
|
|
message: #isDigit;
|
|
predicate: node predicate;
|
|
yourself
|
|
].
|
|
|
|
(charSet equals: (PPCharSetPredicate on: [ :char | char isAlphaNumeric])) ifTrue: [
|
|
^ PPCMessagePredicateNode new
|
|
name: node name;
|
|
message: #isAlphaNumeric;
|
|
predicate: node predicate;
|
|
yourself
|
|
].
|
|
|
|
(charSet equals: (PPCharSetPredicate on: [ :char | char isSeparator])) ifTrue: [
|
|
^ PPCMessagePredicateNode new
|
|
name: node name;
|
|
message: #isSeparator;
|
|
predicate: node predicate;
|
|
yourself
|
|
].
|
|
|
|
(charSet equals: (PPCharSetPredicate on: [ :char | true ])) ifTrue: [
|
|
^ PPCAnyNode new
|
|
name: node name;
|
|
yourself
|
|
].
|
|
|
|
^ PPCCharSetPredicateNode new
|
|
name: node name;
|
|
predicate: charSet;
|
|
yourself.
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitStarNode: node [
|
|
self visitChildren: node.
|
|
|
|
(node child isKindOf: PPCMessagePredicateNode) ifTrue: [
|
|
^ PPCStarMessagePredicateNode new
|
|
name: node name;
|
|
child: node child;
|
|
message: node child message;
|
|
yourself
|
|
].
|
|
|
|
(node child isKindOf: PPCAnyNode) ifTrue: [
|
|
^ PPCStarAnyNode new
|
|
name: node name;
|
|
child: node child;
|
|
yourself
|
|
].
|
|
|
|
(node child isKindOf: PPCCharSetPredicateNode) ifTrue: [
|
|
^ PPCStarCharSetPredicateNode new
|
|
name: node name;
|
|
predicate: node child predicate;
|
|
child: node child;
|
|
yourself
|
|
].
|
|
|
|
^ node
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitTokenConsumeNode: node [
|
|
"Let the Scanner to handle this stuff"
|
|
^ node
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitTokenizingParserNode: node [
|
|
self visitChild: node parser of: node.
|
|
^ node
|
|
]
|
|
|
|
{ #category : 'visiting' }
|
|
PPCSpecializingVisitor >> visitTrimmingTokenNode: node [
|
|
|
|
self visitChildren: node.
|
|
|
|
(node child isKindOf: PPCCharacterNode) ifTrue: [
|
|
^ PPCTrimmingCharacterTokenNode new
|
|
child: node child;
|
|
whitespace: node whitespace;
|
|
tokenClass: node tokenClass;
|
|
character: node child character;
|
|
name: node name;
|
|
yourself
|
|
].
|
|
|
|
^ node
|
|
|
|
"Modified: / 21-05-2015 / 14:41:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
|
]
|