compiler/PPCTokenizingCodeGenerator.st
changeset 525 751532c8f3db
parent 516 3b81c9e53352
parent 524 f6f68d32de73
equal deleted inserted replaced
523:09afcf28ed60 525:751532c8f3db
     1 "{ Package: 'stx:goodies/petitparser/compiler' }"
     1 "{ Package: 'stx:goodies/petitparser/compiler' }"
     2 
     2 
     3 "{ NameSpace: Smalltalk }"
     3 "{ NameSpace: Smalltalk }"
     4 
     4 
     5 PPCCodeGenerator subclass:#PPCTokenizingCodeGenerator
     5 PPCCodeGenerator subclass:#PPCTokenizingCodeGenerator
     6 	instanceVariableNames:'tokenGenerator'
     6 	instanceVariableNames:''
     7 	classVariableNames:''
     7 	classVariableNames:''
     8 	poolDictionaries:''
     8 	poolDictionaries:''
     9 	category:'PetitCompiler-Visitors'
     9 	category:'PetitCompiler-Visitors-CodeGenerators'
    10 !
    10 !
    11 
    11 
    12 
    12 
    13 !PPCTokenizingCodeGenerator methodsFor:'accessing'!
    13 !PPCTokenizingCodeGenerator methodsFor:'accessing'!
    14 
    14 
    15 guards
    15 guards
       
    16     self flag: 'Hack alert, the codeGenerator needs refactoring so that we can remove this method'.
       
    17     self halt: 'deprecated'.
    16     "When tokenizing, do not use guards"
    18     "When tokenizing, do not use guards"
    17     ^ false
    19     ^ false
    18 !
       
    19 
       
    20 tokenGenerator
       
    21     self error: 'deprecated'.
       
    22     
       
    23     tokenGenerator isNil ifTrue: [ 
       
    24         tokenGenerator := (PPCTokenCodeGenerator on: compiler)
       
    25             arguments: arguments;
       
    26             yourself.
       
    27     ].
       
    28     ^ tokenGenerator
       
    29 !
       
    30 
       
    31 tokenGenerator: whatever
       
    32     tokenGenerator := whatever
       
    33 !
       
    34 
       
    35 tokenGuards
       
    36     "When tokenizing, do not use guards"
       
    37     ^ arguments guards
       
    38 ! !
    20 ! !
    39 
    21 
    40 !PPCTokenizingCodeGenerator methodsFor:'guards'!
    22 !PPCTokenizingCodeGenerator methodsFor:'initialization'!
    41 
    23 
    42 addGuard: node ifTrue: trueBlock ifFalse: falseBlock
    24 initialize
    43     |  guard id |
    25     super initialize.
    44     guard := PPCTokenGuard on: node.
       
    45     (self guards not or: guard makesSense not) ifTrue: [ ^ false ].
       
    46     
    26     
    47     id := compiler idFor: guard firstToken.
    27     codeGen := PPCTokenizingCodeGen new
    48 
       
    49     compiler add: 'self ', id asString.
       
    50 
       
    51     trueBlock isNil ifFalse: [ 
       
    52         compiler addOnLine: ' ifTrue: ['.
       
    53         compiler indent.
       
    54         trueBlock value.
       
    55         compiler dedent.
       
    56         falseBlock isNil 	ifTrue: [ compiler addOnLine: '].' ]
       
    57                               		ifFalse: [ compiler add: ']'. ]
       
    58     ].
       
    59     falseBlock isNil ifFalse: [ 
       
    60         compiler addOnLine: ' ifFalse: ['.
       
    61         compiler indent.
       
    62         falseBlock value.
       
    63         compiler dedent.
       
    64         compiler addOnLine: '].'.
       
    65     ].
       
    66     ^ true
       
    67 ! !
       
    68 
       
    69 !PPCTokenizingCodeGenerator methodsFor:'scanner'!
       
    70 
       
    71 compileScanner
       
    72     compiler addConstant: self tokenGenerator compileScanner as: #scannerClass.
       
    73 ! !
    28 ! !
    74 
    29 
    75 !PPCTokenizingCodeGenerator methodsFor:'visiting'!
    30 !PPCTokenizingCodeGenerator methodsFor:'visiting'!
    76 
    31 
    77 visitAndNode: node
    32 visitAndNode: node
    78     | mementoVar currentTokenVar |
    33     | mementoVar  |
    79     
    34     
    80     mementoVar := compiler allocateTemporaryVariableNamed: 'memento'.
    35     mementoVar := codeGen allocateTemporaryVariableNamed: 'memento'.
    81     currentTokenVar := compiler allocateTemporaryVariableNamed: 'currentToken'.
    36     codeGen remember: node child to: mementoVar.
    82 
    37 
    83     compiler smartRemember: node child to: mementoVar.
    38     codeGen 
    84     compiler codeAssign: '{ currentTokenValue . currentTokenType }.' to: currentTokenVar.
    39           codeEvaluateAndAssign:[ self visit:node child ]
    85 
       
    86     compiler 
       
    87           codeAssignParsedValueOf:[ self visit:node child ]
       
    88           to:self retvalVar.
    40           to:self retvalVar.
    89 
    41 
    90     compiler smartRestore: node child from: mementoVar.
    42     codeGen restore: node child from: mementoVar.
    91     compiler codeAssign: '(', currentTokenVar, ' at: 1).' to: 'currentTokenValue'.
    43     codeGen codeReturn.
    92     compiler codeAssign: '(', currentTokenVar, ' at: 2).' to: 'currentTokenType'.
       
    93 
       
    94     compiler codeReturn.
       
    95 !
    44 !
    96 
    45 
    97 visitChoiceNode: node
    46 visitChoiceNode: node
    98 "       true ifTrue: [ ^ super visitChoiceNode: node ]."
    47 "       true ifTrue: [ ^ super visitChoiceNode: node ]."
    99     | possibleError |
    48     | possibleError memento |
   100     possibleError := true.
    49     possibleError := true.
       
    50 
       
    51     memento := codeGen allocateTemporaryVariableNamed: 'memento'.
       
    52     codeGen codeScannerRememberTo: memento.
   101 
    53 
   102     node children do: [ :child |
    54     node children do: [ :child |
   103         | tokenMethodName |
    55         | tokenMethodName |
   104 
    56 
   105         "TODO: JK: fix this in a proper way. Commented for now to make LRPParser cimpilable 
       
   106          with tokenizing"
       
   107         child acceptsEpsilon "false" ifTrue: [  
    57         child acceptsEpsilon "false" ifTrue: [  
   108             possibleError := false.
    58             possibleError := false.
   109             compiler codeIf: 'true' then: [ 
    59             codeGen codeEvaluateAndAssign:[ self visit:child ] to:self retvalVar.
   110                 compiler codeAssignParsedValueOf:[ self visit:child ] to:self retvalVar.
    60             codeGen codeReturn.
   111                 compiler codeReturn
    61             "makes no sense to compile more..."
   112             ].
    62             ^ self
   113         ] ifFalse: [
    63         ] ifFalse: [
   114             child firstSetWithTokens do: [ :first |
    64             child firstSetWithTokens do: [ :first |
   115                 "For each child, for each first compile this:"
    65                 "For each child, for each first compile this:"
   116             
    66             
   117                 tokenMethodName := compiler idFor: first.
    67                 tokenMethodName := codeGen idFor: first.
   118                 compiler add: '(self ', tokenMethodName asString, ')'.
    68                 codeGen codeIf: '(scanner ', tokenMethodName asString, ')' then: [ 
   119                 compiler addOnLine: ' ifTrue: ['.
    69                     codeGen codeEvaluateAndAssignParsedValueOf:[ self visit:child ] to:self retvalVar.
   120                 compiler indent.
    70                     codeGen codeIf: 'error' then: [ 
   121                     compiler codeAssignParsedValueOf:[ self visit:child ] to:self retvalVar.
    71                         codeGen codeClearError.
   122                     compiler add: 'error ifFalse: ['.
    72                         codeGen codeScannerRestoreFrom: memento.
   123                     compiler indent.
    73                     ] else: [ 
   124                         compiler codeReturn: self retvalVar.
    74                         codeGen codeReturn: self retvalVar.
   125                     compiler dedent.
    75                     ]
   126                     compiler add: '] ifTrue: ['.
    76                 ]
   127                     compiler indent.
       
   128                         compiler codeClearError.
       
   129                         compiler codeAssign: 'nil.' to: 'currentTokenType'.
       
   130                         compiler add: 'context position: currentTokenValue start - 1.'.
       
   131                     compiler dedent.
       
   132                     compiler add: ']'.
       
   133                 compiler dedent.
       
   134                 compiler add: '].'
       
   135             ]
    77             ]
   136         ]
    78         ]
   137     ].
    79     ].
   138     possibleError ifTrue: [
    80     possibleError ifTrue: [
   139         compiler codeError: 'no choice found'.
    81         codeGen codeError: 'no choice found'.
   140     ]
    82     ]
   141 
    83 
   142     "Modified: / 31-07-2015 / 08:07:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    84     "Modified: / 31-07-2015 / 08:07:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   143 !
    85 !
   144 
    86 
   145 visitDeterministicChoiceNode: node
    87 visitDeterministicChoiceNode: node
   146     | dictionary isInlined |
    88     | dictionary isInlined |
   147     dictionary := IdentityDictionary new.
    89     dictionary := IdentityDictionary new.
   148     
    90     
       
    91 "	codeGen currentMethod methodName asSymbol = #'ch' ifTrue: [ self halt ]."
   149     isInlined := node isMarkedForInline.
    92     isInlined := node isMarkedForInline.
   150     
    93     
   151     node children do: [ :child |
    94     node children do: [ :child |
   152         | firstSet |
    95         | firstSet |
   153         firstSet := child firstSetWithTokens.
    96         firstSet := child firstSetWithTokens.
   157     "Tokens are unique"
   100     "Tokens are unique"
   158     self assert: dictionary values asSet size = node children size.
   101     self assert: dictionary values asSet size = node children size.
   159     
   102     
   160     node children do: [ :child |
   103     node children do: [ :child |
   161         | tokenMethodName |
   104         | tokenMethodName |
   162         tokenMethodName := compiler idFor: (dictionary at: child).
   105         tokenMethodName := codeGen idFor: (dictionary at: child).
   163         compiler add: '(self ', tokenMethodName asString, ')'.
   106         codeGen code: '(scanner ', tokenMethodName asString, ')'.
   164         compiler addOnLine: ' ifTrue: ['.
   107         codeGen codeOnLine: ' ifTrue: ['.
   165         compiler indent.
   108         codeGen indent.
   166         compiler codeReturnParsedValueOf:[ self visit:child ].
   109         codeGen codeReturnParsedValueOf:[ self visit:child ].
   167         compiler dedent.
   110         codeGen dedent.
   168         isInlined ifTrue:[
   111         isInlined ifTrue:[
   169             compiler add: '] ifFalse: ['
   112             codeGen code: '] ifFalse: ['
   170         ] ifFalse:[
   113         ] ifFalse:[
   171             compiler add: '].'.
   114             codeGen code: '].'.
   172         ]
   115         ]
   173     ].
   116     ].
   174     compiler codeError: 'no choice found'.
   117     codeGen codeError: 'no choice found'.
   175     isInlined ifTrue:[
   118     isInlined ifTrue:[
   176         node children size timesRepeat: [ compiler addOnLine: ']' ].
   119         node children size timesRepeat: [ codeGen addOnLine: ']' ].
   177         compiler addOnLine: '.'.
   120         codeGen codeOnLine: '.'.
   178     ]
   121     ]
   179 
   122 
   180     "Modified: / 21-05-2015 / 15:31:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   123     "Modified: / 21-05-2015 / 15:31:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   181 !
   124 !
   182 
   125 
   183 visitTokenChoiceNode: node
       
   184     | trimmingToken |
       
   185     self assert: (node children allSatisfy: [ :e | e isMarkedForInline not ]).
       
   186     
       
   187     node children do: [ :child |
       
   188         self tokenGenerator visit: child
       
   189     ]
       
   190     
       
   191 "	
       
   192     trimmingToken := node children detect: [ :e | e isTrimmingTokenNode ] ifNone: [ nil ].
       
   193     trimmingToken isNil ifFalse: [ 
       
   194         compiler codeStoreValueOf: [ self visit: trimmingToken whitespace ] intoVariable: #whatever.
       
   195     ].
       
   196     super visitChoiceNode: node."
       
   197 !
       
   198 
       
   199 visitTokenConsumeNode: node
   126 visitTokenConsumeNode: node
   200     "dont do anything here"
   127     | id |
   201     ^ node
   128     id := codeGen idFor: node.
       
   129     codeGen codeReturn: 'scanner ', id, ' ifNil: [ error := true ].'.
   202 !
   130 !
   203 
   131 
   204 visitTokenNode: node
   132 visitTokenNode: node
   205     self error: 'should not happen!!'
   133     self error: 'should not happen!!'
   206 !
   134 !
   207 
   135 
   208 visitTokenizingParserNode: node
   136 visitTokenizingParserNode: node
   209     self visit: node whitespace.
   137     codeGen codeHaltIfShiftPressed.
   210     
   138     codeGen 
   211     compiler codeHaltIfShiftPressed.
   139           codeEvaluateAndAssign:[ self visit:node parser ]
   212     compiler 
       
   213           codeAssignParsedValueOf:[ self visit:node parser ]
       
   214           to:self retvalVar.
   140           to:self retvalVar.
   215     compiler codeReturn.
   141     codeGen codeReturn.
   216 !
   142 !
   217 
   143 
   218 visitTrimmingTokenCharacterNode: node
   144 visitTrimmingTokenCharacterNode: node
   219     self error: 'should not happen!!'
   145     self error: 'should not happen!!'
   220 !
   146 !