compiler/PPCFSACodeGen.st
changeset 502 1e45d3c96ec5
child 515 b5316ef15274
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/compiler/PPCFSACodeGen.st	Fri Jul 24 15:06:54 2015 +0100
@@ -0,0 +1,211 @@
+"{ Package: 'stx:goodies/petitparser/compiler' }"
+
+"{ NameSpace: Smalltalk }"
+
+PPCCodeGen subclass:#PPCFSACodeGen
+	instanceVariableNames:'fsa backlinkStates'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'PetitCompiler-Scanner'
+!
+
+!PPCFSACodeGen methodsFor:'accessing'!
+
+methodCategory
+    ^ 'generated - scanning'
+! !
+
+!PPCFSACodeGen methodsFor:'analysis'!
+
+beginOfRange: characterSet
+    characterSet withIndexDo: [ :e :index | 
+        e ifTrue: [ ^ index ]
+    ].
+    self error: 'should not happend'
+!
+
+endOfRange: characterSet
+    | change |
+    change := false.
+    characterSet withIndexDo: [ :e :index | 
+        e ifTrue: [ change := true ].
+        (e not and: [ change ]) ifTrue: [ ^ index - 1]
+    ].
+    ^ characterSet size
+!
+
+isLetter: characterSet
+    | changes previous |
+    changes := 0.
+    previous := false.
+    characterSet withIndexDo: [ :e :index |
+        (e == (Character codePoint: index) isLetter) ifFalse: [ ^ false ].
+    ].
+    ^ true
+!
+
+isSingleCharacter: characterSet
+    ^ (characterSet select: [ :e | e ]) size = 1
+!
+
+isSingleRange: characterSet
+    | changes previous |
+    changes := 0.
+    previous := false.
+    characterSet do: [ :e | 
+        (e == previous) ifFalse: [ changes := changes + 1 ].
+        previous := e.
+    ].
+    ^ changes < 3
+! !
+
+!PPCFSACodeGen methodsFor:'coding'!
+
+codeAbsoluteReturn: code
+    self add: '^ ', code
+!
+
+codeAssertPeek: characterSet
+    | character id extendedCharacterSet |
+    
+    (self isSingleCharacter: characterSet) ifTrue: [ 
+        character := self character: characterSet.
+        self addOnLine: 'self peek == ', character storeString.
+        ^ self
+    ].
+
+    (self isLetter: characterSet) ifTrue: [ 
+        self addOnLine: 'self peek isLetter'.
+        ^ self
+    ].
+
+    (self isSingleRange: characterSet) ifTrue: [ 
+        | begin end |
+        begin := self beginOfRange: characterSet.
+        end := self endOfRange: characterSet.
+        self addOnLine: 'self peekBetween: ', begin asString, ' and: ', end asString.
+        ^ self
+    ].
+
+    extendedCharacterSet := (characterSet asOrderedCollection addLast: false; yourself) asArray.
+    id := self idFor: characterSet prefixed: 'characterSet'.
+    
+    self addConstant: extendedCharacterSet as: id.
+    self addOnLine: id, ' at: self peek asInteger'.
+!
+
+codeAssertPeek: characterSet ifTrue: block
+    self addOnLine: '('.
+    self codeAssertPeek: characterSet.
+    self addOnLine: ') ifTrue: ['.
+    self indent.
+    self code: block.
+    self dedent.
+    self add: ']'.
+!
+
+codeAssertPeek: characterSet orReturn: priority
+    self add: '('.
+    self codeAssertPeek: characterSet.
+    self addOnLine: ') ifFalse: [ '.
+    self codeReturnResult: priority.
+    self addOnLine: ']'.
+    self codeDot.
+!
+
+codeAssertPeek: characterSet whileTrue: block
+    self add: '['.
+    self codeAssertPeek: characterSet.
+    self addOnLine: '] whileTrue: ['.
+    self indent.
+    self code: block.
+    self dedent.
+    self add: '].'.
+    self nl.
+!
+
+codeEndBlock
+    self dedent.	
+    self add: ']'.
+!
+
+codeEndBlockWhileTrue
+    self dedent.	
+    self add: '] whileTrue.'.
+!
+
+codeIfFalse
+    self addOnLine: ' ifFalse: ['.
+!
+
+codeNextChar
+    self add: 'self step.'
+!
+
+codeNl
+    self add: ''.
+!
+
+codeNlAssertPeek: characterSet
+    self add: ''.
+    self codeAssertPeek: characterSet.
+!
+
+codeNlReturnResult
+    self add: '^ self return.'
+!
+
+codeNlReturnResult: priority
+    priority isNil ifTrue: [ 
+        ^ self codeNlReturnResult
+    ].
+    self add: '^ self returnPriority: ', priority asString, '.'
+!
+
+codeRecordMatch: state
+    self add: 'self recordMatch: ', state storeString, '.'
+!
+
+codeRecordMatch: state priority: priority
+    priority isNil ifTrue: [ 
+        ^ self codeRecordMatch: state
+    ].
+    
+    self add: 'self recordMatch: ', state storeString, ' priority: ', priority asString, '.'
+!
+
+codeReturnResult
+    self addOnLine: '^ self return.'
+!
+
+codeReturnResult: priority
+    priority isNil ifTrue: [ 
+        ^ self codeReturnResult
+    ].
+
+    self addOnLine: '^ self returnPriority: ', priority asString, '.'
+!
+
+codeStartBlock
+    self add: '['.
+    self indent.
+! !
+
+!PPCFSACodeGen methodsFor:'helpers'!
+
+character: characterSet
+    self assert: (self isSingleCharacter: characterSet).
+    characterSet withIndexDo: [ :e :index | e ifTrue: [ ^ Character codePoint: index ] ].
+    
+    self error: 'should not happen'
+! !
+
+!PPCFSACodeGen methodsFor:'intitialization'!
+
+initialize
+    super initialize.
+    backlinkStates := IdentityDictionary new.
+
+    "Modified: / 24-07-2015 / 15:03:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+