PetitCommonMark/software/petitcompiler/PPCFSAVisitor.class.st

152 lines
3.7 KiB
Smalltalk

"
I create following:
- FSAs equivalents for tokens
- FSAs for followSetsWithTokens
"
Class {
#name : 'PPCFSAVisitor',
#superclass : 'PPCPassVisitor',
#instVars : [
'fsaCache',
'idGen'
],
#category : 'PetitCompiler-Visitors'
}
{ #category : 'accessing' }
PPCFSAVisitor >> idGen: anObject [
idGen := anObject
]
{ #category : 'initialization' }
PPCFSAVisitor >> initialize [
super initialize.
"for the given set of nodes, remember the unordered choice fsa
see `unorderedChoiceFromFollowSet:`
"
fsaCache := Dictionary new.
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> unorderedChoiceFromFsas: fsas [
| result startState |
result := PEGFsa new.
startState := PEGFsaState new.
result addState: startState.
result startState: startState.
fsas do: [ :fsa |
result adopt: fsa.
result addTransitionFrom: startState to: fsa startState.
].
result determinizeStandard.
^ result
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> unorderedChoiceFromSet: aSet [
| followFsas |
^ fsaCache at: aSet ifAbsentPut: [
followFsas := aSet collect: [ :followNode |
followNode asFsa
name: (context idGenerator idFor: followNode);
retval: (context idGenerator idFor: followNode);
yourself
].
self unorderedChoiceFromFsas: followFsas.
]
"Modified: / 03-09-2015 / 21:28:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> visitChoiceNode: node [
| anFsa firstSet |
super visitChoiceNode: node.
firstSet := node firstSetWithTokens.
anFsa := self unorderedChoiceFromSet: firstSet.
anFsa name: (context idGenerator idFor: anFsa defaultName: node defaultName prefix: 'firstOf').
node firstFsa: anFsa.
node children do: [ :child |
firstSet := child firstSetWithTokens.
anFsa := self unorderedChoiceFromSet: firstSet.
anFsa name: 'firstOf_', (context idGenerator idFor: anFsa defaultName: child defaultName prefix: 'firstOf').
child firstFsa: anFsa.
].
^ node
"Modified: / 03-09-2015 / 21:27:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> visitToken: tokenNode [
| anFsa |
anFsa := tokenNode asFsa determinize.
anFsa name: (context idGenerator idFor: tokenNode).
anFsa retval: (context idGenerator idFor: tokenNode).
tokenNode fsa: anFsa.
^ tokenNode
"Modified: / 03-09-2015 / 21:27:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> visitTokenConsumeNode: node [
| epsilon anFsa followSet |
followSet := node followSetWithTokens.
epsilon := followSet anySatisfy: [ :e | e acceptsEpsilon ].
followSet := followSet reject: [ :e | e acceptsEpsilon ].
epsilon ifTrue: [ followSet add: PPCEndOfFileNode instance ].
anFsa := self unorderedChoiceFromSet: followSet.
anFsa name: (context idGenerator idFor: anFsa defaultName: node defaultName prefix: 'nextToken').
node nextFsa: anFsa.
"Modified: / 03-09-2015 / 21:27:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> visitTokenNode: node [
^ self visitToken: node
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> visitTokenizingParserNode: node [
"TODO JK: hack alert, change the handling of WS!"
self visitWhitespace: node whitespace.
self visit: node tokens.
self visit: node parser.
^ node
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> visitTrimmingTokenNode: node [
^ self visitToken: node
]
{ #category : 'as yet unclassified' }
PPCFSAVisitor >> visitWhitespace: node [
"JK HACK: treat ws as token -> create FSA for whitespace"
| retval |
retval := self visitToken: node.
"we don't care about the finals of whitespace"
node fsa removeFinals.
^ retval
]