PetitCommonMark/software/petitcompiler/PPCSpecializingVisitor.class.st

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