49 mNumEvents (0), |
49 mNumEvents (0), |
50 mCurrentMode (ETopLevelMode), |
50 mCurrentMode (ETopLevelMode), |
51 mStateSpawnDefined (false), |
51 mStateSpawnDefined (false), |
52 mGotMainLoop (false), |
52 mGotMainLoop (false), |
53 mScopeCursor (-1), |
53 mScopeCursor (-1), |
54 mCanElse (false) {} |
54 mCanElse (false), |
|
55 mHighestGlobalVarIndex (0), |
|
56 mHighestStateVarIndex (0) {} |
55 |
57 |
56 // ============================================================================ |
58 // ============================================================================ |
57 // |
59 // |
58 BotscriptParser::~BotscriptParser() |
60 BotscriptParser::~BotscriptParser() |
59 { |
61 { |
75 if (mCurrentMode == ETopLevelMode) |
77 if (mCurrentMode == ETopLevelMode) |
76 Error ("%1-statements must not be defined at top level!", GetTokenString()); |
78 Error ("%1-statements must not be defined at top level!", GetTokenString()); |
77 } |
79 } |
78 |
80 |
79 // ============================================================================ |
81 // ============================================================================ |
80 // Main Parser code. Begins read of the script file, checks the syntax of it |
82 // |
|
83 // Main compiler code. Begins read of the script file, checks the syntax of it |
81 // and writes the data to the object file via Objwriter - which also takes care |
84 // and writes the data to the object file via Objwriter - which also takes care |
82 // of necessary buffering so stuff is written in the correct order. |
85 // of necessary buffering so stuff is written in the correct order. |
|
86 // |
83 void BotscriptParser::ParseBotscript (String fileName) |
87 void BotscriptParser::ParseBotscript (String fileName) |
84 { |
88 { |
85 // Lex and preprocess the file |
89 // Lex and preprocess the file |
86 mLexer->ProcessFile (fileName); |
90 mLexer->ProcessFile (fileName); |
87 PushScope(); |
91 PushScope(); |
323 void BotscriptParser::ParseVar() |
327 void BotscriptParser::ParseVar() |
324 { |
328 { |
325 Variable* var = new Variable; |
329 Variable* var = new Variable; |
326 var->origin = mLexer->DescribeCurrentPosition(); |
330 var->origin = mLexer->DescribeCurrentPosition(); |
327 const bool isconst = mLexer->GetNext (tkConst); |
331 const bool isconst = mLexer->GetNext (tkConst); |
328 const bool isglobal = true; |
|
329 mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); |
332 mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); |
330 |
333 |
331 EType vartype = (TokenIs (tkInt)) ? EIntType : |
334 EType vartype = (TokenIs (tkInt)) ? EIntType : |
332 (TokenIs (tkStr)) ? EStringType : |
335 (TokenIs (tkStr)) ? EStringType : |
333 EBoolType; |
336 EBoolType; |
334 |
337 |
335 mLexer->MustGetNext (tkSymbol); |
338 mLexer->MustGetNext (tkSymbol); |
336 String name = GetTokenString(); |
339 String name = GetTokenString(); |
337 |
|
338 /* |
|
339 * TODO |
|
340 if (isglobal && mScopeStack[0].globalVariables.Size() >= gMaxGlobalVars) |
|
341 Error ("too many global variables!"); |
|
342 */ |
|
343 |
340 |
344 for (Variable* var : SCOPE(0).globalVariables + SCOPE(0).localVariables) |
341 for (Variable* var : SCOPE(0).globalVariables + SCOPE(0).localVariables) |
345 { |
342 { |
346 if (var->name == name) |
343 if (var->name == name) |
347 Error ("Variable $%1 is already declared on this scope; declared at %2", |
344 Error ("Variable $%1 is already declared on this scope; declared at %2", |
393 if (IsInGlobalState()) |
390 if (IsInGlobalState()) |
394 SCOPE(0).globalVariables << var; |
391 SCOPE(0).globalVariables << var; |
395 else |
392 else |
396 SCOPE(0).localVariables << var; |
393 SCOPE(0).localVariables << var; |
397 |
394 |
|
395 SuggestHighestVarIndex (IsInGlobalState(), var->index); |
398 mLexer->MustGetNext (tkSemicolon); |
396 mLexer->MustGetNext (tkSemicolon); |
399 Print ("Declared %3 variable #%1 $%2\n", var->index, var->name, IsInGlobalState() ? "global" : "state-local"); |
397 Print ("Declared %3 variable #%1 $%2\n", var->index, var->name, IsInGlobalState() ? "global" : "state-local"); |
400 } |
398 } |
401 |
399 |
402 // ============================================================================ |
400 // ============================================================================ |
1357 // |
1355 // |
1358 // Write the compiled bytecode to a file |
1356 // Write the compiled bytecode to a file |
1359 // |
1357 // |
1360 void BotscriptParser::WriteToFile (String outfile) |
1358 void BotscriptParser::WriteToFile (String outfile) |
1361 { |
1359 { |
1362 FILE* fp = fopen (outfile, "w"); |
1360 FILE* fp = fopen (outfile, "wb"); |
1363 |
1361 |
1364 if (fp == null) |
1362 if (fp == null) |
1365 Error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); |
1363 Error ("couldn't open %1 for writing: %2", outfile, strerror (errno)); |
1366 |
1364 |
1367 // First, resolve references |
1365 // First, resolve references |
1400 // |
1398 // |
1401 bool BotscriptParser::IsInGlobalState() const |
1399 bool BotscriptParser::IsInGlobalState() const |
1402 { |
1400 { |
1403 return mCurrentState.IsEmpty(); |
1401 return mCurrentState.IsEmpty(); |
1404 } |
1402 } |
|
1403 |
|
1404 // ============================================================================ |
|
1405 // |
|
1406 void BotscriptParser::SuggestHighestVarIndex (bool global, int index) |
|
1407 { |
|
1408 if (global) |
|
1409 mHighestGlobalVarIndex = max (mHighestGlobalVarIndex, index); |
|
1410 else |
|
1411 mHighestStateVarIndex = max (mHighestStateVarIndex, index); |
|
1412 } |
|
1413 |
|
1414 // ============================================================================ |
|
1415 // |
|
1416 int BotscriptParser::GetHighestVarIndex (bool global) |
|
1417 { |
|
1418 if (global) |
|
1419 return mHighestGlobalVarIndex; |
|
1420 |
|
1421 return mHighestStateVarIndex; |
|
1422 } |