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 ! |