1 // Token Interpreter
2 //
3 // -- jweier
4
5 #ifdef _WIN32
6 #include <direct.h> //For getcwd()
7 #include <conio.h> //For getch()
8 #else
9 #include <curses.h>
10 #include <unistd.h>
11 #endif
12
13 #include <stdio.h>
14
15 #include "tokenizer.h"
16 #include "blockstream.h"
17 #include "interpreter.h"
18
19 /*
20 ===================================================================================================
21
22 Table Definitions
23
24 ===================================================================================================
25 */
26
27 //FIXME: The following tables should be passed in to the interpreter for flexibility
28
29 //Symbol Table
30
31 keywordArray_t CInterpreter::m_symbolKeywords[] =
32 {
33 //Blocks
34 "{", TK_BLOCK_START,
35 "}", TK_BLOCK_END,
36
37 //Vectors
38 "<", TK_VECTOR_START,
39 ">", TK_VECTOR_END,
40
41 //Groups
42 "(", TK_OPEN_PARENTHESIS,
43 ")", TK_CLOSED_PARENTHESIS,
44
45 "=", TK_EQUALS,
46 "!", TK_NOT,
47
48 //End
49 "", TK_EOF,
50 };
51
52 keywordArray_t CInterpreter::m_conditionalKeywords[] =
53 {
54 "", TK_EOF,
55 };
56
57 //ID Table
58
59 keywordArray_t CInterpreter::m_IDKeywords[] =
60 {
61 "AFFECT", ID_AFFECT,
62 "SOUND", ID_SOUND,
63 "MOVE", ID_MOVE,
64 "ROTATE", ID_ROTATE,
65 "WAIT", ID_WAIT,
66 "SET", ID_SET,
67 "LOOP", ID_LOOP,
68 "PRINT", ID_PRINT,
69 "TAG", ID_TAG,
70 "USE", ID_USE,
71 "FLUSH", ID_FLUSH,
72 "RUN", ID_RUN,
73 "KILL", ID_KILL,
74 "REMOVE", ID_REMOVE,
75 "CAMERA", ID_CAMERA,
76 "GET", ID_GET,
77 "RANDOM", ID_RANDOM,
78 "IF", ID_IF,
79 "ELSE", ID_ELSE,
80 "REM", ID_REM,
81 "FLOAT", TK_FLOAT,
82 "VECTOR", TK_VECTOR,
83 "STRING", TK_STRING,
84 "TASK", ID_TASK,
85 "DO", ID_DO,
86 "DECLARE", ID_DECLARE,
87 "FREE", ID_FREE,
88 "DOWAIT", ID_DOWAIT,
89 "SIGNAL", ID_SIGNAL,
90 "WAITSIGNAL", ID_WAITSIGNAL,
91 "PLAY", ID_PLAY,
92
93 "", ID_EOF,
94 };
95
96 //Type Table
97
98 keywordArray_t CInterpreter::m_typeKeywords[] =
99 {
100 //Set types
101 "ANGLES", TYPE_ANGLES,
102 "ORIGIN", TYPE_ORIGIN,
103
104 //Affect types
105 "INSERT", TYPE_INSERT,
106 "FLUSH", TYPE_FLUSH,
107
108 //Get types
109 "FLOAT", TK_FLOAT,
110 "INT", TK_INT,
111 "VECTOR", TK_VECTOR,
112 "STRING", TK_STRING,
113
114 "PAN", TYPE_PAN,
115 "ZOOM", TYPE_ZOOM,
116 "MOVE", TYPE_MOVE,
117 "FADE", TYPE_FADE,
118 "PATH", TYPE_PATH,
119 "ENABLE", TYPE_ENABLE,
120 "DISABLE", TYPE_DISABLE,
121 "SHAKE", TYPE_SHAKE,
122 "ROLL", TYPE_ROLL,
123 "TRACK", TYPE_TRACK,
124 "FOLLOW", TYPE_FOLLOW,
125 "DISTANCE", TYPE_DISTANCE,
126
127 //End
128 "", TYPE_EOF,
129 };
130
131
132 /*
133 ===================================================================================================
134
135 Constructor / Destructor
136
137 ===================================================================================================
138 */
139
CInterpreter()140 CInterpreter::CInterpreter()
141 {
142 }
143
~CInterpreter()144 CInterpreter::~CInterpreter()
145 {
146 }
147
148 /*
149 ===================================================================================================
150
151 Error Handling
152
153 ===================================================================================================
154 */
155
Error(char * format,...)156 int CInterpreter::Error( char *format, ... )
157 {
158 va_list argptr;
159 char *error_file, error_msg[1024]="", work_dir[1024]="", out_msg[1024]="";
160 int error_line = m_iCurrentLine; // m_tokenizer->GetCurLine();
161
162 m_tokenizer->GetCurFilename( &error_file );
163 if (!error_file)
164 {
165 // 99% of the time we'll get here now, because of pushed parse streams
166 //
167 error_file = (char *)m_sCurrentFile.c_str();
168 }
169
170 va_start (argptr, format);
171 vsprintf (error_msg, format, argptr);
172 va_end (argptr);
173
174 strcpy((char *) work_dir, getcwd( (char *) &work_dir, 1024 ) );
175
176 if (error_file[1] == ':')
177 {
178 sprintf((char *) out_msg, "%s (%d) : error: %s\n", error_file, error_line, error_msg);
179 }
180 else
181 {
182 sprintf((char *) out_msg, "%s\\%s (%d) : error: %s\n", work_dir, error_file, error_line, error_msg);
183 }
184
185 if (m_sCurrentLine.length())
186 {
187 strcat(out_msg, "\nLine:\n\n");
188 strcat(out_msg, m_sCurrentLine.c_str());
189 strcat(out_msg, "\n");
190 }
191
192 #ifdef __POP_UPS__
193
194 MessageBox( NULL, out_msg, "Error", MB_OK );
195
196 #else
197
198 printf(out_msg);
199
200 #endif
201
202 // A bit of kludge code that takes care of the case where there's some garbage at the beginning of the file
203 // before any blocks are read as valid. This is needed because ints are incapable of containing 0
204 //
205 // This'll mean that technically it's saying block 1 is wrong, rather than the one in between them, but I can
206 // live with that.
207 //
208 if (m_iBadCBlockNumber == 0)
209 {
210 m_iBadCBlockNumber = 1;
211 }
212 return false;
213 }
214
215 /*
216 ===================================================================================================
217
218 Local Variable Functions
219
220 ===================================================================================================
221 */
222
223 /*
224 -------------------------
225 InitVars
226 -------------------------
227 */
228
InitVars(void)229 void CInterpreter::InitVars( void )
230 {
231 m_vars.clear();
232 m_varMap.clear();
233 }
234
235 /*
236 -------------------------
237 FreeVars
238 -------------------------
239 */
240
FreeVars(void)241 void CInterpreter::FreeVars( void )
242 {
243 variable_v::iterator vi;
244
245 for ( vi = m_vars.begin(); vi != m_vars.end(); ++vi )
246 {
247 delete (*vi);
248 }
249
250 InitVars();
251 }
252
253 /*
254 -------------------------
255 AddVar
256 -------------------------
257 */
258
AddVar(const char * name,int type)259 variable_t *CInterpreter::AddVar( const char *name, int type )
260 {
261 variable_t *var;
262
263 var = new variable_t;
264
265 if ( var == NULL )
266 return NULL;
267
268 //Specify the type
269 var->type = type;
270
271 //Retain the name internally
272 strncpy( (char *) var->name, name, MAX_VAR_NAME );
273
274 //Associate it
275 m_varMap[ name ] = var;
276
277 return var;
278 }
279
280 /*
281 -------------------------
282 FindVar
283 -------------------------
284 */
285
FindVar(const char * name)286 variable_t *CInterpreter::FindVar( const char *name )
287 {
288 variable_m::iterator vmi;
289
290 vmi = m_varMap.find( name );
291
292 if ( vmi == m_varMap.end() )
293 return NULL;
294
295 return (*vmi).second;
296 }
297
298 /*
299 -------------------------
300 GetVariable
301 -------------------------
302 */
303
GetVariable(int type)304 int CInterpreter::GetVariable( int type )
305 {
306 const char *varName;
307 variable_t *var;
308 CToken *token;
309
310 //Get the variable's name
311 token = m_tokenizer->GetToken( 0, 0 );
312 varName = token->GetStringValue();
313
314 //See if we already have a variable by this name
315 var = FindVar( varName );
316
317 //Variable names must be unique on creation
318 if ( var )
319 return Error( "\"%s\" : already exists\n", varName );
320
321 //Add the variable
322 AddVar( varName, type );
323
324 //Insert the variable into the stream
325
326 CBlock block;
327
328 block.Create( TYPE_VARIABLE );
329 block.Write( TK_FLOAT, (float) type );
330 block.Write( TK_STRING, varName );
331
332 m_blockStream->WriteBlock( &block );
333
334 token->Delete();
335
336 return true;
337 }
338
339 /*
340 ===================================================================================================
341
342 ID Table Functions
343
344 ===================================================================================================
345 */
346
GetVector(CBlock * block)347 int CInterpreter::GetVector( CBlock *block )
348 {
349 //Look for a tag
350 if ( MatchTag() )
351 {
352 return GetTag( block );
353 }
354
355 //Look for a get
356 if ( MatchGet() )
357 {
358 return GetGet( block );
359 }
360
361 if ( Match( TK_VECTOR_START ) )
362 {
363 //Get the vector
364 block->Write( TK_VECTOR, (float) TK_VECTOR );
365
366 for (int i=0; i<3; i++)
367 GetFloat( block );
368
369 if (!Match( TK_VECTOR_END ))
370 {
371 return Error("syntax error : expected end of vector");
372 }
373
374 return true;
375 }
376
377 return false;
378 }
379
380 /*
381 ===================================================================================================
382
383 MatchTag()
384
385 Attempts to match to a tag identifier.
386
387 ===================================================================================================
388 */
389
MatchTag(void)390 int CInterpreter::MatchTag( void )
391 {
392 CToken *token;
393 const char *idName;
394 int id;
395
396 token = m_tokenizer->GetToken( 0, 0 );
397 idName = token->GetStringValue();
398 id = FindSymbol( idName, m_IDKeywords );
399
400 if ( id != ID_TAG )
401 {
402 //Return the token
403 m_tokenizer->PutBackToken( token );
404 return false;
405 }
406
407 token->Delete();
408 return true;
409 }
410
411 /*
412 ===================================================================================================
413
414 MatchGet()
415
416 Attempts to match to a get identifier.
417
418 ===================================================================================================
419 */
420
MatchGet(void)421 int CInterpreter::MatchGet( void )
422 {
423 CToken *token;
424 const char *idName;
425 int id;
426
427 token = m_tokenizer->GetToken( 0, 0 );
428 idName = token->GetStringValue();
429 id = FindSymbol( idName, m_IDKeywords );
430
431 if ( id != ID_GET )
432 {
433 //Return the token
434 m_tokenizer->PutBackToken( token );
435 return false;
436 }
437
438 token->Delete();
439 return true;
440 }
441
442 /*
443 ===================================================================================================
444
445 MatchRandom()
446
447 Attempts to match to a random identifier.
448
449 ===================================================================================================
450 */
451
MatchRandom(void)452 int CInterpreter::MatchRandom( void )
453 {
454 CToken *token;
455 const char *idName;
456 int id;
457
458 token = m_tokenizer->GetToken( 0, 0 );
459 idName = token->GetStringValue();
460 id = FindSymbol( idName, m_IDKeywords );
461
462 if ( id != ID_RANDOM )
463 {
464 //Return the token
465 m_tokenizer->PutBackToken( token );
466 return false;
467 }
468
469 token->Delete();
470 return true;
471 }
472
473 /*
474 ===================================================================================================
475
476 FindSymbol()
477
478 Searches the symbol table for the given name. Returns the ID if found.
479
480 ===================================================================================================
481 */
482
FindSymbol(const char * name,keywordArray_t * table)483 int CInterpreter::FindSymbol( const char *name, keywordArray_t *table)
484 {
485 keywordArray_t *ids;
486
487 for (ids = table; (strcmp(ids->m_keyword, "")); ids++)
488 {
489 if (!stricmp(name, ids->m_keyword))
490 return ids->m_tokenvalue;
491 }
492
493 return -1;
494 }
495
496
497 /*
498 ===================================================================================================
499
500 Match()
501
502 Looks ahead to the next token to try and match it to the passed token, consumes token on success.
503
504 ===================================================================================================
505 */
506
507 //NOTENOTE: LookAhead() was separated from Match() for clarity
508
Match(int token_id)509 int CInterpreter::Match( int token_id )
510 {
511 CToken *token;
512
513 token = m_tokenizer->GetToken( 0, 0 );
514
515 if ( token->GetType() != token_id )
516 {
517 //This may have been a check, so don't loose the token
518 m_tokenizer->PutBackToken( token );
519
520 return false;
521 }
522
523 return true;
524 }
525
526 /*
527 -------------------------
528 GetNextType
529 -------------------------
530 */
531
GetNextType(void)532 int CInterpreter::GetNextType( void )
533 {
534 CToken *token = m_tokenizer->GetToken( 0, 0 );
535 int id = token->GetType();
536
537 m_tokenizer->PutBackToken( token );
538
539 return id;
540 }
541
542 /*
543 ===================================================================================================
544
545 LookAhead()
546
547 Looks ahead without consuming on success.
548
549 ===================================================================================================
550 */
551
LookAhead(int token_id)552 int CInterpreter::LookAhead( int token_id )
553 {
554 CToken *token;
555
556 token = m_tokenizer->GetToken( 0, 0 );
557
558 if ( token->GetType() != token_id )
559 {
560 m_tokenizer->PutBackToken( token );
561
562 return false;
563 }
564
565 m_tokenizer->PutBackToken( token );
566
567 return true;
568 }
569
570 /*
571 ===================================================================================================
572
573 GetTokenName()
574
575 Returns the name of a token.
576
577 ===================================================================================================
578 */
579
GetTokenName(int token_id)580 const char *CInterpreter::GetTokenName( int token_id )
581 {
582 switch ( token_id )
583 {
584 case TK_STRING:
585 return "STRING";
586 break;
587
588 case TK_CHAR:
589 return "CHARACTER";
590 break;
591
592 case TK_IDENTIFIER:
593 return "IDENTIFIER";
594 break;
595
596 case TK_FLOAT:
597 return "FLOAT";
598 break;
599
600 case TK_INTEGER:
601 return "INTEGER";
602 break;
603
604 default:
605 return "UNKNOWN";
606 break;
607 }
608 }
609
610 /*
611 ===================================================================================================
612
613 Token Value Functions
614
615 ===================================================================================================
616 */
617
618 /*
619 ===================================================================================================
620
621 GetFloat()
622
623 Attempts to match and retrieve the value of a float token.
624
625 ===================================================================================================
626 */
627
GetFloat(CBlock * block)628 int CInterpreter::GetFloat( CBlock *block )
629 {
630 CToken *token;
631 int type;
632
633 //Look for a get
634 if ( MatchGet() )
635 {
636 return GetGet( block );
637 }
638
639 //Look for a random
640 if ( MatchRandom() )
641 {
642 return GetRandom( block );
643 }
644
645 token = m_tokenizer->GetToken(0,0);
646 type = token->GetType();
647
648 //Floats can accept either int or float values
649 if ( ( type != TK_FLOAT ) && ( type != TK_INT ) )
650 {
651 return Error("syntax error : expected float; found %s", GetTokenName(type) );
652 }
653
654 if (type == TK_FLOAT)
655 {
656 block->Write( TK_FLOAT, (float) token->GetFloatValue() );
657 }
658 else
659 {
660 block->Write( TK_FLOAT, (float) token->GetIntValue() );
661 }
662
663 token->Delete();
664
665 return true;
666 }
667
668 /*
669 ===================================================================================================
670
671 GetInteger()
672
673 Attempts to match and retrieve the value of an integer token.
674
675 ===================================================================================================
676 */
677
GetInteger(CBlock * block)678 int CInterpreter::GetInteger( CBlock *block )
679 {
680 return GetFloat( block );
681 }
682
683 /*
684 ===================================================================================================
685
686 GetString()
687
688 Attempts to match and retrieve the value of a string token.
689
690 ===================================================================================================
691 */
692
GetString(CBlock * block)693 int CInterpreter::GetString( CBlock *block )
694 {
695 CToken *token;
696 int type;
697
698 //Look for a get
699 if ( MatchGet() )
700 {
701 return GetGet( block );
702 }
703
704 //Look for a random
705 if ( MatchRandom() )
706 {
707 return GetRandom( block );
708 }
709
710 token = m_tokenizer->GetToken(0, 0);
711 type = token->GetType();
712
713 if ( (type != TK_STRING) && (type != TK_CHAR) )
714 {
715 return Error("syntax error : expected string; found %s", GetTokenName(type));
716 }
717
718 //UGLY HACK!!!
719
720 const char *temptr;
721 char temp[1024];
722
723 temptr = token->GetStringValue();
724
725 if ( strlen(temptr)+1 > sizeof( temp ) )
726 {
727 return false;
728 }
729
730 for ( int i = 0; i < strlen( temptr ); i++ )
731 {
732 if ( temptr[i] == '#' )
733 temp[i] = '\n';
734 else
735 temp[i] = temptr[i];
736 }
737
738 temp[ strlen( temptr ) ] = 0;
739
740 //UGLY HACK END!!!
741
742 block->Write( TK_STRING, (const char *) &temp );
743
744 token->Delete();
745
746 return true;
747 }
748
749 /*
750 ===================================================================================================
751
752 GetIdentifier()
753
754 Attempts to match and retrieve the value of an indentifier token.
755
756 ===================================================================================================
757 */
758
GetIdentifier(CBlock * block)759 int CInterpreter::GetIdentifier( CBlock *block )
760 {
761 CToken *token;
762 int type;
763
764 //FIXME: Should identifiers do this?
765 if ( MatchGet() )
766 {
767 if ( GetGet( block ) == false )
768 return false;
769
770 return true;
771 }
772
773 token = m_tokenizer->GetToken(0, 0);
774 type = token->GetType();
775
776 if ( type != TK_IDENTIFIER )
777 {
778 return Error("syntax error : expected indentifier; found %s", GetTokenName(type));
779 }
780
781 block->Write( TK_IDENTIFIER, (const char *) token->GetStringValue() );
782
783 token->Delete();
784
785 return true;
786 }
787
788 /*
789 ===================================================================================================
790
791 GetEvaluator()
792
793 Attempts to match and retrieve the value of an evaluator token.
794
795 ===================================================================================================
796 */
797
GetEvaluator(CBlock * block)798 int CInterpreter::GetEvaluator( CBlock *block )
799 {
800 CToken *token;
801 int type;
802
803 if ( MatchGet() )
804 return false;
805
806 if ( MatchRandom() )
807 return false;
808
809 token = m_tokenizer->GetToken(0, 0);
810 type = token->GetType();
811 token->Delete();
812
813 switch ( type )
814 {
815 case TK_GREATER_THAN:
816 case TK_LESS_THAN:
817 case TK_EQUALS:
818 case TK_NOT:
819 break;
820
821 case TK_VECTOR_START:
822 type = TK_LESS_THAN;
823 break;
824
825 case TK_VECTOR_END:
826 type = TK_GREATER_THAN;
827 break;
828
829 default:
830 return Error("syntax error : expected operator type, found %s", GetTokenName( type ) );
831 }
832
833 block->Write( type, 0 );
834
835 return true;
836 }
837
838 /*
839 ===================================================================================================
840
841 GetAny()
842
843 Attempts to match and retrieve any valid data type.
844
845 ===================================================================================================
846 */
847
GetAny(CBlock * block)848 int CInterpreter::GetAny( CBlock *block )
849 {
850 CToken *token;
851 int type;
852
853 if ( MatchGet() )
854 {
855 if ( GetGet( block ) == false )
856 return false;
857
858 return true;
859 }
860
861 if ( MatchRandom() )
862 {
863 if ( GetRandom( block ) == false )
864 return false;
865
866 return true;
867 }
868
869 if ( MatchTag() )
870 {
871 if ( GetTag( block ) == false )
872 return false;
873
874 return true;
875 }
876
877 token = m_tokenizer->GetToken(0, 0);
878 type = token->GetType();
879
880 switch ( type )
881 {
882 case TK_FLOAT:
883 m_tokenizer->PutBackToken( token );
884 if ( GetFloat( block ) == false )
885 return false;
886
887 break;
888
889 case TK_INT:
890 m_tokenizer->PutBackToken( token );
891 if ( GetInteger( block ) == false )
892 return false;
893
894 break;
895
896 case TK_VECTOR_START:
897 m_tokenizer->PutBackToken( token );
898 if ( GetVector( block ) == false )
899 return false;
900
901 break;
902
903 case TK_STRING:
904 case TK_CHAR:
905 m_tokenizer->PutBackToken( token );
906 if ( GetString( block ) == false )
907 return false;
908
909 break;
910
911 case TK_IDENTIFIER:
912 m_tokenizer->PutBackToken( token );
913 if ( GetIdentifier( block ) == false )
914 return false;
915
916 break;
917
918 default:
919 return false;
920 }
921
922 return true;
923 }
924
925 /*
926 ===================================================================================================
927
928 GetType()
929
930 Attempts to match and retrieve the value of a type token.
931
932 ===================================================================================================
933 */
934
GetType(char * get)935 int CInterpreter::GetType( char *get )
936 {
937 CToken *token;
938 char *string;
939 int type;
940
941 token = m_tokenizer->GetToken(0, 0);
942 type = token->GetType();
943
944 if ( type != TK_IDENTIFIER )
945 {
946 return Error("syntax error : expected identifier; found %s", GetTokenName(type));
947 }
948
949 string = (char *) token->GetStringValue();
950
951 if ( (strlen(string) + 1) > MAX_STRING_LENGTH)
952 {
953 Error("string exceeds 256 character limit");
954 return false;
955 }
956
957 strcpy(get, string);
958
959 return true;
960 }
961
962 /*
963 ===================================================================================================
964
965 GetID()
966
967 Attempts to match and interpret an identifier.
968
969 ===================================================================================================
970 */
971
972 //FIXME: This should use an externally defined table to match ID and functions
973
GetID(char * id_name)974 int CInterpreter::GetID( char *id_name )
975 {
976 int id;
977
978 id = FindSymbol( id_name, m_IDKeywords );
979
980 if ( id == -1 )
981 return Error("'%s' : unknown identifier", id_name);
982
983 //FIXME: Function pointers would be awfully nice.. but not inside a class! Weee!!
984
985 switch (id)
986 {
987
988 //Affect takes control of an entity
989
990 case ID_AFFECT:
991 return GetAffect();
992 break;
993
994 //Wait for a specified amount of time
995
996 case ID_WAIT:
997 return GetWait();
998 break;
999
1000 //Generic set call
1001
1002 case ID_SET:
1003 return GetSet();
1004 break;
1005
1006 case ID_LOOP:
1007 return GetLoop();
1008 break;
1009
1010 case ID_PRINT:
1011 return GetPrint();
1012 break;
1013
1014 case ID_USE:
1015 return GetUse();
1016 break;
1017
1018 case ID_FLUSH:
1019 return GetFlush();
1020 break;
1021
1022 case ID_RUN:
1023 return GetRun();
1024 break;
1025
1026 case ID_KILL:
1027 return GetKill();
1028 break;
1029
1030 case ID_REMOVE:
1031 return GetRemove();
1032 break;
1033
1034 case ID_CAMERA:
1035 return GetCamera();
1036 break;
1037
1038 case ID_SOUND:
1039 return GetSound();
1040 break;
1041
1042 case ID_MOVE:
1043 return GetMove();
1044 break;
1045
1046 case ID_ROTATE:
1047 return GetRotate();
1048 break;
1049
1050 case ID_IF:
1051 return GetIf();
1052 break;
1053
1054 case ID_ELSE:
1055 //return Error("syntax error : else without matching if");
1056 return GetElse(); //FIXME: Protect this call so that floating else's aren't allowed
1057 break;
1058
1059 case ID_GET:
1060 return Error("syntax error : illegal use of \"get\"");
1061 break;
1062
1063 case ID_TAG:
1064 return Error("syntax error : illegal use of \"tag\"");
1065 break;
1066
1067 case ID_TASK:
1068 return GetTask();
1069 break;
1070
1071 case ID_DO:
1072 return GetDo();
1073 break;
1074
1075 case ID_DECLARE:
1076 return GetDeclare();
1077 break;
1078
1079 case ID_FREE:
1080 return GetFree();
1081 break;
1082
1083 case ID_REM:
1084 GetRem();
1085 break;
1086
1087 case ID_DOWAIT:
1088 GetDoWait();
1089 break;
1090
1091 case ID_SIGNAL:
1092 GetSignal();
1093 break;
1094
1095 case ID_WAITSIGNAL:
1096 GetWaitSignal();
1097 break;
1098
1099 case ID_PLAY:
1100 GetPlay(); //Bad eighties slang joke... yeah, it's not really funny, I know...
1101 break;
1102
1103 //Local variable types
1104 case TK_FLOAT:
1105 case TK_INT:
1106 case TK_STRING:
1107 case TK_VECTOR:
1108 GetVariable( id );
1109 break;
1110
1111 //Unknown ID
1112
1113 default:
1114 case -1:
1115 return Error("'%s' : unknown identifier", id_name);
1116 break;
1117 }
1118
1119 return true;
1120 }
1121
1122 /*
1123 ===================================================================================================
1124
1125 ID Interpreting Functions
1126
1127 ===================================================================================================
1128 */
1129
1130 /*
1131 -------------------------
1132 GetDeclare
1133 -------------------------
1134 */
1135
GetDeclare(void)1136 int CInterpreter::GetDeclare( void )
1137 {
1138 CBlock block;
1139 char typeName[MAX_STRING_LENGTH];
1140 int type;
1141
1142 block.Create( ID_DECLARE );
1143
1144 if (!Match( TK_OPEN_PARENTHESIS ))
1145 return Error("syntax error : '(' not found");
1146
1147 if ( GetType( (char *) typeName ) == false )
1148 return false;
1149
1150 type = FindSymbol( typeName, m_typeKeywords);
1151
1152 switch ( type )
1153 {
1154 case TK_FLOAT:
1155 case TK_VECTOR:
1156 case TK_STRING:
1157 block.Write( TK_FLOAT, (float) type );
1158 break;
1159
1160 default:
1161 return Error("unknown identifier %s", typeName );
1162 break;
1163 }
1164
1165 if ( GetString( &block ) == false )
1166 return false;
1167
1168 if (!Match( TK_CLOSED_PARENTHESIS ))
1169 return Error("declare : too many parameters");
1170
1171 m_blockStream->WriteBlock( &block );
1172
1173 return true;
1174 }
1175
1176
1177 /*
1178 -------------------------
1179 GetFree
1180 -------------------------
1181 */
1182
GetFree(void)1183 int CInterpreter::GetFree( void )
1184 {
1185 CBlock block;
1186
1187 block.Create( ID_FREE );
1188
1189 if ( Match( TK_OPEN_PARENTHESIS ) == false )
1190 return Error("syntax error : '(' not found");
1191
1192 if ( GetString( &block ) == false )
1193 return false;
1194
1195 if ( Match( TK_CLOSED_PARENTHESIS ) == false )
1196 return Error("free : too many parameters");
1197
1198 m_blockStream->WriteBlock( &block );
1199
1200 return true;
1201 }
1202
1203 /*
1204 ===================================================================================================
1205
1206 GetIf()
1207
1208 Handles the if() conditional statement.
1209
1210 ===================================================================================================
1211 */
1212
1213 // if ( STRING ? STRING )
1214
GetIf(void)1215 int CInterpreter::GetIf( void )
1216 {
1217 CBlock block;
1218
1219 block.Create( ID_IF );
1220
1221 if ( Match( TK_OPEN_PARENTHESIS ) == false )
1222 return Error("syntax error : '(' not found");
1223
1224 if ( GetAny( &block ) == false )
1225 return false;
1226
1227 if ( GetEvaluator( &block ) == false )
1228 return false;
1229
1230 if ( GetAny( &block ) == false )
1231 return false;
1232
1233 if ( Match( TK_CLOSED_PARENTHESIS ) == false )
1234 return Error("if : too many parameters");
1235
1236 m_blockStream->WriteBlock( &block );
1237
1238 return true;
1239 }
1240
1241 /*
1242 ===================================================================================================
1243
1244 GetElse()
1245
1246 Handles the else() conditional statement.
1247
1248 ===================================================================================================
1249 */
1250
1251 // else
1252
GetElse(void)1253 int CInterpreter::GetElse( void )
1254 {
1255 CBlock block;
1256
1257 block.Create( ID_ELSE );
1258
1259 /*
1260 if ( Match( TK_OPEN_PARENTHESIS ) == false )
1261 return Error("syntax error : '(' not found");
1262 */
1263
1264 /*
1265 if ( GetAny( &block ) == false )
1266 return false;
1267
1268 if ( GetEvaluator( &block ) == false )
1269 return false;
1270
1271 if ( GetAny( &block ) == false )
1272 return false;
1273 */
1274
1275 /*
1276 if ( Match( TK_CLOSED_PARENTHESIS ) == false )
1277 return Error("sound : too many parameters");
1278 */
1279
1280 m_blockStream->WriteBlock( &block );
1281
1282 return true;
1283 }
1284
1285 /*
1286 ===================================================================================================
1287
1288 GetTask()
1289
1290 Handles the task() sequence specifier.
1291
1292 ===================================================================================================
1293 */
1294
1295 //task ( name ) { }
1296
GetTask(void)1297 int CInterpreter::GetTask( void )
1298 {
1299 CBlock block;
1300
1301 block.Create( ID_TASK );
1302
1303 if (!Match( TK_OPEN_PARENTHESIS ))
1304 return Error("syntax error : '(' not found");
1305
1306 if ( GetString( &block ) == false )
1307 return false;
1308
1309 if (!Match( TK_CLOSED_PARENTHESIS ))
1310 return Error("GetTask: too many parameters");
1311
1312 m_blockStream->WriteBlock( &block );
1313
1314 return true;
1315
1316 }
1317
1318 /*
1319 ===================================================================================================
1320
1321 GetDo()
1322
1323 Handles the do() function.
1324
1325 ===================================================================================================
1326 */
1327
1328 //do ( taskName )
1329
GetDo(void)1330 int CInterpreter::GetDo( void )
1331 {
1332 CBlock block;
1333
1334 block.Create( ID_DO );
1335
1336 if (!Match( TK_OPEN_PARENTHESIS ))
1337 return Error("syntax error : '(' not found");
1338
1339 if ( GetString( &block ) == false )
1340 return false;
1341
1342 if (!Match( TK_CLOSED_PARENTHESIS ))
1343 return Error("do : too many parameters");
1344
1345 m_blockStream->WriteBlock( &block );
1346
1347 return true;
1348 }
1349
1350 /*
1351 ===================================================================================================
1352
1353 GetGet()
1354
1355 Handles the get() function.
1356
1357 ===================================================================================================
1358 */
1359
1360 // get( TYPE, NAME );
1361
GetGet(CBlock * block)1362 int CInterpreter::GetGet( CBlock *block )
1363 {
1364 char typeName[MAX_STRING_LENGTH];
1365 int type;
1366
1367 block->Write( ID_GET, (float) ID_GET );
1368
1369 if (!Match( TK_OPEN_PARENTHESIS ))
1370 return Error("syntax error : '(' not found");
1371
1372 if ( GetType( (char *) typeName ) == false )
1373 return false;
1374
1375 type = FindSymbol( typeName, m_typeKeywords);
1376
1377 switch ( type )
1378 {
1379 case TK_FLOAT:
1380 case TK_INT:
1381 case TK_VECTOR:
1382 case TK_STRING:
1383 block->Write( TK_FLOAT, (float) type );
1384 break;
1385
1386 default:
1387 return Error("unknown identifier %s", typeName );
1388 break;
1389 }
1390
1391 if ( GetString( block ) == false )
1392 return false;
1393
1394 if (!Match( TK_CLOSED_PARENTHESIS ))
1395 return Error("affect : too many parameters");
1396
1397 return true;
1398 }
1399
1400 /*
1401 ===================================================================================================
1402
1403 GetRandom()
1404
1405 Handles the random() function.
1406
1407 ===================================================================================================
1408 */
1409
1410 // random( low, high );
1411
GetRandom(CBlock * block)1412 int CInterpreter::GetRandom( CBlock *block )
1413 {
1414 block->Write( ID_RANDOM, (float) ID_RANDOM );
1415
1416 if (!Match( TK_OPEN_PARENTHESIS ))
1417 return Error("syntax error : '(' not found");
1418
1419 if ( GetFloat( block ) == false )
1420 return false;
1421
1422 if ( GetFloat( block ) == false )
1423 return false;
1424
1425 if (!Match( TK_CLOSED_PARENTHESIS ))
1426 return Error("affect : too many parameters");
1427
1428 return true;
1429 }
1430
1431 /*
1432 ===================================================================================================
1433
1434 GetSound()
1435
1436 Handles the sound() function.
1437
1438 ===================================================================================================
1439 */
1440
1441 // sound( NAME );
1442
GetSound(void)1443 int CInterpreter::GetSound( void )
1444 {
1445 CBlock block;
1446
1447 block.Create( ID_SOUND );
1448
1449 if (!Match( TK_OPEN_PARENTHESIS ))
1450 return Error("syntax error : '(' not found");
1451
1452 if ( GetIdentifier( &block ) == false )
1453 return false;
1454
1455 if ( GetString( &block ) == false )
1456 return false;
1457
1458 if (!Match( TK_CLOSED_PARENTHESIS ))
1459 return Error("sound : too many parameters");
1460
1461 m_blockStream->WriteBlock( &block );
1462
1463 return true;
1464 }
1465
1466 /*
1467 ===================================================================================================
1468
1469 GetMove()
1470
1471 Handles the move() function.
1472
1473 ===================================================================================================
1474 */
1475
1476 // move( ORIGIN, ANGLES, DURATION );
1477
GetMove(void)1478 int CInterpreter::GetMove( void )
1479 {
1480 CBlock block;
1481
1482 block.Create( ID_MOVE );
1483
1484 if (!Match( TK_OPEN_PARENTHESIS ))
1485 return Error("syntax error : '(' not found");
1486
1487 if ( GetVector( &block ) == false )
1488 return false;
1489
1490 //Angles are optional
1491 if ( LookAhead( TK_VECTOR_START ) || LookAhead( TK_IDENTIFIER ) )
1492 {
1493 if ( GetVector( &block ) == false )
1494 return false;
1495 }
1496
1497 if ( GetFloat( &block ) == false )
1498 return false;
1499
1500 if (!Match( TK_CLOSED_PARENTHESIS ))
1501 return Error("move : too many parameters");
1502
1503 m_blockStream->WriteBlock( &block );
1504
1505 return true;
1506 }
1507
1508 /*
1509 ===================================================================================================
1510
1511 GetRotate()
1512
1513 Handles the rotate() function.
1514
1515 ===================================================================================================
1516 */
1517
1518 // move( ANGLES, DURATION );
1519
GetRotate(void)1520 int CInterpreter::GetRotate( void )
1521 {
1522 CBlock block;
1523
1524 block.Create( ID_ROTATE );
1525
1526 if (!Match( TK_OPEN_PARENTHESIS ))
1527 return Error("syntax error : '(' not found");
1528
1529 if ( GetVector( &block ) == false )
1530 return false;
1531
1532 if ( GetFloat( &block ) == false )
1533 return false;
1534
1535 if (!Match( TK_CLOSED_PARENTHESIS ))
1536 return Error("move : too many parameters");
1537
1538 m_blockStream->WriteBlock( &block );
1539
1540 return true;
1541 }
1542
1543 /*
1544 ===================================================================================================
1545
1546 GetAffect()
1547
1548 Handles the affect() function.
1549
1550 ===================================================================================================
1551 */
1552
1553 //FIXME: This should be externally defined
1554
GetAffect(void)1555 int CInterpreter::GetAffect( void )
1556 {
1557 CBlock block;
1558 char typeName[MAX_STRING_SIZE];
1559 int type;
1560
1561 block.Create( ID_AFFECT );
1562
1563 if (!Match( TK_OPEN_PARENTHESIS ))
1564 return Error("syntax error : '(' not found");
1565
1566 if ( GetString( &block ) == false )
1567 return false;
1568
1569 if (!LookAhead( TK_IDENTIFIER ))
1570 return Error("syntax error : identifier not found");
1571
1572 if ( MatchGet() )
1573 return Error("syntax error : illegal use of \"get\"");
1574
1575 if ( GetType( (char *) typeName ) == false )
1576 return false;
1577
1578 type = FindSymbol( typeName, m_typeKeywords);
1579
1580 switch ( type )
1581 {
1582 case TYPE_INSERT:
1583 case TYPE_FLUSH:
1584
1585 block.Write( TK_FLOAT, (float) type );
1586 break;
1587
1588 default:
1589 return Error("'%s': unknown affect type", typeName );
1590 break;
1591
1592 }
1593
1594 if (!Match( TK_CLOSED_PARENTHESIS ))
1595 return Error("affect : too many parameters");
1596
1597 if (!LookAhead( TK_BLOCK_START ))
1598 return Error("syntax error : '{' not found");
1599
1600 m_blockStream->WriteBlock( &block );
1601
1602 return true;
1603 }
1604
1605 /*
1606 ===================================================================================================
1607
1608 GetWait()
1609
1610 Handles the wait() function.
1611
1612 ===================================================================================================
1613 */
1614
1615 //FIXME: This should be externally defined
1616
GetWait(void)1617 int CInterpreter::GetWait( void )
1618 {
1619 CBlock block;
1620
1621 block.Create( ID_WAIT );
1622
1623 if (!Match( TK_OPEN_PARENTHESIS ))
1624 return Error("syntax error : '(' not found");
1625
1626 if ( LookAhead( TK_STRING ) )
1627 {
1628 if ( GetString( &block ) == false )
1629 return false;
1630 }
1631 else
1632 {
1633 if ( GetFloat( &block ) == false )
1634 return false;
1635 }
1636
1637 if (!Match( TK_CLOSED_PARENTHESIS ))
1638 return Error("wait : too many parameters");
1639
1640 m_blockStream->WriteBlock( &block );
1641
1642 return true;
1643 }
1644
1645 /*
1646 ===================================================================================================
1647
1648 GetSet()
1649
1650 Handles the set() function.
1651
1652 ===================================================================================================
1653 */
1654
1655 //FIXME: This should be externally defined
1656
GetSet(void)1657 int CInterpreter::GetSet( void )
1658 {
1659 CBlock block;
1660
1661 block.Create( ID_SET );
1662
1663 if (!Match( TK_OPEN_PARENTHESIS ))
1664 return Error("syntax error : '(' not found");
1665
1666 if ( GetString( &block ) == false )
1667 return false;
1668
1669 //Check for get placement
1670 if ( MatchGet() )
1671 {
1672 if ( GetGet( &block ) == false )
1673 return false;
1674 }
1675 else
1676 {
1677 switch( GetNextType() )
1678 {
1679 case TK_INT:
1680
1681 if ( GetInteger( &block ) == false )
1682 return false;
1683
1684 break;
1685
1686 case TK_FLOAT:
1687
1688 if ( GetFloat( &block ) == false )
1689 return false;
1690
1691 break;
1692
1693 case TK_STRING:
1694
1695 if ( GetString( &block ) == false )
1696 return false;
1697
1698 break;
1699
1700 case TK_VECTOR_START:
1701
1702 if ( GetVector( &block ) == false )
1703 return false;
1704
1705 break;
1706
1707 default:
1708
1709 if ( MatchTag() )
1710 {
1711 GetTag( &block );
1712 break;
1713 }
1714
1715 if ( MatchRandom() )
1716 {
1717 GetRandom( &block );
1718 break;
1719 }
1720
1721 return Error("unknown parameter type");
1722 break;
1723 }
1724 }
1725
1726 if (!Match( TK_CLOSED_PARENTHESIS ))
1727 return Error("set : too many parameters");
1728
1729 m_blockStream->WriteBlock( &block );
1730
1731 return true;
1732 }
1733
1734 /*
1735 ===================================================================================================
1736
1737 GetLoop()
1738
1739 Handles the loop() function.
1740
1741 ===================================================================================================
1742 */
1743
GetLoop(void)1744 int CInterpreter::GetLoop( void )
1745 {
1746 CBlock block;
1747
1748 block.Create( ID_LOOP );
1749
1750 if (!Match( TK_OPEN_PARENTHESIS ))
1751 return Error("syntax error : '(' not found");
1752
1753 if ( LookAhead( TK_CLOSED_PARENTHESIS ) )
1754 {
1755 //-1 denotes an infinite loop
1756 block.Write( TK_FLOAT, (float) -1);
1757 }
1758 else
1759 {
1760 if ( GetInteger( &block ) == false )
1761 return false;
1762 }
1763
1764 if (!Match( TK_CLOSED_PARENTHESIS ))
1765 return Error("GetLoop : too many parameters");
1766
1767 m_blockStream->WriteBlock( &block );
1768
1769 return true;
1770 }
1771
1772 /*
1773 ===================================================================================================
1774
1775 GetPrint()
1776
1777 Handles the print() function.
1778
1779 ===================================================================================================
1780 */
1781
GetPrint(void)1782 int CInterpreter::GetPrint( void )
1783 {
1784 CBlock block;
1785
1786 block.Create( ID_PRINT );
1787
1788 if (!Match( TK_OPEN_PARENTHESIS ))
1789 return Error("syntax error : '(' not found");
1790
1791 if ( GetString( &block ) == false )
1792 return false;
1793
1794 if (!Match( TK_CLOSED_PARENTHESIS ))
1795 return Error("print : too many parameters");
1796
1797 m_blockStream->WriteBlock( &block );
1798
1799 return true;
1800 }
1801
1802 /*
1803 ===================================================================================================
1804
1805 GetUse()
1806
1807 Handles the use() function.
1808
1809 ===================================================================================================
1810 */
1811
GetUse(void)1812 int CInterpreter::GetUse( void )
1813 {
1814 CBlock block;
1815
1816 block.Create( ID_USE );
1817
1818 if (!Match( TK_OPEN_PARENTHESIS ))
1819 return Error("syntax error : '(' not found");
1820
1821 if ( GetString( &block ) == false )
1822 return false;
1823
1824 if (!Match( TK_CLOSED_PARENTHESIS ))
1825 return Error("use : too many parameters");
1826
1827 m_blockStream->WriteBlock( &block );
1828
1829 return true;
1830 }
1831
1832 /*
1833 ===================================================================================================
1834
1835 GetFlush()
1836
1837 Handles the flush() function.
1838
1839 ===================================================================================================
1840 */
1841
GetFlush(void)1842 int CInterpreter::GetFlush( void )
1843 {
1844 CBlock block;
1845
1846 block.Create( ID_FLUSH );
1847
1848 if (!Match( TK_OPEN_PARENTHESIS ))
1849 return Error("syntax error : '(' not found");
1850
1851 if (!Match( TK_CLOSED_PARENTHESIS ))
1852 return Error("flush : too many parameters");
1853
1854 m_blockStream->WriteBlock( &block );
1855
1856 return true;
1857 }
1858
1859 /*
1860 ===================================================================================================
1861
1862 GetRun()
1863
1864 Handles the run() function.
1865
1866 ===================================================================================================
1867 */
1868
GetRun(void)1869 int CInterpreter::GetRun( void )
1870 {
1871 CBlock block;
1872
1873 block.Create( ID_RUN );
1874
1875 if (!Match( TK_OPEN_PARENTHESIS ))
1876 return Error("syntax error : '(' not found");
1877
1878 if ( GetString( &block ) == false )
1879 return false;
1880
1881 if (!Match( TK_CLOSED_PARENTHESIS ))
1882 return Error("run : too many parameters");
1883
1884 m_blockStream->WriteBlock( &block );
1885
1886 return true;
1887 }
1888
1889 /*
1890 ===================================================================================================
1891
1892 GetKill()
1893
1894 Handles the kill() function.
1895
1896 ===================================================================================================
1897 */
1898
GetKill(void)1899 int CInterpreter::GetKill( void )
1900 {
1901 CBlock block;
1902
1903 block.Create( ID_KILL );
1904
1905 if (!Match( TK_OPEN_PARENTHESIS ))
1906 return Error("syntax error : '(' not found");
1907
1908 if ( GetString( &block ) == false )
1909 return false;
1910
1911 if (!Match( TK_CLOSED_PARENTHESIS ))
1912 return Error("kill : too many parameters");
1913
1914 m_blockStream->WriteBlock( &block );
1915
1916 return true;
1917 }
1918
1919 /*
1920 ===================================================================================================
1921
1922 GetRemove()
1923
1924 Handles the remove() function.
1925
1926 ===================================================================================================
1927 */
1928
GetRemove(void)1929 int CInterpreter::GetRemove( void )
1930 {
1931 CBlock block;
1932
1933 block.Create( ID_REMOVE );
1934
1935 if (!Match( TK_OPEN_PARENTHESIS ))
1936 return Error("syntax error : '(' not found");
1937
1938 if ( GetString( &block ) == false )
1939 return false;
1940
1941 if (!Match( TK_CLOSED_PARENTHESIS ))
1942 return Error("remove : too many parameters");
1943
1944 m_blockStream->WriteBlock( &block );
1945
1946 return true;
1947 }
1948
1949 /*
1950 ===================================================================================================
1951
1952 GetRem()
1953
1954 Handles the rem() function.
1955
1956 ===================================================================================================
1957 */
1958
1959 // this is just so people can put comments in scripts in BehavEd and not have them lost as normal comments would be.
1960 //
GetRem(void)1961 int CInterpreter::GetRem( void )
1962 {
1963 CBlock block;
1964
1965 block.Create( ID_REM );
1966
1967 if (!Match( TK_OPEN_PARENTHESIS ))
1968 return Error("syntax error : '(' not found");
1969
1970 // optional string?
1971
1972 if (Match( TK_CLOSED_PARENTHESIS ))
1973 return true;
1974
1975 GetString( &block );
1976
1977 if (!Match( TK_CLOSED_PARENTHESIS ))
1978 return Error("rem : function only takes 1 optional parameter");
1979
1980 return true;
1981 }
1982
1983
1984 /*
1985 ===================================================================================================
1986
1987 GetCamera()
1988
1989 Handles the camera() function.
1990
1991 ===================================================================================================
1992 */
1993
GetCamera(void)1994 int CInterpreter::GetCamera( void )
1995 {
1996 CBlock block;
1997 char typeName[MAX_STRING_SIZE];
1998 int type;
1999
2000 block.Create( ID_CAMERA );
2001
2002 if (!Match( TK_OPEN_PARENTHESIS ))
2003 return Error("syntax error : '(' not found");
2004
2005 if ( GetType( (char *) typeName ) == false )
2006 return false;
2007
2008 type = FindSymbol( typeName, m_typeKeywords);
2009
2010 switch ( type )
2011 {
2012 case TYPE_PAN: //PAN ( ANGLES, DURATION )
2013
2014 block.Write( TK_FLOAT, (float) type );
2015
2016 if ( GetVector( &block ) == false )
2017 return false;
2018
2019 if ( GetVector( &block ) == false )
2020 return false;
2021
2022 if ( GetFloat( &block ) == false )
2023 return false;
2024
2025 break;
2026
2027 case TYPE_ZOOM: //ZOOM ( FOV, DURATION )
2028
2029 block.Write( TK_FLOAT, (float) type );
2030
2031 if ( GetFloat( &block ) == false )
2032 return false;
2033
2034 if ( GetFloat( &block ) == false )
2035 return false;
2036
2037 break;
2038
2039 case TYPE_MOVE: //MOVE ( ORIGIN, DURATION )
2040
2041 block.Write( TK_FLOAT, (float) type );
2042
2043 if ( GetVector( &block ) == false )
2044 return false;
2045
2046 if ( GetFloat( &block ) == false )
2047 return false;
2048
2049 break;
2050
2051 case TYPE_FADE: //FADE ( SOURCE(R,G,B,A), DEST(R,G,B,A), DURATION )
2052
2053 block.Write( TK_FLOAT, (float) type );
2054
2055 //Source color
2056 if ( GetVector( &block ) == false )
2057 return false;
2058 if ( GetFloat( &block ) == false )
2059 return false;
2060
2061 //Dest color
2062 if ( GetVector( &block ) == false )
2063 return false;
2064 if ( GetFloat( &block ) == false )
2065 return false;
2066
2067 //Duration
2068 if ( GetFloat( &block ) == false )
2069 return false;
2070
2071 break;
2072
2073 case TYPE_PATH: //PATH ( FILENAME )
2074
2075 block.Write( TK_FLOAT, (float) type );
2076
2077 //Filename
2078 if ( GetString( &block ) == false )
2079 return false;
2080
2081 break;
2082
2083 case TYPE_ENABLE:
2084 case TYPE_DISABLE:
2085
2086 block.Write( TK_FLOAT, (float) type );
2087 break;
2088
2089 case TYPE_SHAKE: //SHAKE ( INTENSITY, DURATION )
2090
2091 block.Write( TK_FLOAT, (float) type );
2092
2093 //Intensity
2094 if ( GetFloat( &block ) == false )
2095 return false;
2096
2097 //Duration
2098 if ( GetFloat( &block ) == false )
2099 return false;
2100
2101 break;
2102
2103 case TYPE_ROLL: //ROLL ( ANGLE, TIME )
2104
2105 block.Write( TK_FLOAT, (float) type );
2106
2107 //Angle
2108 if ( GetFloat( &block ) == false )
2109 return false;
2110
2111 //Time
2112 if ( GetFloat( &block ) == false )
2113 return false;
2114
2115 break;
2116
2117 case TYPE_TRACK: //TRACK ( TARGETNAME, SPEED, INITLERP )
2118
2119 block.Write( TK_FLOAT, (float) type );
2120
2121 //Target name
2122 if ( GetString( &block ) == false )
2123 return false;
2124
2125 //Speed
2126 if ( GetFloat( &block ) == false )
2127 return false;
2128
2129 //Init lerp
2130 if ( GetFloat( &block ) == false )
2131 return false;
2132
2133 break;
2134
2135 case TYPE_FOLLOW: //FOLLOW ( CAMERAGROUP, SPEED, INITLERP )
2136
2137 block.Write( TK_FLOAT, (float) type );
2138
2139 //Camera group
2140 if ( GetString( &block ) == false )
2141 return false;
2142
2143 //Speed
2144 if ( GetFloat( &block ) == false )
2145 return false;
2146
2147 //Init lerp
2148 if ( GetFloat( &block ) == false )
2149 return false;
2150
2151 break;
2152
2153 case TYPE_DISTANCE: //DISTANCE ( DISTANCE, INITLERP )
2154
2155 block.Write( TK_FLOAT, (float) type );
2156
2157 //Distance
2158 if ( GetFloat( &block ) == false )
2159 return false;
2160
2161 //Init lerp
2162 if ( GetFloat( &block ) == false )
2163 return false;
2164
2165 break;
2166 }
2167
2168 if (!Match( TK_CLOSED_PARENTHESIS ))
2169 return Error("camera : too many parameters");
2170
2171 m_blockStream->WriteBlock( &block );
2172
2173 return true;
2174 }
2175
2176 /*
2177 -------------------------
2178 GetDoWait
2179 -------------------------
2180 */
2181
GetDoWait(void)2182 int CInterpreter::GetDoWait( void )
2183 {
2184 CBlock block;
2185
2186 //Write out the "do" portion
2187 block.Create( ID_DO );
2188
2189 if (!Match( TK_OPEN_PARENTHESIS ))
2190 return Error("syntax error : '(' not found");
2191
2192 if ( GetString( &block ) == false )
2193 return false;
2194
2195 if (!Match( TK_CLOSED_PARENTHESIS ))
2196 return Error("do : too many parameters");
2197
2198 //Write out the accompanying "wait"
2199 char *str = (char *) block.GetMemberData( 0 );
2200
2201 CBlock block2;
2202
2203 block2.Create( ID_WAIT );
2204
2205 block2.Write( TK_STRING, (char *) str );
2206
2207 m_blockStream->WriteBlock( &block );
2208 m_blockStream->WriteBlock( &block2 );
2209
2210 return true;
2211 }
2212
2213 /*
2214 -------------------------
2215 GetSignal
2216 -------------------------
2217 */
2218
GetSignal(void)2219 int CInterpreter::GetSignal( void )
2220 {
2221 CBlock block;
2222
2223 block.Create( ID_SIGNAL );
2224
2225 if (!Match( TK_OPEN_PARENTHESIS ))
2226 return Error("syntax error : '(' not found");
2227
2228 if ( GetString( &block ) == false )
2229 return false;
2230
2231 if (!Match( TK_CLOSED_PARENTHESIS ))
2232 return Error("signal : too many parameters");
2233
2234 m_blockStream->WriteBlock( &block );
2235
2236 return true;
2237 }
2238
2239 /*
2240 -------------------------
2241 GetSignal
2242 -------------------------
2243 */
2244
GetWaitSignal(void)2245 int CInterpreter::GetWaitSignal( void )
2246 {
2247 CBlock block;
2248
2249 block.Create( ID_WAITSIGNAL );
2250
2251 if (!Match( TK_OPEN_PARENTHESIS ))
2252 return Error("syntax error : '(' not found");
2253
2254 if ( GetString( &block ) == false )
2255 return false;
2256
2257 if (!Match( TK_CLOSED_PARENTHESIS ))
2258 return Error("waitsignal : too many parameters");
2259
2260 m_blockStream->WriteBlock( &block );
2261
2262 return true;
2263 }
2264
2265 /*
2266 -------------------------
2267 GetPlay
2268 -------------------------
2269 */
2270
GetPlay(void)2271 int CInterpreter::GetPlay( void )
2272 {
2273 CBlock block;
2274
2275 block.Create( ID_PLAY );
2276
2277 if (!Match( TK_OPEN_PARENTHESIS ))
2278 return Error("syntax error : '(' not found");
2279
2280 if ( GetString( &block ) == false )
2281 return false;
2282
2283 if ( GetString( &block ) == false )
2284 return false;
2285
2286 if (!Match( TK_CLOSED_PARENTHESIS ))
2287 return Error("waitsignal : too many parameters");
2288
2289 m_blockStream->WriteBlock( &block );
2290
2291 return true;
2292 }
2293
2294 /*
2295 ===================================================================================================
2296
2297 GetTag()
2298
2299 Handles the tag() identifier.
2300
2301 ===================================================================================================
2302 */
2303
2304 //NOTENOTE: The tag's information is included as block members, not as a separate block.
2305
GetTag(CBlock * block)2306 int CInterpreter::GetTag( CBlock *block )
2307 {
2308 char typeName[MAX_STRING_SIZE];
2309 int typeID;
2310
2311 //Mark as a tag
2312 block->Write( ID_TAG, (float) ID_TAG );
2313
2314 if (!Match( TK_OPEN_PARENTHESIS ))
2315 return Error("syntax error : '(' not found");
2316
2317 //Get the tag name
2318 if ( GetString( block ) == false )
2319 return false;
2320
2321 //Get the lookup ID
2322 GetType( (char *) typeName );
2323
2324 typeID = FindSymbol( (char *) typeName, m_typeKeywords);
2325
2326 //Tags only contain origin and angles lookups
2327 if ( (typeID != TYPE_ORIGIN) && (typeID != TYPE_ANGLES) )
2328 {
2329 return Error("syntax error : 'tag' : %s is not a valid look up identifier", typeName );
2330 }
2331
2332 block->Write( TK_FLOAT, (float) typeID );
2333
2334 if (!Match( TK_CLOSED_PARENTHESIS ))
2335 return Error("tag : too many parameters");
2336
2337 return true;
2338 }
2339
2340 /*
2341 ===================================================================================================
2342
2343 Interpret function
2344
2345 ===================================================================================================
2346 */
2347
2348 // note new return type, this now returns the bad block number, else 0 for success.
2349 //
2350 // I also return -ve block numbers for errors between blocks. Eg if you read 3 good blocks, then find an unexpected
2351 // float in the script between blocks 3 & 4 then I return -3 to indicate the error is after that, but not block 4
2352 //
Interpret(CTokenizer * Tokenizer,CBlockStream * BlockStream,char * filename)2353 int CInterpreter::Interpret( CTokenizer *Tokenizer, CBlockStream *BlockStream, char *filename )
2354 {
2355 CBlock block;
2356 CToken *token;
2357 int type, blockLevel = 0, parenthesisLevel = 0;
2358
2359 m_sCurrentFile = filename; // used during error reporting because you can't ask tokenizer for pushed streams
2360
2361 m_tokenizer = Tokenizer;
2362 m_blockStream = BlockStream;
2363
2364 m_iCurrentLine = m_tokenizer->GetCurLine();
2365 token = m_tokenizer->GetToEndOfLine(TK_STRING);
2366 m_sCurrentLine = token->GetStringValue();
2367 m_tokenizer->PutBackToken(token, false, NULL, true);
2368
2369 m_iBadCBlockNumber = 0;
2370
2371 while (m_tokenizer->GetRemainingSize() > 0)
2372 {
2373 token = m_tokenizer->GetToken( TKF_USES_EOL, 0 );
2374 type = token->GetType();
2375
2376 switch ( type )
2377 {
2378 case TK_UNDEFINED:
2379 token->Delete();
2380 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2381 Error("%d : undefined token", type);
2382 return m_iBadCBlockNumber;
2383 break;
2384
2385 case TK_EOF:
2386 break;
2387
2388 case TK_EOL:
2389 // read the next line, then put it back
2390 token->Delete();
2391 m_iCurrentLine = m_tokenizer->GetCurLine();
2392 token = m_tokenizer->GetToEndOfLine(TK_STRING);
2393 m_sCurrentLine = token->GetStringValue();
2394 m_tokenizer->PutBackToken(token, false, NULL, true);
2395 break;
2396
2397 case TK_CHAR:
2398 case TK_STRING:
2399 token->Delete();
2400 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2401 Error("syntax error : unexpected string");
2402 return m_iBadCBlockNumber;
2403 break;
2404
2405 case TK_INT:
2406 token->Delete();
2407 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2408 Error("syntax error : unexpected integer");
2409 return m_iBadCBlockNumber;
2410 break;
2411
2412 case TK_FLOAT:
2413 token->Delete();
2414 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2415 Error("syntax error : unexpected float");
2416 return m_iBadCBlockNumber;
2417 break;
2418
2419 case TK_IDENTIFIER:
2420 m_iBadCBlockNumber++;
2421 if (!GetID( (char *) token->GetStringValue() ))
2422 {
2423 token->Delete();
2424 return m_iBadCBlockNumber;
2425 }
2426 token->Delete();
2427 break;
2428
2429 case TK_BLOCK_START:
2430 token->Delete();
2431 if (parenthesisLevel)
2432 {
2433 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2434 Error("syntax error : brace inside parenthesis");
2435 return m_iBadCBlockNumber;
2436 }
2437
2438 blockLevel++;
2439 break;
2440
2441 case TK_BLOCK_END:
2442 token->Delete();
2443 if (parenthesisLevel)
2444 {
2445 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2446 Error("syntax error : brace inside parenthesis");
2447 return m_iBadCBlockNumber;
2448 }
2449
2450 block.Create( ID_BLOCK_END );
2451 m_blockStream->WriteBlock( &block );
2452 block.Free();
2453
2454 blockLevel--;
2455 break;
2456
2457 case TK_OPEN_PARENTHESIS:
2458 token->Delete();
2459 blockLevel++;
2460 parenthesisLevel++;
2461 break;
2462
2463 case TK_CLOSED_PARENTHESIS:
2464 token->Delete();
2465 blockLevel--;
2466 parenthesisLevel--;
2467
2468 if (parenthesisLevel<0)
2469 {
2470 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2471 Error("syntax error : closed parenthesis with no opening match");
2472 return m_iBadCBlockNumber;
2473 }
2474 break;
2475
2476 case TK_VECTOR_START:
2477 token->Delete();
2478 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2479 Error("syntax error : unexpected vector");
2480 return m_iBadCBlockNumber;
2481 break;
2482
2483 case TK_VECTOR_END:
2484 token->Delete();
2485 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2486 Error("syntax error : unexpected vector");
2487 return m_iBadCBlockNumber;
2488 break;
2489 }
2490 }
2491
2492 if ( blockLevel )
2493 {
2494 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2495 Error("error : open brace was not closed");
2496 return m_iBadCBlockNumber;
2497 }
2498
2499 if ( parenthesisLevel )
2500 {
2501 m_iBadCBlockNumber = -m_iBadCBlockNumber;
2502 Error("error: open parenthesis");
2503 return m_iBadCBlockNumber;
2504 }
2505
2506 //Release all the variable information, because it's already been written out
2507 FreeVars();
2508
2509 m_iBadCBlockNumber = 0;
2510 return m_iBadCBlockNumber; //true;
2511 }
2512
2513