ScriptStack 1.0.5
Loading...
Searching...
No Matches
ScriptStack.Compiler.Parser Class Reference

The parser builds an ScriptStack.Runtime.Executable out of the Token stream returned from the ScriptStack.Compiler.Lexer while checking for correct syntax. More...

Classes

struct  Variable
struct  FunctionDescriptor
struct  LoopControl
class  AccessSegment

Public Member Functions

string ToLiteral (string input)
 Parser (Script script, List< Token > tokenStream)
Executable Parse ()
 Parse the token stream into an executable.

Private Member Functions

bool More ()
 Check if there are more tokens available.
Token ReadToken ()
 Get the next available token.
Token LookAhead ()
 Get the next available token without actually increasing the tokenstream index.
Token LookAhead (int i)
 Get the token 'n' steps forward without actually increasing the tokenstream index.
void UndoToken ()
 If you read a token wrong, push it back so the stream stays intact.
bool AssignmentOperator (TokenType tokenType)
OpCode AssignmentOpcode (TokenType tokenType)
bool RelationalOperator (TokenType tokenType)
OpCode RelationalOpcode (TokenType tokenType)
Type Literal (TokenType tokenType)
 Get the literal type of a token.
Type Derivate (Token token, Type first, Type second)
 Get the resulting type of two computed types.
void AllocateVariable (string identifier)
 Allocate a local variable.
void AllocateFunctionFrame ()
 Increase the function frame index.
string AllocateTemporaryVariable ()
 Add a temporary variable to the current function frames local memory.
void FreeFunctionFrame ()
 Decrease the function frame index.
void ReadSemicolon ()
void ReadComma ()
void ReadLeftParenthesis ()
void ReadRightParenthesis ()
void ReadLeftBrace ()
void ReadRightBrace ()
void ReadLeftBracket ()
void ReadRightBracket ()
void ReadPeriod ()
void InsertDebugInfo (Token token)
string ReadIdentifier ()
 Read a new (previously NOT declared) identifier.
string ReadQualifiedIdentifier ()
 Read a dotted (qualified) identifier like: std.print or ns.io.print.
string ExpectIdentifier ()
 Read an expected (previously declared) identifier.
void VariableDeclaration ()
 Shared or local variable declaration.
void LocalVariableDeclaration ()
void Run ()
Variable RoutineCall ()
Variable Pointer ()
 Array access.
Variable Member ()
 Member access.
Variable AccessChain ()
 Mixed access chain parser.
Variable PreIncrement ()
Variable PreDecrement ()
Variable PostIncrement ()
Variable PostDecrement ()
Variable ShiftLeft ()
Variable ShiftRight ()
Variable BinaryAnd ()
Variable BinaryOr ()
Variable BinaryNotAssign ()
Variable BinaryNot ()
Variable Xor ()
Variable Atom ()
 The smallest unit.
Variable BraceArray ()
 An array enclosed in braces.
Variable BracketArray ()
 An array enclosed in brackets.
Variable Factor ()
 Atom | Array.
Variable Term ()
 Factor ( [*|/|%] Factor ).
Variable Arithmetic ()
 Multiplication and division before Addition and substraction.
Variable Relation ()
Variable Not ()
 Proposition.
Variable BitwiseAnd ()
 Bitwise AND '&'.
Variable BitwiseXor ()
 Bitwise XOR '^'.
Variable BitwiseOr ()
 Bitwise OR '|'.
Variable And ()
 Conjunction.
Variable Or ()
 Disjunction (not exclusive).
Variable VariableAssignment ()
Variable AccessChainAssignment ()
 Mixed access chain assignment.
Variable ArrayAssignment ()
Variable MemberAssignment ()
Variable Assignment ()
 An assignment can be a variable assignment, an array assignment or a member assignment.
bool IsAccessChainAssignment ()
 Detect whether the upcoming tokens form an assignment expression.
bool IsPointer ()
bool IsMember ()
Variable Expression ()
 An expression is an assignment or a disjunction.
void If ()
void While ()
void For ()
void ForEach ()
void Break ()
void Continue ()
void Switch ()
void Return ()
 By default null is returned.
void FunctionDeclaration ()
 Parameter variables are already set to true but not assigned yet. Pop all of them in reverse order onto the stack.
Variable FunctionCall (bool background)
 Call a forward declared function Push all parameter identifier onto the stack and call the function/routine Only functions can run in background because routines are not translated!
Variable FunctionCall ()
 Can be a call to a forward declared Function or a Routine. To check what it is we look if it is a registered routine, if not it must be a function.
void Statement ()
 A statement can be a local variable declaration, a statement list, an expression or a keyword.
void StatementList ()
 A list of statements. If its not a list (not in braces) just return a single statement.
void LockedStatementList ()
void Yield ()
void Wait ()
 Wait for a locked secion of code to be freed.
void Notify ()
void ParseScript ()
 After the first function declaration no more variable, struct or enum declarations are allowed anymore.
void ResolveForwardFunctionDeclarations ()
 Resolve unresolved, forward declared functions.

Private Attributes

Script script
bool debugMode
List< TokentokenStream
int nextToken
Dictionary< string, bool > variables
Dictionary< string, bool > localVariables
int functionFrameIndex
Dictionary< Instruction, FunctionDescriptorforwardDeclarations
Stack< LoopControlloopControl
Derivation derivation
Executable executable

Detailed Description

The parser builds an ScriptStack.Runtime.Executable out of the Token stream returned from the ScriptStack.Compiler.Lexer while checking for correct syntax.

The parser takes the output from the Lexer in the form of a Token stream and matches it against syntax rules to detect any errors. The output is an abstract syntax tree in form of Instruction's which can be executed by the ScriptStack.Runtime.Interpreter. More details are coming soon.

Not all methods are well documented yet but please be patient - i am working on it.

See https://en.wikipedia.org/wiki/Parsing

Definition at line 21 of file Parser.cs.

Constructor & Destructor Documentation

◆ Parser()

ScriptStack.Compiler.Parser.Parser ( Script script,
List< Token > tokenStream )

Definition at line 3336 of file Parser.cs.

3337 {
3338 this.script = script;
3339 debugMode = false;
3340 nextToken = 0;
3341 variables = new Dictionary<String, bool>();
3342 localVariables = new Dictionary<String, bool>();
3343 functionFrameIndex = 0;
3344 forwardDeclarations = new Dictionary<Instruction, FunctionDescriptor>();
3345 loopControl = new Stack<LoopControl>();
3346 this.tokenStream = new List<Token>(tokenStream);
3347 derivation = new Derivation();
3348 executable = null;
3349 }

References debugMode, derivation, executable, forwardDeclarations, functionFrameIndex, localVariables, loopControl, nextToken, script, tokenStream, and variables.

Member Function Documentation

◆ AccessChain()

Variable ScriptStack.Compiler.Parser.AccessChain ( )
private

Mixed access chain parser.

Supports combinations of member and index access in arbitrary order, e.g.

obj.pets[0].name
pets[0].name
obj.map["x"].y[1]

The implementation lowers each postfix operation into a MOV into a temporary variable, so the runtime only needs to support OperandType.Member and OperandType.Pointer.

Definition at line 841 of file Parser.cs.

842 {
843
844 string identifier = ReadIdentifier();
845
846 // We only get here if the next token is '[' or '.'
847 string tmp = null;
848
849 while (true)
850 {
851
852 if (LookAhead().Type == TokenType.LeftBracket)
853 {
854
855 ReadLeftBracket();
856
857 Variable index = Expression();
858
859 ReadRightBracket();
860
861 tmp = AllocateTemporaryVariable();
862
863 executable.InstructionsInternal.Add(
864 new Instruction(OpCode.MOV,
865 Operand.Variable(tmp),
866 Operand.CreatePointer(identifier, index.name)));
867
868 identifier = tmp;
869
870 continue;
871
872 }
873
874 if (LookAhead().Type == TokenType.Period)
875 {
876
877 ReadPeriod();
878
879 string member = ReadIdentifier();
880
881 // Method call on CLR object: obj.Member(...)
882 // Lowered into: PUSH args..., MIV obj.Member, <argc>, POP tmp
883 if (LookAhead().Type == TokenType.LeftParen)
884 {
885
886 ReadLeftParenthesis();
887
888 int parameterCount = 0;
889
890 if (LookAhead().Type != TokenType.RightParen)
891 {
892 while (true)
893 {
894 Variable parameter = Expression();
895 executable.InstructionsInternal.Add(new Instruction(OpCode.PUSH, Operand.Variable(parameter.name)));
896 ++parameterCount;
897
898 if (LookAhead().Type == TokenType.RightParen)
899 break;
900
901 ReadComma();
902 }
903 }
904
905 ReadRightParenthesis();
906
907 // invoke member
908 executable.InstructionsInternal.Add(
909 new Instruction(OpCode.MIV,
910 Operand.MemberVariable(identifier, member),
911 Operand.Literal(parameterCount)));
912
913 tmp = AllocateTemporaryVariable();
914 executable.InstructionsInternal.Add(new Instruction(OpCode.POP, Operand.Variable(tmp)));
915
916 identifier = tmp;
917 continue;
918
919 }
920
921 tmp = AllocateTemporaryVariable();
922
923 executable.InstructionsInternal.Add(
924 new Instruction(OpCode.MOV,
925 Operand.Variable(tmp),
926 Operand.MemberVariable(identifier, member)));
927
928 identifier = tmp;
929
930 continue;
931
932 }
933
934 break;
935
936 }
937
938 return new Variable(identifier, Scope.Local, null);
939
940 }
TokenType
Known types of Token.
Definition Token.cs:12

References AllocateTemporaryVariable(), ScriptStack.Runtime.Operand.CreatePointer(), executable, Expression(), ScriptStack.Runtime.Operand.Literal(), LookAhead(), ScriptStack.Runtime.Operand.MemberVariable(), ScriptStack.Compiler.Parser.Variable.name, ReadComma(), ReadIdentifier(), ReadLeftBracket(), ReadLeftParenthesis(), ReadPeriod(), ReadRightBracket(), ReadRightParenthesis(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Atom().

◆ AccessChainAssignment()

Variable ScriptStack.Compiler.Parser.AccessChainAssignment ( )
private

Mixed access chain assignment.

Supports combinations of member and index access in arbitrary order on the LHS, e.g.

obj.pets[0].name = "Bello";
pets[0].name += "!";
obj.ints[0] = 123;
obj.map["x"].y[1] = 7;

The chain is lowered into temporary MOVs for intermediate steps; the last step becomes the actual assignment target (Variable/Member/Pointer).

Definition at line 2022 of file Parser.cs.

2023 {
2024
2025 string identifier = ExpectIdentifier();
2026
2027 List<Instruction> listInstructions = executable.InstructionsInternal;
2028
2029 // Parse postfix chain (.) and ([]) until we hit an assignment operator.
2030 List<AccessSegment> segments = new List<AccessSegment>();
2031
2032 while (true)
2033 {
2034 if (LookAhead().Type == TokenType.Period)
2035 {
2036 ReadPeriod();
2037 segments.Add(AccessSegment.Member(ReadIdentifier()));
2038 continue;
2039 }
2040
2041 if (LookAhead().Type == TokenType.LeftBracket)
2042 {
2043 ReadLeftBracket();
2044 Variable idx = Expression();
2045 ReadRightBracket();
2046 segments.Add(AccessSegment.Index(idx.name));
2047 continue;
2048 }
2049
2050 break;
2051 }
2052
2053 Token tok = ReadToken();
2054
2055 if (!AssignmentOperator(tok.Type))
2056 throw new ParserException("Ein Zuweisungsoperator wurde erwartet.", tok);
2057
2058 Variable expression = Expression();
2059
2060 // Lower intermediate access steps into temporaries.
2061 string current = identifier;
2062
2063 for (int i = 0; i < segments.Count - 1; i++)
2064 {
2065 string tmp = AllocateTemporaryVariable();
2066 var seg = segments[i];
2067
2068 Operand rhs = seg.IsMember
2069 ? Operand.MemberVariable(current, seg.MemberName)
2070 : Operand.CreatePointer(current, seg.IndexVar);
2071
2072 listInstructions.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), rhs));
2073 current = tmp;
2074 }
2075
2076 // Final destination operand (last segment) or plain variable.
2077 Operand dest;
2078
2079 if (segments.Count == 0)
2080 {
2081 dest = Operand.Variable(current);
2082 }
2083 else
2084 {
2085 var last = segments[segments.Count - 1];
2086 dest = last.IsMember
2087 ? Operand.MemberVariable(current, last.MemberName)
2088 : Operand.CreatePointer(current, last.IndexVar);
2089 }
2090
2091 listInstructions.Add(new Instruction(AssignmentOpcode(tok.Type), dest, Operand.Variable(expression.name)));
2092
2093 // Return value of assignment expression
2094 string tmpIdentifier = AllocateTemporaryVariable();
2095 listInstructions.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), dest));
2096
2097 return new Variable(tmpIdentifier, Scope.Local, expression.derivatedType);
2098
2099 }
static Operand MemberVariable(string identifier, object val)
Definition Operand.cs:64
static Operand CreatePointer(string identifier, string pointer)
Definition Operand.cs:69
static Operand Variable(string identifier)
Definition Operand.cs:59

References AllocateTemporaryVariable(), AssignmentOpcode(), AssignmentOperator(), ScriptStack.Runtime.Operand.CreatePointer(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ExpectIdentifier(), Expression(), ScriptStack.Compiler.Parser.AccessSegment.Index(), LookAhead(), ScriptStack.Compiler.Parser.AccessSegment.Member(), ScriptStack.Runtime.Operand.MemberVariable(), ScriptStack.Compiler.Parser.Variable.name, ReadIdentifier(), ReadLeftBracket(), ReadPeriod(), ReadRightBracket(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Assignment().

◆ AllocateFunctionFrame()

void ScriptStack.Compiler.Parser.AllocateFunctionFrame ( )
private

Increase the function frame index.

Definition at line 321 of file Parser.cs.

322 {
323
324 functionFrameIndex++;
325
326 }

References functionFrameIndex.

Referenced by Statement().

◆ AllocateTemporaryVariable()

string ScriptStack.Compiler.Parser.AllocateTemporaryVariable ( )
private

Add a temporary variable to the current function frames local memory.

Returns
Todo
performance?

Definition at line 333 of file Parser.cs.

334 {
335
336 int index = 0;
337
338 while (true)
339 {
340
341 string identifier = "[" + functionFrameIndex + ":" + index + "]";
342
343 if (!localVariables.ContainsKey(identifier) && !variables.ContainsKey(identifier))
344 {
345
346 localVariables[identifier] = true;
347
348 return identifier;
349
350 }
351
352 ++index;
353
354 }
355
356 }

References functionFrameIndex, localVariables, and variables.

Referenced by AccessChain(), AccessChainAssignment(), ArrayAssignment(), Atom(), BraceArray(), BracketArray(), Factor(), For(), ForEach(), FunctionCall(), Member(), MemberAssignment(), Pointer(), PostDecrement(), PostIncrement(), RoutineCall(), Switch(), and VariableAssignment().

◆ AllocateVariable()

void ScriptStack.Compiler.Parser.AllocateVariable ( string identifier)
private

Allocate a local variable.

Parameters
identifier

Definition at line 303 of file Parser.cs.

304 {
305
306 if (variables.ContainsKey(identifier))
307 throw new ParserException("Die Variable '" + identifier + "' ist in einem umschliessenden Bereich bereits deklariert.");
308
309 if (localVariables.ContainsKey(identifier))
310 throw new ParserException("Die Variable '" + identifier + "' ist in diesem Bereich bereits deklariert.");
311
312 localVariables[identifier] = true;
313
314 executable.InstructionsInternal.Add(new Instruction(OpCode.DB, Operand.Variable(identifier)));
315
316 }

References executable, localVariables, ScriptStack.Runtime.Operand.Variable(), and variables.

Referenced by FunctionDeclaration(), and LocalVariableDeclaration().

◆ And()

Variable ScriptStack.Compiler.Parser.And ( )
private

Conjunction.

Check for proposition (a signed atom)

Returns

Definition at line 1901 of file Parser.cs.

1902 {
1903
1904 List<Instruction> instructions = executable.InstructionsInternal;
1905
1906 Variable first = BitwiseOr();
1907
1908 while (true)
1909 {
1910
1911 Token token = ReadToken();
1912
1913 if (token.Type == TokenType.And)
1914 {
1915
1916 Variable second = BitwiseOr();
1917
1918 instructions.Add(new Instruction(OpCode.AND, Operand.Variable(first.name), Operand.Variable(second.name)));
1919
1920 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1921
1922 continue;
1923
1924 }
1925
1926 UndoToken();
1927 return first;
1928
1929 }
1930
1931 }

References BitwiseOr(), Derivate(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, UndoToken(), and ScriptStack.Runtime.Operand.Variable().

Referenced by Or().

◆ Arithmetic()

Variable ScriptStack.Compiler.Parser.Arithmetic ( )
private

Multiplication and division before Addition and substraction.

Refer to https://en.wikipedia.org/wiki/Order_of_operations

Returns

Definition at line 1669 of file Parser.cs.

1670 {
1671
1672 List<Instruction> listInstructions = executable.InstructionsInternal;
1673
1674 Variable first = Term();
1675
1676 Variable second = new Variable();
1677
1678 while(true)
1679 {
1680
1681 Token token = ReadToken();
1682
1683 switch (token.Type)
1684 {
1685
1686 case TokenType.Plus:
1687
1688 second = Term();
1689
1690 listInstructions.Add(new Instruction(OpCode.ADD, Operand.Variable(first.name), Operand.Variable(second.name)));
1691
1692 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1693
1694 break;
1695
1696 case TokenType.Minus:
1697
1698 second = Term();
1699
1700 listInstructions.Add(new Instruction(OpCode.SUB, Operand.Variable(first.name), Operand.Variable(second.name)));
1701
1702 break;
1703
1704 default:
1705
1706 UndoToken();
1707
1708 return first;
1709
1710 }
1711
1712 }
1713
1714 }

References Derivate(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ScriptStack.Compiler.Parser.Variable.name, ReadToken(), Term(), ScriptStack.Compiler.Token.Type, UndoToken(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Relation().

◆ ArrayAssignment()

Variable ScriptStack.Compiler.Parser.ArrayAssignment ( )
private
Returns

Definition at line 2105 of file Parser.cs.

2106 {
2107
2108 string identifier = ExpectIdentifier();
2109
2110 List<Instruction> listInstructions = executable.InstructionsInternal;
2111
2112 Variable tmp = new Variable();
2113
2114 string src = identifier;
2115
2116 string dst = null;
2117
2118 while (!AssignmentOperator(LookAhead().Type))
2119 {
2120
2121 ReadLeftBracket();
2122
2123 tmp = Expression();
2124
2125 ReadRightBracket();
2126
2127 if (!AssignmentOperator(LookAhead().Type))
2128 {
2129
2130 dst = AllocateTemporaryVariable();
2131
2132 listInstructions.Add(new Instruction(OpCode.MOV, Operand.Variable(dst), Operand.CreatePointer(src, tmp.name)));
2133
2134 src = dst;
2135
2136 }
2137
2138 }
2139
2140 Token tok = ReadToken();
2141
2142 Variable expression = Expression();
2143
2144 if (dst == null)
2145 dst = identifier;
2146
2147 listInstructions.Add(new Instruction(AssignmentOpcode(tok.Type), Operand.CreatePointer(dst, tmp.name), Operand.Variable(expression.name)));
2148
2149 string tmpIdentifier = AllocateTemporaryVariable();
2150
2151 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.CreatePointer(dst, tmp.name)));
2152
2153 return new Variable(tmpIdentifier, Scope.Local, expression.derivatedType);
2154
2155 }

References AllocateTemporaryVariable(), AssignmentOpcode(), AssignmentOperator(), ScriptStack.Runtime.Operand.CreatePointer(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ExpectIdentifier(), Expression(), LookAhead(), ScriptStack.Compiler.Parser.Variable.name, ReadLeftBracket(), ReadRightBracket(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

◆ Assignment()

Variable ScriptStack.Compiler.Parser.Assignment ( )
private

An assignment can be a variable assignment, an array assignment or a member assignment.

Returns

Definition at line 2218 of file Parser.cs.

2219 {
2220 // Unified assignment parser (supports Variable, Pointer, Member and mixed chains)
2221 return AccessChainAssignment();
2222 }

References AccessChainAssignment().

Referenced by Expression(), For(), and LocalVariableDeclaration().

◆ AssignmentOpcode()

OpCode ScriptStack.Compiler.Parser.AssignmentOpcode ( TokenType tokenType)
private
Parameters
tokenType
Returns

Definition at line 179 of file Parser.cs.

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 }

Referenced by AccessChainAssignment(), ArrayAssignment(), MemberAssignment(), and VariableAssignment().

◆ AssignmentOperator()

bool ScriptStack.Compiler.Parser.AssignmentOperator ( TokenType tokenType)
private
Parameters
tokenType
Returns

Definition at line 149 of file Parser.cs.

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 }

Referenced by AccessChainAssignment(), ArrayAssignment(), IsAccessChainAssignment(), IsMember(), IsPointer(), MemberAssignment(), and VariableAssignment().

◆ Atom()

Variable ScriptStack.Compiler.Parser.Atom ( )
private

The smallest unit.

Returns

Definition at line 1222 of file Parser.cs.

1223 {
1224
1225 Token token = ReadToken();
1226
1227 Variable variable = new Variable();
1228
1229 switch (token.Type)
1230 {
1231
1232 case TokenType.Minus:
1233
1234 variable = Atom();
1235
1236 string tmpIdentifier = AllocateTemporaryVariable();
1237
1238 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.Variable(variable.name)));
1239
1240 executable.InstructionsInternal.Add(new Instruction(OpCode.NEG, Operand.Variable(tmpIdentifier)));
1241
1242 variable.name = tmpIdentifier;
1243
1244 return variable;
1245
1246 case TokenType.Null:
1247
1248 variable.name = AllocateTemporaryVariable();
1249
1250 variable.scope = Scope.Local;
1251
1252 variable.derivatedType = typeof(NullReference);
1253
1254 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(variable.name), Operand.Literal(NullReference.Instance)));
1255
1256 return variable;
1257
1258 case TokenType.Integer:
1259 case TokenType.Float:
1260 case TokenType.Boolean:
1261 case TokenType.String:
1262 case TokenType.Char:
1263 case TokenType.Double:
1264 case TokenType.Decimal:
1265
1266 variable.name = AllocateTemporaryVariable();
1267
1268 variable.scope = Scope.Local;
1269
1270 variable.derivatedType = Literal(token.Type);
1271
1272 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(variable.name), Operand.Literal(token.Lexeme)));
1273
1274 return variable;
1275
1276 case TokenType.Increment:
1277
1278 UndoToken();
1279
1280 variable = PreIncrement();
1281
1282 return variable;
1283
1284 case TokenType.Decrement:
1285
1286 UndoToken();
1287
1288 variable = PreDecrement();
1289
1290 return variable;
1291
1292 case TokenType.Identifier:
1293
1294 string identifier = token.Lexeme.ToString();
1295
1296 switch (LookAhead().Type)
1297 {
1298
1299 case TokenType.Increment:
1300
1301 UndoToken();
1302
1303 return PostIncrement();
1304
1305 case TokenType.Decrement:
1306
1307 UndoToken();
1308
1309 return PostDecrement();
1310
1311 case TokenType.LeftBracket:
1312
1313 // Support mixed access chains like obj.pets[0].name
1314 // by parsing consecutive member (.) and index ([...]) postfixes.
1315 UndoToken();
1316
1317 return AccessChain();
1318
1319 case TokenType.Period:
1320
1321 // Ambiguity: "std.print()" could be either a member-call on an object "std"
1322 // or a qualified routine name.
1323 //
1324 // Rule: If the dotted name is followed by '(' AND the manager has a registered
1325 // routine with that qualified name, treat it as a routine/function call.
1326 // Otherwise parse it as an access chain (supports obj.method(...)).
1327 {
1328
1329 int i = nextToken;
1330 string qualified = identifier;
1331 bool hasDot = false;
1332
1333 while (i < tokenStream.Count && tokenStream[i].Type == TokenType.Period)
1334 {
1335
1336 if (i + 1 >= tokenStream.Count || tokenStream[i + 1].Type != TokenType.Identifier)
1337 break;
1338
1339 hasDot = true;
1340 qualified += "." + tokenStream[i + 1].Lexeme.ToString();
1341 i += 2;
1342
1343 }
1344
1345 bool looksLikeQualifiedCall = hasDot && i < tokenStream.Count && tokenStream[i].Type == TokenType.LeftParen;
1346
1347 if (looksLikeQualifiedCall && executable.Script.Manager.IsRegistered(qualified))
1348 {
1349 UndoToken();
1350 return FunctionCall();
1351 }
1352
1353 UndoToken();
1354 return AccessChain();
1355
1356 }
1357
1358 case TokenType.LeftParen:
1359
1360 UndoToken();
1361
1362 return FunctionCall();
1363
1364 case TokenType.ShiftLeft:
1365
1366 UndoToken();
1367
1368 return ShiftLeft();
1369
1370 case TokenType.ShiftRight:
1371
1372 UndoToken();
1373
1374 return ShiftRight();
1375
1376 default:
1377
1378 UndoToken();
1379
1380 identifier = ExpectIdentifier();
1381
1382 variable.name = AllocateTemporaryVariable();
1383
1384 variable.scope = Scope.Local;
1385
1386 variable.derivatedType = null;
1387
1388 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(variable.name), Operand.Variable(identifier)));
1389
1390 return variable;
1391
1392 }
1393
1394 case TokenType.LeftParen:
1395
1396 variable = Expression();
1397
1398 ReadRightParenthesis();
1399
1400 return variable;
1401
1402 default:
1403
1404 throw new ParserException( "Fehlerhafter Token '" + token + "'.", token);
1405
1406 }
1407
1408 }

References AccessChain(), AllocateTemporaryVariable(), Atom(), executable, ExpectIdentifier(), Expression(), FunctionCall(), ScriptStack.Compiler.Token.Lexeme, Literal(), ScriptStack.Runtime.Operand.Literal(), LookAhead(), ScriptStack.Compiler.Parser.Variable.name, nextToken, PostDecrement(), PostIncrement(), PreDecrement(), PreIncrement(), ReadRightParenthesis(), ReadToken(), ShiftLeft(), ShiftRight(), tokenStream, ScriptStack.Compiler.Token.Type, UndoToken(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Atom(), and Factor().

◆ BinaryAnd()

Variable ScriptStack.Compiler.Parser.BinaryAnd ( )
private
Returns

Definition at line 1078 of file Parser.cs.

1079 {
1080
1081 string left = ExpectIdentifier();
1082
1083 Token token = ReadToken();
1084
1085 if (token.Type != TokenType.AssignBinaryAnd)
1086 throw new ParserException("Binary AND '&=' erwartet.", token);
1087
1088 Variable right = Factor();
1089
1090 executable.InstructionsInternal.Add(new Instruction(OpCode.ANDB, Operand.Variable(left), Operand.Variable(right.name)));
1091
1092 return right;
1093
1094 }

References executable, ExpectIdentifier(), Factor(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

◆ BinaryNot()

Variable ScriptStack.Compiler.Parser.BinaryNot ( )
private
Returns

Definition at line 1144 of file Parser.cs.

1145 {
1146
1147 Token token = ReadToken();
1148
1149 if (token.Type != TokenType.AssignBinaryNot)
1150 throw new ParserException("Binary NOT '~=' erwartet.", token);
1151
1152 Variable right = Factor();
1153
1154 executable.InstructionsInternal.Add(new Instruction(OpCode.NOTB, Operand.Variable(right.name)));
1155
1156 return right;
1157
1158 }

References executable, Factor(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

◆ BinaryNotAssign()

Variable ScriptStack.Compiler.Parser.BinaryNotAssign ( )
private
Returns

Definition at line 1122 of file Parser.cs.

1123 {
1124
1125 string left = ExpectIdentifier();
1126
1127 Token token = ReadToken();
1128
1129 if (token.Type != TokenType.AssignBinaryNot)
1130 throw new ParserException("Binary NEG '~=' erwartet.", token);
1131
1132 Variable right = Factor();
1133
1134 executable.InstructionsInternal.Add(new Instruction(OpCode.NOTB, Operand.Variable(left), Operand.Variable(right.name)));
1135
1136 return right;
1137
1138 }

References executable, ExpectIdentifier(), Factor(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

◆ BinaryOr()

Variable ScriptStack.Compiler.Parser.BinaryOr ( )
private
Returns

Definition at line 1100 of file Parser.cs.

1101 {
1102
1103 string left = ExpectIdentifier();
1104
1105 Token token = ReadToken();
1106
1107 if (token.Type != TokenType.AssignBinaryOr)
1108 throw new ParserException("Binary OR '|=' erwartet.", token);
1109
1110 Variable right = Factor();
1111
1112 executable.InstructionsInternal.Add(new Instruction(OpCode.ORB, Operand.Variable(left), Operand.Variable(right.name)));
1113
1114 return right;
1115
1116 }

References executable, ExpectIdentifier(), Factor(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

◆ BitwiseAnd()

Variable ScriptStack.Compiler.Parser.BitwiseAnd ( )
private

Bitwise AND '&'.

Precedence (high -> low): ! (logical NOT) & ^ | && ||

This mirrors common C-like precedence and keeps bitwise ops above logical ops.

Definition at line 1792 of file Parser.cs.

1793 {
1794
1795 List<Instruction> instructions = executable.InstructionsInternal;
1796
1797 Variable first = Not();
1798
1799 while (true)
1800 {
1801
1802 Token token = ReadToken();
1803
1804 if (token.Type == TokenType.BinaryAnd)
1805 {
1806
1807 Variable second = Not();
1808
1809 instructions.Add(new Instruction(OpCode.ANDB, Operand.Variable(first.name), Operand.Variable(second.name)));
1810
1811 // Bitwise ops currently work on int in the runtime
1812 first.derivatedType = typeof(int);
1813
1814 continue;
1815
1816 }
1817
1818 UndoToken();
1819 return first;
1820
1821 }
1822
1823 }

References executable, ScriptStack.Compiler.Parser.Variable.name, Not(), ReadToken(), ScriptStack.Compiler.Token.Type, UndoToken(), and ScriptStack.Runtime.Operand.Variable().

Referenced by BitwiseXor().

◆ BitwiseOr()

Variable ScriptStack.Compiler.Parser.BitwiseOr ( )
private

Bitwise OR '|'.

Definition at line 1863 of file Parser.cs.

1864 {
1865
1866 List<Instruction> instructions = executable.InstructionsInternal;
1867
1868 Variable first = BitwiseXor();
1869
1870 while (true)
1871 {
1872
1873 Token token = ReadToken();
1874
1875 if (token.Type == TokenType.BinaryOr)
1876 {
1877
1878 Variable second = BitwiseXor();
1879
1880 instructions.Add(new Instruction(OpCode.ORB, Operand.Variable(first.name), Operand.Variable(second.name)));
1881
1882 first.derivatedType = typeof(int);
1883
1884 continue;
1885
1886 }
1887
1888 UndoToken();
1889 return first;
1890
1891 }
1892
1893 }

References BitwiseXor(), executable, ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, UndoToken(), and ScriptStack.Runtime.Operand.Variable().

Referenced by And().

◆ BitwiseXor()

Variable ScriptStack.Compiler.Parser.BitwiseXor ( )
private

Bitwise XOR '^'.

Definition at line 1828 of file Parser.cs.

1829 {
1830
1831 List<Instruction> instructions = executable.InstructionsInternal;
1832
1833 Variable first = BitwiseAnd();
1834
1835 while (true)
1836 {
1837
1838 Token token = ReadToken();
1839
1840 if (token.Type == TokenType.Xor)
1841 {
1842
1843 Variable second = BitwiseAnd();
1844
1845 instructions.Add(new Instruction(OpCode.XOR, Operand.Variable(first.name), Operand.Variable(second.name)));
1846
1847 first.derivatedType = typeof(int);
1848
1849 continue;
1850
1851 }
1852
1853 UndoToken();
1854 return first;
1855
1856 }
1857
1858 }

References BitwiseAnd(), executable, ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, UndoToken(), and ScriptStack.Runtime.Operand.Variable().

Referenced by BitwiseOr().

◆ BraceArray()

Variable ScriptStack.Compiler.Parser.BraceArray ( )
private

An array enclosed in braces.

Returns

Definition at line 1414 of file Parser.cs.

1415 {
1416
1417 ReadLeftBrace();
1418
1419 int index = 0;
1420
1421 string identifier = AllocateTemporaryVariable();
1422
1423 string indexIdentifier = AllocateTemporaryVariable();
1424
1425 executable.InstructionsInternal.Add(new Instruction(OpCode.DC, Operand.Variable(identifier)));
1426
1427 if (LookAhead().Type != TokenType.RightBrace)
1428 {
1429
1430 while (true)
1431 {
1432
1433 Variable tmp = Expression();
1434
1435 Token token = LookAhead();
1436
1437 if (token.Type == TokenType.Comma || token.Type == TokenType.SemiColon || token.Type == TokenType.RightBrace)
1438 {
1439
1440 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.MemberVariable(identifier, index++), Operand.Variable(tmp.name)));
1441
1442 if (token.Type == TokenType.RightBrace)
1443 break;
1444
1445 /* todo: could be comma or semicolon, depends on current cultureinfo */
1446 if (token.Type == TokenType.Comma)
1447 ReadComma();
1448
1449 if (token.Type == TokenType.SemiColon)
1450 ReadSemicolon();
1451
1452 }
1453
1454 else if (token.Type == TokenType.Colon)
1455 {
1456
1457 ReadToken();
1458
1459 Variable variableKey = tmp;
1460
1461 tmp = Expression();
1462
1463 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.CreatePointer(identifier, variableKey.name), Operand.Variable(tmp.name)));
1464
1465 if (LookAhead().Type == TokenType.RightBrace)
1466 break;
1467
1468 /* todo: could be comma or semicolon, depends on current cultureinfo */
1469 if (LookAhead().Type == TokenType.Comma)
1470 ReadComma();
1471
1472 if (LookAhead().Type == TokenType.SemiColon)
1473 ReadSemicolon();
1474
1475 }
1476
1477 else
1478 throw new ParserException( "Ein Comma ',', Semicolon ';' oder Colon ':' wurde erwartet.");
1479
1480 }
1481
1482 }
1483
1484 ReadRightBrace();
1485
1486 return new Variable(identifier, Scope.Local, typeof(ArrayList));
1487
1488 }

References AllocateTemporaryVariable(), ScriptStack.Runtime.Operand.CreatePointer(), executable, Expression(), LookAhead(), ScriptStack.Runtime.Operand.MemberVariable(), ScriptStack.Compiler.Parser.Variable.name, ReadComma(), ReadLeftBrace(), ReadRightBrace(), ReadSemicolon(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Factor().

◆ BracketArray()

Variable ScriptStack.Compiler.Parser.BracketArray ( )
private

An array enclosed in brackets.

Returns

Definition at line 1494 of file Parser.cs.

1495 {
1496
1497 ReadLeftBracket();
1498
1499 int index = 0;
1500
1501 string identifier = AllocateTemporaryVariable();
1502
1503 string indexIdentifier = AllocateTemporaryVariable();
1504
1505 executable.InstructionsInternal.Add(new Instruction(OpCode.DC, Operand.Variable(identifier)));
1506
1507 if (LookAhead().Type != TokenType.RightBracket)
1508 {
1509
1510 while (true)
1511 {
1512
1513 Variable tmp = Expression();
1514
1515 Token token = LookAhead();
1516
1517 if (token.Type == TokenType.Comma || token.Type == TokenType.RightBracket)
1518 {
1519
1520 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.MemberVariable(identifier, index++), Operand.Variable(tmp.name)));
1521
1522 if (token.Type == TokenType.RightBracket)
1523 break;
1524
1525 ReadComma();
1526
1527 }
1528
1529 else if (token.Type == TokenType.Colon)
1530 {
1531
1532 ReadToken();
1533
1534 Variable key = tmp;
1535
1536 tmp = Expression();
1537
1538 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.CreatePointer(identifier, key.name), Operand.Variable(tmp.name)));
1539
1540 if(LookAhead().Type == TokenType.RightBracket)
1541 break;
1542
1543 ReadComma();
1544
1545 }
1546
1547 else
1548 throw new ParserException( "Ein Comma ',' oder Colon ':' wurde erwartet.");
1549
1550 }
1551
1552 }
1553
1554 ReadRightBracket();
1555
1556 return new Variable(identifier, Scope.Local, typeof(ArrayList));
1557
1558 }

References AllocateTemporaryVariable(), ScriptStack.Runtime.Operand.CreatePointer(), executable, Expression(), LookAhead(), ScriptStack.Runtime.Operand.MemberVariable(), ScriptStack.Compiler.Parser.Variable.name, ReadComma(), ReadLeftBracket(), ReadRightBracket(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Factor().

◆ Break()

void ScriptStack.Compiler.Parser.Break ( )
private

Definition at line 2664 of file Parser.cs.

2665 {
2666
2667 Token token = ReadToken();
2668
2669 if (token.Type != TokenType.Break)
2670 throw new ParserException("Keyword 'break' erwartet.", token);
2671
2672 ReadSemicolon();
2673
2674 if (loopControl.Count == 0)
2675 throw new ParserException("Das Keyword 'break' kann nur innerhalb von Loops verwendet werden.", token);
2676
2677 Instruction breakInstruction = loopControl.Peek().Break;
2678
2679 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(breakInstruction)));
2680
2681 }

References ScriptStack.Runtime.Operand.AllocateInstructionPointer(), executable, loopControl, ReadSemicolon(), ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by Statement().

◆ Continue()

void ScriptStack.Compiler.Parser.Continue ( )
private

Definition at line 2686 of file Parser.cs.

2687 {
2688
2689 Token token = ReadToken();
2690
2691 if (token.Type != TokenType.Continue)
2692 throw new ParserException("Keyword 'continue' erwartet.", token);
2693
2694 ReadSemicolon();
2695
2696 if (loopControl.Count == 0)
2697 throw new ParserException("Das Keyword 'continue' kann nur innerhalb von Loops verwendet werden.", token);
2698
2699 Instruction continueInstruction = loopControl.Peek().Continue;
2700
2701 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(continueInstruction)));
2702
2703 }

References ScriptStack.Runtime.Operand.AllocateInstructionPointer(), executable, loopControl, ReadSemicolon(), ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by Statement().

◆ Derivate()

Type ScriptStack.Compiler.Parser.Derivate ( Token token,
Type first,
Type second )
private

Get the resulting type of two computed types.

Parameters
token
first
second
Returns

Definition at line 292 of file Parser.cs.

293 {
294
295 return derivation.Derivate(token, first, second);
296
297 }

References derivation.

Referenced by And(), Arithmetic(), Or(), Relation(), and Term().

◆ ExpectIdentifier()

string ScriptStack.Compiler.Parser.ExpectIdentifier ( )
private

Read an expected (previously declared) identifier.

Returns

Definition at line 555 of file Parser.cs.

556 {
557
558 Token token = ReadToken();
559
560 if (token.Type != TokenType.Identifier)
561 throw new ParserException("Ein Keyword oder eine Variable wurde erwartet.", token);
562
563 string identifier = token.Lexeme.ToString();
564
565 if (!variables.ContainsKey(identifier) && !localVariables.ContainsKey(identifier))
566 throw new ParserException("Ein nicht vorhandener Identifier '" + identifier + "' wurde referenziert.", token);
567
568 return identifier;
569
570 }

References ScriptStack.Compiler.Token.Lexeme, localVariables, ReadToken(), ScriptStack.Compiler.Token.Type, and variables.

Referenced by AccessChainAssignment(), ArrayAssignment(), Atom(), BinaryAnd(), BinaryNotAssign(), BinaryOr(), ForEach(), MemberAssignment(), Notify(), PostDecrement(), PostIncrement(), PreDecrement(), PreIncrement(), ShiftLeft(), ShiftRight(), Switch(), VariableAssignment(), Wait(), and Xor().

◆ Expression()

Variable ScriptStack.Compiler.Parser.Expression ( )
private

An expression is an assignment or a disjunction.

Returns

Definition at line 2371 of file Parser.cs.

2372 {
2373
2374 if (IsAccessChainAssignment())
2375 return Assignment();
2376
2377 else
2378 return Or();
2379
2380 }

References Assignment(), IsAccessChainAssignment(), and Or().

Referenced by AccessChain(), AccessChainAssignment(), ArrayAssignment(), Atom(), BraceArray(), BracketArray(), For(), ForEach(), FunctionCall(), If(), IsAccessChainAssignment(), IsPointer(), LockedStatementList(), MemberAssignment(), Not(), Pointer(), Return(), RoutineCall(), Statement(), Switch(), VariableAssignment(), and While().

◆ Factor()

Variable ScriptStack.Compiler.Parser.Factor ( )
private

Atom | Array.

Returns

Definition at line 1564 of file Parser.cs.

1565 {
1566
1567
1568 if (LookAhead().Type == TokenType.LeftBrace)
1569 return BraceArray();
1570
1571 // test
1572 if (LookAhead().Type == TokenType.LeftBracket)
1573 return BracketArray();
1574
1575 // unary bitwise NOT: "~x"
1576 if (LookAhead().Type == TokenType.BinaryNot)
1577 {
1578 ReadToken(); // "~"
1579
1580 // binds tight and is right-associative: "~~x" etc.
1581 Variable right = Factor();
1582
1583 string tmp = AllocateTemporaryVariable();
1584
1585 executable.InstructionsInternal.Add(new Instruction(
1586 OpCode.NOTB,
1587 Operand.Variable(tmp),
1588 Operand.Variable(right.name)
1589 ));
1590
1591 // type: same as right, but practically int for bitwise
1592 Variable result = new Variable(tmp, Scope.Local, typeof(int));
1593 result.derivatedType = typeof(int);
1594
1595 return result;
1596 }
1597
1598 Variable variable = Atom();
1599
1600 return variable;
1601
1602 }

References AllocateTemporaryVariable(), Atom(), BraceArray(), BracketArray(), executable, Factor(), LookAhead(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by BinaryAnd(), BinaryNot(), BinaryNotAssign(), BinaryOr(), Factor(), ShiftLeft(), ShiftRight(), Term(), and Xor().

◆ For()

void ScriptStack.Compiler.Parser.For ( )
private

Definition at line 2472 of file Parser.cs.

2473 {
2474
2475 Token token = ReadToken();
2476
2477 if (token.Type != TokenType.For)
2478 throw new ParserException("Keyword 'for' erwartet.", token);
2479
2480 ReadLeftParenthesis();
2481
2482 if (LookAhead().Type == TokenType.SemiColon)
2483 ReadSemicolon();
2484
2485 else if (LookAhead().Type == TokenType.Var)
2486 LocalVariableDeclaration();
2487
2488 else
2489 {
2490
2491 Assignment();
2492
2493 ReadSemicolon();
2494
2495 }
2496
2497 Instruction start = new Instruction(OpCode.NOP);
2498
2499 executable.InstructionsInternal.Add(start);
2500
2501 Instruction continueInstruction = new Instruction(OpCode.NOP);
2502
2503 Variable condition = new Variable();
2504
2505 if (LookAhead().Type == TokenType.SemiColon)
2506 {
2507
2508 condition = new Variable(AllocateTemporaryVariable(), Scope.Local, typeof(bool));
2509
2510 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(condition.name), Operand.Literal(true)));
2511
2512 ReadSemicolon();
2513
2514 }
2515
2516 else
2517 {
2518
2519 condition = Expression();
2520
2521 if (condition.derivatedType != null && condition.derivatedType != typeof(bool))
2522 throw new ParserException("In For Loops wird ein logischer Ausdruck oder 'null' erwartet.", token);
2523
2524 ReadSemicolon();
2525
2526 }
2527
2528 List<Instruction> expression = null;
2529
2530 if (LookAhead().Type != TokenType.RightParen)
2531 {
2532
2533 int loopStart = executable.InstructionsInternal.Count;
2534
2535 Expression();
2536
2537 int loopCount = executable.InstructionsInternal.Count - loopStart;
2538
2539 expression = executable.InstructionsInternal.GetRange(loopStart, loopCount);
2540
2541 executable.InstructionsInternal.RemoveRange(loopStart, loopCount);
2542
2543 }
2544
2545 else
2546 expression = new List<Instruction>();
2547
2548 ReadRightParenthesis();
2549
2550 Instruction end = new Instruction(OpCode.NOP);
2551
2552 executable.InstructionsInternal.Add(new Instruction(OpCode.JZ, Operand.Variable(condition.name), Operand.AllocateInstructionPointer(end)));
2553
2554 LoopControl loopControl = new LoopControl();
2555
2556 loopControl.Break = end;
2557
2558 loopControl.Continue = continueInstruction;
2559
2560 this.loopControl.Push(loopControl);
2561
2562 StatementList();
2563
2564 this.loopControl.Pop();
2565
2566 executable.InstructionsInternal.Add(continueInstruction);
2567
2568 executable.InstructionsInternal.AddRange(expression);
2569
2570 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(start)));
2571
2572 executable.InstructionsInternal.Add(end);
2573
2574 }

References ScriptStack.Runtime.Operand.AllocateInstructionPointer(), AllocateTemporaryVariable(), Assignment(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, Expression(), ScriptStack.Runtime.Operand.Literal(), LocalVariableDeclaration(), LookAhead(), loopControl, ScriptStack.Compiler.Parser.Variable.name, ReadLeftParenthesis(), ReadRightParenthesis(), ReadSemicolon(), ReadToken(), StatementList(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Statement().

◆ ForEach()

void ScriptStack.Compiler.Parser.ForEach ( )
private

Definition at line 2579 of file Parser.cs.

2580 {
2581
2582 Token token = ReadToken();
2583
2584 if (token.Type != TokenType.Foreach)
2585 throw new ParserException("Keyword 'foreach' erwartet.", token);
2586
2587 ReadLeftParenthesis();
2588
2589 string key = null;
2590
2591 string val = ExpectIdentifier();
2592
2593 token = ReadToken();
2594
2595 if (token.Type == TokenType.Comma)
2596 {
2597
2598 key = val;
2599
2600 val = ExpectIdentifier();
2601
2602 token = ReadToken();
2603
2604 }
2605
2606 if (token.Type != TokenType.In)
2607 throw new ParserException("Keyword 'in' erwartet.", token);
2608
2609 if (key == null)
2610 key = AllocateTemporaryVariable();
2611
2612 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(key), Operand.Literal(NullReference.Instance)));
2613
2614 Instruction start = new Instruction(OpCode.NOP);
2615
2616 executable.InstructionsInternal.Add(start);
2617
2618 Variable array = Expression();
2619
2620 if (array.derivatedType != null
2621 && array.derivatedType != typeof(ArrayList)
2622 && array.derivatedType != typeof(string)
2623 && !typeof(System.Collections.IEnumerable).IsAssignableFrom(array.derivatedType))
2624 throw new ParserException("In ForEach Loops wird ein iterierbarer Ausdruck erwartet (Array/List/String/IEnumerable).", token);
2625
2626 ReadRightParenthesis();
2627
2628 executable.InstructionsInternal.Add(new Instruction(OpCode.PTR, Operand.Variable(key), Operand.Variable(array.name)));
2629
2630 string identifier = AllocateTemporaryVariable();
2631
2632 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(identifier), Operand.Variable(key)));
2633
2634 //executable.InstructionsInternal.Add(new Instruction(OpCode.CEQ, Operand.Variable(identifier), Operand.Literal(true)));
2635 executable.InstructionsInternal.Add(new Instruction(OpCode.TEST, Operand.Variable(identifier)));
2636
2637 Instruction end = new Instruction(OpCode.NOP);
2638
2639 executable.InstructionsInternal.Add(new Instruction(OpCode.JNZ, Operand.Variable(identifier), Operand.AllocateInstructionPointer(end)));
2640
2641 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(val), Operand.CreatePointer(array.name, key)));
2642
2643 LoopControl loopControl = new LoopControl();
2644
2645 loopControl.Break = end;
2646
2647 loopControl.Continue = start;
2648
2649 this.loopControl.Push(loopControl);
2650
2651 StatementList();
2652
2653 this.loopControl.Pop();
2654
2655 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(start)));
2656
2657 executable.InstructionsInternal.Add(end);
2658
2659 }

References ScriptStack.Runtime.Operand.AllocateInstructionPointer(), AllocateTemporaryVariable(), ScriptStack.Runtime.Operand.CreatePointer(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ExpectIdentifier(), Expression(), ScriptStack.Runtime.Operand.Literal(), loopControl, ScriptStack.Compiler.Parser.Variable.name, ReadLeftParenthesis(), ReadRightParenthesis(), ReadToken(), StatementList(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Statement().

◆ FreeFunctionFrame()

void ScriptStack.Compiler.Parser.FreeFunctionFrame ( )
private

Decrease the function frame index.

Definition at line 361 of file Parser.cs.

362 {
363
364 if (functionFrameIndex == 0)
365 return;
366
367 List<string> candidates = new List<string>();
368
369 foreach (string identifier in localVariables.Keys)
370 if (identifier.StartsWith("[" + functionFrameIndex + ":"))
371 candidates.Add(identifier);
372
373 foreach (string identifier in candidates)
374 localVariables.Remove(identifier);
375
376 --functionFrameIndex;
377
378 }

References functionFrameIndex, and localVariables.

Referenced by Statement().

◆ FunctionCall() [1/2]

Variable ScriptStack.Compiler.Parser.FunctionCall ( )
private

Can be a call to a forward declared Function or a Routine. To check what it is we look if it is a registered routine, if not it must be a function.

Returns

Definition at line 3034 of file Parser.cs.

3035 {
3036
3037 // We must be able to look ahead without losing how many tokens we consumed.
3038 // For qualified routine names like "std.print(...)" we consume multiple tokens.
3039 int start = nextToken;
3040
3041 string functionName = ReadQualifiedIdentifier();
3042
3043 nextToken = start;
3044
3045 if (executable.Script.Manager.IsRegistered(functionName))
3046 return RoutineCall();
3047
3048 return FunctionCall(false);
3049
3050 }

References executable, FunctionCall(), nextToken, ReadQualifiedIdentifier(), and RoutineCall().

Referenced by Atom(), FunctionCall(), and Run().

◆ FunctionCall() [2/2]

Variable ScriptStack.Compiler.Parser.FunctionCall ( bool background)
private

Call a forward declared function Push all parameter identifier onto the stack and call the function/routine Only functions can run in background because routines are not translated!

Todo
translate routines to msil?
Parameters
background
Returns

Definition at line 2922 of file Parser.cs.

2923 {
2924
2925 string name = ReadQualifiedIdentifier();
2926
2927 // lets expect it is a function
2928 bool forwardDeclared = true;
2929
2930 // if it is registered to the manager it is a routine of course
2931 if (!executable.Functions.ContainsKey(name))
2932 forwardDeclared = false;
2933
2934 ReadLeftParenthesis();
2935
2936 uint parameterCount = 0;
2937
2938 if (LookAhead().Type != TokenType.RightParen)
2939 {
2940
2941 // parameters are on the stack, already set to true so we just assign them
2942 while (true)
2943 {
2944
2945 Variable parameter = Expression();
2946
2947 executable.InstructionsInternal.Add(new Instruction(OpCode.PUSH, Operand.Variable(parameter.name)));
2948
2949 ++parameterCount;
2950
2951 if (LookAhead().Type == TokenType.RightParen)
2952 break;
2953
2954 else
2955 ReadComma();
2956
2957 }
2958
2959 }
2960
2961 ReadRightParenthesis();
2962
2963 Instruction instruction = null;
2964
2965 Function function = null;
2966
2967 if (forwardDeclared)
2968 {
2969
2970 function = executable.Functions[name];
2971
2972 if (function.ParameterCount > parameterCount)
2973 throw new ParserException("Der Aufruf der Funktion '" + name + "' hat fehlende Parameter. Erwartet werden " + function.ParameterCount + " Parameter.");
2974
2975 // \todo should we just throw the rest?
2976 if (function.ParameterCount < parameterCount)
2977 throw new ParserException("Der Aufruf der Funktion '" + name + "' hat zu viele Parameter. Erwartet werden " + function.ParameterCount + " Parameter.");
2978
2979 }
2980
2981 Variable variable = new Variable();
2982
2983 if (background)
2984 {
2985
2986 instruction = new Instruction(OpCode.RUN, Operand.AllocateFunctionPointer(function));
2987
2988 executable.InstructionsInternal.Add(instruction);
2989
2990 }
2991
2992 else
2993 {
2994
2995 instruction = new Instruction(OpCode.CALL, Operand.AllocateFunctionPointer(function));
2996
2997 executable.InstructionsInternal.Add(instruction);
2998
2999 // the result is popped onto the stack so a temp variable is created like '[0:0]'
3000 variable.name = AllocateTemporaryVariable();
3001
3002 variable.scope = Scope.Local;
3003
3004 variable.derivatedType = null;
3005
3006 executable.InstructionsInternal.Add(new Instruction(OpCode.POP, Operand.Variable(variable.name)));
3007
3008 }
3009
3010 if (!forwardDeclared)
3011 {
3012
3013 FunctionDescriptor functionDescriptor = new FunctionDescriptor();
3014
3015 functionDescriptor.name = name;
3016
3017 functionDescriptor.parameterCount = parameterCount;
3018
3019 functionDescriptor.instruction = null;
3020
3021 forwardDeclarations[instruction] = functionDescriptor;
3022
3023 }
3024
3025 return variable;
3026
3027 }

References ScriptStack.Runtime.Operand.AllocateFunctionPointer(), AllocateTemporaryVariable(), executable, Expression(), forwardDeclarations, LookAhead(), ScriptStack.Compiler.Parser.Variable.name, ReadComma(), ReadLeftParenthesis(), ReadQualifiedIdentifier(), ReadRightParenthesis(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

◆ FunctionDeclaration()

void ScriptStack.Compiler.Parser.FunctionDeclaration ( )
private

Parameter variables are already set to true but not assigned yet. Pop all of them in reverse order onto the stack.

Definition at line 2832 of file Parser.cs.

2833 {
2834
2835 Token token = ReadToken();
2836
2837 if (token.Type != TokenType.Function)
2838 throw new ParserException("Funktion werden mit 'function' deklariert.", token);
2839
2840 string functionName = ReadIdentifier();
2841
2842 if (executable.Functions.ContainsKey(functionName))
2843 throw new ParserException("Die Funktion '" + functionName + "' ist bereits vorhanden.", token);
2844
2845 ReadLeftParenthesis();
2846
2847 InsertDebugInfo(token);
2848
2849 List<string> parameters = new List<string>();
2850
2851 if (LookAhead().Type != TokenType.RightParen)
2852 {
2853
2854 while (true)
2855 {
2856
2857 token = ReadToken();
2858
2859 if (token.Type != TokenType.Identifier)
2860 throw new ParserException("Unerwarteter Token '" + token.Lexeme + "'.", token);
2861
2862 string parameter = token.Lexeme.ToString();
2863
2864 AllocateVariable(parameter);
2865
2866 parameters.Add(parameter);
2867
2868 token = LookAhead();
2869
2870 if (token.Type == TokenType.Comma)
2871 ReadComma();
2872
2873 else if (token.Type == TokenType.RightParen)
2874 break;
2875
2876 else
2877 throw new ParserException("Comma ',' oder schliessende Klammer ')' erwartet.");
2878
2879 }
2880
2881 }
2882
2883 ReadRightParenthesis();
2884
2885 Instruction scriptInstructionFunctionEntry = new Instruction(OpCode.NOP);
2886
2887 executable.InstructionsInternal.Add(scriptInstructionFunctionEntry);
2888
2889 Function scriptFunction = new Function(executable, functionName, parameters, scriptInstructionFunctionEntry);
2890
2891 executable.Functions[functionName] = scriptFunction;
2892
2893 parameters.Reverse();
2894
2895 foreach (string parameter in parameters)
2896 {
2897
2898 Instruction scriptInstructionPop = new Instruction(OpCode.POP, Operand.Variable(parameter));
2899
2900 executable.InstructionsInternal.Add(scriptInstructionPop);
2901
2902 }
2903
2904 StatementList();
2905
2906 executable.InstructionsInternal.Add(new Instruction( OpCode.PUSH, Operand.Literal(NullReference.Instance)));
2907
2908 executable.InstructionsInternal.Add(new Instruction(OpCode.RET));
2909
2910 localVariables.Clear();
2911
2912 }

References AllocateVariable(), executable, ScriptStack.Compiler.Function, InsertDebugInfo(), ScriptStack.Compiler.Token.Lexeme, ScriptStack.Runtime.Operand.Literal(), localVariables, LookAhead(), ReadComma(), ReadIdentifier(), ReadLeftParenthesis(), ReadRightParenthesis(), ReadToken(), StatementList(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by ParseScript().

◆ If()

void ScriptStack.Compiler.Parser.If ( )
private

Definition at line 2385 of file Parser.cs.

2386 {
2387
2388 Token token = ReadToken();
2389
2390 if (token.Type != TokenType.If)
2391 throw new ParserException( "Keyword 'if' erwartet.", token);
2392
2393 ReadLeftParenthesis();
2394
2395 Variable condition = Expression();
2396
2397 ReadRightParenthesis();
2398
2399 Instruction start = new Instruction(OpCode.NOP);
2400
2401 Instruction end = new Instruction(OpCode.NOP);
2402
2403 executable.InstructionsInternal.Add(new Instruction(OpCode.JZ, Operand.Variable(condition.name), Operand.AllocateInstructionPointer(start)));
2404
2405 StatementList();
2406
2407 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(end)));
2408
2409 executable.InstructionsInternal.Add(start);
2410
2411 if (LookAhead().Type == TokenType.Else)
2412 {
2413
2414 ReadToken();
2415
2416 StatementList();
2417 }
2418
2419 executable.InstructionsInternal.Add(end);
2420
2421 }

References ScriptStack.Runtime.Operand.AllocateInstructionPointer(), executable, Expression(), LookAhead(), ScriptStack.Compiler.Parser.Variable.name, ReadLeftParenthesis(), ReadRightParenthesis(), ReadToken(), StatementList(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Statement().

◆ InsertDebugInfo()

void ScriptStack.Compiler.Parser.InsertDebugInfo ( Token token)
private

Definition at line 497 of file Parser.cs.

498 {
499
500 if (!debugMode)
501 return;
502
503 string text = token.Text;
504
505 //text = text.Replace("\r", "").Replace("\n", "");
506
507 executable.InstructionsInternal.Add(new Instruction(OpCode.DBG, Operand.Literal(token.Line), Operand.Literal(text)));
508
509 }

References debugMode, executable, ScriptStack.Compiler.Token.Line, ScriptStack.Runtime.Operand.Literal(), and ScriptStack.Compiler.Token.Text.

Referenced by FunctionDeclaration(), Statement(), Switch(), and VariableDeclaration().

◆ IsAccessChainAssignment()

bool ScriptStack.Compiler.Parser.IsAccessChainAssignment ( )
private

Detect whether the upcoming tokens form an assignment expression.

Supports mixed access chains on the LHS ('.' and '[]' in arbitrary order).

Definition at line 2229 of file Parser.cs.

2230 {
2231
2232 Token start = LookAhead();
2233
2234 if (start.Type != TokenType.Identifier)
2235 return false;
2236
2237 int iInstructionCheckpoint = executable.InstructionsInternal.Count;
2238
2239 // base identifier
2240 ReadIdentifier();
2241
2242 while (true)
2243 {
2244 if (LookAhead().Type == TokenType.LeftBracket)
2245 {
2246 ReadLeftBracket();
2247 Expression();
2248 ReadRightBracket();
2249 continue;
2250 }
2251
2252 if (LookAhead().Type == TokenType.Period)
2253 {
2254 ReadPeriod();
2255
2256 Token token = ReadToken();
2257
2258 if (token.Type != TokenType.Identifier)
2259 {
2260 while (LookAhead() != start)
2261 UndoToken();
2262
2263 executable.InstructionsInternal.RemoveRange(
2264 iInstructionCheckpoint,
2265 executable.InstructionsInternal.Count - iInstructionCheckpoint);
2266
2267 return false;
2268 }
2269
2270 continue;
2271 }
2272
2273 break;
2274 }
2275
2276 Token tok = ReadToken();
2277
2278 while (LookAhead() != start)
2279 UndoToken();
2280
2281 executable.InstructionsInternal.RemoveRange(
2282 iInstructionCheckpoint,
2283 executable.InstructionsInternal.Count - iInstructionCheckpoint);
2284
2285 return AssignmentOperator(tok.Type);
2286
2287 }

References AssignmentOperator(), executable, Expression(), LookAhead(), ReadIdentifier(), ReadLeftBracket(), ReadPeriod(), ReadRightBracket(), ReadToken(), ScriptStack.Compiler.Token.Type, and UndoToken().

Referenced by Expression().

◆ IsMember()

bool ScriptStack.Compiler.Parser.IsMember ( )
private
Returns

Definition at line 2329 of file Parser.cs.

2330 {
2331
2332 Token start = LookAhead();
2333
2334 if (start.Type != TokenType.Identifier)
2335 return false;
2336
2337 string identifier = ReadIdentifier();
2338
2339 while (LookAhead().Type == TokenType.Period)
2340 {
2341
2342 ReadPeriod();
2343
2344 Token token = ReadToken();
2345
2346 if (token.Type != TokenType.Identifier)
2347 {
2348
2349 while (LookAhead() != start)
2350 UndoToken();
2351
2352 return false;
2353
2354 }
2355
2356 }
2357
2358 Token tok = ReadToken();
2359
2360 while (LookAhead() != start)
2361 UndoToken();
2362
2363 return AssignmentOperator(tok.Type);
2364
2365 }

References AssignmentOperator(), LookAhead(), ReadIdentifier(), ReadPeriod(), ReadToken(), ScriptStack.Compiler.Token.Type, and UndoToken().

◆ IsPointer()

bool ScriptStack.Compiler.Parser.IsPointer ( )
private
Returns

Definition at line 2293 of file Parser.cs.

2294 {
2295
2296 Token start = LookAhead();
2297
2298 if (start.Type != TokenType.Identifier)
2299 return false;
2300
2301 int iInstructionCheckpoint = executable.InstructionsInternal.Count;
2302
2303 string identifier = ReadIdentifier();
2304
2305 while (LookAhead().Type == TokenType.LeftBracket)
2306 {
2307
2308 ReadLeftBracket();
2309 Expression();
2310 ReadRightBracket();
2311
2312 }
2313
2314 Token tok = ReadToken();
2315
2316 while (LookAhead() != start)
2317 UndoToken();
2318
2319 executable.InstructionsInternal.RemoveRange(iInstructionCheckpoint, executable.InstructionsInternal.Count - iInstructionCheckpoint);
2320
2321 return AssignmentOperator(tok.Type);
2322
2323 }

References AssignmentOperator(), executable, Expression(), LookAhead(), ReadIdentifier(), ReadLeftBracket(), ReadRightBracket(), ReadToken(), ScriptStack.Compiler.Token.Type, and UndoToken().

◆ Literal()

Type ScriptStack.Compiler.Parser.Literal ( TokenType tokenType)
private

Get the literal type of a token.

Parameters
tokenType
Returns
Todo
float <> double

Definition at line 258 of file Parser.cs.

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 case TokenType.Double:
275 return typeof(double);
276 case TokenType.Decimal:
277 return typeof(decimal);
278 default:
279 throw new ParserException( "Der Token '" + tokenType.ToString() + "' kann keinem Literal zugeordnet werden.");
280
281 }
282
283 }

Referenced by Atom().

◆ LocalVariableDeclaration()

void ScriptStack.Compiler.Parser.LocalVariableDeclaration ( )
private

Definition at line 625 of file Parser.cs.

626 {
627
628 Token token = ReadToken();
629
630 if (token.Type != TokenType.Var)
631 throw new ParserException( "Lokale Variablen werden mit 'var' deklariert.", token);
632
633 string identifier = ReadIdentifier();
634
635 while (true)
636 {
637
638 AllocateVariable(identifier);
639
640 token = ReadToken();
641
642 if (token.Type == TokenType.SemiColon)
643 return;
644
645 if (token.Type == TokenType.Assign)
646 {
647
648 UndoToken();
649
650 UndoToken();
651
652 Assignment();
653
654 token = ReadToken();
655
656 if (token.Type == TokenType.SemiColon)
657 return;
658
659 }
660
661 if (token.Type != TokenType.Comma)
662 throw new ParserException( "Comma ',' erwartet.", token);
663
664 identifier = ReadIdentifier();
665
666 }
667
668 }

References AllocateVariable(), Assignment(), ReadIdentifier(), ReadToken(), ScriptStack.Compiler.Token.Type, and UndoToken().

Referenced by For(), and Statement().

◆ LockedStatementList()

void ScriptStack.Compiler.Parser.LockedStatementList ( )
private

Definition at line 3172 of file Parser.cs.

3173 {
3174
3175 Token token = ReadToken();
3176
3177 if (token.Type != TokenType.Lock)
3178 throw new ExecutionException("ParserException: Keyword 'lock' erwartet.");
3179
3180 Variable variable = Expression();
3181
3182 executable.InstructionsInternal.Add(new Instruction(OpCode.LOCK, Operand.Variable(variable.name)));
3183
3184 Statement();
3185
3186 executable.InstructionsInternal.Add(new Instruction(OpCode.FREE, Operand.Variable(variable.name)));
3187
3188 }

References executable, Expression(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), Statement(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Statement().

◆ LookAhead() [1/2]

Token ScriptStack.Compiler.Parser.LookAhead ( )
private

Get the next available token without actually increasing the tokenstream index.

Returns

Definition at line 106 of file Parser.cs.

107 {
108
109 if (!More())
110 throw new ParserException("Es sind keine weiteren Token vorhanden.");
111
112 return tokenStream[nextToken];
113
114 }

References More(), nextToken, and tokenStream.

Referenced by AccessChain(), AccessChainAssignment(), ArrayAssignment(), Atom(), BraceArray(), BracketArray(), Factor(), For(), FunctionCall(), FunctionDeclaration(), If(), IsAccessChainAssignment(), IsMember(), IsPointer(), Member(), MemberAssignment(), Not(), ParseScript(), Pointer(), ReadQualifiedIdentifier(), Return(), RoutineCall(), Statement(), StatementList(), and Switch().

◆ LookAhead() [2/2]

Token ScriptStack.Compiler.Parser.LookAhead ( int i)
private

Get the token 'n' steps forward without actually increasing the tokenstream index.

Parameters
i
Returns

Definition at line 121 of file Parser.cs.

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 }

References More(), nextToken, and tokenStream.

◆ Member()

Variable ScriptStack.Compiler.Parser.Member ( )
private

Member access.

Returns

Definition at line 800 of file Parser.cs.

801 {
802
803 string arrayIdentifier = ReadIdentifier();
804
805 string tmp = null;
806
807 while (LookAhead().Type == TokenType.Period)
808 {
809
810 ReadPeriod();
811
812 string member = ReadIdentifier();
813
814 tmp = AllocateTemporaryVariable();
815
816 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), Operand.MemberVariable(arrayIdentifier, member)));
817
818 arrayIdentifier = tmp;
819
820 }
821
822 return new Variable(tmp, Scope.Local, null);
823
824 }

References AllocateTemporaryVariable(), executable, LookAhead(), ScriptStack.Runtime.Operand.MemberVariable(), ReadIdentifier(), ReadPeriod(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

◆ MemberAssignment()

Variable ScriptStack.Compiler.Parser.MemberAssignment ( )
private
Returns

Definition at line 2161 of file Parser.cs.

2162 {
2163
2164 string identifier = ExpectIdentifier();
2165
2166 List<string> members = new List<string>();
2167
2168 while (LookAhead().Type == TokenType.Period)
2169 {
2170
2171 ReadPeriod();
2172
2173 members.Add(ReadIdentifier());
2174
2175 }
2176
2177 Token tok = ReadToken();
2178
2179 if (!AssignmentOperator(tok.Type))
2180 throw new ParserException("Ein Zuweisungsoperator wurde erwartet.", tok);
2181
2182 Variable expression = Expression();
2183
2184 string dst = null;
2185
2186 string src = identifier;
2187
2188 for (int i = 0; i < members.Count - 1; i++)
2189 {
2190
2191 dst = AllocateTemporaryVariable();
2192
2193 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(dst), Operand.MemberVariable(src, members[i])));
2194
2195 src = dst;
2196
2197 }
2198
2199 if (dst == null)
2200 dst = identifier;
2201
2202 executable.InstructionsInternal.Add(new Instruction(AssignmentOpcode(tok.Type), Operand.MemberVariable(dst, members[members.Count - 1]), Operand.Variable(expression.name)));
2203
2204 string tmpIdentifier = AllocateTemporaryVariable();
2205
2206 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.MemberVariable(dst, members[members.Count - 1])));
2207
2208 Variable variable = new Variable(tmpIdentifier, Scope.Local, expression.derivatedType);
2209
2210 return variable;
2211
2212 }

References AllocateTemporaryVariable(), AssignmentOpcode(), AssignmentOperator(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ExpectIdentifier(), Expression(), LookAhead(), ScriptStack.Runtime.Operand.MemberVariable(), ScriptStack.Compiler.Parser.Variable.name, ReadIdentifier(), ReadPeriod(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

◆ More()

bool ScriptStack.Compiler.Parser.More ( )
private

Check if there are more tokens available.

Returns

Definition at line 83 of file Parser.cs.

84 {
85 return nextToken < tokenStream.Count;
86 }

References nextToken, and tokenStream.

Referenced by LookAhead(), LookAhead(), ParseScript(), ReadQualifiedIdentifier(), and ReadToken().

◆ Not()

Variable ScriptStack.Compiler.Parser.Not ( )
private

Proposition.

May be a signed atom or a relation

Returns

Definition at line 1752 of file Parser.cs.

1753 {
1754
1755 Variable proposition = new Variable();
1756
1757 if (LookAhead().Type == TokenType.Not)
1758 {
1759
1760 ReadToken();
1761
1762 if (LookAhead().Type == TokenType.LeftParen)
1763 proposition = Expression();
1764
1765 else
1766 proposition = Relation();
1767
1768 executable.InstructionsInternal.Add(new Instruction(OpCode.NOT, Operand.Variable(proposition.name)));
1769
1770 return proposition;
1771
1772 }
1773
1774 else
1775 return Relation();
1776
1777 }

References executable, Expression(), LookAhead(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), Relation(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by BitwiseAnd().

◆ Notify()

void ScriptStack.Compiler.Parser.Notify ( )
private
Todo

Definition at line 3244 of file Parser.cs.

3245 {
3246
3247 Token token = ReadToken();
3248
3249 if (token.Type != TokenType.Notify)
3250 throw new ParserException("Keyword 'notify' erwartet.", token);
3251
3252 string identifier = ExpectIdentifier();
3253
3254 ReadSemicolon();
3255
3256 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(identifier), Operand.Literal(true)));
3257
3258 }

References executable, ExpectIdentifier(), ScriptStack.Runtime.Operand.Literal(), ReadSemicolon(), ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Statement().

◆ Or()

Variable ScriptStack.Compiler.Parser.Or ( )
private

Disjunction (not exclusive).

Check for conjunction

Returns

Definition at line 1939 of file Parser.cs.

1940 {
1941
1942 List<Instruction> instructions = executable.InstructionsInternal;
1943
1944 Variable first = And();
1945
1946 while (true)
1947 {
1948
1949 Token token = ReadToken();
1950
1951 if (token.Type == TokenType.Or)
1952 {
1953
1954 Variable second = And();
1955
1956 instructions.Add(new Instruction(OpCode.OR, Operand.Variable(first.name), Operand.Variable(second.name)));
1957
1958 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1959
1960 continue;
1961
1962 }
1963
1964 UndoToken();
1965 return first;
1966
1967 }
1968
1969 }

References And(), Derivate(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, UndoToken(), and ScriptStack.Runtime.Operand.Variable().

Referenced by Expression().

◆ Parse()

Executable ScriptStack.Compiler.Parser.Parse ( )

Parse the token stream into an executable.

Returns

Definition at line 3355 of file Parser.cs.

3356 {
3357 nextToken = 0;
3358 variables.Clear();
3359 localVariables.Clear();
3360 functionFrameIndex = -1;
3361 forwardDeclarations.Clear();
3362 loopControl.Clear();
3363
3364 executable = new Executable(script);
3365
3366 ParseScript();
3367 ResolveForwardFunctionDeclarations();
3368 executable.Clean();
3369
3370 return executable;
3371 }

References executable, forwardDeclarations, functionFrameIndex, localVariables, loopControl, nextToken, ParseScript(), ResolveForwardFunctionDeclarations(), script, and variables.

Referenced by ScriptStack.Runtime.Script.Script(), and ScriptStack.Runtime.Script.Script().

◆ ParseScript()

void ScriptStack.Compiler.Parser.ParseScript ( )
private

After the first function declaration no more variable, struct or enum declarations are allowed anymore.

Todo

Definition at line 3265 of file Parser.cs.

3266 {
3267
3268 while (More())
3269 {
3270
3271 Token token = LookAhead();
3272
3273 if (token.Type == TokenType.Shared || token.Type == TokenType.Var)
3274 VariableDeclaration();
3275
3276 else
3277 break;
3278
3279 }
3280
3281 if (!More())
3282 return;
3283
3284 while (More())
3285 {
3286
3287 Token token = LookAhead();
3288
3289 if (token.Type != TokenType.Function)
3290 throw new ParserException( "Ausserhalb von Funktionen sind keine Anweisungen erlaubt.", token);
3291
3292 FunctionDeclaration();
3293
3294 }
3295
3296 }

References FunctionDeclaration(), LookAhead(), More(), ScriptStack.Compiler.Token.Type, and VariableDeclaration().

Referenced by Parse().

◆ Pointer()

Variable ScriptStack.Compiler.Parser.Pointer ( )
private

Array access.

like

var arr = [1, 2, 3];
print(arr[1]); // the brackets are the array access
Todo
rename this! its not a pointer
Returns

Definition at line 768 of file Parser.cs.

769 {
770
771 string identifier = ReadIdentifier();
772
773 string tmp = null;
774
775 while (LookAhead().Type == TokenType.LeftBracket)
776 {
777
778 ReadLeftBracket();
779
780 Variable index = Expression();
781
782 ReadRightBracket();
783
784 tmp = AllocateTemporaryVariable();
785
786 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), Operand.CreatePointer(identifier, index.name)));
787
788 identifier = tmp;
789
790 }
791
792 return new Variable(tmp, Scope.Local, null);
793
794 }

References AllocateTemporaryVariable(), ScriptStack.Runtime.Operand.CreatePointer(), executable, Expression(), LookAhead(), ScriptStack.Compiler.Parser.Variable.name, ReadIdentifier(), ReadLeftBracket(), ReadRightBracket(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

◆ PostDecrement()

Variable ScriptStack.Compiler.Parser.PostDecrement ( )
private
Returns

Definition at line 1010 of file Parser.cs.

1011 {
1012
1013 string identifier = ExpectIdentifier();
1014
1015 Token token = ReadToken();
1016
1017 if (token.Type != TokenType.Decrement)
1018 throw new ParserException("Post-decrement '--' erwartet.", token);
1019
1020 string tmp = AllocateTemporaryVariable();
1021
1022 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), Operand.Variable(identifier)));
1023
1024 executable.InstructionsInternal.Add(new Instruction(OpCode.DEC, Operand.Variable(identifier)));
1025
1026 return new Variable(tmp, Scope.Local, null);
1027
1028 }

References AllocateTemporaryVariable(), executable, ExpectIdentifier(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Atom().

◆ PostIncrement()

Variable ScriptStack.Compiler.Parser.PostIncrement ( )
private
Returns

Definition at line 986 of file Parser.cs.

987 {
988
989 string identifier = ExpectIdentifier();
990
991 Token token = ReadToken();
992
993 if (token.Type != TokenType.Increment)
994 throw new ParserException("Post-increment '++' erwartet.", token);
995
996 string tmp = AllocateTemporaryVariable();
997
998 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmp), Operand.Variable(identifier)));
999
1000 executable.InstructionsInternal.Add(new Instruction(OpCode.INC, Operand.Variable(identifier)));
1001
1002 return new Variable(tmp, Scope.Local, null);
1003
1004 }

References AllocateTemporaryVariable(), executable, ExpectIdentifier(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Atom().

◆ PreDecrement()

Variable ScriptStack.Compiler.Parser.PreDecrement ( )
private
Returns

Definition at line 966 of file Parser.cs.

967 {
968
969 Token token = ReadToken();
970
971 if (token.Type != TokenType.Decrement)
972 throw new ParserException("Pre-decrement '--' erwartet.", token);
973
974 string identifier = ExpectIdentifier();
975
976 executable.InstructionsInternal.Add(new Instruction(OpCode.DEC, Operand.Variable(identifier)));
977
978 return new Variable(identifier, Scope.Local, null);
979
980 }

References executable, ExpectIdentifier(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Atom().

◆ PreIncrement()

Variable ScriptStack.Compiler.Parser.PreIncrement ( )
private
Returns

Definition at line 946 of file Parser.cs.

947 {
948
949 Token token = ReadToken();
950
951 if (token.Type != TokenType.Increment)
952 throw new ParserException( "Pre-increment '++' erwartet.", token);
953
954 string identifier = ExpectIdentifier();
955
956 executable.InstructionsInternal.Add(new Instruction(OpCode.INC, Operand.Variable(identifier)));
957
958 return new Variable(identifier, Scope.Local, null);
959
960 }

References executable, ExpectIdentifier(), ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Atom().

◆ ReadComma()

void ScriptStack.Compiler.Parser.ReadComma ( )
private

Definition at line 396 of file Parser.cs.

397 {
398
399 Token token = ReadToken();
400
401 if (token.Type != TokenType.Comma)
402 throw new ParserException("Comma ',' erwartet.", token);
403
404 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by AccessChain(), BraceArray(), BracketArray(), FunctionCall(), FunctionDeclaration(), and RoutineCall().

◆ ReadIdentifier()

string ScriptStack.Compiler.Parser.ReadIdentifier ( )
private

Read a new (previously NOT declared) identifier.

Returns

Definition at line 515 of file Parser.cs.

516 {
517
518 Token token = ReadToken();
519
520 if (token.Type != TokenType.Identifier)
521 throw new ParserException("Ein Keyword oder eine Variable wurde erwartet.", token);
522
523 return token.Lexeme.ToString();
524
525 }

References ScriptStack.Compiler.Token.Lexeme, ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by AccessChain(), AccessChainAssignment(), FunctionDeclaration(), IsAccessChainAssignment(), IsMember(), IsPointer(), LocalVariableDeclaration(), Member(), MemberAssignment(), Pointer(), ReadQualifiedIdentifier(), and VariableDeclaration().

◆ ReadLeftBrace()

void ScriptStack.Compiler.Parser.ReadLeftBrace ( )
private

Definition at line 435 of file Parser.cs.

436 {
437
438 Token token = ReadToken();
439
440 if (token.Type != TokenType.LeftBrace)
441 throw new ParserException("Geschwungene Klammer '{' erwartet.", token);
442
443 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by BraceArray(), and Switch().

◆ ReadLeftBracket()

void ScriptStack.Compiler.Parser.ReadLeftBracket ( )
private

Definition at line 461 of file Parser.cs.

462 {
463
464 Token token = ReadToken();
465
466 if (token.Type != TokenType.LeftBracket)
467 throw new ParserException("Eckige Klammer '[' erwartet.", token);
468
469 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by AccessChain(), AccessChainAssignment(), ArrayAssignment(), BracketArray(), IsAccessChainAssignment(), IsPointer(), and Pointer().

◆ ReadLeftParenthesis()

void ScriptStack.Compiler.Parser.ReadLeftParenthesis ( )
private

Definition at line 409 of file Parser.cs.

410 {
411
412 Token token = ReadToken();
413
414 if (token.Type != TokenType.LeftParen)
415 throw new ParserException("Klammer '(' erwartet.", token);
416
417 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by AccessChain(), For(), ForEach(), FunctionCall(), FunctionDeclaration(), If(), RoutineCall(), Switch(), and While().

◆ ReadPeriod()

void ScriptStack.Compiler.Parser.ReadPeriod ( )
private

Definition at line 487 of file Parser.cs.

488 {
489
490 Token token = ReadToken();
491
492 if (token.Type != TokenType.Period)
493 throw new ParserException("Punkt '.' erwartet.", token);
494
495 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by AccessChain(), AccessChainAssignment(), IsAccessChainAssignment(), IsMember(), Member(), MemberAssignment(), and ReadQualifiedIdentifier().

◆ ReadQualifiedIdentifier()

string ScriptStack.Compiler.Parser.ReadQualifiedIdentifier ( )
private

Read a dotted (qualified) identifier like: std.print or ns.io.print.

This is intentionally ONLY used for function/routine names. Member access on variables is parsed by AccessChain.

Definition at line 533 of file Parser.cs.

534 {
535
536 string id = ReadIdentifier();
537
538 while (More() && LookAhead().Type == TokenType.Period)
539 {
540
541 ReadPeriod();
542
543 id += "." + ReadIdentifier();
544
545 }
546
547 return id;
548
549 }

References LookAhead(), More(), ReadIdentifier(), and ReadPeriod().

Referenced by FunctionCall(), FunctionCall(), and RoutineCall().

◆ ReadRightBrace()

void ScriptStack.Compiler.Parser.ReadRightBrace ( )
private

Definition at line 448 of file Parser.cs.

449 {
450
451 Token token = ReadToken();
452
453 if (token.Type != TokenType.RightBrace)
454 throw new ParserException("Geschwungene Klammer '}' erwartet.", token);
455
456 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by BraceArray(), StatementList(), and Switch().

◆ ReadRightBracket()

void ScriptStack.Compiler.Parser.ReadRightBracket ( )
private

Definition at line 474 of file Parser.cs.

475 {
476
477 Token token = ReadToken();
478
479 if (token.Type != TokenType.RightBracket)
480 throw new ParserException("Eckige Klammer ']' erwartet.", token);
481
482 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by AccessChain(), AccessChainAssignment(), ArrayAssignment(), BracketArray(), IsAccessChainAssignment(), IsPointer(), and Pointer().

◆ ReadRightParenthesis()

void ScriptStack.Compiler.Parser.ReadRightParenthesis ( )
private

Definition at line 422 of file Parser.cs.

423 {
424
425 Token token = ReadToken();
426
427 if (token.Type != TokenType.RightParen)
428 throw new ParserException("Klammer ')' erwartet.", token);
429
430 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by AccessChain(), Atom(), For(), ForEach(), FunctionCall(), FunctionDeclaration(), If(), RoutineCall(), Switch(), and While().

◆ ReadSemicolon()

void ScriptStack.Compiler.Parser.ReadSemicolon ( )
private

Definition at line 383 of file Parser.cs.

384 {
385
386 Token token = ReadToken();
387
388 if (token.Type != TokenType.SemiColon)
389 throw new ParserException("Semicolon ';' erwartet.", token);
390
391 }

References ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by BraceArray(), Break(), Continue(), For(), Notify(), Return(), Run(), Statement(), Wait(), and Yield().

◆ ReadToken()

◆ Relation()

Variable ScriptStack.Compiler.Parser.Relation ( )
private
Returns

Definition at line 1720 of file Parser.cs.

1721 {
1722
1723 List<Instruction> instructions = executable.InstructionsInternal;
1724
1725 Variable first = Arithmetic();
1726
1727 Token token = ReadToken();
1728
1729 if (RelationalOperator(token.Type)) {
1730
1731 Variable second = Arithmetic();
1732
1733 instructions.Add(new Instruction(RelationalOpcode(token.Type), Operand.Variable(first.name), Operand.Variable(second.name)));
1734
1735 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1736
1737 }
1738
1739 else
1740 UndoToken();
1741
1742 return first;
1743
1744 }

References Arithmetic(), Derivate(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ScriptStack.Compiler.Parser.Variable.name, ReadToken(), RelationalOpcode(), RelationalOperator(), ScriptStack.Compiler.Token.Type, UndoToken(), and ScriptStack.Runtime.Operand.Variable().

Referenced by Not().

◆ RelationalOpcode()

OpCode ScriptStack.Compiler.Parser.RelationalOpcode ( TokenType tokenType)
private
Parameters
tokenType
Returns

Definition at line 233 of file Parser.cs.

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 }

Referenced by Relation().

◆ RelationalOperator()

bool ScriptStack.Compiler.Parser.RelationalOperator ( TokenType tokenType)
private
Parameters
tokenType
Returns

Definition at line 207 of file Parser.cs.

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 }

Referenced by Relation().

◆ ResolveForwardFunctionDeclarations()

void ScriptStack.Compiler.Parser.ResolveForwardFunctionDeclarations ( )
private

Resolve unresolved, forward declared functions.

Definition at line 3301 of file Parser.cs.

3302 {
3303
3304 foreach (Instruction instruction in forwardDeclarations.Keys)
3305 {
3306
3307 FunctionDescriptor functionDescriptor = forwardDeclarations[instruction];
3308
3309 string name = functionDescriptor.name;
3310
3311 if (!executable.Functions.ContainsKey(name))
3312 throw new ParserException("Eine nicht deklarierte Funktion '" + name + "' wurde referenziert.");
3313
3314 Function function = executable.Functions[name];
3315
3316 instruction.First.FunctionPointer = function;
3317
3318 }
3319
3320 }

References executable, forwardDeclarations, and ScriptStack.Compiler.Parser.FunctionDescriptor.name.

Referenced by Parse().

◆ Return()

void ScriptStack.Compiler.Parser.Return ( )
private

By default null is returned.

Definition at line 2807 of file Parser.cs.

2808 {
2809
2810 Token token = ReadToken();
2811
2812 if (token.Type != TokenType.Return)
2813 throw new ParserException("Keyword 'return' erwartet.", token);
2814
2815 if (LookAhead().Type != TokenType.SemiColon)
2816 executable.InstructionsInternal.Add(new Instruction(OpCode.PUSH, Operand.Variable(Expression().name)));
2817
2818 else
2819 executable.InstructionsInternal.Add(new Instruction(OpCode.PUSH, Operand.Literal(NullReference.Instance)));
2820
2821 ReadSemicolon();
2822
2823 executable.InstructionsInternal.Add(new Instruction(OpCode.RET));
2824
2825 return;
2826
2827 }

References executable, Expression(), ScriptStack.Runtime.Operand.Literal(), LookAhead(), ReadSemicolon(), ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Statement().

◆ RoutineCall()

Variable ScriptStack.Compiler.Parser.RoutineCall ( )
private
Todo
Run routines in background? bad for cloud
Returns

Definition at line 692 of file Parser.cs.

693 {
694
695 string identifier = ReadQualifiedIdentifier();
696
697 ReadLeftParenthesis();
698
699 List<object> parameters = new List<object>();
700
701 int parameterCount = 0;
702
703 if (LookAhead().Type != TokenType.RightParen)
704 {
705
706 while (true)
707 {
708
709 Variable parameter = Expression();
710
711 executable.InstructionsInternal.Add(new Instruction( OpCode.PUSH, Operand.Variable(parameter.name)));
712
713 ++parameterCount;
714
715 if (LookAhead().Type == TokenType.RightParen)
716 break;
717
718 else
719 ReadComma();
720
721 }
722
723 }
724
725 ReadRightParenthesis();
726
727 Manager manager = executable.Script.Manager;
728
729 if (!manager.Routines.ContainsKey(identifier))
730 throw new ParserException("Die Routine '" + identifier + "' ist nicht vorhanden.");
731
732 Routine routine = manager.Routines[identifier];
733
734 if (routine.ParameterTypes.Count > parameterCount)
735 throw new ParserException("Der Aufruf der Routine '" + identifier + "' hat fehlende Parameter. Erwartet werden " + routine.ParameterTypes.Count + " Parameter.\nBeschreibung der Routine: " + routine.Description().ToString());
736
737 if (routine.ParameterTypes.Count < parameterCount)
738 throw new ParserException("Der Aufruf der Routine '" + identifier + "' hat zu viele Parameter. Erwartet werden " + routine.ParameterTypes.Count + " Parameter.\nBeschreibung der Routine: " + routine.Description().ToString());
739
740 executable.InstructionsInternal.Add(new Instruction(OpCode.INV, Operand.AllocateRoutinePointer(routine)));
741
742 Variable variable = new Variable
743 {
744 name = AllocateTemporaryVariable(),
745 scope = Scope.Local,
746 derivatedType = null
747 };
748
749 executable.InstructionsInternal.Add(new Instruction(OpCode.POP, Operand.Variable(variable.name)));
750
751 return variable;
752
753 }
ReadOnlyDictionary< String, Routine > Routines
Definition Manager.cs:307
List< Type > ParameterTypes
Definition Routine.cs:313

References ScriptStack.Runtime.Operand.AllocateRoutinePointer(), AllocateTemporaryVariable(), ScriptStack.Runtime.Routine.Description(), executable, Expression(), LookAhead(), ScriptStack.Compiler.Parser.Variable.name, ScriptStack.Runtime.Routine.ParameterTypes, ReadComma(), ReadLeftParenthesis(), ReadQualifiedIdentifier(), ReadRightParenthesis(), ScriptStack.Manager.Routines, and ScriptStack.Runtime.Operand.Variable().

Referenced by FunctionCall().

◆ Run()

void ScriptStack.Compiler.Parser.Run ( )
private

Definition at line 673 of file Parser.cs.

674 {
675
676 Token token = ReadToken();
677
678 if (token.Type != TokenType.Run)
679 throw new ParserException("Keyword 'run' erwartet.", token);
680
681 FunctionCall(true);
682
683 ReadSemicolon();
684
685 }

References FunctionCall(), ReadSemicolon(), ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by Statement().

◆ ShiftLeft()

Variable ScriptStack.Compiler.Parser.ShiftLeft ( )
private
Returns

Definition at line 1034 of file Parser.cs.

1035 {
1036
1037 string left = ExpectIdentifier();
1038
1039 Token token = ReadToken();
1040
1041 if (token.Type != TokenType.ShiftLeft)
1042 throw new ParserException("Shift Left '<<' erwartet.", token);
1043
1044 Variable right = Factor();
1045
1046 executable.InstructionsInternal.Add(new Instruction(OpCode.SHL, Operand.Variable(left), Operand.Variable(right.name)));
1047
1048 return right;
1049
1050 }

References executable, ExpectIdentifier(), Factor(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Atom().

◆ ShiftRight()

Variable ScriptStack.Compiler.Parser.ShiftRight ( )
private
Returns

Definition at line 1056 of file Parser.cs.

1057 {
1058
1059 string left = ExpectIdentifier();
1060
1061 Token token = ReadToken();
1062
1063 if (token.Type != TokenType.ShiftRight)
1064 throw new ParserException("Shift Right '>>' erwartet.", token);
1065
1066 Variable right = Factor();
1067
1068 executable.InstructionsInternal.Add(new Instruction(OpCode.SHR, Operand.Variable(left), Operand.Variable(right.name)));
1069
1070 return right;
1071
1072 }

References executable, ExpectIdentifier(), Factor(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Atom().

◆ Statement()

void ScriptStack.Compiler.Parser.Statement ( )
private

A statement can be a local variable declaration, a statement list, an expression or a keyword.

Definition at line 3055 of file Parser.cs.

3056 {
3057
3058 AllocateFunctionFrame();
3059
3060 Token token = LookAhead();
3061
3062 InsertDebugInfo(token);
3063
3064 switch (token.Type)
3065 {
3066
3067 case TokenType.SemiColon:
3068 ReadToken();
3069 break;
3070
3071 case TokenType.Var:
3072 LocalVariableDeclaration();
3073 break;
3074
3075 case TokenType.LeftBrace:
3076 StatementList();
3077 break;
3078
3079 case TokenType.Increment:
3080 case TokenType.Decrement:
3081 case TokenType.LeftParen:
3082 case TokenType.Identifier:
3083 case TokenType.Null:
3084 case TokenType.Integer:
3085 case TokenType.Float:
3086 case TokenType.Boolean:
3087 case TokenType.String:
3088 case TokenType.Char:
3089 Expression();
3090 if(LookAhead().Type == TokenType.SemiColon)
3091 ReadSemicolon();
3092 break;
3093
3094 case TokenType.If:
3095 If();
3096 break;
3097 case TokenType.While:
3098 While();
3099 break;
3100 case TokenType.For:
3101 For();
3102 break;
3103 case TokenType.Foreach:
3104 ForEach();
3105 break;
3106 case TokenType.Break:
3107 Break();
3108 break;
3109 case TokenType.Continue:
3110 Continue();
3111 break;
3112 case TokenType.Switch:
3113 Switch();
3114 break;
3115 case TokenType.Return:
3116 Return();
3117 break;
3118
3119 case TokenType.Run:
3120 Run();
3121 break;
3122 case TokenType.Yield:
3123 Yield();
3124 break;
3125 case TokenType.Wait:
3126 Wait();
3127 break;
3128 case TokenType.Notify:
3129 Notify();
3130 break;
3131 case TokenType.Lock:
3132 LockedStatementList();
3133 break;
3134
3135 default: throw new ParserException("ParserException::Statement: Ein unerwarteter Token '" + token.Lexeme + "' wurde gefunden.", token);
3136
3137 }
3138
3139 FreeFunctionFrame();
3140
3141 }

References AllocateFunctionFrame(), Break(), Continue(), Expression(), For(), ForEach(), FreeFunctionFrame(), If(), InsertDebugInfo(), ScriptStack.Compiler.Token.Lexeme, LocalVariableDeclaration(), LockedStatementList(), LookAhead(), Notify(), ReadSemicolon(), ReadToken(), Return(), Run(), StatementList(), Switch(), ScriptStack.Compiler.Token.Type, Wait(), While(), and Yield().

Referenced by LockedStatementList(), StatementList(), and Switch().

◆ StatementList()

void ScriptStack.Compiler.Parser.StatementList ( )
private

A list of statements. If its not a list (not in braces) just return a single statement.

Definition at line 3147 of file Parser.cs.

3148 {
3149
3150 // if there are no braces, just read a single statement
3151 if (LookAhead().Type != TokenType.LeftBrace)
3152 {
3153
3154 Statement();
3155
3156 return;
3157
3158 }
3159
3160 ReadToken();
3161
3162 while (LookAhead().Type != TokenType.RightBrace)
3163 Statement();
3164
3165 ReadRightBrace();
3166
3167 }

References LookAhead(), ReadRightBrace(), ReadToken(), and Statement().

Referenced by For(), ForEach(), FunctionDeclaration(), If(), Statement(), and While().

◆ Switch()

void ScriptStack.Compiler.Parser.Switch ( )
private

Definition at line 2708 of file Parser.cs.

2709 {
2710
2711 Token token = ReadToken();
2712
2713 if (token.Type != TokenType.Switch)
2714 throw new ParserException("Keyword 'switch' erwartet.", token);
2715
2716 ReadLeftParenthesis();
2717
2718 string switchIdentifier = ExpectIdentifier();
2719
2720 ReadRightParenthesis();
2721
2722 ReadLeftBrace();
2723
2724 token = LookAhead();
2725
2726 if (token.Type != TokenType.Case && token.Type != TokenType.Default)
2727 throw new ParserException("Keyword 'case' oder 'default' erwartet.", token);
2728
2729 string tmpIdentifier = AllocateTemporaryVariable();
2730
2731 string identifier = AllocateTemporaryVariable();
2732
2733 Instruction end = new Instruction(OpCode.NOP);
2734
2735 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.Literal(false)));
2736
2737 while (LookAhead().Type != TokenType.Default && LookAhead().Type != TokenType.RightBrace)
2738 {
2739
2740 token = ReadToken();
2741
2742 if (token.Type != TokenType.Case)
2743 throw new ParserException("Keyword 'case' erwartet.", token);
2744
2745 InsertDebugInfo(token);
2746
2747 Variable expression = Expression();
2748
2749 token = ReadToken();
2750
2751 if (token.Type != TokenType.Colon)
2752 throw new ParserException("Colon ':' erwartet.", token);
2753
2754 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(identifier), Operand.Variable(switchIdentifier)));
2755
2756 executable.InstructionsInternal.Add(new Instruction(OpCode.CEQ, Operand.Variable(identifier), Operand.Variable(expression.name)));
2757
2758 executable.InstructionsInternal.Add(new Instruction(OpCode.OR, Operand.Variable(tmpIdentifier), Operand.Variable(identifier)));
2759
2760 if (LookAhead().Type != TokenType.Case)
2761 {
2762 Instruction switchInstruction = new Instruction(OpCode.NOP);
2763
2764 executable.InstructionsInternal.Add(new Instruction(OpCode.JZ, Operand.Variable(tmpIdentifier), Operand.AllocateInstructionPointer(switchInstruction)));
2765
2766 Statement();
2767
2768 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(end)));
2769
2770 executable.InstructionsInternal.Add(switchInstruction);
2771
2772 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.Literal(false)));
2773
2774 }
2775 }
2776
2777 token = ReadToken();
2778
2779 if (token.Type == TokenType.RightBrace)
2780 {
2781
2782 executable.InstructionsInternal.Add(end);
2783
2784 return;
2785
2786 }
2787
2788 if (token.Type != TokenType.Default)
2789 throw new ParserException("Das Keyword 'default' oder eine schliessende geschwungene Klammer '}' wird am Ende einer 'switch' Anweisung erwartet.", token);
2790
2791 token = ReadToken();
2792
2793 if (token.Type != TokenType.Colon)
2794 throw new ParserException("Ein Colon ':' wurde erwartet.", token);
2795
2796 Statement();
2797
2798 ReadRightBrace();
2799
2800 executable.InstructionsInternal.Add(end);
2801
2802 }

References ScriptStack.Runtime.Operand.AllocateInstructionPointer(), AllocateTemporaryVariable(), executable, ExpectIdentifier(), Expression(), InsertDebugInfo(), ScriptStack.Runtime.Operand.Literal(), LookAhead(), ScriptStack.Compiler.Parser.Variable.name, ReadLeftBrace(), ReadLeftParenthesis(), ReadRightBrace(), ReadRightParenthesis(), ReadToken(), Statement(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Statement().

◆ Term()

Variable ScriptStack.Compiler.Parser.Term ( )
private

Factor ( [*|/|%] Factor ).

Returns

Definition at line 1608 of file Parser.cs.

1609 {
1610
1611 List<Instruction> listInstructions = executable.InstructionsInternal;
1612
1613 Variable first = Factor();
1614
1615 Variable second = new Variable();
1616
1617 while (true)
1618 {
1619
1620 Token token = ReadToken();
1621
1622 switch (token.Type)
1623 {
1624
1625 case TokenType.Multiply:
1626 second = Factor();
1627
1628 listInstructions.Add(new Instruction(OpCode.MUL, Operand.Variable(first.name), Operand.Variable(second.name)));
1629
1630 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1631
1632 break;
1633
1634 case TokenType.Divide:
1635
1636 second = Factor();
1637
1638 listInstructions.Add(new Instruction(OpCode.DIV, Operand.Variable(first.name), Operand.Variable(second.name)));
1639
1640 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1641
1642 break;
1643
1644 case TokenType.Modulo:
1645 second = Factor();
1646
1647 listInstructions.Add(new Instruction(OpCode.MOD, Operand.Variable(first.name), Operand.Variable(second.name)));
1648
1649 first.derivatedType = Derivate(token, first.derivatedType, second.derivatedType);
1650
1651 break;
1652
1653 default:
1654 UndoToken();
1655 return first;
1656
1657 }
1658
1659 }
1660
1661 }

References Derivate(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, Factor(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, UndoToken(), ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

Referenced by Arithmetic().

◆ ToLiteral()

string ScriptStack.Compiler.Parser.ToLiteral ( string input)

Definition at line 1182 of file Parser.cs.

1183 {
1184 var literal = new StringBuilder(input.Length + 2);
1185 literal.Append("\"");
1186 foreach (var c in input)
1187 {
1188 switch (c)
1189 {
1190 case '\'': literal.Append(@"\'"); break;
1191 case '\"': literal.Append("\\\""); break;
1192 case '\\': literal.Append(@"\\"); break;
1193 case '\0': literal.Append(@"\0"); break;
1194 case '\a': literal.Append(@"\a"); break;
1195 case '\b': literal.Append(@"\b"); break;
1196 case '\f': literal.Append(@"\f"); break;
1197 case '\n': literal.Append(@"\n"); break;
1198 case '\r': literal.Append(@"\r"); break;
1199 case '\t': literal.Append(@"\t"); break;
1200 case '\v': literal.Append(@"\v"); break;
1201 default:
1202 if (char.GetUnicodeCategory(c) != System.Globalization.UnicodeCategory.Control)
1203 {
1204 literal.Append(c);
1205 }
1206 else
1207 {
1208 literal.Append(@"\u");
1209 literal.Append(((ushort)c).ToString("x4"));
1210 }
1211 break;
1212 }
1213 }
1214 literal.Append("\"");
1215 return literal.ToString();
1216 }

◆ UndoToken()

void ScriptStack.Compiler.Parser.UndoToken ( )
private

If you read a token wrong, push it back so the stream stays intact.

Definition at line 134 of file Parser.cs.

135 {
136
137 if (nextToken <= 0)
138 throw new ParserException("Es sind keine vorangehenden Token mehr vorhanden.");
139
140 --nextToken;
141
142 }

References nextToken.

Referenced by And(), Arithmetic(), Atom(), BitwiseAnd(), BitwiseOr(), BitwiseXor(), IsAccessChainAssignment(), IsMember(), IsPointer(), LocalVariableDeclaration(), Or(), Relation(), and Term().

◆ VariableAssignment()

Variable ScriptStack.Compiler.Parser.VariableAssignment ( )
private
Returns

Definition at line 1975 of file Parser.cs.

1976 {
1977
1978 string identifier = ExpectIdentifier();
1979
1980 Token token = ReadToken();
1981
1982 if (!AssignmentOperator(token.Type))
1983 throw new ParserException("Ein Zuweisungsoperator wurde erwartet erwartet.", token);
1984
1985 Variable expression = Expression();
1986
1987 executable.InstructionsInternal.Add(new Instruction(AssignmentOpcode(token.Type), Operand.Variable(identifier), Operand.Variable(expression.name)));
1988
1989 string tmpIdentifier = AllocateTemporaryVariable();
1990
1991 executable.InstructionsInternal.Add(new Instruction(OpCode.MOV, Operand.Variable(tmpIdentifier), Operand.Variable(identifier)));
1992
1993 return new Variable(tmpIdentifier, Scope.Local, expression.derivatedType);
1994
1995 }

References AllocateTemporaryVariable(), AssignmentOpcode(), AssignmentOperator(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, ExpectIdentifier(), Expression(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and ScriptStack.Runtime.Variable.

◆ VariableDeclaration()

void ScriptStack.Compiler.Parser.VariableDeclaration ( )
private

Shared or local variable declaration.

Definition at line 575 of file Parser.cs.

576 {
577
578 Token token = ReadToken();
579
580 if (token.Type != TokenType.Shared && token.Type != TokenType.Var)
581 throw new ParserException( "Variablen werden mit 'shared' oder 'var' deklariert.", token);
582
583 InsertDebugInfo(token);
584
585 OpCode opcode = OpCode.DB;
586
587 if(token.Type == TokenType.Shared)
588 opcode = OpCode.DSB;
589
590 string identifier = ReadIdentifier();
591
592 while (true)
593 {
594
595 if (variables.ContainsKey(identifier))
596 throw new ParserException( "Die Variable '" + identifier + "' ist bereits vorhanden.", token);
597
598 variables[identifier] = true;
599
600 executable.InstructionsInternal.Add(new Instruction(opcode, Operand.Variable(identifier)));
601
602 if (opcode == OpCode.DSB)
603 script.Manager.SharedMemory[identifier] = NullReference.Instance;
604
605 else
606 executable.ScriptMemory[identifier] = NullReference.Instance;
607
608 token = ReadToken();
609
610 if (token.Type == TokenType.SemiColon)
611 return;
612
613 if (token.Type != TokenType.Comma)
614 throw new ParserException("Comma ',' erwartet.", token);
615
616 identifier = ReadIdentifier();
617
618 }
619
620 }

References executable, InsertDebugInfo(), ReadIdentifier(), ReadToken(), script, ScriptStack.Compiler.Token.Type, ScriptStack.Runtime.Operand.Variable(), and variables.

Referenced by ParseScript().

◆ Wait()

void ScriptStack.Compiler.Parser.Wait ( )
private

Wait for a locked secion of code to be freed.

Todo

Definition at line 3212 of file Parser.cs.

3213 {
3214
3215 Token token = ReadToken();
3216
3217 if (token.Type != TokenType.Wait)
3218 throw new ParserException("Keyword 'wailt' erwartet.", token);
3219
3220 string identifier = ExpectIdentifier();
3221
3222 ReadSemicolon();
3223
3224 List<Instruction> instructions = executable.InstructionsInternal;
3225
3226 Instruction arrived = new Instruction(OpCode.NOP);
3227
3228 Instruction waiting = new Instruction(OpCode.JZ, Operand.Variable(identifier), Operand.AllocateInstructionPointer(arrived));
3229
3230 instructions.Add(waiting);
3231
3232 instructions.Add(new Instruction(OpCode.INT));
3233
3234 instructions.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(waiting)));
3235
3236 instructions.Add(arrived);
3237
3238 }

References ScriptStack.Runtime.Operand.AllocateInstructionPointer(), executable, ExpectIdentifier(), ReadSemicolon(), ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Statement().

◆ While()

void ScriptStack.Compiler.Parser.While ( )
private

Definition at line 2426 of file Parser.cs.

2427 {
2428
2429 Token token = ReadToken();
2430
2431 if (token.Type != TokenType.While)
2432 throw new ParserException("Keyword 'while' erwartet.", token);
2433
2434 Instruction start = new Instruction(OpCode.NOP);
2435
2436 executable.InstructionsInternal.Add(start);
2437
2438 ReadLeftParenthesis();
2439
2440 Variable condition = Expression();
2441
2442 if (condition.derivatedType != null && condition.derivatedType != typeof(bool))
2443 throw new ParserException("In While Loops wird ein logischer Ausdruck erwartet.", token);
2444
2445 ReadRightParenthesis();
2446
2447 Instruction end = new Instruction(OpCode.NOP);
2448
2449 executable.InstructionsInternal.Add(new Instruction(OpCode.JZ, Operand.Variable(condition.name), Operand.AllocateInstructionPointer(end)));
2450
2451 LoopControl loopControl = new LoopControl();
2452
2453 loopControl.Break = end;
2454
2455 loopControl.Continue = start;
2456
2457 this.loopControl.Push(loopControl);
2458
2459 StatementList();
2460
2461 this.loopControl.Pop();
2462
2463 executable.InstructionsInternal.Add(new Instruction(OpCode.JMP, Operand.AllocateInstructionPointer(start)));
2464
2465 executable.InstructionsInternal.Add(end);
2466
2467 }

References ScriptStack.Runtime.Operand.AllocateInstructionPointer(), ScriptStack.Compiler.Parser.Variable.derivatedType, executable, Expression(), loopControl, ScriptStack.Compiler.Parser.Variable.name, ReadLeftParenthesis(), ReadRightParenthesis(), ReadToken(), StatementList(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

Referenced by Statement().

◆ Xor()

Variable ScriptStack.Compiler.Parser.Xor ( )
private
Returns

Definition at line 1164 of file Parser.cs.

1165 {
1166
1167 string left = ExpectIdentifier();
1168
1169 Token token = ReadToken();
1170
1171 if (token.Type != TokenType.AssignXor)
1172 throw new ParserException("Binary XOR '~=' erwartet.", token);
1173
1174 Variable right = Factor();
1175
1176 executable.InstructionsInternal.Add(new Instruction(OpCode.XOR, Operand.Variable(left), Operand.Variable(right.name)));
1177
1178 return right;
1179
1180 }

References executable, ExpectIdentifier(), Factor(), ScriptStack.Compiler.Parser.Variable.name, ReadToken(), ScriptStack.Compiler.Token.Type, and ScriptStack.Runtime.Operand.Variable().

◆ Yield()

void ScriptStack.Compiler.Parser.Yield ( )
private

Definition at line 3193 of file Parser.cs.

3194 {
3195
3196 Token token = ReadToken();
3197
3198 if (token.Type != TokenType.Yield)
3199 throw new ParserException("ParserException: Keyword 'yield' erwartet.", token);
3200
3201 ReadSemicolon();
3202
3203 executable.InstructionsInternal.Add(new Instruction(OpCode.INT));
3204
3205 }

References executable, ReadSemicolon(), ReadToken(), and ScriptStack.Compiler.Token.Type.

Referenced by Statement().

Member Data Documentation

◆ debugMode

bool ScriptStack.Compiler.Parser.debugMode
private

Definition at line 64 of file Parser.cs.

Referenced by InsertDebugInfo(), and Parser().

◆ derivation

Derivation ScriptStack.Compiler.Parser.derivation
private

Definition at line 72 of file Parser.cs.

Referenced by Derivate(), and Parser().

◆ executable

◆ forwardDeclarations

Dictionary<Instruction, FunctionDescriptor> ScriptStack.Compiler.Parser.forwardDeclarations
private

Definition at line 70 of file Parser.cs.

Referenced by FunctionCall(), Parse(), Parser(), and ResolveForwardFunctionDeclarations().

◆ functionFrameIndex

int ScriptStack.Compiler.Parser.functionFrameIndex
private

◆ localVariables

Dictionary<string, bool> ScriptStack.Compiler.Parser.localVariables
private

◆ loopControl

Stack<LoopControl> ScriptStack.Compiler.Parser.loopControl
private

Definition at line 71 of file Parser.cs.

Referenced by Break(), Continue(), For(), ForEach(), Parse(), Parser(), and While().

◆ nextToken

int ScriptStack.Compiler.Parser.nextToken
private

Definition at line 66 of file Parser.cs.

Referenced by Atom(), FunctionCall(), LookAhead(), LookAhead(), More(), Parse(), Parser(), ReadToken(), and UndoToken().

◆ script

Script ScriptStack.Compiler.Parser.script
private

Definition at line 63 of file Parser.cs.

Referenced by Parse(), Parser(), and VariableDeclaration().

◆ tokenStream

List<Token> ScriptStack.Compiler.Parser.tokenStream
private

Definition at line 65 of file Parser.cs.

Referenced by Atom(), LookAhead(), LookAhead(), More(), Parser(), and ReadToken().

◆ variables

Dictionary<string, bool> ScriptStack.Compiler.Parser.variables
private

The documentation for this class was generated from the following file: