Beispiel #1
0
static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls)
{
	FScriptPosition scpos(sc);
	if (sc.CheckToken('('))
	{
		FxExpression *data = ParseExpressionM (sc, cls);
		sc.MustGetToken(')');
		return data;
	}
	else if (sc.CheckToken(TK_True))
	{
		return new FxConstant(1, scpos);
	}
	else if (sc.CheckToken(TK_False))
	{
		return new FxConstant(0, scpos);
	}
	else if (sc.CheckToken(TK_IntConst))
	{
		return new FxConstant(sc.Number, scpos);
	}
	else if (sc.CheckToken(TK_FloatConst))
	{
		return new FxConstant(sc.Float, scpos);
	}
	else if (sc.CheckToken(TK_NameConst))
	{
		return new FxConstant(sc.Name, scpos);
	}
	else if (sc.CheckToken(TK_StringConst))
	{
		// String parameters are converted to names. Technically, this should be
		// done at a higher level, as needed, but since no functions take string
		// arguments and ACS_NamedExecuteWithResult/CallACS need names, this is
		// a cheap way to get them working when people use "name" instead of 'name'.
		return new FxConstant(FName(sc.String), scpos);
	}
	else if (sc.CheckToken(TK_Identifier))
	{
		FName identifier = FName(sc.String);
		FArgumentList *args;
		PFunction *func;

		switch (identifier)
		{
		case NAME_Random:
		case NAME_FRandom:
			return ParseRandom(sc, identifier, cls);
		case NAME_RandomPick:
		case NAME_FRandomPick:
			return ParseRandomPick(sc, identifier, cls);
		case NAME_Random2:
			return ParseRandom2(sc, cls);
		default:
			break;
		}
		if (sc.CheckToken('('))
		{
			switch (identifier)
			{
			case NAME_Min:
			case NAME_Max:
				return ParseMinMax(sc, identifier, cls);
			case NAME_Clamp:
				return ParseClamp(sc, cls);
			case NAME_Abs:
				return ParseAbs(sc, cls);
			default:
				args = new FArgumentList;
				func = dyn_cast<PFunction>(cls->Symbols.FindSymbol(identifier, true));
				try
				{
					// There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work.
					if (func != NULL && identifier != NAME_ACS_NamedExecuteWithResult)
					{
						sc.UnGet();
						ParseFunctionParameters(sc, cls, *args, func, "", NULL);
						return new FxVMFunctionCall(func, args, sc);
					}
					else if (!sc.CheckToken(')'))
					{
						do
						{
							args->Push(ParseExpressionM (sc, cls));
						}
						while (sc.CheckToken(','));
						sc.MustGetToken(')');
					}
					return new FxFunctionCall(NULL, identifier, args, sc);
				}
				catch (...)
				{
					delete args;
					throw;
				}
				break;
			}
		}	
		else
		{
			return new FxIdentifier(identifier, sc);
		}
	}
	else
	{
		FString tokname = sc.TokenName(sc.TokenType, sc.String);
		sc.ScriptError ("Unexpected token %s", tokname.GetChars());
	}
	return NULL;
}
Beispiel #2
0
static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls)
{
	FScriptPosition scpos(sc);
	if (sc.CheckToken('('))
	{
		FxExpression *data = ParseExpressionM (sc, cls);
		sc.MustGetToken(')');
		return data;
	}
	else if (sc.CheckToken(TK_True))
	{
		return new FxConstant(1, scpos);
	}
	else if (sc.CheckToken(TK_False))
	{
		return new FxConstant(0, scpos);
	}
	else if (sc.CheckToken(TK_IntConst))
	{
		return new FxConstant(sc.Number, scpos);
	}
	else if (sc.CheckToken(TK_FloatConst))
	{
		return new FxConstant(sc.Float, scpos);
	}
	else if (sc.CheckToken(TK_NameConst))
	{
		return new FxConstant(sc.Name, scpos);
	}
	else if (sc.CheckToken(TK_StringConst))
	{
		// String parameters are converted to names. Technically, this should be
		// done at a higher level, as needed, but since no functions take string
		// arguments and ACS_NamedExecuteWithResult/CallACS need names, this is
		// a cheap way to get them working when people use "name" instead of 'name'.
		return new FxConstant(FName(sc.String), scpos);
	}
	else if (sc.CheckToken(TK_Random))
	{
		FRandom *rng;

		if (sc.CheckToken('['))
		{
			sc.MustGetToken(TK_Identifier);
			rng = FRandom::StaticFindRNG(sc.String);
			sc.MustGetToken(']');
		}
		else
		{
			rng = &pr_exrandom;
		}
		sc.MustGetToken('(');

		FxExpression *min = ParseExpressionM (sc, cls);
		sc.MustGetToken(',');
		FxExpression *max = ParseExpressionM (sc, cls);
		sc.MustGetToken(')');

		return new FxRandom(rng, min, max, sc);
	}
	else if (sc.CheckToken(TK_RandomPick) || sc.CheckToken(TK_FRandomPick))
	{
		bool floaty = sc.TokenType == TK_FRandomPick;
		FRandom *rng;
		TArray<FxExpression*> list;
		list.Clear();
		int index = 0;

		if (sc.CheckToken('['))
		{
			sc.MustGetToken(TK_Identifier);
			rng = FRandom::StaticFindRNG(sc.String);
			sc.MustGetToken(']');
		}
		else
		{
			rng = &pr_exrandom;
		}
		sc.MustGetToken('(');

		for (;;)
		{
			FxExpression *expr = ParseExpressionM(sc, cls);
			list.Push(expr);
			if (sc.CheckToken(')'))
				break;
			sc.MustGetToken(',');
		}
		return new FxRandomPick(rng, list, floaty, sc);
	}
	else if (sc.CheckToken(TK_FRandom))
	{
		FRandom *rng;

		if (sc.CheckToken('['))
		{
			sc.MustGetToken(TK_Identifier);
			rng = FRandom::StaticFindRNG(sc.String);
			sc.MustGetToken(']');
		}
		else
		{
			rng = &pr_exrandom;
		}
		sc.MustGetToken('(');

		FxExpression *min = ParseExpressionM (sc, cls);
		sc.MustGetToken(',');
		FxExpression *max = ParseExpressionM (sc, cls);
		sc.MustGetToken(')');

		return new FxFRandom(rng, min, max, sc);
	}
	else if (sc.CheckToken(TK_Random2))
	{
		FRandom *rng;

		if (sc.CheckToken('['))
		{
			sc.MustGetToken(TK_Identifier);
			rng = FRandom::StaticFindRNG(sc.String);
			sc.MustGetToken(']');
		}
		else
		{
			rng = &pr_exrandom;
		}

		sc.MustGetToken('(');

		FxExpression *mask = NULL;

		if (!sc.CheckToken(')'))
		{
			mask = ParseExpressionM(sc, cls);
			sc.MustGetToken(')');
		}
		return new FxRandom2(rng, mask, sc);
	}
	else if (sc.CheckToken(TK_Abs))
	{
		sc.MustGetToken('(');
		FxExpression *x = ParseExpressionM (sc, cls);
		sc.MustGetToken(')');
		return new FxAbs(x); 
	}
	else if (sc.CheckToken(TK_Identifier))
	{
		FName identifier = FName(sc.String);
		if (sc.CheckToken('('))
		{
			FArgumentList *args = new FArgumentList;
			PFunction *func = dyn_cast<PFunction>(cls->Symbols.FindSymbol(identifier, true));
			try
			{
				if (func != NULL)
				{
					sc.UnGet();
					ParseFunctionParameters(sc, cls, *args, func, "", NULL);
					return new FxVMFunctionCall(func, args, sc);
				}
				else if (!sc.CheckToken(')'))
				{
					do
					{
						args->Push(ParseExpressionM (sc, cls));
					}
					while (sc.CheckToken(','));
					sc.MustGetToken(')');
				}
				return new FxFunctionCall(NULL, identifier, args, sc);
			}
			catch (...)
			{
				delete args;
				throw;
			}
		}	
		else
		{
			return new FxIdentifier(identifier, sc);
		}
	}
	else
	{
		FString tokname = sc.TokenName(sc.TokenType, sc.String);
		sc.ScriptError ("Unexpected token %s", tokname.GetChars());
	}
	return NULL;
}