ScriptStack 1.0.4
Loading...
Searching...
No Matches
Parser.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5using ScriptStack;
7
9{
10
21 public class Parser
22 {
23
24 #region Private Structs
25
26 private struct Variable
27 {
28
29 public string name;
30 public Scope scope;
31 public Type derivatedType;
32
33 public Variable(string name, Scope scope, Type derivatedType)
34 {
35
36 this.name = name;
37
38 this.scope = scope;
39
40 this.derivatedType = derivatedType;
41
42 }
43
44 }
45
46 private struct FunctionDescriptor
47 {
48 public string name;
49 public uint parameterCount;
50 public Instruction instruction;
51 }
52
53 private struct LoopControl
54 {
55 public Instruction Break;
56 public Instruction Continue;
57 }
58
59 #endregion
60
61 #region Private Variables
62
63 private Script script;
64 private bool debugMode;
65 private List<Token> tokenStream;
66 private int nextToken;
67 private Dictionary<string, bool> variables;
68 private Dictionary<string, bool> localVariables;
69 private int functionFrameIndex;
70 private Dictionary<Instruction, FunctionDescriptor> forwardDeclarations;
71 private Stack<LoopControl> loopControl;
72 private Derivation derivation;
73 private Executable executable;
74
75 #endregion
76
77 #region Private Methods
78
83 private bool More()
84 {
85 return nextToken < tokenStream.Count;
86 }
87
92 private Token ReadToken()
93 {
94
95 if (!More())
96 throw new ParserException("Es sind keine weiteren Token vorhanden.");
97
98 return tokenStream[nextToken++];
99
100 }
101
106 private Token LookAhead()
107 {
108
109 if (!More())
110 throw new ParserException("Es sind keine weiteren Token vorhanden.");
111
112 return tokenStream[nextToken];
113
114 }
115
121 private Token LookAhead(int i)
122 {
123
124 if (!More() || null == tokenStream[nextToken + i] )
125 throw new ParserException("Es sind keine weiteren Token vorhanden.");
126
127 return tokenStream[nextToken + i];
128
129 }
130
134 private void UndoToken()
135 {
136
137 if (nextToken <= 0)
138 throw new ParserException("Es sind keine vorangehenden Token mehr vorhanden.");
139
140 --nextToken;
141
142 }
143
149 private bool AssignmentOperator(TokenType tokenType)
150 {
151
152 switch (tokenType)
153 {
154
155 case TokenType.Assign:
156 case TokenType.AssignPlus:
157 case TokenType.AssignMinus:
158 case TokenType.AssignMultiply:
159 case TokenType.AssignDivide:
160 case TokenType.AssignBinaryAnd:
161 case TokenType.AssignBinaryOr:
162 case TokenType.AssignXor:
163 case TokenType.AssignBinaryNot:
164 case TokenType.AssignModulo:
165 return true;
166
167 default:
168 return false;
169
170 }
171
172 }
173
179 private OpCode AssignmentOpcode(TokenType tokenType)
180 {
181
182 switch (tokenType)
183 {
184
185 case TokenType.Assign: return OpCode.MOV;
186 case TokenType.AssignPlus: return OpCode.ADD;
187 case TokenType.AssignMinus: return OpCode.SUB;
188 case TokenType.AssignMultiply: return OpCode.MUL;
189 case TokenType.AssignDivide: return OpCode.DIV;
190 case TokenType.AssignBinaryAnd: return OpCode.ANDB;
191 case TokenType.AssignBinaryOr: return OpCode.ORB;
192 case TokenType.AssignXor: return OpCode.XOR;
193 case TokenType.AssignBinaryNot: return OpCode.NOTB;
194 case TokenType.AssignModulo: return OpCode.MOD;
195 default:
196 throw new ParserException("Der Token '" + tokenType + "' ist kein Zuweisungsoperator.");
197
198 }
199
200 }
201
207 private bool RelationalOperator(TokenType tokenType)
208 {
209
210 switch (tokenType)
211 {
212
213 case TokenType.Equal:
214 case TokenType.NotEqual:
215 case TokenType.Greater:
216 case TokenType.GreaterEqual:
217 case TokenType.Less:
218 case TokenType.LessEqual:
219 return true;
220
221 default:
222 return false;
223
224 }
225
226 }
227
233 private OpCode RelationalOpcode(TokenType tokenType)
234 {
235
236 switch (tokenType)
237 {
238
239 case TokenType.Equal: return OpCode.CEQ;
240 case TokenType.NotEqual: return OpCode.CNE;
241 case TokenType.Greater: return OpCode.CG;
242 case TokenType.GreaterEqual: return OpCode.CGE;
243 case TokenType.Less: return OpCode.CL;
244 case TokenType.LessEqual: return OpCode.CLE;
245 default:
246 throw new ParserException("Der Token '" + tokenType + "' ist kein relationaler Operator.");
247
248 }
249
250 }
251
258 private Type Literal(TokenType tokenType)
259 {
260
261 switch (tokenType)
262 {
263
264 case TokenType.Integer:
265 return typeof(int);
266 case TokenType.Float:
267 return typeof(float);
268 case TokenType.Boolean:
269 return typeof(bool);
270 case TokenType.String:
271 return typeof(string);
272 case TokenType.Char:
273 return typeof(char);
274 default:
275 throw new ParserException( "Der Token '" + tokenType.ToString() + "' kann keinem Literal zugeordnet werden.");
276
277 }
278
279 }
280
288 private Type Derivate(Token token, Type first, Type second)
289 {
290
291 return derivation.Derivate(token, first, second);
292
293 }
294
299 private void AllocateVariable(string identifier)
300 {
301
302 if (variables.ContainsKey(identifier))
303 throw new ParserException("Die Variable '" + identifier + "' ist in einem umschliessenden Bereich bereits deklariert.");
304
305 if (localVariables.ContainsKey(identifier))
306 throw new ParserException("Die Variable '" + identifier + "' ist in diesem Bereich bereits deklariert.");
307
308 localVariables[identifier] = true;
309
310 executable.InstructionsInternal.Add(new Instruction(OpCode.DB, Operand.Variable(identifier)));
311
312 }
313
317 private void AllocateFunctionFrame()
318 {
319
320 functionFrameIndex++;
321
322 }
323
329 private string AllocateTemporaryVariable()
330 {
331
332 int index = 0;
333
334 while (true)
335 {
336
337 string identifier = "[" + functionFrameIndex + ":" + index + "]";
338
339 if (!localVariables.ContainsKey(identifier) && !variables.ContainsKey(identifier))
340 {
341
342 localVariables[identifier] = true;
343
344 return identifier;
345
346 }
347
348 ++index;
349
350 }
351
352 }
353
357 private void FreeFunctionFrame()
358 {
359
360 if (functionFrameIndex == 0)
361 return;
362
363 List<string> candidates = new List<string>();
364
365 foreach (string identifier in localVariables.Keys)
366 if (identifier.StartsWith("[" + functionFrameIndex + ":"))
367 candidates.Add(identifier);
368
369 foreach (string identifier in candidates)
370 localVariables.Remove(identifier);
371
372 --functionFrameIndex;
373
374 }
375
379 private void ReadSemicolon()
380 {
381
382 Token token = ReadToken();
383
384 if (token.Type != TokenType.SemiColon)
385 throw new ParserException("Semicolon ';' erwartet.", token);
386
387 }
388
392 private void ReadComma()
393 {
394
395 Token token = ReadToken();
396
397 if (token.Type != TokenType.Comma)
398 throw new ParserException("Comma ',' erwartet.", token);
399
400 }
401
405 private void ReadLeftParenthesis()
406 {
407
408 Token token = ReadToken();
409
410 if (token.Type != TokenType.LeftParen)
411 throw new ParserException("Klammer '(' erwartet.", token);
412
413 }
414
418 private void ReadRightParenthesis()
419 {
420
421 Token token = ReadToken();
422
423 if (token.Type != TokenType.RightParen)
424 throw new ParserException("Klammer ')' erwartet.", token);
425
426 }
427
431 private void ReadLeftBrace()
432 {
433
434 Token token = ReadToken();
435
436 if (token.Type != TokenType.LeftBrace)
437 throw new ParserException("Geschwungene Klammer '{' erwartet.", token);
438
439 }
440
444 private void ReadRightBrace()
445 {
446
447 Token token = ReadToken();
448
449 if (token.Type != TokenType.RightBrace)
450 throw new ParserException("Geschwungene Klammer '}' erwartet.", token);
451
452 }
453
457 private void ReadLeftBracket()
458 {
459
460 Token token = ReadToken();
461
462 if (token.Type != TokenType.LeftBracket)
463 throw new ParserException("Eckige Klammer '[' erwartet.", token);
464
465 }
466
470 private void ReadRightBracket()
471 {
472
473 Token token = ReadToken();
474
475 if (token.Type != TokenType.RightBracket)
476 throw new ParserException("Eckige Klammer ']' erwartet.", token);
477
478 }
479
483 private void ReadPeriod()
484 {
485
486 Token token = ReadToken();
487
488 if (token.Type != TokenType.Period)
489 throw new ParserException("Punkt '.' erwartet.", token);
490
491 }
492
493 private void InsertDebugInfo(Token token)
494 {
495
496 if (!debugMode)
497 return;
498
499 string text = token.Text;
500
501 //text = text.Replace("\r", "").Replace("\n", "");
502
503 executable.InstructionsInternal.Add(new Instruction(OpCode.DBG, Operand.Literal(token.Line), Operand.Literal(text)));
504
505 }
506
511 private string ReadIdentifier()
512 {
513
514 Token token = ReadToken();
515
516 if (token.Type != TokenType.Identifier)
517 throw new ParserException("Ein Keyword oder eine Variable wurde erwartet.", token);
518
519 return token.Lexeme.ToString();
520
521 }
522
527 private string ExpectIdentifier()
528 {
529
530 Token token = ReadToken();
531
532 if (token.Type != TokenType.Identifier)
533 throw new ParserException("Ein Keyword oder eine Variable wurde erwartet.", token);
534
535 string identifier = token.Lexeme.ToString();
536
537 if (!variables.ContainsKey(identifier) && !localVariables.ContainsKey(identifier))
538 throw new ParserException("Ein nicht vorhandener Identifier '" + identifier + "' wurde referenziert.", token);
539
540 return identifier;
541
542 }
543
547 private void VariableDeclaration()
548 {
549
550 Token token = ReadToken();
551
552 if (token.Type != TokenType.Shared && token.Type != TokenType.Var)
553 throw new ParserException( "Variablen werden mit 'shared' oder 'var' deklariert.", token);
554
555 InsertDebugInfo(token);
556
557 OpCode opcode = OpCode.DB;
558
559 if(token.Type == TokenType.Shared)
560 opcode = OpCode.DSB;
561
562 string identifier = ReadIdentifier();
563
564 while (true)
565 {
566
567 if (variables.ContainsKey(identifier))
568 throw new ParserException( "Die Variable '" + identifier + "' ist bereits vorhanden.", token);
569
570 variables[identifier] = true;
571
572 executable.InstructionsInternal.Add(new Instruction(opcode, Operand.Variable(identifier)));
573
574 if (opcode == OpCode.DSB)
575 script.Manager.SharedMemory[identifier] = NullReference.Instance;
576
577 else
578 executable.ScriptMemory[identifier] = NullReference.Instance;
579
580 token = ReadToken();
581
582 if (token.Type == TokenType.SemiColon)
583 return;
584
585 if (token.Type != TokenType.Comma)
586 throw new ParserException("Comma ',' erwartet.", token);
587
588 identifier = ReadIdentifier();
589
590 }
591
592 }
593
599 private Variable StructDeclaration()
600 {
601
602 AllocateFunctionFrame();
603
604 Token token = ReadToken();
605
606 if (token.Type != TokenType.Struct)
607 throw new ParserException("Strukturen werden mit 'struct' deklariert.", token);
608
609 InsertDebugInfo(token);
610
611 string identifier = ReadIdentifier();
612
613 executable.InstructionsInternal.Add(new Instruction(OpCode.DCO, Operand.Variable(identifier)));
614
615 string alloc = AllocateTemporaryVariable();
616
617 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(alloc), Operand.Variable(identifier)));
618
619 variables[identifier] = true;
620
621 ArrayList array = new ArrayList();
622
623 ReadLeftBrace();
624
625 int i = 0;
626
627 while (true)
628 {
629
630 Token tok = ReadToken();
631
632 if (tok.Type == TokenType.RightBrace)
633 {
634
635 UndoToken();
636 break;
637
638 }
639
640 if (LookAhead().Type == TokenType.RightBrace)
641 {
642
643 executable.InstructionsInternal.Add(new Instruction(OpCode.ADD, Operand.CreatePointer(identifier, (string)tok.Lexeme), Operand.Literal(0)));
644 array.Add(tok.Lexeme, 0);
645 break;
646
647 }
648
649 else if (LookAhead().Type == TokenType.Colon)
650 {
651
652 ReadToken();
653
654 Token tmpToken = ReadToken();
655
656 executable.InstructionsInternal.Add(new Instruction(OpCode.ADD, Operand.CreatePointer(identifier, (string)tok.Lexeme), Operand.Variable(tmpToken.Lexeme.ToString())));
657
658 array.Add(tok.Lexeme, tmpToken.Lexeme);
659
660 }
661
662 else
663 {
664
665 executable.InstructionsInternal.Add(new Instruction(OpCode.ADD, Operand.CreatePointer(identifier, (string)tok.Lexeme), Operand.Literal(0)));
666
667 array.Add(tok.Lexeme, 0);
668
669 }
670
671 if (LookAhead().Type == TokenType.RightBrace)
672 break;
673
674 ReadComma();
675
676 i++;
677
678 }
679
680 ReadRightBrace();
681
682 executable.ScriptMemory[identifier] = array;
683
684 FreeFunctionFrame();
685
686 return new Variable(identifier, Scope.Local, typeof(ArrayList));
687
688 }
689
696 private Variable EnumDeclaration()
697 {
698
699 AllocateFunctionFrame();
700
701 Token token = ReadToken();
702
703 if (token.Type != TokenType.Enum)
704 throw new ParserException("Enumerationen werden mit 'enum' deklariert.", token);
705
706 InsertDebugInfo(token);
707
708 string identifier = ReadIdentifier();
709
710 executable.InstructionsInternal.Add(new Instruction(OpCode.DCO, Operand.Variable(identifier)));
711
712 string alloc = AllocateTemporaryVariable();
713
714 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(alloc), Operand.Variable(identifier)));
715
716 variables[identifier] = true;
717
718 ArrayList array = new ArrayList();
719
720 ReadLeftBrace();
721
722 int i = 0;
723
724 while (true)
725 {
726
727 Token tok = ReadToken();
728
729 if (tok.Type == TokenType.RightBrace)
730 {
731
732 UndoToken();
733 break;
734
735 }
736
737 if (LookAhead().Type == TokenType.RightBrace)
738 {
739
740 executable.InstructionsInternal.Add(new Instruction(OpCode.ADD, Operand.CreatePointer(identifier, (string)tok.Lexeme), Operand.Literal(i)));
741 array.Add(tok.Lexeme, i);
742 break;
743
744 }
745 else
746 {
747
748 executable.InstructionsInternal.Add(new Instruction(OpCode.ADD, Operand.CreatePointer(identifier, (string)tok.Lexeme), Operand.Literal(i)));
749
750 array.Add(tok.Lexeme, i);
751
752 }
753
754 if (LookAhead().Type == TokenType.RightBrace)
755 break;
756
757 ReadComma();
758
759 i++;
760
761 }
762
763 ReadRightBrace();
764
765 executable.ScriptMemory[identifier] = array;
766
767 FreeFunctionFrame();
768
769 return new Variable(identifier, Scope.Local, typeof(ArrayList));
770
771 }
772
776 private void LocalVariableDeclaration()
777 {
778
779 Token token = ReadToken();
780
781 if (token.Type != TokenType.Var)
782 throw new ParserException( "Lokale Variablen werden mit 'var' deklariert.", token);
783
784 string identifier = ReadIdentifier();
785
786 while (true)
787 {
788
789 AllocateVariable(identifier);
790
791 token = ReadToken();
792
793 if (token.Type == TokenType.SemiColon)
794 return;
795
796 if (token.Type == TokenType.Assign)
797 {
798
799 UndoToken();
800
801 UndoToken();
802
803 Assignment();
804
805 token = ReadToken();
806
807 if (token.Type == TokenType.SemiColon)
808 return;
809
810 }
811
812 if (token.Type != TokenType.Comma)
813 throw new ParserException( "Comma ',' erwartet.", token);
814
815 identifier = ReadIdentifier();
816
817 }
818
819 }
820
824 private void Run()
825 {
826
827 Token token = ReadToken();
828
829 if (token.Type != TokenType.Run)
830 throw new ParserException("Keyword 'run' erwartet.", token);
831
832 FunctionCall(true);
833
834 ReadSemicolon();
835
836 }
837
843 private Variable RoutineCall()
844 {
845
846 string identifier = ReadIdentifier();
847
848 ReadLeftParenthesis();
849
850 List<object> parameters = new List<object>();
851
852 int parameterCount = 0;
853
854 if (LookAhead().Type != TokenType.RightParen)
855 {
856
857 while (true)
858 {
859
860 Variable parameter = Expression();
861
862 executable.InstructionsInternal.Add(new Instruction( OpCode.PUSH, Operand.Variable(parameter.name)));
863
864 ++parameterCount;
865
866 if (LookAhead().Type == TokenType.RightParen)
867 break;
868
869 else
870 ReadComma();
871
872 }
873
874 }
875
876 ReadRightParenthesis();
877
878 Manager manager = executable.Script.Manager;
879
880 if (!manager.Routines.ContainsKey(identifier))
881 throw new ParserException("Die Routine '" + identifier + "' ist nicht vorhanden.");
882
883 Routine routine = manager.Routines[identifier];
884
885 if (routine.ParameterTypes.Count > parameterCount)
886 throw new ParserException("Der Aufruf der Routine '" + identifier + "' hat fehlende Parameter. Erwartet werden " + routine.ParameterTypes.Count + " Parameter.\nBeschreibung der Routine: " + routine.Description().ToString());
887
888 if (routine.ParameterTypes.Count < parameterCount)
889 throw new ParserException("Der Aufruf der Routine '" + identifier + "' hat zu viele Parameter. Erwartet werden " + routine.ParameterTypes.Count + " Parameter.\nBeschreibung der Routine: " + routine.Description().ToString());
890
891 executable.InstructionsInternal.Add(new Instruction(OpCode.INV, Operand.AllocateRoutinePointer(routine)));
892
893 Variable variable = new Variable
894 {
895 name = AllocateTemporaryVariable(),
896 scope = Scope.Local,
897 derivatedType = null
898 };
899
900 executable.InstructionsInternal.Add(new Instruction(OpCode.POP, Operand.Variable(variable.name)));
901
902 return variable;
903
904 }
905
919 private Variable Pointer()
920 {
921
922 string identifier = ReadIdentifier();
923
924 string tmp = null;
925
926 while (LookAhead().Type == TokenType.LeftBracket)
927 {
928
929 ReadLeftBracket();
930
931 Variable index = Expression();
932
933 ReadRightBracket();
934
935 tmp = AllocateTemporaryVariable();
936
937 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), Operand.CreatePointer(identifier, index.name)));
938
939 identifier = tmp;
940
941 }
942
943 return new Variable(tmp, Scope.Local, null);
944
945 }
946
951 private Variable Member()
952 {
953
954 string arrayIdentifier = ReadIdentifier();
955
956 string tmp = null;
957
958 while (LookAhead().Type == TokenType.Period)
959 {
960
961 ReadPeriod();
962
963 string member = ReadIdentifier();
964
965 tmp = AllocateTemporaryVariable();
966
967 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), Operand.MemberVariable(arrayIdentifier, member)));
968
969 arrayIdentifier = tmp;
970
971 }
972
973 return new Variable(tmp, Scope.Local, null);
974
975 }
976
981 private Variable PreIncrement()
982 {
983
984 Token token = ReadToken();
985
986 if (token.Type != TokenType.Increment)
987 throw new ParserException( "Pre-increment '++' erwartet.", token);
988
989 string identifier = ExpectIdentifier();
990
991 executable.InstructionsInternal.Add(new Instruction(OpCode.INC, Operand.Variable(identifier)));
992
993 return new Variable(identifier, Scope.Local, null);
994
995 }
996
1001 private Variable PreDecrement()
1002 {
1003
1004 Token token = ReadToken();
1005
1006 if (token.Type != TokenType.Decrement)
1007 throw new ParserException("Pre-decrement '--' erwartet.", token);
1008
1009 string identifier = ExpectIdentifier();
1010
1011 executable.InstructionsInternal.Add(new Instruction(OpCode.DEC, Operand.Variable(identifier)));
1012
1013 return new Variable(identifier, Scope.Local, null);
1014
1015 }
1016
1021 private Variable PostIncrement()
1022 {
1023
1024 string identifier = ExpectIdentifier();
1025
1026 Token token = ReadToken();
1027
1028 if (token.Type != TokenType.Increment)
1029 throw new ParserException("Post-increment '++' erwartet.", token);
1030
1031 string tmp = AllocateTemporaryVariable();
1032
1033 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), Operand.Variable(identifier)));
1034
1035 executable.InstructionsInternal.Add(new Instruction(OpCode.INC, Operand.Variable(identifier)));
1036
1037 return new Variable(tmp, Scope.Local, null);
1038
1039 }
1040
1045 private Variable PostDecrement()
1046 {
1047
1048 string identifier = ExpectIdentifier();
1049
1050 Token token = ReadToken();
1051
1052 if (token.Type != TokenType.Decrement)
1053 throw new ParserException("Post-decrement '--' erwartet.", token);
1054
1055 string tmp = AllocateTemporaryVariable();
1056
1057 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), Operand.Variable(identifier)));
1058
1059 executable.InstructionsInternal.Add(new Instruction(OpCode.DEC, Operand.Variable(identifier)));
1060
1061 return new Variable(tmp, Scope.Local, null);
1062
1063 }
1064
1069 private Variable ShiftLeft()
1070 {
1071
1072 string left = ExpectIdentifier();
1073
1074 Token token = ReadToken();
1075
1076 if (token.Type != TokenType.ShiftLeft)
1077 throw new ParserException("Shift Left '<<' erwartet.", token);
1078
1079 Variable right = Factor();
1080
1081 executable.InstructionsInternal.Add(new Instruction(OpCode.SHL, Operand.Variable(left), Operand.Variable(right.name)));
1082
1083 return right;
1084
1085 }
1086
1091 private Variable ShiftRight()
1092 {
1093
1094 string left = ExpectIdentifier();
1095
1096 Token token = ReadToken();
1097
1098 if (token.Type != TokenType.ShiftRight)
1099 throw new ParserException("Shift Right '>>' erwartet.", token);
1100
1101 Variable right = Factor();
1102
1103 executable.InstructionsInternal.Add(new Instruction(OpCode.SHR, Operand.Variable(left), Operand.Variable(right.name)));
1104
1105 return right;
1106
1107 }
1108
1113 private Variable BinaryAnd()
1114 {
1115
1116 string left = ExpectIdentifier();
1117
1118 Token token = ReadToken();
1119
1120 if (token.Type != TokenType.AssignBinaryAnd)
1121 throw new ParserException("Binary AND '&=' erwartet.", token);
1122
1123 Variable right = Factor();
1124
1125 executable.InstructionsInternal.Add(new Instruction(OpCode.ANDB, Operand.Variable(left), Operand.Variable(right.name)));
1126
1127 return right;
1128
1129 }
1130
1135 private Variable BinaryOr()
1136 {
1137
1138 string left = ExpectIdentifier();
1139
1140 Token token = ReadToken();
1141
1142 if (token.Type != TokenType.AssignBinaryOr)
1143 throw new ParserException("Binary OR '|=' erwartet.", token);
1144
1145 Variable right = Factor();
1146
1147 executable.InstructionsInternal.Add(new Instruction(OpCode.ORB, Operand.Variable(left), Operand.Variable(right.name)));
1148
1149 return right;
1150
1151 }
1152
1157 private Variable BinaryNotAssign()
1158 {
1159
1160 string left = ExpectIdentifier();
1161
1162 Token token = ReadToken();
1163
1164 if (token.Type != TokenType.AssignBinaryNot)
1165 throw new ParserException("Binary NEG '~=' erwartet.", token);
1166
1167 Variable right = Factor();
1168
1169 executable.InstructionsInternal.Add(new Instruction(OpCode.NOTB, Operand.Variable(left), Operand.Variable(right.name)));
1170
1171 return right;
1172
1173 }
1174
1179 private Variable BinaryNot()
1180 {
1181
1182 Token token = ReadToken();
1183
1184 if (token.Type != TokenType.AssignBinaryNot)
1185 throw new ParserException("Binary NOT '~=' erwartet.", token);
1186
1187 Variable right = Factor();
1188
1189 executable.InstructionsInternal.Add(new Instruction(OpCode.NOTB, Operand.Variable(right.name)));
1190
1191 return right;
1192
1193 }
1194
1199 private Variable Xor()
1200 {
1201
1202 string left = ExpectIdentifier();
1203
1204 Token token = ReadToken();
1205
1206 if (token.Type != TokenType.AssignXor)
1207 throw new ParserException("Binary XOR '~=' erwartet.", token);
1208
1209 Variable right = Factor();
1210
1211 executable.InstructionsInternal.Add(new Instruction(OpCode.XOR, Operand.Variable(left), Operand.Variable(right.name)));
1212
1213 return right;
1214
1215 }
1216
1217 public string ToLiteral(string input)
1218 {
1219 var literal = new StringBuilder(input.Length + 2);
1220 literal.Append("\"");
1221 foreach (var c in input)
1222 {
1223 switch (c)
1224 {
1225 case '\'': literal.Append(@"\'"); break;
1226 case '\"': literal.Append("\\\""); break;
1227 case '\\': literal.Append(@"\\"); break;
1228 case '\0': literal.Append(@"\0"); break;
1229 case '\a': literal.Append(@"\a"); break;
1230 case '\b': literal.Append(@"\b"); break;
1231 case '\f': literal.Append(@"\f"); break;
1232 case '\n': literal.Append(@"\n"); break;
1233 case '\r': literal.Append(@"\r"); break;
1234 case '\t': literal.Append(@"\t"); break;
1235 case '\v': literal.Append(@"\v"); break;
1236 default:
1237 if (char.GetUnicodeCategory(c) != System.Globalization.UnicodeCategory.Control)
1238 {
1239 literal.Append(c);
1240 }
1241 else
1242 {
1243 literal.Append(@"\u");
1244 literal.Append(((ushort)c).ToString("x4"));
1245 }
1246 break;
1247 }
1248 }
1249 literal.Append("\"");
1250 return literal.ToString();
1251 }
1252
1257 private Variable Atom()
1258 {
1259
1260 Token token = ReadToken();
1261
1262 Variable variable = new Variable();
1263
1264 switch (token.Type)
1265 {
1266
1267 case TokenType.Minus:
1268
1269 variable = Atom();
1270
1271 string tmpIdentifier = AllocateTemporaryVariable();
1272
1273 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.Variable(variable.name)));
1274
1275 executable.InstructionsInternal.Add(new Instruction(OpCode.NEG, Operand.Variable(tmpIdentifier)));
1276
1277 variable.name = tmpIdentifier;
1278
1279 return variable;
1280
1281 case TokenType.Null:
1282
1283 variable.name = AllocateTemporaryVariable();
1284
1285 variable.scope = Scope.Local;
1286
1287 variable.derivatedType = typeof(NullReference);
1288
1289 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(variable.name), Operand.Literal(NullReference.Instance)));
1290
1291 return variable;
1292
1293 case TokenType.Integer:
1294 case TokenType.Float:
1295 case TokenType.Boolean:
1296 case TokenType.String:
1297 case TokenType.Char:
1298
1299 variable.name = AllocateTemporaryVariable();
1300
1301 variable.scope = Scope.Local;
1302
1303 variable.derivatedType = Literal(token.Type);
1304
1305 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(variable.name), Operand.Literal(token.Lexeme)));
1306
1307 return variable;
1308
1309 case TokenType.Increment:
1310
1311 UndoToken();
1312
1313 variable = PreIncrement();
1314
1315 return variable;
1316
1317 case TokenType.Decrement:
1318
1319 UndoToken();
1320
1321 variable = PreDecrement();
1322
1323 return variable;
1324
1325 case TokenType.Identifier:
1326
1327 string identifier = token.Lexeme.ToString();
1328
1329 switch (LookAhead().Type)
1330 {
1331
1332 case TokenType.Increment:
1333
1334 UndoToken();
1335
1336 return PostIncrement();
1337
1338 case TokenType.Decrement:
1339
1340 UndoToken();
1341
1342 return PostDecrement();
1343
1344 case TokenType.LeftBracket:
1345
1346 UndoToken();
1347
1348 return Pointer();
1349
1350 case TokenType.Period:
1351
1352 UndoToken();
1353
1354 return Member();
1355
1356 case TokenType.LeftParen:
1357
1358 UndoToken();
1359
1360 return FunctionCall();
1361
1362 case TokenType.ShiftLeft:
1363
1364 UndoToken();
1365
1366 return ShiftLeft();
1367
1368 case TokenType.ShiftRight:
1369
1370 UndoToken();
1371
1372 return ShiftRight();
1373
1374 default:
1375
1376 UndoToken();
1377
1378 identifier = ExpectIdentifier();
1379
1380 variable.name = AllocateTemporaryVariable();
1381
1382 variable.scope = Scope.Local;
1383
1384 variable.derivatedType = null;
1385
1386 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(variable.name), Operand.Variable(identifier)));
1387
1388 return variable;
1389
1390 }
1391
1392 case TokenType.LeftParen:
1393
1394 variable = Expression();
1395
1396 ReadRightParenthesis();
1397
1398 return variable;
1399
1400 default:
1401
1402 throw new ParserException( "Fehlerhafter Token '" + token + "'.", token);
1403
1404 }
1405
1406 }
1407
1412 private Variable BraceArray()
1413 {
1414
1415 ReadLeftBrace();
1416
1417 int index = 0;
1418
1419 string identifier = AllocateTemporaryVariable();
1420
1421 string indexIdentifier = AllocateTemporaryVariable();
1422
1423 executable.InstructionsInternal.Add(new Instruction(OpCode.DC, Operand.Variable(identifier)));
1424
1425 if (LookAhead().Type != TokenType.RightBrace)
1426 {
1427
1428 while (true)
1429 {
1430
1431 Variable tmp = Expression();
1432
1433 Token token = LookAhead();
1434
1435 if (token.Type == TokenType.Comma || token.Type == TokenType.SemiColon || token.Type == TokenType.RightBrace)
1436 {
1437
1438 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.MemberVariable(identifier, index++), Operand.Variable(tmp.name)));
1439
1440 if (token.Type == TokenType.RightBrace)
1441 break;
1442
1443 /* todo: could be comma or semicolon, depends on current cultureinfo */
1444 if (token.Type == TokenType.Comma)
1445 ReadComma();
1446
1447 if (token.Type == TokenType.SemiColon)
1448 ReadSemicolon();
1449
1450 }
1451
1452 else if (token.Type == TokenType.Colon)
1453 {
1454
1455 ReadToken();
1456
1457 Variable variableKey = tmp;
1458
1459 tmp = Expression();
1460
1461 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.CreatePointer(identifier, variableKey.name), Operand.Variable(tmp.name)));
1462
1463 if (LookAhead().Type == TokenType.RightBrace)
1464 break;
1465
1466 /* todo: could be comma or semicolon, depends on current cultureinfo */
1467 if (LookAhead().Type == TokenType.Comma)
1468 ReadComma();
1469
1470 if (LookAhead().Type == TokenType.SemiColon)
1471 ReadSemicolon();
1472
1473 }
1474
1475 else
1476 throw new ParserException( "Ein Comma ',', Semicolon ';' oder Colon ':' wurde erwartet.");
1477
1478 }
1479
1480 }
1481
1482 ReadRightBrace();
1483
1484 return new Variable(identifier, Scope.Local, typeof(ArrayList));
1485
1486 }
1487
1492 private Variable BracketArray()
1493 {
1494
1495 ReadLeftBracket();
1496
1497 int index = 0;
1498
1499 string identifier = AllocateTemporaryVariable();
1500
1501 string indexIdentifier = AllocateTemporaryVariable();
1502
1503 executable.InstructionsInternal.Add(new Instruction(OpCode.DC, Operand.Variable(identifier)));
1504
1505 if (LookAhead().Type != TokenType.RightBracket)
1506 {
1507
1508 while (true)
1509 {
1510
1511 Variable tmp = Expression();
1512
1513 Token token = LookAhead();
1514
1515 if (token.Type == TokenType.Comma || token.Type == TokenType.RightBracket)
1516 {
1517
1518 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.MemberVariable(identifier, index++), Operand.Variable(tmp.name)));
1519
1520 if (token.Type == TokenType.RightBracket)
1521 break;
1522
1523 ReadComma();
1524
1525 }
1526
1527 else if (token.Type == TokenType.Colon)
1528 {
1529
1530 ReadToken();
1531
1532 Variable key = tmp;
1533
1534 tmp = Expression();
1535
1536 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.CreatePointer(identifier, key.name), Operand.Variable(tmp.name)));
1537
1538 if(LookAhead().Type == TokenType.RightBracket)
1539 break;
1540
1541 ReadComma();
1542
1543 }
1544
1545 else
1546 throw new ParserException( "Ein Comma ',' oder Colon ':' wurde erwartet.");
1547
1548 }
1549
1550 }
1551
1552 ReadRightBracket();
1553
1554 return new Variable(identifier, Scope.Local, typeof(ArrayList));
1555
1556 }
1557
1562 private Variable Factor()
1563 {
1564
1565 if (LookAhead().Type == TokenType.LeftBrace)
1566 return BraceArray();
1567
1568 // test
1569 if (LookAhead().Type == TokenType.LeftBracket)
1570 return BracketArray();
1571
1572 Variable variable = Atom();
1573
1574 return variable;
1575
1576 }
1577
1582 private Variable Term()
1583 {
1584
1585 List<Instruction> listInstructions = executable.InstructionsInternal;
1586
1587 Variable first = Factor();
1588
1589 Variable second = new Variable();
1590
1591 while (true)
1592 {
1593
1594 Token token = ReadToken();
1595
1596 switch (token.Type)
1597 {
1598
1599 case TokenType.Multiply:
1600 second = Factor();
1601
1602 listInstructions.Add(new Instruction(OpCode.MUL, Operand.Variable(first.name), Operand.Variable(second.name)));
1603
1604 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1605
1606 break;
1607
1608 case TokenType.Divide:
1609
1610 second = Factor();
1611
1612 listInstructions.Add(new Instruction(OpCode.DIV, Operand.Variable(first.name), Operand.Variable(second.name)));
1613
1614 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1615
1616 break;
1617
1618 case TokenType.Modulo:
1619 second = Factor();
1620
1621 listInstructions.Add(new Instruction(OpCode.MOD, Operand.Variable(first.name), Operand.Variable(second.name)));
1622
1623 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1624
1625 break;
1626
1627 default:
1628 UndoToken();
1629 return first;
1630
1631 }
1632
1633 }
1634
1635 }
1636
1643 private Variable Arithmetic()
1644 {
1645
1646 List<Instruction> listInstructions = executable.InstructionsInternal;
1647
1648 Variable first = Term();
1649
1650 Variable second = new Variable();
1651
1652 while(true)
1653 {
1654
1655 Token token = ReadToken();
1656
1657 switch (token.Type)
1658 {
1659
1660 case TokenType.Plus:
1661
1662 second = Term();
1663
1664 listInstructions.Add(new Instruction(OpCode.ADD, Operand.Variable(first.name), Operand.Variable(second.name)));
1665
1666 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1667
1668 break;
1669
1670 case TokenType.Minus:
1671
1672 second = Term();
1673
1674 listInstructions.Add(new Instruction(OpCode.SUB, Operand.Variable(first.name), Operand.Variable(second.name)));
1675
1676 break;
1677
1678 default:
1679
1680 UndoToken();
1681
1682 return first;
1683
1684 }
1685
1686 }
1687
1688 }
1689
1694 private Variable Relation()
1695 {
1696
1697 List<Instruction> instructions = executable.InstructionsInternal;
1698
1699 Variable first = Arithmetic();
1700
1701 Token token = ReadToken();
1702
1703 if (RelationalOperator(token.Type)) {
1704
1705 Variable second = Arithmetic();
1706
1707 instructions.Add(new Instruction(RelationalOpcode(token.Type), Operand.Variable(first.name), Operand.Variable(second.name)));
1708
1709 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1710
1711 }
1712
1713 else
1714 UndoToken();
1715
1716 return first;
1717
1718 }
1719
1726 private Variable Not()
1727 {
1728
1729 Variable proposition = new Variable();
1730
1731 if (LookAhead().Type == TokenType.Not)
1732 {
1733
1734 ReadToken();
1735
1736 if (LookAhead().Type == TokenType.LeftParen)
1737 proposition = Expression();
1738
1739 else
1740 proposition = Relation();
1741
1742 executable.InstructionsInternal.Add(new Instruction(OpCode.NOT, Operand.Variable(proposition.name)));
1743
1744 return proposition;
1745
1746 }
1747
1748 else
1749 return Relation();
1750
1751 }
1752
1759 private Variable And()
1760 {
1761
1762 List<Instruction> instructions = executable.InstructionsInternal;
1763
1764 Variable first = Not();
1765
1766 while (true)
1767 {
1768
1769 Token token = ReadToken();
1770
1771 if (token.Type == TokenType.And)
1772 {
1773
1774 Variable second = Not();
1775
1776 instructions.Add(new Instruction(OpCode.AND, Operand.Variable(first.name), Operand.Variable(second.name)));
1777
1778 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1779
1780 break;
1781
1782 }
1783
1784 else
1785 {
1786
1787 UndoToken();
1788
1789 return first;
1790
1791 }
1792
1793 }
1794
1795 return first;
1796
1797 }
1798
1805 private Variable Or()
1806 {
1807
1808 List<Instruction> instructions = executable.InstructionsInternal;
1809
1810 Variable first = And();
1811
1812 while (true)
1813 {
1814
1815 Token token = ReadToken();
1816
1817 if (token.Type == TokenType.Or)
1818 {
1819
1820 Variable second = And();
1821
1822 instructions.Add( new Instruction(OpCode.OR, Operand.Variable(first.name), Operand.Variable(second.name)));
1823
1824 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1825
1826 break;
1827
1828 }
1829
1830 else
1831 {
1832
1833 UndoToken();
1834
1835 return first;
1836
1837 }
1838
1839 }
1840
1841 return first;
1842
1843 }
1844
1849 private Variable VariableAssignment()
1850 {
1851
1852 string identifier = ExpectIdentifier();
1853
1854 Token token = ReadToken();
1855
1856 if (!AssignmentOperator(token.Type))
1857 throw new ParserException("Ein Zuweisungsoperator wurde erwartet erwartet.", token);
1858
1859 Variable expression = Expression();
1860
1861 executable.InstructionsInternal.Add(new Instruction(AssignmentOpcode(token.Type), Operand.Variable(identifier), Operand.Variable(expression.name)));
1862
1863 string tmpIdentifier = AllocateTemporaryVariable();
1864
1865 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.Variable(identifier)));
1866
1867 return new Variable(tmpIdentifier, Scope.Local, expression.derivatedType);
1868
1869 }
1870
1875 private Variable ArrayAssignment()
1876 {
1877
1878 string identifier = ExpectIdentifier();
1879
1880 List<Instruction> listInstructions = executable.InstructionsInternal;
1881
1882 Variable tmp = new Variable();
1883
1884 string src = identifier;
1885
1886 string dst = null;
1887
1888 while (!AssignmentOperator(LookAhead().Type))
1889 {
1890
1891 ReadLeftBracket();
1892
1893 tmp = Expression();
1894
1895 ReadRightBracket();
1896
1897 if (!AssignmentOperator(LookAhead().Type))
1898 {
1899
1900 dst = AllocateTemporaryVariable();
1901
1902 listInstructions.Add(new Instruction(OpCode.MOV, Operand.Variable(dst), Operand.CreatePointer(src, tmp.name)));
1903
1904 src = dst;
1905
1906 }
1907
1908 }
1909
1910 Token tok = ReadToken();
1911
1912 Variable expression = Expression();
1913
1914 if (dst == null)
1915 dst = identifier;
1916
1917 listInstructions.Add(new Instruction(AssignmentOpcode(tok.Type), Operand.CreatePointer(dst, tmp.name), Operand.Variable(expression.name)));
1918
1919 string tmpIdentifier = AllocateTemporaryVariable();
1920
1921 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.CreatePointer(dst, tmp.name)));
1922
1923 return new Variable(tmpIdentifier, Scope.Local, expression.derivatedType);
1924
1925 }
1926
1931 private Variable MemberAssignment()
1932 {
1933
1934 string identifier = ExpectIdentifier();
1935
1936 List<string> members = new List<string>();
1937
1938 while (LookAhead().Type == TokenType.Period)
1939 {
1940
1941 ReadPeriod();
1942
1943 members.Add(ReadIdentifier());
1944
1945 }
1946
1947 Token tok = ReadToken();
1948
1949 if (!AssignmentOperator(tok.Type))
1950 throw new ParserException("Ein Zuweisungsoperator wurde erwartet.", tok);
1951
1952 Variable expression = Expression();
1953
1954 string dst = null;
1955
1956 string src = identifier;
1957
1958 for (int i = 0; i < members.Count - 1; i++)
1959 {
1960
1961 dst = AllocateTemporaryVariable();
1962
1963 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(dst), Operand.MemberVariable(src, members[i])));
1964
1965 src = dst;
1966
1967 }
1968
1969 if (dst == null)
1970 dst = identifier;
1971
1972 executable.InstructionsInternal.Add(new Instruction(AssignmentOpcode(tok.Type), Operand.MemberVariable(dst, members[members.Count - 1]), Operand.Variable(expression.name)));
1973
1974 string tmpIdentifier = AllocateTemporaryVariable();
1975
1976 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.MemberVariable(dst, members[members.Count - 1])));
1977
1978 Variable variable = new Variable(tmpIdentifier, Scope.Local, expression.derivatedType);
1979
1980 return variable;
1981
1982 }
1983
1988 private Variable Assignment()
1989 {
1990
1991 string identifier = ExpectIdentifier();
1992
1993 Token token = LookAhead();
1994
1995 switch (token.Type)
1996 {
1997
1998 case TokenType.Assign:
1999 case TokenType.AssignPlus:
2000 case TokenType.AssignMinus:
2001 case TokenType.AssignMultiply:
2002 case TokenType.AssignDivide:
2003 case TokenType.AssignBinaryAnd:
2004 case TokenType.AssignBinaryOr:
2005 case TokenType.AssignXor:
2006 case TokenType.AssignBinaryNot:
2007 case TokenType.AssignModulo:
2008 UndoToken();
2009 return VariableAssignment();
2010
2011 case TokenType.LeftBracket:
2012 UndoToken();
2013 return ArrayAssignment();
2014
2015 case TokenType.Period:
2016 UndoToken();
2017 return MemberAssignment();
2018
2019 default:
2020 throw new ExecutionException("Es wurde ein Zuweisungoperator erwartet.");
2021
2022 }
2023
2024 }
2025
2030 private bool IsPointer()
2031 {
2032
2033 Token start = LookAhead();
2034
2035 if (start.Type != TokenType.Identifier)
2036 return false;
2037
2038 int iInstructionCheckpoint = executable.InstructionsInternal.Count;
2039
2040 string identifier = ReadIdentifier();
2041
2042 while (LookAhead().Type == TokenType.LeftBracket)
2043 {
2044
2045 ReadLeftBracket();
2046 Expression();
2047 ReadRightBracket();
2048
2049 }
2050
2051 Token tok = ReadToken();
2052
2053 while (LookAhead() != start)
2054 UndoToken();
2055
2056 executable.InstructionsInternal.RemoveRange(iInstructionCheckpoint, executable.InstructionsInternal.Count - iInstructionCheckpoint);
2057
2058 return AssignmentOperator(tok.Type);
2059
2060 }
2061
2066 private bool IsMember()
2067 {
2068
2069 Token start = LookAhead();
2070
2071 if (start.Type != TokenType.Identifier)
2072 return false;
2073
2074 string identifier = ReadIdentifier();
2075
2076 while (LookAhead().Type == TokenType.Period)
2077 {
2078
2079 ReadPeriod();
2080
2081 Token token = ReadToken();
2082
2083 if (token.Type != TokenType.Identifier)
2084 {
2085
2086 while (LookAhead() != start)
2087 UndoToken();
2088
2089 return false;
2090
2091 }
2092
2093 }
2094
2095 Token tok = ReadToken();
2096
2097 while (LookAhead() != start)
2098 UndoToken();
2099
2100 return AssignmentOperator(tok.Type);
2101
2102 }
2103
2108 private Variable Expression()
2109 {
2110
2111 if (IsPointer() || IsMember())
2112 return Assignment();
2113
2114 else
2115 return Or();
2116
2117 }
2118
2122 private void If()
2123 {
2124
2125 Token token = ReadToken();
2126
2127 if (token.Type != TokenType.If)
2128 throw new ParserException( "Keyword 'if' erwartet.", token);
2129
2130 ReadLeftParenthesis();
2131
2132 Variable condition = Expression();
2133
2134 ReadRightParenthesis();
2135
2136 Instruction start = new Instruction(OpCode.NOP);
2137
2138 Instruction end = new Instruction(OpCode.NOP);
2139
2140 executable.InstructionsInternal.Add(new Instruction(OpCode.JNZ, Operand.Variable(condition.name), Operand.AllocateInstructionPointer(start)));
2141
2142 StatementList();
2143
2144 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(end)));
2145
2146 executable.InstructionsInternal.Add(start);
2147
2148 if (LookAhead().Type == TokenType.Else)
2149 {
2150
2151 ReadToken();
2152
2153 StatementList();
2154 }
2155
2156 executable.InstructionsInternal.Add(end);
2157
2158 }
2159
2163 private void While()
2164 {
2165
2166 Token token = ReadToken();
2167
2168 if (token.Type != TokenType.While)
2169 throw new ParserException("Keyword 'while' erwartet.", token);
2170
2171 Instruction start = new Instruction(OpCode.NOP);
2172
2173 executable.InstructionsInternal.Add(start);
2174
2175 ReadLeftParenthesis();
2176
2177 Variable condition = Expression();
2178
2179 if (condition.derivatedType != null && condition.derivatedType != typeof(bool))
2180 throw new ParserException("In While Loops wird ein logischer Ausdruck erwartet.", token);
2181
2182 ReadRightParenthesis();
2183
2184 Instruction end = new Instruction(OpCode.NOP);
2185
2186 executable.InstructionsInternal.Add(new Instruction(OpCode.JNZ, Operand.Variable(condition.name), Operand.AllocateInstructionPointer(end)));
2187
2188 LoopControl loopControl = new LoopControl();
2189
2190 loopControl.Break = end;
2191
2192 loopControl.Continue = start;
2193
2194 this.loopControl.Push(loopControl);
2195
2196 StatementList();
2197
2198 this.loopControl.Pop();
2199
2200 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(start)));
2201
2202 executable.InstructionsInternal.Add(end);
2203
2204 }
2205
2209 private void For()
2210 {
2211
2212 Token token = ReadToken();
2213
2214 if (token.Type != TokenType.For)
2215 throw new ParserException("Keyword 'for' erwartet.", token);
2216
2217 ReadLeftParenthesis();
2218
2219 if (LookAhead().Type == TokenType.SemiColon)
2220 ReadSemicolon();
2221
2222 else if (LookAhead().Type == TokenType.Var)
2223 LocalVariableDeclaration();
2224
2225 else
2226 {
2227
2228 Assignment();
2229
2230 ReadSemicolon();
2231
2232 }
2233
2234 Instruction start = new Instruction(OpCode.NOP);
2235
2236 executable.InstructionsInternal.Add(start);
2237
2238 Instruction continueInstruction = new Instruction(OpCode.NOP);
2239
2240 Variable condition = new Variable();
2241
2242 if (LookAhead().Type == TokenType.SemiColon)
2243 {
2244
2245 condition = new Variable(AllocateTemporaryVariable(), Scope.Local, typeof(bool));
2246
2247 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(condition.name), Operand.Literal(true)));
2248
2249 ReadSemicolon();
2250
2251 }
2252
2253 else
2254 {
2255
2256 condition = Expression();
2257
2258 if (condition.derivatedType != null && condition.derivatedType != typeof(bool))
2259 throw new ParserException("In For Loops wird ein logischer Ausdruck oder 'null' erwartet.", token);
2260
2261 ReadSemicolon();
2262
2263 }
2264
2265 List<Instruction> expression = null;
2266
2267 if (LookAhead().Type != TokenType.RightParen)
2268 {
2269
2270 int loopStart = executable.InstructionsInternal.Count;
2271
2272 Expression();
2273
2274 int loopCount = executable.InstructionsInternal.Count - loopStart;
2275
2276 expression = executable.InstructionsInternal.GetRange(loopStart, loopCount);
2277
2278 executable.InstructionsInternal.RemoveRange(loopStart, loopCount);
2279
2280 }
2281
2282 else
2283 expression = new List<Instruction>();
2284
2285 ReadRightParenthesis();
2286
2287 Instruction end = new Instruction(OpCode.NOP);
2288
2289 executable.InstructionsInternal.Add(new Instruction(OpCode.JNZ, Operand.Variable(condition.name), Operand.AllocateInstructionPointer(end)));
2290
2291 LoopControl loopControl = new LoopControl();
2292
2293 loopControl.Break = end;
2294
2295 loopControl.Continue = continueInstruction;
2296
2297 this.loopControl.Push(loopControl);
2298
2299 StatementList();
2300
2301 this.loopControl.Pop();
2302
2303 executable.InstructionsInternal.Add(continueInstruction);
2304
2305 executable.InstructionsInternal.AddRange(expression);
2306
2307 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(start)));
2308
2309 executable.InstructionsInternal.Add(end);
2310
2311 }
2312
2316 private void ForEach()
2317 {
2318
2319 Token token = ReadToken();
2320
2321 if (token.Type != TokenType.Foreach)
2322 throw new ParserException("Keyword 'foreach' erwartet.", token);
2323
2324 ReadLeftParenthesis();
2325
2326 string key = null;
2327
2328 string val = ExpectIdentifier();
2329
2330 token = ReadToken();
2331
2332 if (token.Type == TokenType.Comma)
2333 {
2334
2335 key = val;
2336
2337 val = ExpectIdentifier();
2338
2339 token = ReadToken();
2340
2341 }
2342
2343 if (token.Type != TokenType.In)
2344 throw new ParserException("Keyword 'in' erwartet.", token);
2345
2346 if (key == null)
2347 key = AllocateTemporaryVariable();
2348
2349 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(key), Operand.Literal(NullReference.Instance)));
2350
2351 Instruction start = new Instruction(OpCode.NOP);
2352
2353 executable.InstructionsInternal.Add(start);
2354
2355 Variable array = Expression();
2356
2357 if (array.derivatedType != null && array.derivatedType != typeof(ArrayList))
2358 throw new ParserException("In ForEach Loops wird ein logischer Ausdruck erwartet.", token);
2359
2360 ReadRightParenthesis();
2361
2362 executable.InstructionsInternal.Add(new Instruction(OpCode.PTR, Operand.Variable(key), Operand.Variable(array.name)));
2363
2364 string identifier = AllocateTemporaryVariable();
2365
2366 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(identifier), Operand.Variable(key)));
2367
2368 //executable.InstructionsInternal.Add(new Instruction(OpCode.CEQ, Operand.Variable(identifier), Operand.Literal(true)));
2369 executable.InstructionsInternal.Add(new Instruction(OpCode.TEST, Operand.Variable(identifier)));
2370
2371 Instruction end = new Instruction(OpCode.NOP);
2372
2373 executable.InstructionsInternal.Add(new Instruction(OpCode.JZ, Operand.Variable(identifier), Operand.AllocateInstructionPointer(end)));
2374
2375 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(val), Operand.CreatePointer(array.name, key)));
2376
2377 LoopControl loopControl = new LoopControl();
2378
2379 loopControl.Break = end;
2380
2381 loopControl.Continue = start;
2382
2383 this.loopControl.Push(loopControl);
2384
2385 StatementList();
2386
2387 this.loopControl.Pop();
2388
2389 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(start)));
2390
2391 executable.InstructionsInternal.Add(end);
2392
2393 }
2394
2398 private void Break()
2399 {
2400
2401 Token token = ReadToken();
2402
2403 if (token.Type != TokenType.Break)
2404 throw new ParserException("Keyword 'break' erwartet.", token);
2405
2406 ReadSemicolon();
2407
2408 if (loopControl.Count == 0)
2409 throw new ParserException("Das Keyword 'break' kann nur innerhalb von Loops verwendet werden.", token);
2410
2411 Instruction breakInstruction = loopControl.Peek().Break;
2412
2413 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(breakInstruction)));
2414
2415 }
2416
2420 private void Continue()
2421 {
2422
2423 Token token = ReadToken();
2424
2425 if (token.Type != TokenType.Continue)
2426 throw new ParserException("Keyword 'continue' erwartet.", token);
2427
2428 ReadSemicolon();
2429
2430 if (loopControl.Count == 0)
2431 throw new ParserException("Das Keyword 'continue' kann nur innerhalb von Loops verwendet werden.", token);
2432
2433 Instruction continueInstruction = loopControl.Peek().Continue;
2434
2435 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(continueInstruction)));
2436
2437 }
2438
2442 private void Switch()
2443 {
2444
2445 Token token = ReadToken();
2446
2447 if (token.Type != TokenType.Switch)
2448 throw new ParserException("Keyword 'switch' erwartet.", token);
2449
2450 ReadLeftParenthesis();
2451
2452 string switchIdentifier = ExpectIdentifier();
2453
2454 ReadRightParenthesis();
2455
2456 ReadLeftBrace();
2457
2458 token = LookAhead();
2459
2460 if (token.Type != TokenType.Case && token.Type != TokenType.Default)
2461 throw new ParserException("Keyword 'case' oder 'default' erwartet.", token);
2462
2463 string tmpIdentifier = AllocateTemporaryVariable();
2464
2465 string identifier = AllocateTemporaryVariable();
2466
2467 Instruction end = new Instruction(OpCode.NOP);
2468
2469 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.Literal(false)));
2470
2471 while (LookAhead().Type != TokenType.Default && LookAhead().Type != TokenType.RightBrace)
2472 {
2473
2474 token = ReadToken();
2475
2476 if (token.Type != TokenType.Case)
2477 throw new ParserException("Keyword 'case' erwartet.", token);
2478
2479 InsertDebugInfo(token);
2480
2481 Variable expression = Expression();
2482
2483 token = ReadToken();
2484
2485 if (token.Type != TokenType.Colon)
2486 throw new ParserException("Colon ':' erwartet.", token);
2487
2488 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(identifier), Operand.Variable(switchIdentifier)));
2489
2490 executable.InstructionsInternal.Add(new Instruction(OpCode.CEQ, Operand.Variable(identifier), Operand.Variable(expression.name)));
2491
2492 executable.InstructionsInternal.Add(new Instruction(OpCode.OR, Operand.Variable(tmpIdentifier), Operand.Variable(identifier)));
2493
2494 if (LookAhead().Type != TokenType.Case)
2495 {
2496 Instruction switchInstruction = new Instruction(OpCode.NOP);
2497
2498 executable.InstructionsInternal.Add(new Instruction(OpCode.JNZ, Operand.Variable(tmpIdentifier), Operand.AllocateInstructionPointer(switchInstruction)));
2499
2500 Statement();
2501
2502 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(end)));
2503
2504 executable.InstructionsInternal.Add(switchInstruction);
2505
2506 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.Literal(false)));
2507
2508 }
2509 }
2510
2511 token = ReadToken();
2512
2513 if (token.Type == TokenType.RightBrace)
2514 {
2515
2516 executable.InstructionsInternal.Add(end);
2517
2518 return;
2519
2520 }
2521
2522 if (token.Type != TokenType.Default)
2523 throw new ParserException("Das Keyword 'default' oder eine schliessende geschwungene Klammer '}' wird am Ende einer 'switch' Anweisung erwartet.", token);
2524
2525 token = ReadToken();
2526
2527 if (token.Type != TokenType.Colon)
2528 throw new ParserException("Ein Colon ':' wurde erwartet.", token);
2529
2530 Statement();
2531
2532 ReadRightBrace();
2533
2534 executable.InstructionsInternal.Add(end);
2535
2536 }
2537
2541 private void Return()
2542 {
2543
2544 Token token = ReadToken();
2545
2546 if (token.Type != TokenType.Return)
2547 throw new ParserException("Keyword 'return' erwartet.", token);
2548
2549 if (LookAhead().Type != TokenType.SemiColon)
2550 executable.InstructionsInternal.Add(new Instruction(OpCode.PUSH, Operand.Variable(Expression().name)));
2551
2552 else
2553 executable.InstructionsInternal.Add(new Instruction(OpCode.PUSH, Operand.Literal(NullReference.Instance)));
2554
2555 ReadSemicolon();
2556
2557 executable.InstructionsInternal.Add(new Instruction(OpCode.RET));
2558
2559 return;
2560
2561 }
2562
2566 private void FunctionDeclaration()
2567 {
2568
2569 Token token = ReadToken();
2570
2571 if (token.Type != TokenType.Function)
2572 throw new ParserException("Funktion werden mit 'function' deklariert.", token);
2573
2574 string functionName = ReadIdentifier();
2575
2576 if (executable.Functions.ContainsKey(functionName))
2577 throw new ParserException("Die Funktion '" + functionName + "' ist bereits vorhanden.", token);
2578
2579 ReadLeftParenthesis();
2580
2581 InsertDebugInfo(token);
2582
2583 List<string> parameters = new List<string>();
2584
2585 if (LookAhead().Type != TokenType.RightParen)
2586 {
2587
2588 while (true)
2589 {
2590
2591 token = ReadToken();
2592
2593 if (token.Type != TokenType.Identifier)
2594 throw new ParserException("Unerwarteter Token '" + token.Lexeme + "'.", token);
2595
2596 string parameter = token.Lexeme.ToString();
2597
2598 AllocateVariable(parameter);
2599
2600 parameters.Add(parameter);
2601
2602 token = LookAhead();
2603
2604 if (token.Type == TokenType.Comma)
2605 ReadComma();
2606
2607 else if (token.Type == TokenType.RightParen)
2608 break;
2609
2610 else
2611 throw new ParserException("Comma ',' oder schliessende Klammer ')' erwartet.");
2612
2613 }
2614
2615 }
2616
2617 ReadRightParenthesis();
2618
2619 Instruction scriptInstructionFunctionEntry = new Instruction(OpCode.NOP);
2620
2621 executable.InstructionsInternal.Add(scriptInstructionFunctionEntry);
2622
2623 Function scriptFunction = new Function(executable, functionName, parameters, scriptInstructionFunctionEntry);
2624
2625 executable.Functions[functionName] = scriptFunction;
2626
2627 parameters.Reverse();
2628
2629 foreach (string parameter in parameters)
2630 {
2631
2632 Instruction scriptInstructionPop = new Instruction(OpCode.POP, Operand.Variable(parameter));
2633
2634 executable.InstructionsInternal.Add(scriptInstructionPop);
2635
2636 }
2637
2638 StatementList();
2639
2640 executable.InstructionsInternal.Add(new Instruction( OpCode.PUSH, Operand.Literal(NullReference.Instance)));
2641
2642 executable.InstructionsInternal.Add(new Instruction(OpCode.RET));
2643
2644 localVariables.Clear();
2645
2646 }
2647
2656 private Variable FunctionCall(bool background)
2657 {
2658
2659 string name = ReadIdentifier();
2660
2661 // lets expect it is a function
2662 bool forwardDeclared = true;
2663
2664 // if it is registered to the manager it is a routine of course
2665 if (!executable.Functions.ContainsKey(name))
2666 forwardDeclared = false;
2667
2668 ReadLeftParenthesis();
2669
2670 uint parameterCount = 0;
2671
2672 if (LookAhead().Type != TokenType.RightParen)
2673 {
2674
2675 // parameters are on the stack, already set to true so we just assign them
2676 while (true)
2677 {
2678
2679 Variable parameter = Expression();
2680
2681 executable.InstructionsInternal.Add(new Instruction(OpCode.PUSH, Operand.Variable(parameter.name)));
2682
2683 ++parameterCount;
2684
2685 if (LookAhead().Type == TokenType.RightParen)
2686 break;
2687
2688 else
2689 ReadComma();
2690
2691 }
2692
2693 }
2694
2695 ReadRightParenthesis();
2696
2697 Instruction instruction = null;
2698
2699 Function function = null;
2700
2701 if (forwardDeclared)
2702 {
2703
2704 function = executable.Functions[name];
2705
2706 if (function.ParameterCount > parameterCount)
2707 throw new ParserException("Der Aufruf der Funktion '" + name + "' hat fehlende Parameter. Erwartet werden " + function.ParameterCount + " Parameter.");
2708
2709 // \todo should we just throw the rest?
2710 if (function.ParameterCount < parameterCount)
2711 throw new ParserException("Der Aufruf der Funktion '" + name + "' hat zu viele Parameter. Erwartet werden " + function.ParameterCount + " Parameter.");
2712
2713 }
2714
2715 Variable variable = new Variable();
2716
2717 if (background)
2718 {
2719
2720 instruction = new Instruction(OpCode.RUN, Operand.AllocateFunctionPointer(function));
2721
2722 executable.InstructionsInternal.Add(instruction);
2723
2724 }
2725
2726 else
2727 {
2728
2729 instruction = new Instruction(OpCode.CALL, Operand.AllocateFunctionPointer(function));
2730
2731 executable.InstructionsInternal.Add(instruction);
2732
2733 // the result is popped onto the stack so a temp variable is created like '[0:0]'
2734 variable.name = AllocateTemporaryVariable();
2735
2736 variable.scope = Scope.Local;
2737
2738 variable.derivatedType = null;
2739
2740 executable.InstructionsInternal.Add(new Instruction(OpCode.POP, Operand.Variable(variable.name)));
2741
2742 }
2743
2744 if (!forwardDeclared)
2745 {
2746
2747 FunctionDescriptor functionDescriptor = new FunctionDescriptor();
2748
2749 functionDescriptor.name = name;
2750
2751 functionDescriptor.parameterCount = parameterCount;
2752
2753 functionDescriptor.instruction = null;
2754
2755 forwardDeclarations[instruction] = functionDescriptor;
2756
2757 }
2758
2759 return variable;
2760
2761 }
2762
2768 private Variable FunctionCall()
2769 {
2770
2771 string functionName = ReadIdentifier();
2772
2773 UndoToken();
2774
2775 if (executable.Script.Manager.IsRegistered(functionName))
2776 return RoutineCall();
2777
2778 else
2779 return FunctionCall(false);
2780
2781 }
2782
2786 private void Statement()
2787 {
2788
2789 AllocateFunctionFrame();
2790
2791 Token token = LookAhead();
2792
2793 InsertDebugInfo(token);
2794
2795 switch (token.Type)
2796 {
2797
2798 case TokenType.SemiColon:
2799 ReadToken();
2800 break;
2801
2802 case TokenType.Var:
2803 LocalVariableDeclaration();
2804 break;
2805
2806 case TokenType.LeftBrace:
2807 StatementList();
2808 break;
2809
2810 case TokenType.Increment:
2811 case TokenType.Decrement:
2812 case TokenType.LeftParen:
2813 case TokenType.Identifier:
2814 case TokenType.Null:
2815 case TokenType.Integer:
2816 case TokenType.Float:
2817 case TokenType.Boolean:
2818 case TokenType.String:
2819 case TokenType.Char:
2820 Expression();
2821 if(LookAhead().Type == TokenType.SemiColon)
2822 ReadSemicolon();
2823 break;
2824
2825 case TokenType.If:
2826 If();
2827 break;
2828 case TokenType.While:
2829 While();
2830 break;
2831 case TokenType.For:
2832 For();
2833 break;
2834 case TokenType.Foreach:
2835 ForEach();
2836 break;
2837 case TokenType.Break:
2838 Break();
2839 break;
2840 case TokenType.Continue:
2841 Continue();
2842 break;
2843 case TokenType.Switch:
2844 Switch();
2845 break;
2846 case TokenType.Return:
2847 Return();
2848 break;
2849
2850 case TokenType.Run:
2851 Run();
2852 break;
2853 case TokenType.Yield:
2854 Yield();
2855 break;
2856 case TokenType.Wait:
2857 Wait();
2858 break;
2859 case TokenType.Notify:
2860 Notify();
2861 break;
2862 case TokenType.Lock:
2863 LockedStatementList();
2864 break;
2865
2866 default: throw new ParserException("ParserException::Statement: Ein unerwarteter Token '" + token.Lexeme + "' wurde gefunden.", token);
2867
2868 }
2869
2870 FreeFunctionFrame();
2871
2872 }
2873
2878 private void StatementList()
2879 {
2880
2881 // if there are no braces, just read a single statement
2882 if (LookAhead().Type != TokenType.LeftBrace)
2883 {
2884
2885 Statement();
2886
2887 return;
2888
2889 }
2890
2891 ReadToken();
2892
2893 while (LookAhead().Type != TokenType.RightBrace)
2894 Statement();
2895
2896 ReadRightBrace();
2897
2898 }
2899
2903 private void LockedStatementList()
2904 {
2905
2906 Token token = ReadToken();
2907
2908 if (token.Type != TokenType.Lock)
2909 throw new ExecutionException("ParserException: Keyword 'lock' erwartet.");
2910
2911 Variable variable = Expression();
2912
2913 executable.InstructionsInternal.Add(new Instruction(OpCode.LOCK, Operand.Variable(variable.name)));
2914
2915 Statement();
2916
2917 executable.InstructionsInternal.Add(new Instruction(OpCode.FREE, Operand.Variable(variable.name)));
2918
2919 }
2920
2924 private void Yield()
2925 {
2926
2927 Token token = ReadToken();
2928
2929 if (token.Type != TokenType.Yield)
2930 throw new ParserException("ParserException: Keyword 'yield' erwartet.", token);
2931
2932 ReadSemicolon();
2933
2934 executable.InstructionsInternal.Add(new Instruction(OpCode.INT));
2935
2936 }
2937
2943 private void Wait()
2944 {
2945
2946 Token token = ReadToken();
2947
2948 if (token.Type != TokenType.Wait)
2949 throw new ParserException("Keyword 'wailt' erwartet.", token);
2950
2951 string identifier = ExpectIdentifier();
2952
2953 ReadSemicolon();
2954
2955 List<Instruction> instructions = executable.InstructionsInternal;
2956
2957 Instruction arrived = new Instruction(OpCode.NOP);
2958
2959 Instruction waiting = new Instruction(OpCode.JZ, Operand.Variable(identifier), Operand.AllocateInstructionPointer(arrived));
2960
2961 instructions.Add(waiting);
2962
2963 instructions.Add(new Instruction(OpCode.INT));
2964
2965 instructions.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(waiting)));
2966
2967 instructions.Add(arrived);
2968
2969 }
2970
2975 private void Notify()
2976 {
2977
2978 Token token = ReadToken();
2979
2980 if (token.Type != TokenType.Notify)
2981 throw new ParserException("Keyword 'notify' erwartet.", token);
2982
2983 string identifier = ExpectIdentifier();
2984
2985 ReadSemicolon();
2986
2987 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(identifier), Operand.Literal(true)));
2988
2989 }
2990
2996 private void ParseScript()
2997 {
2998
2999 while (More())
3000 {
3001
3002 Token token = LookAhead();
3003
3004 if (token.Type == TokenType.Shared || token.Type == TokenType.Var)
3005 VariableDeclaration();
3006
3007 else if (token.Type == TokenType.Struct)
3008 StructDeclaration();
3009
3010 else if (token.Type == TokenType.Enum)
3011 EnumDeclaration();
3012
3013 else
3014 break;
3015
3016 }
3017
3018 if (!More())
3019 return;
3020
3021 while (More())
3022 {
3023
3024 Token token = LookAhead();
3025
3026 if (token.Type != TokenType.Function)
3027 throw new ParserException( "Ausserhalb von Funktionen sind keine Anweisungen erlaubt.", token);
3028
3029 FunctionDeclaration();
3030
3031 }
3032
3033 }
3034
3038 private void ResolveForwardFunctionDeclarations()
3039 {
3040
3041 foreach (Instruction instruction in forwardDeclarations.Keys)
3042 {
3043
3044 FunctionDescriptor functionDescriptor = forwardDeclarations[instruction];
3045
3046 string name = functionDescriptor.name;
3047
3048 if (!executable.Functions.ContainsKey(name))
3049 throw new ParserException("Eine nicht deklarierte Funktion '" + name + "' wurde referenziert.");
3050
3051 Function function = executable.Functions[name];
3052
3053 instruction.First.FunctionPointer = function;
3054
3055 }
3056
3057 }
3058
3059 #endregion
3060
3061 #region Internal Properties
3062
3063 internal bool DebugMode
3064 {
3065 get { return debugMode; }
3066 set { debugMode = value; }
3067 }
3068
3069 #endregion
3070
3071 #region Public Methods
3072
3073 public Parser(Script script, List<Token> tokenStream)
3074 {
3075 this.script = script;
3076 debugMode = false;
3077 nextToken = 0;
3078 variables = new Dictionary<String, bool>();
3079 localVariables = new Dictionary<String, bool>();
3080 functionFrameIndex = 0;
3081 forwardDeclarations = new Dictionary<Instruction, FunctionDescriptor>();
3082 loopControl = new Stack<LoopControl>();
3083 this.tokenStream = new List<Token>(tokenStream);
3084 derivation = new Derivation();
3085 executable = null;
3086 }
3087
3093 {
3094 nextToken = 0;
3095 variables.Clear();
3096 localVariables.Clear();
3097 functionFrameIndex = -1;
3098 forwardDeclarations.Clear();
3099 loopControl.Clear();
3100
3101 executable = new Executable(script);
3102
3103 ParseScript();
3104 ResolveForwardFunctionDeclarations();
3105 executable.Clean();
3106
3107 return executable;
3108 }
3109
3110 #endregion
3111
3112 }
3113
3114}
Parser(Script script, List< Token > tokenStream)
Definition Parser.cs:3073
Executable Parse()
Parse the token stream into an executable.
Definition Parser.cs:3092
string ToLiteral(string input)
Definition Parser.cs:1217
A lexical token or simply token is a string with an assigned and thus identified meaning.
Definition Token.cs:100
API entry point.
Definition Manager.cs:20
Manager()
A Manager object is responsible for memory management, type evaluation and loading of plugins.
Definition Manager.cs:48
ReadOnlyDictionary< String, Routine > Routines
Definition Manager.cs:241
void Add(object objectValue)
Definition ArrayList.cs:95
An instruction in a virtual intermediate language.
static Operand MemberVariable(string identifier, object val)
Definition Operand.cs:64
static Operand Literal(object val)
Definition Operand.cs:54
static Operand CreatePointer(string identifier, string pointer)
Definition Operand.cs:69
static Operand AllocateRoutinePointer(Routine routine)
Definition Operand.cs:84
static Operand Variable(string identifier)
Definition Operand.cs:59
A Routine is an abstract representation of a method.
Definition Routine.cs:70
List< Type > ParameterTypes
Definition Routine.cs:312
Internal representation of a text file (source code) which can be passed to the Interpreter to execut...
Definition Script.cs:18
TokenType
Known types of Token.
Definition Token.cs:12