897 // |
897 // |
898 void BotscriptParser::ParseFuncdef() |
898 void BotscriptParser::ParseFuncdef() |
899 { |
899 { |
900 CommandInfo* comm = new CommandInfo; |
900 CommandInfo* comm = new CommandInfo; |
901 |
901 |
|
902 // Return value |
|
903 mLexer->MustGetAnyOf ({tkInt, tkVoid, tkBool, tkStr}); |
|
904 comm->returnvalue = GetTypeByName (mLexer->GetToken()->text); // TODO |
|
905 assert (comm->returnvalue != -1); |
|
906 |
902 // Number |
907 // Number |
903 mLexer->MustGetNext (tkNumber); |
908 mLexer->MustGetNext (tkNumber); |
904 comm->number = mLexer->GetToken()->text.ToLong(); |
909 comm->number = mLexer->GetToken()->text.ToLong(); |
905 mLexer->MustGetNext (tkColon); |
910 mLexer->MustGetNext (tkColon); |
906 |
911 |
907 // Name |
912 // Name |
908 mLexer->MustGetNext (tkSymbol); |
913 mLexer->MustGetNext (tkSymbol); |
909 comm->name = mLexer->GetToken()->text; |
914 comm->name = mLexer->GetToken()->text; |
910 mLexer->MustGetNext (tkColon); |
915 |
911 |
916 // Arguments |
912 // Return value |
917 mLexer->MustGetNext (tkParenStart); |
913 mLexer->MustGetAnyOf ({tkInt, tkVoid, tkBool, tkStr}); |
918 comm->minargs = 0; |
914 comm->returnvalue = GetTypeByName (mLexer->GetToken()->text); // TODO |
919 |
915 assert (comm->returnvalue != -1); |
920 while (mLexer->PeekNextType (tkParenEnd) == false) |
916 mLexer->MustGetNext (tkColon); |
921 { |
917 |
922 if (comm->args.IsEmpty() == false) |
918 // Num args |
923 mLexer->MustGetNext (tkComma); |
919 mLexer->MustGetNext (tkNumber); |
924 |
920 comm->numargs = mLexer->GetToken()->text.ToLong(); |
|
921 mLexer->MustGetNext (tkColon); |
|
922 |
|
923 // Max args |
|
924 mLexer->MustGetNext (tkNumber); |
|
925 comm->maxargs = mLexer->GetToken()->text.ToLong(); |
|
926 |
|
927 // Argument types |
|
928 int curarg = 0; |
|
929 |
|
930 while (curarg < comm->maxargs) |
|
931 { |
|
932 CommandArgument arg; |
925 CommandArgument arg; |
933 mLexer->MustGetNext (tkColon); |
|
934 mLexer->MustGetAnyOf ({tkInt, tkBool, tkStr}); |
926 mLexer->MustGetAnyOf ({tkInt, tkBool, tkStr}); |
935 EType type = GetTypeByName (mLexer->GetToken()->text); |
927 EType type = GetTypeByName (mLexer->GetToken()->text); // TODO |
936 assert (type != -1 && type != EVoidType); |
928 assert (type != -1 && type != EVoidType); |
937 arg.type = type; |
929 arg.type = type; |
938 |
930 |
939 mLexer->MustGetNext (tkParenStart); |
|
940 mLexer->MustGetNext (tkSymbol); |
931 mLexer->MustGetNext (tkSymbol); |
941 arg.name = mLexer->GetToken()->text; |
932 arg.name = mLexer->GetToken()->text; |
942 |
933 |
943 // If this is an optional parameter, we need the default value. |
934 // If this is an optional parameter, we need the default value. |
944 if (curarg >= comm->numargs) |
935 if (comm->minargs < comm->args.Size() || mLexer->PeekNextType (tkAssign)) |
945 { |
936 { |
946 mLexer->MustGetNext (tkAssign); |
937 mLexer->MustGetNext (tkAssign); |
947 |
938 |
948 switch (type) |
939 switch (type) |
949 { |
940 { |
951 case EBoolType: |
942 case EBoolType: |
952 mLexer->MustGetNext (tkNumber); |
943 mLexer->MustGetNext (tkNumber); |
953 break; |
944 break; |
954 |
945 |
955 case EStringType: |
946 case EStringType: |
956 mLexer->MustGetNext (tkString); |
947 Error ("string arguments cannot have default values"); |
957 break; |
|
958 |
948 |
959 case EUnknownType: |
949 case EUnknownType: |
960 case EVoidType: |
950 case EVoidType: |
961 break; |
951 break; |
962 } |
952 } |
963 |
953 |
964 arg.defvalue = mLexer->GetToken()->text.ToLong(); |
954 arg.defvalue = mLexer->GetToken()->text.ToLong(); |
965 } |
955 } |
966 |
956 else |
967 mLexer->MustGetNext (tkParenEnd); |
957 comm->minargs++; |
|
958 |
968 comm->args << arg; |
959 comm->args << arg; |
969 curarg++; |
960 } |
970 } |
961 |
971 |
962 mLexer->MustGetNext (tkParenEnd); |
972 mLexer->MustGetNext (tkSemicolon); |
963 mLexer->MustGetNext (tkSemicolon); |
973 AddCommandDefinition (comm); |
964 AddCommandDefinition (comm); |
974 } |
965 } |
975 |
966 |
976 // ============================================================================ |
967 // ============================================================================ |
985 mLexer->MustGetNext (tkParenStart); |
976 mLexer->MustGetNext (tkParenStart); |
986 mLexer->MustGetNext(); |
977 mLexer->MustGetNext(); |
987 |
978 |
988 int curarg = 0; |
979 int curarg = 0; |
989 |
980 |
990 while (1) |
981 for (;;) |
991 { |
982 { |
992 if (TokenIs (tkParenEnd)) |
983 if (TokenIs (tkParenEnd)) |
993 { |
984 { |
994 if (curarg < comm->numargs) |
985 if (curarg < comm->minargs) |
995 Error ("too few arguments passed to %1\n\tusage is: %2", |
986 Error ("too few arguments passed to %1\n\tusage is: %2", |
996 comm->name, comm->GetSignature()); |
987 comm->name, comm->GetSignature()); |
997 |
988 |
998 break; |
989 break; |
999 curarg++; |
990 curarg++; |
1000 } |
991 } |
1001 |
992 |
1002 if (curarg >= comm->maxargs) |
993 if (curarg >= comm->args.Size()) |
1003 Error ("too many arguments passed to %1\n\tusage is: %2", |
994 Error ("too many arguments passed to %1\n\tusage is: %2", |
1004 comm->name, comm->GetSignature()); |
995 comm->name, comm->GetSignature()); |
1005 |
996 |
1006 r->MergeAndDestroy (ParseExpression (comm->args[curarg].type, true)); |
997 r->MergeAndDestroy (ParseExpression (comm->args[curarg].type, true)); |
1007 mLexer->MustGetNext(); |
998 mLexer->MustGetNext(); |
1008 |
999 |
1009 if (curarg < comm->numargs - 1) |
1000 if (curarg < comm->minargs - 1) |
1010 { |
1001 { |
1011 mLexer->TokenMustBe (tkComma); |
1002 mLexer->TokenMustBe (tkComma); |
1012 mLexer->MustGetNext(); |
1003 mLexer->MustGetNext(); |
1013 } |
1004 } |
1014 else if (curarg < comm->maxargs - 1) |
1005 else if (curarg < comm->args.Size() - 1) |
1015 { |
1006 { |
1016 // Can continue, but can terminate as well. |
1007 // Can continue, but can terminate as well. |
1017 if (TokenIs (tkParenEnd)) |
1008 if (TokenIs (tkParenEnd)) |
1018 { |
1009 { |
1019 curarg++; |
1010 curarg++; |
1028 |
1019 |
1029 curarg++; |
1020 curarg++; |
1030 } |
1021 } |
1031 |
1022 |
1032 // If the script skipped any optional arguments, fill in defaults. |
1023 // If the script skipped any optional arguments, fill in defaults. |
1033 while (curarg < comm->maxargs) |
1024 while (curarg < comm->args.Size()) |
1034 { |
1025 { |
1035 r->WriteDWord (dhPushNumber); |
1026 r->WriteDWord (dhPushNumber); |
1036 r->WriteDWord (comm->args[curarg].defvalue); |
1027 r->WriteDWord (comm->args[curarg].defvalue); |
1037 curarg++; |
1028 curarg++; |
1038 } |
1029 } |
1039 |
1030 |
1040 r->WriteDWord (dhCommand); |
1031 r->WriteDWord (dhCommand); |
1041 r->WriteDWord (comm->number); |
1032 r->WriteDWord (comm->number); |
1042 r->WriteDWord (comm->maxargs); |
1033 r->WriteDWord (comm->args.Size()); |
1043 |
1034 |
1044 return r; |
1035 return r; |
1045 } |
1036 } |
1046 |
1037 |
1047 // ============================================================================ |
1038 // ============================================================================ |