1
1
'use strict' ;
2
2
3
- const cradle = require ( './cradle' ) ;
3
+ const cradle = require ( './cradle' ) ,
4
+ q = require ( 'q' ) ;
4
5
5
6
const look = cradle . look ,
6
7
expected = cradle . expected ,
8
+ getName = cradle . getName ,
7
9
getChar = cradle . getChar ,
10
+ getNum = cradle . getNum ,
8
11
init = cradle . init ,
9
12
emitLn = cradle . emitLn ,
10
- match = cradle . match ;
13
+ match = cradle . match ,
14
+ isAlpha = cradle . isAlpha ;
11
15
12
16
13
17
function isBoolean ( c ) {
@@ -54,19 +58,63 @@ function boolExpression() {
54
58
} ) ;
55
59
}
56
60
61
+
62
+
63
+
57
64
function boolTerm ( ) {
58
- let nextChar = look ( ) ;
59
- if ( ! isBoolean ( nextChar ) ) return expected ( 'Boolean Literal' ) ;
60
- return getBoolean ( )
61
- . then ( ( myBool ) => {
62
- if ( myBool ) {
63
- emitLn ( 'MOVE #-1,D0' )
64
- } else {
65
- emitLn ( 'CLR D0' ) ;
66
- }
65
+ function boolTermInner ( ) {
66
+ let nextChar = look ( ) ;
67
+ if ( nextChar === '&' ) {
68
+ emitLn ( 'MOVE D0,-(SP)' ) ;
69
+ return match ( '&' )
70
+ . then ( ( ) => {
71
+ return notFactor ( ) ;
72
+ } )
73
+ . then ( ( ) => {
74
+ emitLn ( 'AND (SP)+,D0' ) ;
75
+ return boolTermInner ( ) ;
76
+ } ) ;
77
+ }
78
+ }
79
+ return notFactor ( )
80
+ . then ( ( ) => {
81
+ return boolTermInner ( ) ;
67
82
} ) ;
68
83
}
69
84
85
+
86
+ function boolFactor ( ) {
87
+ let nextChar = look ( ) ;
88
+ if ( isBoolean ( nextChar ) ) {
89
+ return getBoolean ( )
90
+ . then ( ( myBool ) => {
91
+ if ( myBool ) {
92
+ emitLn ( 'MOVE #-1,D0' )
93
+ } else {
94
+ emitLn ( 'CLR D0' ) ;
95
+ }
96
+ } ) ;
97
+ } else {
98
+ return relation ( ) ;
99
+ }
100
+ }
101
+
102
+ function notFactor ( ) {
103
+ let nextChar = look ( ) ;
104
+
105
+ if ( nextChar === '!' ) {
106
+ return match ( '!' )
107
+ . then ( ( ) => {
108
+ return boolFactor ( ) ;
109
+ } )
110
+ . then ( ( ) => {
111
+ emitLn ( 'EOR #-1,D0' ) ;
112
+ } ) ;
113
+ } else {
114
+ return boolFactor ( ) ;
115
+ }
116
+ }
117
+
70
118
function isOrOp ( c ) {
71
119
return c === '|' || c === '~' ;
72
120
}
@@ -91,11 +139,253 @@ function boolXor() {
91
139
} )
92
140
}
93
141
142
+ function isRelOp ( c ) {
143
+ return c === '=' || c === '#' || c === '<' || c === '>' ;
144
+ }
145
+
146
+ function equals ( ) {
147
+ return match ( '=' )
148
+ . then ( ( ) => {
149
+ return expression ( ) ;
150
+ } )
151
+ . then ( ( ) => {
152
+ emitLn ( 'CMP (SP)+,D0' ) ;
153
+ emitLn ( 'SEQ D0' ) ;
154
+ } ) ;
155
+ }
156
+
157
+ function notEquals ( ) {
158
+ return match ( '#' )
159
+ . then ( ( ) => {
160
+ return expression ( ) ;
161
+ } )
162
+ . then ( ( ) => {
163
+ emitLn ( 'CMP (SP)+,D0' ) ;
164
+ emitLn ( 'SNE D0' ) ;
165
+ } ) ;
166
+ }
167
+
168
+ function less ( ) {
169
+ return match ( '<' )
170
+ . then ( ( ) => {
171
+ return expression ( ) ;
172
+ } )
173
+ . then ( ( ) => {
174
+ emitLn ( 'CMP (SP)+,D0' ) ;
175
+ emitLn ( 'SGE D0' ) ;
176
+ } ) ;
177
+ }
178
+
179
+ function greater ( ) {
180
+ return match ( '>' )
181
+ . then ( ( ) => {
182
+ return expression ( ) ;
183
+ } )
184
+ . then ( ( ) => {
185
+ emitLn ( 'CMP (SP)+,D0' ) ;
186
+ emitLn ( 'SLE D0' ) ;
187
+ } ) ;
188
+ }
189
+
190
+ function relation ( ) {
191
+ return expression ( )
192
+ . then ( ( ) => {
193
+ let nextChar = look ( ) ;
194
+ if ( isRelOp ( nextChar ) ) {
195
+ emitLn ( 'MOVE D0,-(SP)' ) ;
196
+ let nextStep ;
197
+ switch ( nextChar ) {
198
+ case '=' :
199
+ nextStep = equals ;
200
+ break ;
201
+ case '#' :
202
+ nextStep = notEquals ;
203
+ break ;
204
+ case '<' :
205
+ nextStep = less ;
206
+ break ;
207
+ case '>' :
208
+ nextStep = greater ;
209
+ break ;
210
+ }
211
+ return nextStep ( )
212
+ . then ( ( ) => {
213
+ emitLn ( 'TST D0' ) ;
214
+ } ) ;
215
+ }
216
+ } ) ;
217
+ }
218
+
219
+ function expression ( ) {
220
+ let nextChar = look ( ) ;
221
+ return q ( )
222
+ . then ( ( ) => {
223
+ if ( isAddOp ( nextChar ) ) {
224
+ emitLn ( 'CLR D0' )
225
+ } else {
226
+ return term ( ) ;
227
+ }
228
+ } )
229
+ . then ( ( ) => {
230
+ return expressionTail ( ) ;
231
+ } ) ;
232
+ }
233
+
234
+ function expressionTail ( ) {
235
+ let nextChar = look ( ) ;
236
+ if ( isAddOp ( nextChar ) ) {
237
+ emitLn ( 'MOVE D0,-(SP)' ) ;
238
+ return q ( )
239
+ . then ( ( ) => {
240
+ let nextChar = look ( ) ;
241
+ switch ( nextChar ) {
242
+ case '+' :
243
+ return add ( ) ;
244
+ case '-' :
245
+ return subtract ( ) ;
246
+ }
247
+ } )
248
+ . then ( ( ) => {
249
+ return expressionTail ( ) ;
250
+ } ) ;
251
+ } else {
252
+ return ;
253
+ }
254
+ }
255
+
256
+ function isAddOp ( c ) {
257
+ return ( c === '+' || c === '-' )
258
+ }
259
+
260
+ function term ( ) {
261
+ return factor ( )
262
+ . then ( ( ) => {
263
+ return termTail ( ) ;
264
+ } ) ;
265
+ }
266
+
267
+ function divide ( ) {
268
+ return match ( '/' )
269
+ . then ( ( ) => {
270
+ return factor ( )
271
+ } )
272
+ . then ( ( ) => {
273
+ emitLn ( 'MOVE (SP)+,D1' ) ;
274
+ emitLn ( 'DIVS D1,D0' ) ;
275
+ } ) ;
276
+ }
277
+ function termTail ( ) {
278
+ let nextChar = look ( ) ;
279
+ if ( nextChar === '*' || nextChar === '/' ) {
280
+ emitLn ( 'MOVE D0,-(SP)' ) ;
281
+ return q ( )
282
+ . then ( ( ) => {
283
+ let nextChar = look ( ) ;
284
+ switch ( nextChar ) {
285
+ case '*' :
286
+ return multiply ( ) ;
287
+ case '/' :
288
+ return divide ( ) ;
289
+ }
290
+ } )
291
+ . then ( ( ) => {
292
+ return termTail ( ) ;
293
+ } ) ;
294
+ } else {
295
+ return ;
296
+ }
297
+ }
298
+
299
+ function multiply ( ) {
300
+ return match ( '*' )
301
+ . then ( ( ) => {
302
+ return factor ( )
303
+ } )
304
+ . then ( ( ) => {
305
+ emitLn ( 'MULS (SP)+,D0' ) ;
306
+ } ) ;
307
+ }
308
+
309
+ function divide ( ) {
310
+ return match ( '/' )
311
+ . then ( ( ) => {
312
+ return factor ( )
313
+ } )
314
+ . then ( ( ) => {
315
+ emitLn ( 'MOVE (SP)+,D1' ) ;
316
+ emitLn ( 'DIVS D1,D0' ) ;
317
+ } ) ;
318
+ }
319
+
320
+ function factor ( ) {
321
+ let nextChar = look ( ) ;
322
+ if ( nextChar === '(' ) {
323
+ return match ( '(' )
324
+ . then ( ( ) => {
325
+ return expression ( ) ;
326
+ } )
327
+ . then ( ( ) => {
328
+ return match ( ')' ) ;
329
+ } ) ;
330
+ } else if ( isAlpha ( nextChar ) ) {
331
+ return ident ( ) ;
332
+ } else {
333
+ return getNum ( )
334
+ . then ( ( num ) => {
335
+ emitLn ( 'MOVE #' + num + ',D0' ) ;
336
+ } ) ;
337
+ }
338
+ }
339
+
340
+ function add ( ) {
341
+ return match ( '+' )
342
+ . then ( ( ) => {
343
+ return term ( ) ;
344
+ } )
345
+ . then ( ( ) => {
346
+ emitLn ( 'ADD (SP)+,D0' ) ;
347
+ } ) ;
348
+ }
349
+
350
+ function subtract ( ) {
351
+ return match ( '-' )
352
+ . then ( ( ) => {
353
+ return term ( )
354
+ } )
355
+ . then ( ( ) => {
356
+ emitLn ( 'SUB (SP)+,D0' ) ;
357
+ emitLn ( 'NEG D0' ) ;
358
+ } ) ;
359
+ }
360
+
361
+ function ident ( ) {
362
+ return getName ( )
363
+ . then ( ( name ) => {
364
+ let nextChar = look ( ) ;
365
+ if ( nextChar === '(' ) {
366
+ return match ( '(' )
367
+ . then ( ( ) => {
368
+ return match ( ')' ) ;
369
+ } )
370
+ . then ( ( ) => {
371
+ emitLn ( 'BSR ' + name ) ;
372
+ } ) ;
373
+ } else {
374
+ emitLn ( 'MOVE ' + name + '(PC),D0' ) ;
375
+ }
376
+ } ) ;
377
+ }
378
+
379
+
380
+
94
381
95
382
init ( )
96
383
. then ( ( ) => {
97
384
return boolExpression ( ) ;
98
385
} )
386
+ . then ( ( ) => {
387
+ emitLn ( 'END START' ) ;
388
+ } )
99
389
. catch ( ( err ) => {
100
390
console . log ( err . stack ) ;
101
391
} )
0 commit comments