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