~ubuntu-branches/ubuntu/precise/plib/precise

« back to all changes in this revision

Viewing changes to src/psl/pslCompiler.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Philipp Frauenfelder
  • Date: 2004-08-26 23:31:16 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20040826233116-vqusvk3ytn6lq3rl
Tags: 1.8.3-2
* Corrected C++ syntax in ssgAux/ssgaSky.h. Thanks to
  neuro.harald AT surfeu.at for the patch. Closes: #260355
* Build-Depends on libx11-dev, libxmu-dev instead of xlibs-dev
* Removed build depends on g++, libc6.
* Changed (build) depends on libgl-dev to xlibmesa-gl-dev | libgl-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
     PLIB - A Suite of Portable Game Libraries
 
3
     Copyright (C) 1998,2002  Steve Baker
 
4
 
 
5
     This library is free software; you can redistribute it and/or
 
6
     modify it under the terms of the GNU Library General Public
 
7
     License as published by the Free Software Foundation; either
 
8
     version 2 of the License, or (at your option) any later version.
 
9
 
 
10
     This library is distributed in the hope that it will be useful,
 
11
     but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
     Library General Public License for more details.
 
14
 
 
15
     You should have received a copy of the GNU Library General Public
 
16
     License along with this library; if not, write to the Free Software
 
17
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
18
 
 
19
     For further information visit http://plib.sourceforge.net
 
20
 
 
21
     $Id: pslCompiler.cxx,v 1.29 2003/01/06 05:10:13 sjbaker Exp $
 
22
*/
 
23
 
 
24
 
 
25
#include "pslLocal.h"
 
26
#include "ul.h"
 
27
 
 
28
 
 
29
int pslCompiler::compile ( const char *fname )
 
30
{
 
31
  char filename [ 1024 ] ;
 
32
  _pslMakeScriptPath ( filename, fname ) ;                        
 
33
 
 
34
  FILE *fd = fopen ( filename, "ra" ) ;
 
35
 
 
36
  if ( fd == NULL )
 
37
  {
 
38
    perror ( "PSL:" ) ;
 
39
    ulSetError ( UL_WARNING, "PSL: Failed while opening '%s' for reading.",
 
40
                                                                  filename );
 
41
    return FALSE ;
 
42
  }
 
43
 
 
44
  return compile ( fd, fname ) ;
 
45
}
 
46
 
 
47
 
 
48
int pslCompiler::compile ( const char *memptr, const char *fname )
 
49
{
 
50
  init () ;
 
51
 
 
52
  _pslPushDefaultFile ( memptr, (fname == NULL) ? progName : fname ) ;
 
53
  genProgram     () ;
 
54
  _pslPopDefaultFile  () ;
 
55
 
 
56
  return cleanup () ;
 
57
}
 
58
 
 
59
 
 
60
int pslCompiler::compile ( FILE *fd, const char *fname )
 
61
{
 
62
  init () ;
 
63
 
 
64
  _pslPushDefaultFile ( fd, (fname == NULL) ? progName : fname ) ;
 
65
  genProgram     () ;
 
66
  _pslPopDefaultFile  () ;
 
67
 
 
68
  return cleanup () ;
 
69
}
 
70
 
 
71
 
 
72
int pslCompiler::cleanup ()
 
73
{
 
74
  const char *dump_env = getenv ( "PSL_DUMP" ) ;
 
75
 
 
76
  if ( num_errors != 0 || num_warnings != 0 )
 
77
    fprintf ( stderr, "PSL: '%s' Compiled with %d Warnings, %d Fatal Errors\n",
 
78
             progName, num_warnings, num_errors ) ;
 
79
 
 
80
  /* If there are errors, prevent the program from running. */
 
81
 
 
82
  if ( num_errors != 0 )
 
83
  {
 
84
    if ( dump_env != NULL &&
 
85
         ulStrEqual ( dump_env, "on_error" ) )
 
86
      dump () ;
 
87
 
 
88
    next_code = 0 ;
 
89
    genCodeByte ( OPCODE_HALT ) ;
 
90
  }
 
91
  else
 
92
  if ( dump_env != NULL &&
 
93
       ulStrEqual ( dump_env, "always" ) )
 
94
    dump () ;
 
95
 
 
96
  return num_errors ;
 
97
}
 
98
 
 
99
 
 
100
 
 
101
int pslCompiler::genReturnStatement ()
 
102
{
 
103
  char c [ MAX_TOKEN ] ;
 
104
 
 
105
  getToken ( c ) ;
 
106
 
 
107
  if ( c [ 0 ] == ';' )   /* Return without data == "return 0" */
 
108
  {
 
109
    ungetToken   ( c ) ;
 
110
    genConstant ( "0.0" ) ;
 
111
  }
 
112
  else
 
113
  {
 
114
    ungetToken     ( c ) ;
 
115
    genExpression () ;
 
116
  }
 
117
 
 
118
  genReturn () ;
 
119
  return TRUE ;
 
120
}
 
121
 
 
122
 
 
123
 
 
124
/* Administer the break/continue jump addresses */
 
125
 
 
126
void pslCompiler::pushBreakToLabel ()
 
127
{
 
128
  if ( next_break >= MAX_LABEL-1 )
 
129
    error ( "Too many nested 'break' contexts" ) ;
 
130
  else
 
131
    breakToAddressStack [ next_break++ ] = next_tmp_label++ ;
 
132
}
 
133
 
 
134
void pslCompiler::pushNoContinue ()
 
135
{
 
136
  continueToAddressStack [ next_continue++ ] = -1 ;
 
137
}
 
138
 
 
139
int pslCompiler::pushContinueToLabel ()
 
140
{
 
141
  if ( next_continue >= MAX_LABEL-1 )
 
142
    error ( "Too many nested 'continue' contexts" ) ;
 
143
  else
 
144
    continueToAddressStack [ next_continue++ ] = next_tmp_label++ ;
 
145
 
 
146
  return next_tmp_label-1 ;
 
147
}
 
148
 
 
149
void pslCompiler::setContinueToLabel ( int which )
 
150
{
 
151
  char s [ 10 ] ;
 
152
  sprintf ( s, "L%d", which ) ;
 
153
  setCodeSymbol ( s, next_code ) ;
 
154
}
 
155
 
 
156
void pslCompiler::popBreakToLabel ()
 
157
{
 
158
  char s [ 10 ] ;
 
159
  sprintf ( s, "L%d", breakToAddressStack[next_break-1] ) ;
 
160
  setCodeSymbol ( s, next_code ) ;
 
161
  next_break-- ;
 
162
}
 
163
 
 
164
void pslCompiler::popContinueToLabel ()
 
165
{
 
166
  next_continue-- ;
 
167
}
 
168
 
 
169
 
 
170
 
 
171
/* Implement actual break and continue statements. */
 
172
 
 
173
int pslCompiler::genBreakStatement ()
 
174
{
 
175
  if ( next_break <= 0 )
 
176
    return error ( "'break' statement is not inside a 'switch' or a loop." ) ;
 
177
 
 
178
  char s [ 10 ] ;
 
179
  sprintf ( s, "L%d", breakToAddressStack [ next_break-1 ] ) ;
 
180
  genJump ( getCodeSymbol ( s, next_code+1 ) ) ;
 
181
  return TRUE ;
 
182
}
 
183
 
 
184
 
 
185
int pslCompiler::genContinueStatement ()
 
186
{
 
187
  if ( next_break <= 0 )
 
188
    return error ( "'continue' statement is not inside a loop." ) ;
 
189
 
 
190
  if ( continueToAddressStack [ next_continue-1 ] < 0 )
 
191
    return error ( "'continue' statement not allowed inside a 'switch'." ) ;
 
192
 
 
193
  char s [ 10 ] ;
 
194
  sprintf ( s, "L%d", continueToAddressStack [ next_continue-1 ] ) ;
 
195
  genJump ( getCodeSymbol ( s, next_code+1 ) ) ;
 
196
  return TRUE ;
 
197
}
 
198
 
 
199
 
 
200
 
 
201
 
 
202
 
 
203
int pslCompiler::genSwitchStatement ()
 
204
{
 
205
  if ( ! genExpression () )
 
206
    return error ( "Missing control expression for 'switch'" ) ;
 
207
 
 
208
  char c [ MAX_TOKEN ] ;
 
209
 
 
210
  getToken ( c ) ;    /* Hopefully, the word 'while' */
 
211
  
 
212
  if ( c [ 0 ] != '{' )
 
213
    return error ( "Missing '{' after 'switch'" ) ;
 
214
 
 
215
  int jumpToNextCase = genJump ( 0 ) ;
 
216
  int jumpAfterTest  = 0 ;
 
217
 
 
218
  pushBreakToLabel () ;
 
219
  pushNoContinue   () ;
 
220
 
 
221
  while ( TRUE )
 
222
  {
 
223
    getToken ( c ) ;
 
224
 
 
225
    if ( strcmp ( c, "case" ) == 0 )
 
226
    {
 
227
      jumpAfterTest = genJump ( 0 ) ;
 
228
 
 
229
      code [ jumpToNextCase   ] =   next_code        & 0xFF ;
 
230
      code [ jumpToNextCase+1 ] = ( next_code >> 8 ) & 0xFF ;
 
231
 
 
232
      genStackDup () ;
 
233
 
 
234
      if ( ! genExpression () )
 
235
        error ( "Missing expression after 'case'." ) ;
 
236
 
 
237
      getToken ( c ) ;
 
238
 
 
239
      if ( c[0] != ':' )
 
240
        error ( "Missing ':' after 'case' expression." ) ;
 
241
 
 
242
      genEqual () ;
 
243
 
 
244
      jumpToNextCase = genJumpIfFalse ( 0 ) ;
 
245
 
 
246
      code [ jumpAfterTest   ] = next_code & 0xFF ;
 
247
      code [ jumpAfterTest+1 ] = ( next_code >> 8 ) & 0xFF ;
 
248
    }
 
249
    else
 
250
    if ( strcmp ( c, "default" ) == 0 )
 
251
    {
 
252
      code [ jumpToNextCase   ] =   next_code        & 0xFF ;
 
253
      code [ jumpToNextCase+1 ] = ( next_code >> 8 ) & 0xFF ;
 
254
 
 
255
      getToken ( c ) ;
 
256
 
 
257
      if ( c[0] != ':' )
 
258
        error ( "Missing ':' after 'default'." ) ;
 
259
    }
 
260
    else
 
261
    if ( strcmp ( c, "}" ) == 0 )
 
262
    {
 
263
      ungetToken ( ";" ) ;
 
264
      break ;
 
265
    }
 
266
    else
 
267
    {
 
268
      ungetToken ( c ) ;
 
269
 
 
270
      if ( ! genStatement () )
 
271
        error ( "Missing statement within switch." ) ;
 
272
 
 
273
      getToken ( c ) ;
 
274
 
 
275
      if ( c [ 0 ] != ';' )
 
276
        error ( "Missing semicolon." ) ;
 
277
    }
 
278
  }
 
279
 
 
280
  popBreakToLabel    () ;
 
281
  popContinueToLabel () ;
 
282
  genPop () ;
 
283
  return TRUE ;
 
284
}
 
285
 
 
286
 
 
287
 
 
288
int pslCompiler::genDoWhileStatement ()
 
289
{
 
290
  /* Remember place to jump back to */
 
291
 
 
292
  int start_loc = next_code ;
 
293
 
 
294
  pushBreakToLabel    () ;
 
295
  setContinueToLabel ( pushContinueToLabel () ) ;
 
296
 
 
297
  if ( ! genStatement () )
 
298
    return error ( "Missing statement for 'do/while'" ) ;
 
299
 
 
300
  char c [ MAX_TOKEN ] ;
 
301
 
 
302
  getToken ( c ) ;    /* The final ';' of the action */
 
303
 
 
304
  getToken ( c ) ;    /* Hopefully, the word 'while' */
 
305
  
 
306
  if ( strcmp ( c, "while" ) != 0 )
 
307
    return error ( "Missing 'while' for 'do/while'" ) ;
 
308
 
 
309
  if ( ! genExpression () )
 
310
    return error ( "Missing expression for 'while' in a 'do/while'" ) ;
 
311
 
 
312
  genJumpIfTrue ( start_loc ) ;
 
313
 
 
314
  popBreakToLabel    () ;
 
315
  popContinueToLabel () ;
 
316
  return TRUE ;
 
317
}
 
318
 
 
319
 
 
320
int pslCompiler::genForStatement ()
 
321
{
 
322
  char c [ MAX_TOKEN ] ;
 
323
 
 
324
  pushLocality        () ;
 
325
  pushBreakToLabel    () ;
 
326
  int ct_lab = pushContinueToLabel () ;
 
327
 
 
328
  getToken ( c ) ;    /* The initial '(' of the action */
 
329
 
 
330
  if ( c [ 0 ] != '(' )
 
331
  {
 
332
    popLocality () ;
 
333
    return error ( "Missing '(' for 'for' loop" ) ;
 
334
  }
 
335
 
 
336
  if ( ! genStatement () )
 
337
  {
 
338
    popLocality () ;
 
339
    return error ( "Missing initialiser for 'if'" ) ;
 
340
  }
 
341
 
 
342
  getToken ( c ) ;    /* The ';' after the initialiser */
 
343
 
 
344
  if ( c [ 0 ] != ';' )
 
345
  {
 
346
    popLocality () ;
 
347
    return error ( "Missing ';' after 'for' loop initialisation" ) ;
 
348
  }
 
349
 
 
350
  /* Remember place to jump back to */
 
351
 
 
352
  int start_loc = next_code ;
 
353
 
 
354
  /* The test */
 
355
 
 
356
  if ( ! genExpression () )
 
357
    return error ( "Missing test for 'for' loop" ) ;
 
358
 
 
359
  getToken ( c ) ;    /* The ';' after the initialiser */
 
360
 
 
361
  if ( c [ 0 ] != ';' )
 
362
  {
 
363
    popLocality () ;
 
364
    return error ( "Missing ';' after 'for' loop test" ) ;
 
365
  }
 
366
 
 
367
  char saved [ MAX_UNGET ][ MAX_TOKEN ] ;
 
368
  int next_saved    = 0 ;
 
369
  int paren_counter = 0 ;
 
370
 
 
371
  do
 
372
  {
 
373
    getToken ( saved [ next_saved ] ) ;
 
374
 
 
375
    if ( saved [ next_saved ][ 0 ] == '(' ) paren_counter++ ;
 
376
    if ( saved [ next_saved ][ 0 ] == ')' ) paren_counter-- ;
 
377
 
 
378
    if ( next_saved >= MAX_UNGET-1 )
 
379
    {
 
380
      popLocality () ;
 
381
      return error ( "Too many tokens in 'increment' part of 'for' loop" ) ;
 
382
    }
 
383
 
 
384
    next_saved++ ;
 
385
 
 
386
  } while ( paren_counter >= 0 ) ;
 
387
 
 
388
  next_saved-- ;  /* Throw away the ')' */
 
389
 
 
390
  int label_loc = genJumpIfFalse ( 0 ) ;
 
391
 
 
392
  if ( ! genStatement () )
 
393
  {
 
394
    popLocality () ;
 
395
    return error ( "Missing action body for 'for' loop" ) ;
 
396
  }
 
397
 
 
398
  setContinueToLabel ( ct_lab ) ;
 
399
 
 
400
  getToken ( c ) ;   /* Throw away the ';' */
 
401
 
 
402
  /* Put the increment test back onto the token stream */
 
403
 
 
404
  ungetToken ( ";" ) ;    
 
405
 
 
406
  for ( int i = next_saved-1 ; i >= 0 ; i-- )
 
407
    ungetToken ( saved[i] ) ;    
 
408
 
 
409
  if ( ! genStatement () )
 
410
  {
 
411
    popLocality () ;
 
412
    return error ( "Missing 'increment' part of 'for' loop" ) ;
 
413
  }
 
414
 
 
415
  genJump ( start_loc ) ;
 
416
 
 
417
  code [ label_loc   ] = next_code & 0xFF ;
 
418
  code [ label_loc+1 ] = ( next_code >> 8 ) & 0xFF ;
 
419
 
 
420
  popBreakToLabel    () ;
 
421
  popContinueToLabel () ;
 
422
  popLocality        () ;
 
423
  return TRUE ;
 
424
}
 
425
 
 
426
 
 
427
int pslCompiler::genWhileStatement ()
 
428
{
 
429
  /* Remember place to jump back to */
 
430
 
 
431
  pushBreakToLabel    () ;
 
432
  setContinueToLabel ( pushContinueToLabel () ) ;
 
433
 
 
434
  int start_loc = next_code ;
 
435
 
 
436
  if ( ! genExpression () )
 
437
    return error ( "Missing expression for 'while'" ) ;
 
438
 
 
439
  int label_loc = genJumpIfFalse ( 0 ) ;
 
440
 
 
441
  if ( ! genStatement () )
 
442
    return error ( "Missing statement for 'while'" ) ;
 
443
 
 
444
  genJump ( start_loc ) ;
 
445
 
 
446
  code [ label_loc   ] = next_code & 0xFF ;
 
447
  code [ label_loc+1 ] = ( next_code >> 8 ) & 0xFF ;
 
448
 
 
449
  popBreakToLabel    () ;
 
450
  popContinueToLabel () ;
 
451
 
 
452
  return TRUE ;
 
453
}
 
454
 
 
455
 
 
456
int pslCompiler::genIfStatement ()
 
457
{
 
458
  if ( ! genExpression () )
 
459
    return error ( "Missing expression for 'if'" ) ;
 
460
 
 
461
  int else_loc = genJumpIfFalse ( 0 ) ;
 
462
 
 
463
  if ( ! genStatement () )
 
464
    return error ( "Missing statement for 'if'" ) ;
 
465
 
 
466
  char c [ MAX_TOKEN ] ;
 
467
 
 
468
  getToken ( c ) ;
 
469
 
 
470
  if ( c [ 0 ] != ';' )
 
471
  {
 
472
    ungetToken ( c ) ;
 
473
    return error ( "Missing ';' or 'else' after 'if' statement" ) ;
 
474
  }
 
475
 
 
476
  getToken ( c ) ;
 
477
 
 
478
  if ( strcmp ( c, "else" ) != 0 )
 
479
  {
 
480
    code [ else_loc   ] = next_code & 0xFF ;
 
481
    code [ else_loc+1 ] = ( next_code >> 8 ) & 0xFF ;
 
482
 
 
483
    ungetToken ( c ) ;
 
484
    ungetToken ( ";" ) ;
 
485
    return TRUE ;
 
486
  }
 
487
 
 
488
  int label_loc = genJump ( 0 ) ;
 
489
 
 
490
  code [ else_loc   ] = next_code & 0xFF ;
 
491
  code [ else_loc+1 ] = ( next_code >> 8 ) & 0xFF ;
 
492
 
 
493
  if ( ! genStatement () )
 
494
    return error ( "Missing statement for 'else'" ) ;
 
495
 
 
496
  code [ label_loc   ] = next_code & 0xFF ;
 
497
  code [ label_loc+1 ] = ( next_code >> 8 ) & 0xFF ;
 
498
 
 
499
  return TRUE ;
 
500
}
 
501
 
 
502
 
 
503
int pslCompiler::genFunctionCall ( const char *var )
 
504
{
 
505
  char c [ MAX_TOKEN ] ;
 
506
 
 
507
  getToken ( c ) ;
 
508
 
 
509
  /*
 
510
    'var' should be the name of a function,
 
511
    'c'   should be an '('
 
512
  */
 
513
 
 
514
  if ( c[0] != '(' )
 
515
    return error ( "Missing '(' in call to '%s'", var ) ;
 
516
 
 
517
  getToken ( c ) ;
 
518
 
 
519
  int argc = 0 ;
 
520
 
 
521
  while ( c[0] != ')' )
 
522
  { 
 
523
    ungetToken ( c ) ;
 
524
    genExpression () ;
 
525
    argc++ ;
 
526
    getToken ( c ) ;
 
527
 
 
528
    if ( c[0] == ')' )
 
529
      break ;
 
530
 
 
531
    if ( c[0] != ',' )
 
532
      return error ( "Missing ')' or ',' in call to '%s'", var ) ;
 
533
 
 
534
    getToken ( c ) ;
 
535
  }
 
536
 
 
537
  genCall ( var, argc ) ;
 
538
  return TRUE ;
 
539
}
 
540
 
 
541
 
 
542
int pslCompiler::genCompoundStatement ()
 
543
{
 
544
  char c [ MAX_TOKEN ] ;
 
545
 
 
546
  pushLocality () ;
 
547
 
 
548
  while ( genStatement () )
 
549
  {
 
550
    getToken ( c ) ;
 
551
 
 
552
    if ( c[0] != ';' )
 
553
    {
 
554
      popLocality () ;
 
555
      return warning ( "Unexpected '%s' in Compound statement", c ) ;
 
556
    }
 
557
  }
 
558
 
 
559
  getToken ( c ) ;
 
560
 
 
561
  if ( c[0] == '}' )
 
562
  {
 
563
    popLocality () ;
 
564
    ungetToken ( ";" ) ;
 
565
    return TRUE ;
 
566
  }
 
567
 
 
568
  popLocality () ;
 
569
  ungetToken ( c ) ;
 
570
  return warning ( "Unexpected '%s' in Compound statement", c ) ;
 
571
}
 
572
 
 
573
 
 
574
int pslCompiler::genStatement ()
 
575
{
 
576
  char c [ MAX_TOKEN ] ;
 
577
 
 
578
  if ( generate_line_numbers )
 
579
    genLineNumber ( _pslGetLineNo () ) ;
 
580
 
 
581
  getToken ( c ) ;
 
582
 
 
583
  if ( strcmp ( c, "static"   ) == 0 ) return genStaticVarDecl      () ;
 
584
  if ( strcmp ( c, "string"   ) == 0 ) return genLocalVarDecl ( PSL_STRING) ;
 
585
  if ( strcmp ( c, "int"      ) == 0 ) return genLocalVarDecl ( PSL_INT   ) ;
 
586
  if ( strcmp ( c, "float"    ) == 0 ) return genLocalVarDecl ( PSL_FLOAT ) ;
 
587
  if ( strcmp ( c, "return"   ) == 0 ) return genReturnStatement    () ;
 
588
  if ( strcmp ( c, "break"    ) == 0 ) return genBreakStatement     () ;
 
589
  if ( strcmp ( c, "continue" ) == 0 ) return genContinueStatement  () ;
 
590
  if ( strcmp ( c, "pause"    ) == 0 ) return genPauseStatement     () ;
 
591
  if ( strcmp ( c, "for"      ) == 0 ) return genForStatement       () ;
 
592
  if ( strcmp ( c, "do"       ) == 0 ) return genDoWhileStatement   () ;
 
593
  if ( strcmp ( c, "switch"   ) == 0 ) return genSwitchStatement    () ;
 
594
  if ( strcmp ( c, "while"    ) == 0 ) return genWhileStatement     () ;
 
595
  if ( strcmp ( c, "if"       ) == 0 ) return genIfStatement        () ;
 
596
  if ( strcmp ( c, "case"     ) == 0 || strcmp ( c, "default" ) == 0 )
 
597
    return error ( "'%s' encountered - not inside 'switch' statement", c ) ;
 
598
 
 
599
  if ( c [ 0 ] == '{' ) return genCompoundStatement () ;
 
600
 
 
601
  ungetToken ( c ) ; 
 
602
 
 
603
  if ( genExpression () )
 
604
  {
 
605
    genPop () ;   /* Discard result */
 
606
    return TRUE ;
 
607
  }
 
608
 
 
609
  return FALSE ;
 
610
}
 
611
 
 
612
 
 
613
void pslCompiler::genProgram ()
 
614
{
 
615
  char c [ MAX_TOKEN ] ;
 
616
 
 
617
  /* Compile the program */
 
618
 
 
619
  while ( TRUE )
 
620
  {
 
621
    getToken ( c ) ;
 
622
 
 
623
    if ( c[0] == '\0' )
 
624
      break ;
 
625
 
 
626
    ungetToken ( c ) ;
 
627
 
 
628
    genGlobalDeclaration () ;
 
629
  }
 
630
 
 
631
  /* Have the program call 'main' and then halt */
 
632
 
 
633
  genIntConstant ( 0 ) ;  /* No arguments to main *YET*  */
 
634
 
 
635
  genCodeByte ( OPCODE_CALL ) ;
 
636
  genCodeAddr ( getCodeSymbol ( "main", next_code ) ) ;
 
637
  genCodeByte ( 0 ) ;  /* Argc */
 
638
  genCodeByte ( OPCODE_HALT ) ;
 
639
 
 
640
  checkUnresolvedSymbols () ;
 
641
}
 
642
 
 
643
 
 
644
 
 
645
int pslCompiler::genLocalVarDecl ( pslType t )
 
646
{
 
647
  char c  [ MAX_TOKEN ] ;
 
648
  char s  [ MAX_TOKEN ] ;
 
649
 
 
650
  getToken ( s ) ;
 
651
 
 
652
  setVarSymbol ( s ) ;
 
653
 
 
654
  getToken ( c ) ;
 
655
 
 
656
  if ( c[0] == '[' )
 
657
  {
 
658
    genExpression () ;
 
659
 
 
660
    switch ( t )
 
661
    {
 
662
      case PSL_FLOAT  : genMakeFloatArray  ( s ) ; break ;
 
663
      case PSL_STRING : genMakeStringArray ( s ) ; break ;
 
664
      default :         genMakeIntArray    ( s ) ; break ;
 
665
    }
 
666
 
 
667
    getToken ( c ) ;
 
668
 
 
669
    if ( c[0] != ']' )
 
670
      return error ( "Missing ']' after array declaration" ) ; 
 
671
 
 
672
    return TRUE ;
 
673
  }
 
674
 
 
675
  switch ( t )
 
676
  {
 
677
    case PSL_FLOAT  : genMakeFloatVariable  ( s ) ; break ;
 
678
    case PSL_STRING : genMakeStringVariable ( s ) ; break ;
 
679
    default :         genMakeIntVariable    ( s ) ; break ;
 
680
  }
 
681
 
 
682
  if ( strcmp ( c, "=" ) == 0 )
 
683
  {
 
684
    genVariable ( s, FALSE ) ;
 
685
    genExpression () ;
 
686
    genAssignment () ;
 
687
    genPop        () ;
 
688
    return TRUE ;
 
689
  }
 
690
 
 
691
  ungetToken ( c ) ;
 
692
  return TRUE ;
 
693
}
 
694
 
 
695
 
 
696
 
 
697
int pslCompiler::genStaticVarDecl ()
 
698
{
 
699
  return error ( "Static Local Variables are Not Supported Yet." ) ;
 
700
}
 
701
 
 
702
 
 
703
 
 
704
int pslCompiler::genGlobalVarDecl ( const char *s, pslType t )
 
705
{
 
706
  char c  [ MAX_TOKEN ] ;
 
707
 
 
708
  setVarSymbol ( s ) ;
 
709
 
 
710
  getToken ( c ) ;
 
711
 
 
712
  if ( c[0] == '[' )
 
713
  {
 
714
    genExpression () ;
 
715
 
 
716
    switch ( t )
 
717
    {
 
718
      case PSL_FLOAT  : genMakeFloatArray  ( s ) ; break ;
 
719
      case PSL_STRING : genMakeStringArray ( s ) ; break ;
 
720
      default :         genMakeIntArray    ( s ) ; break ;
 
721
    }
 
722
 
 
723
    getToken ( c ) ;
 
724
 
 
725
    if ( c[0] != ']' )
 
726
      return error ( "Missing ']' after array declaration" ) ; 
 
727
  }
 
728
  else
 
729
  {
 
730
    switch ( t )
 
731
    {
 
732
      case PSL_FLOAT  : genMakeFloatVariable  ( s ) ; break ;
 
733
      case PSL_STRING : genMakeStringVariable ( s ) ; break ;
 
734
      default :         genMakeIntVariable    ( s ) ; break ;
 
735
    }
 
736
 
 
737
    if ( strcmp ( c, "=" ) == 0 )
 
738
    {
 
739
      genVariable ( s, FALSE ) ;
 
740
      genExpression () ;
 
741
      genAssignment () ;
 
742
      genPop        () ;
 
743
      getToken ( c ) ;
 
744
    }
 
745
  }
 
746
 
 
747
  if ( c[0] != ';' )
 
748
    return error ( "Missing ';' after declaration of '%s'", s ) ;
 
749
 
 
750
  return TRUE ;
 
751
}
 
752
 
 
753
 
 
754
 
 
755
int pslCompiler::genGlobalDeclaration ()
 
756
{
 
757
  char c  [ MAX_TOKEN ] ;
 
758
  char fn [ MAX_TOKEN ] ;
 
759
 
 
760
  getToken ( c ) ;
 
761
 
 
762
  if ( strcmp ( c, "static" ) == 0 ||
 
763
       strcmp ( c, "extern" ) == 0 )
 
764
  {
 
765
    /* Something complicated should probably happen here! */
 
766
    getToken ( c ) ;
 
767
  }
 
768
 
 
769
  pslType t ;
 
770
 
 
771
  if ( strcmp ( c, "void"   ) == 0 ) t = PSL_VOID   ; else
 
772
    if ( strcmp ( c, "int"    ) == 0 ) t = PSL_INT    ; else
 
773
      if ( strcmp ( c, "float"  ) == 0 ) t = PSL_FLOAT  ; else
 
774
        if ( strcmp ( c, "string" ) == 0 ) t = PSL_STRING ; else
 
775
          return error ( "Expected declaration - but got '%s'", c ) ;
 
776
 
 
777
  getToken ( fn ) ;
 
778
 
 
779
  getToken ( c ) ;
 
780
 
 
781
  if ( c[0] == '(' )
 
782
  {
 
783
    ungetToken ( c ) ;
 
784
    return genFunctionDeclaration ( fn ) ;
 
785
  }
 
786
 
 
787
  if ( c[0] == '[' || strcmp ( c, "=" ) == 0 || c[0] == ';' )
 
788
  {
 
789
    ungetToken ( c ) ;
 
790
    return genGlobalVarDecl ( fn, t ) ;
 
791
  }
 
792
 
 
793
  return error ( "Expected a declaration - but got '%s'", c);
 
794
}
 
795
 
 
796
 
 
797
int pslCompiler::genFunctionDeclaration ( const char *fn )
 
798
{
 
799
  char c  [ MAX_TOKEN ] ;
 
800
 
 
801
  pslAddress jump_target = genJump ( 0 ) ;
 
802
 
 
803
  setCodeSymbol ( fn, next_code ) ;
 
804
 
 
805
  getToken ( c ) ;
 
806
 
 
807
  if ( c[0] != '(' )
 
808
    return error ( "Missing '(' in declaration of '%s'", fn ) ;
 
809
 
 
810
  pushLocality () ;
 
811
 
 
812
  int argpos = 0 ;
 
813
 
 
814
  while ( 1 )
 
815
  {
 
816
    getToken ( c ) ;
 
817
 
 
818
    if ( c [ 0 ] == ')' || c [ 0 ] == '\0' )
 
819
      break ;
 
820
 
 
821
    char s [ MAX_TOKEN ] ;
 
822
 
 
823
    getToken ( s ) ;
 
824
 
 
825
    pslAddress a = setVarSymbol ( s ) ;
 
826
 
 
827
    if ( strcmp ( c, "int"    ) == 0 ) genMakeIntVariable    ( s ) ; else
 
828
    if ( strcmp ( c, "float"  ) == 0 ) genMakeFloatVariable  ( s ) ; else
 
829
    if ( strcmp ( c, "string" ) == 0 ) genMakeStringVariable ( s ) ; else
 
830
    {
 
831
      popLocality () ;
 
832
      return error ( "Missing ')' in declaration of '%s'", fn ) ;
 
833
    }
 
834
 
 
835
    genGetParameter ( a, argpos++ ) ;
 
836
 
 
837
    getToken ( c ) ;
 
838
 
 
839
    if ( c[0] == ',' )
 
840
      continue ;
 
841
 
 
842
    if ( c[0] == ')' )
 
843
      break ;
 
844
 
 
845
    popLocality () ;
 
846
    return error ( "Missing ',' or ')' in declaration of '%s'", fn ) ;
 
847
  }
 
848
 
 
849
  if ( c[0] != ')' )
 
850
  {
 
851
    popLocality () ;
 
852
    return error ( "Missing ')' in declaration of '%s'", fn ) ;
 
853
  }
 
854
 
 
855
  getToken ( c ) ;
 
856
 
 
857
  if ( c [ 0 ] != '{' )
 
858
  {
 
859
    popLocality () ;
 
860
    return error ( "Missing '{' in function '%s'", fn ) ;
 
861
  }
 
862
 
 
863
  if ( ! genCompoundStatement () )
 
864
  {
 
865
    popLocality () ;
 
866
    return error ( "Missing '}' in function '%s'", fn ) ;
 
867
  }
 
868
 
 
869
  getToken ( c ) ;
 
870
 
 
871
  /* If we fall off the end of the function, we still need a return value */
 
872
 
 
873
  genConstant ( "0.0" ) ;
 
874
  genReturn   () ;
 
875
 
 
876
  code [  jump_target  ] =  next_code       & 0xFF ;
 
877
  code [ jump_target+1 ] = (next_code >> 8) & 0xFF ;
 
878
 
 
879
  popLocality () ;
 
880
  return TRUE ;
 
881
}
 
882
 
 
883
 
 
884