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