src/Parser.cc

changeset 101
9ffae10ef76f
parent 100
e0392814ee31
child 102
28f89ca1a236
equal deleted inserted replaced
100:e0392814ee31 101:9ffae10ef76f
115 case tkOnenter: 115 case tkOnenter:
116 case tkOnexit: 116 case tkOnexit:
117 ParseOnEnterExit(); 117 ParseOnEnterExit();
118 break; 118 break;
119 119
120 case tkInt: 120 case tkVar:
121 case tkStr: 121 ParseVar();
122 case tkVoid:
123 ParseVariableDeclaration();
124 break; 122 break;
125 123
126 case tkGoto: 124 case tkGoto:
127 ParseGoto(); 125 ParseGoto();
128 break; 126 break;
167 ParseContinue(); 165 ParseContinue();
168 break; 166 break;
169 167
170 case tkBraceEnd: 168 case tkBraceEnd:
171 ParseBlockEnd(); 169 ParseBlockEnd();
172 break;
173
174 case tkConst:
175 ParseConst();
176 break; 170 break;
177 171
178 case tkEventdef: 172 case tkEventdef:
179 ParseEventdef(); 173 ParseEventdef();
180 break; 174 break;
326 buffer()->WriteDWord (onenter ? dhOnEnter : dhOnExit); 320 buffer()->WriteDWord (onenter ? dhOnEnter : dhOnExit);
327 } 321 }
328 322
329 // ============================================================================ 323 // ============================================================================
330 // 324 //
331 void BotscriptParser::ParseVariableDeclaration() 325 void BotscriptParser::ParseVar()
332 { 326 {
333 // For now, only globals are supported 327 const bool isconst = mLexer->GetNext (tkConst);
328 mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid});
329
330 // TODO
334 if (mCurrentMode != ETopLevelMode || mCurrentState.IsEmpty() == false) 331 if (mCurrentMode != ETopLevelMode || mCurrentState.IsEmpty() == false)
335 Error ("variables must only be global for now"); 332 Error ("variables must only be global for now");
336 333
337 EType type = (TokenIs (tkInt)) ? EIntType : 334 EType type = (TokenIs (tkInt)) ? EIntType :
338 (TokenIs (tkStr)) ? EStringType : 335 (TokenIs (tkStr)) ? EStringType :
339 EBoolType; 336 EBoolType;
340 337
341 mLexer->MustGetNext(); 338 mLexer->MustGetNext();
342 String varname = GetTokenString(); 339 String varname = GetTokenString();
343 340
344 // Var name must not be a number 341 if (varname[0] >= '0' && varname[0] <= '9')
345 if (varname.IsNumeric()) 342 Error ("variable name must not start with a number");
346 Error ("variable name must not be a number");
347 343
348 ScriptVariable* var = DeclareGlobalVariable (type, varname); 344 ScriptVariable* var = DeclareGlobalVariable (type, varname);
349 (void) var; 345
346 if (isconst == false)
347 {
348 var->writelevel = ScriptVariable::WRITE_Mutable;
349 }
350 else
351 {
352 mLexer->MustGetNext (tkAssign);
353 Expression expr (this, mLexer, type);
354
355 if (expr.GetResult()->IsConstexpr())
356 {
357 var->writelevel = ScriptVariable::WRITE_Constexpr;
358 var->value = expr.GetResult()->GetValue();
359 }
360 else
361 {
362 // TODO: might need a VM-wise oninit for this...
363 Error ("const variables must be constexpr for now");
364 }
365 }
366
350 mLexer->MustGetNext (tkSemicolon); 367 mLexer->MustGetNext (tkSemicolon);
351 } 368 }
352 369
353 // ============================================================================ 370 // ============================================================================
354 // 371 //
797 mLexer->GetNext (tkSemicolon); 814 mLexer->GetNext (tkSemicolon);
798 } 815 }
799 816
800 // ============================================================================ 817 // ============================================================================
801 // 818 //
802 void BotscriptParser::ParseConst()
803 {
804 ConstantInfo info;
805
806 // Get the type
807 mLexer->MustGetNext();
808 String typestring = GetTokenString();
809 info.type = GetTypeByName (typestring);
810
811 if (info.type == EUnknownType || info.type == EVoidType)
812 Error ("unknown type `%1` for constant", typestring);
813
814 mLexer->MustGetNext();
815 info.name = GetTokenString();
816
817 mLexer->MustGetNext (tkAssign);
818
819 switch (info.type)
820 {
821 case EBoolType:
822 case EIntType:
823 {
824 mLexer->MustGetNext (tkNumber);
825 } break;
826
827 case EStringType:
828 {
829 mLexer->MustGetNext (tkString);
830 } break;
831
832 case EUnknownType:
833 case EVoidType:
834 break;
835 }
836
837 info.val = mLexer->GetToken()->text;
838 mConstants << info;
839
840 mLexer->MustGetNext (tkSemicolon);
841 }
842
843 // ============================================================================
844 //
845 void BotscriptParser::ParseLabel() 819 void BotscriptParser::ParseLabel()
846 { 820 {
847 CheckNotToplevel(); 821 CheckNotToplevel();
848 String labelName = GetTokenString(); 822 String labelName = GetTokenString();
849 ByteMark* mark = null; 823 ByteMark* mark = null;
968 // Parses a command call 942 // Parses a command call
969 DataBuffer* BotscriptParser::ParseCommand (CommandInfo* comm) 943 DataBuffer* BotscriptParser::ParseCommand (CommandInfo* comm)
970 { 944 {
971 DataBuffer* r = new DataBuffer (64); 945 DataBuffer* r = new DataBuffer (64);
972 946
973 if (mCurrentMode == ETopLevelMode) 947 if (mCurrentMode == ETopLevelMode && comm->returnvalue == EVoidType)
974 Error ("command call at top level"); 948 Error ("command call at top level");
975 949
976 mLexer->MustGetNext (tkParenStart); 950 mLexer->MustGetNext (tkParenStart);
977 mLexer->MustGetNext(); 951 mLexer->MustGetNext();
978 952
1133 // by an assignment operator, followed by an expression value. Expects current 1107 // by an assignment operator, followed by an expression value. Expects current
1134 // token to be the name of the variable, and expects the variable to be given. 1108 // token to be the name of the variable, and expects the variable to be given.
1135 // 1109 //
1136 DataBuffer* BotscriptParser::ParseAssignment (ScriptVariable* var) 1110 DataBuffer* BotscriptParser::ParseAssignment (ScriptVariable* var)
1137 { 1111 {
1112 if (var->writelevel != ScriptVariable::WRITE_Mutable)
1113 {
1114 Error ("cannot alter read-only variable $%1", var->name);
1115 }
1116
1138 // Get an operator 1117 // Get an operator
1139 EAssignmentOperator oper = ParseAssignmentOperator(); 1118 EAssignmentOperator oper = ParseAssignmentOperator();
1140 DataBuffer* retbuf = new DataBuffer; 1119 DataBuffer* retbuf = new DataBuffer;
1141 1120
1142 if (mCurrentMode == ETopLevelMode) 1121 if (mCurrentMode == ETopLevelMode)
1210 1189
1211 // ============================================================================ 1190 // ============================================================================
1212 // 1191 //
1213 DataBuffer* BotscriptParser::ParseStatement() 1192 DataBuffer* BotscriptParser::ParseStatement()
1214 { 1193 {
1215 if (FindConstant (GetTokenString())) // There should not be constants here.
1216 Error ("invalid use for constant\n");
1217
1218 // If it's a variable, expect assignment. 1194 // If it's a variable, expect assignment.
1219 if (ScriptVariable* var = FindGlobalVariable (GetTokenString())) 1195 if (TokenIs (tkDollarSign))
1196 {
1197 mLexer->MustGetNext (tkSymbol);
1198 ScriptVariable* var = FindGlobalVariable (GetTokenString());
1199
1200 if (var == null)
1201 Error ("unknown variable $%1", var->name);
1202
1220 return ParseAssignment (var); 1203 return ParseAssignment (var);
1204 }
1221 1205
1222 return null; 1206 return null;
1223 } 1207 }
1224 1208
1225 // ============================================================================ 1209 // ============================================================================
1247 info->casecursor++; 1231 info->casecursor++;
1248 } 1232 }
1249 1233
1250 // ============================================================================ 1234 // ============================================================================
1251 // 1235 //
1252 ConstantInfo* BotscriptParser::FindConstant (const String& tok)
1253 {
1254 for (int i = 0; i < mConstants.Size(); i++)
1255 if (mConstants[i].name == tok)
1256 return &mConstants[i];
1257
1258 return null;
1259 }
1260
1261 // ============================================================================
1262 //
1263 bool BotscriptParser::TokenIs (EToken a) 1236 bool BotscriptParser::TokenIs (EToken a)
1264 { 1237 {
1265 return (mLexer->GetTokenType() == a); 1238 return (mLexer->GetTokenType() == a);
1266 } 1239 }
1267 1240

mercurial