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