Cleanup parsing of DECORATE intrinsics

- Split specific parsing for each intrinsic out of ParseExpression0 and
  into their own functions.
- Instead of reserving keywords for intrinsics, identify them by name
  within TK_Identifier's handling.
This commit is contained in:
Randy Heit 2016-02-23 19:36:31 -06:00
parent 01bdd8a7da
commit 326907f6ab
6 changed files with 155 additions and 167 deletions

View file

@ -280,7 +280,10 @@ xx(Cast) // 'damage type' for the cast call
// Special names for thingdef_exp.cpp // Special names for thingdef_exp.cpp
xx(Random) xx(Random)
xx(FRandom)
xx(Random2) xx(Random2)
xx(RandomPick)
xx(FRandomPick)
xx(Cos) xx(Cos)
xx(Sin) xx(Sin)
xx(Alpha) xx(Alpha)

View file

@ -185,14 +185,6 @@ std2:
'#include' { RET(TK_Include); } '#include' { RET(TK_Include); }
'fixed_t' { RET(TK_Fixed_t); } 'fixed_t' { RET(TK_Fixed_t); }
'angle_t' { RET(TK_Angle_t); } 'angle_t' { RET(TK_Angle_t); }
'abs' { RET(TK_Abs); }
'random' { RET(TK_Random); }
'random2' { RET(TK_Random2); }
'frandom' { RET(TK_FRandom); }
'randompick' { RET(TK_RandomPick); }
'frandompick' { RET(TK_FRandomPick); }
'min' { RET(TK_Min); }
'max' { RET(TK_Max); }
L (L|D)* { RET(TK_Identifier); } L (L|D)* { RET(TK_Identifier); }

View file

@ -113,10 +113,6 @@ xx(TK_Stop, "'stop'")
xx(TK_Include, "'include'") xx(TK_Include, "'include'")
xx(TK_Fixed_t, "'fixed_t'") xx(TK_Fixed_t, "'fixed_t'")
xx(TK_Angle_t, "'angle_t'") xx(TK_Angle_t, "'angle_t'")
xx(TK_Abs, "'abs'")
xx(TK_Random, "'random'")
xx(TK_Random2, "'random2'")
xx(TK_FRandom, "'frandom'")
xx(TK_Is, "'is'") xx(TK_Is, "'is'")
xx(TK_Replaces, "'replaces'") xx(TK_Replaces, "'replaces'")
@ -126,10 +122,6 @@ xx(TK_Array, "'array'")
xx(TK_In, "'in'") xx(TK_In, "'in'")
xx(TK_SizeOf, "'sizeof'") xx(TK_SizeOf, "'sizeof'")
xx(TK_AlignOf, "'alignof'") xx(TK_AlignOf, "'alignof'")
xx(TK_RandomPick, "'randompick'")
xx(TK_FRandomPick, "'frandompick'")
xx(TK_Min, "'min'")
xx(TK_Max, "'max'")
xx(TK_States, "'states'") xx(TK_States, "'states'")
xx(TK_Loop, "'loop'") xx(TK_Loop, "'loop'")
xx(TK_Fail, "'fail'") xx(TK_Fail, "'fail'")

View file

@ -52,6 +52,12 @@
FRandom pr_exrandom ("EX_Random"); FRandom pr_exrandom ("EX_Random");
static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cls);
static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor *cls);
static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls);
static FxExpression *ParseAbs(FScanner &sc, PClassActor *cls);
static FxExpression *ParseMinMax(FScanner &sc, FName identifier, PClassActor *cls);
// //
// ParseExpression // ParseExpression
// [GRB] Parses an expression and stores it into Expression array // [GRB] Parses an expression and stores it into Expression array
@ -349,161 +355,63 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls)
// a cheap way to get them working when people use "name" instead of 'name'. // a cheap way to get them working when people use "name" instead of 'name'.
return new FxConstant(FName(sc.String), scpos); return new FxConstant(FName(sc.String), scpos);
} }
else if (sc.CheckToken(TK_Min) || sc.CheckToken(TK_Max))
{
int type = sc.TokenType;
TArray<FxExpression*> list;
sc.MustGetToken('(');
for (;;)
{
FxExpression *expr = ParseExpressionM(sc, cls);
list.Push(expr);
if (sc.CheckToken(')'))
break;
sc.MustGetToken(',');
}
return new FxMinMax(list, type, sc);
}
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)) else if (sc.CheckToken(TK_Identifier))
{ {
FName identifier = FName(sc.String); 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('(')) if (sc.CheckToken('('))
{ {
FArgumentList *args = new FArgumentList; switch (identifier)
PFunction *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. case NAME_Min:
if (func != NULL && identifier != NAME_ACS_NamedExecuteWithResult) case NAME_Max:
return ParseMinMax(sc, identifier, cls);
case NAME_Abs:
return ParseAbs(sc, cls);
default:
args = new FArgumentList;
func = dyn_cast<PFunction>(cls->Symbols.FindSymbol(identifier, true));
try
{ {
sc.UnGet(); // There is an action function ACS_NamedExecuteWithResult which must be ignored here for this to work.
ParseFunctionParameters(sc, cls, *args, func, "", NULL); if (func != NULL && identifier != NAME_ACS_NamedExecuteWithResult)
return new FxVMFunctionCall(func, args, sc);
}
else if (!sc.CheckToken(')'))
{
do
{ {
args->Push(ParseExpressionM (sc, cls)); sc.UnGet();
ParseFunctionParameters(sc, cls, *args, func, "", NULL);
return new FxVMFunctionCall(func, args, sc);
} }
while (sc.CheckToken(',')); else if (!sc.CheckToken(')'))
sc.MustGetToken(')'); {
do
{
args->Push(ParseExpressionM (sc, cls));
}
while (sc.CheckToken(','));
sc.MustGetToken(')');
}
return new FxFunctionCall(NULL, identifier, args, sc);
} }
return new FxFunctionCall(NULL, identifier, args, sc); catch (...)
} {
catch (...) delete args;
{ throw;
delete args; }
throw; break;
} }
} }
else else
@ -519,4 +427,97 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls)
return NULL; return NULL;
} }
static FRandom *ParseRNG(FScanner &sc)
{
FRandom *rng;
if (sc.CheckToken('['))
{
sc.MustGetToken(TK_Identifier);
rng = FRandom::StaticFindRNG(sc.String);
sc.MustGetToken(']');
}
else
{
rng = &pr_exrandom;
}
return rng;
}
static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cls)
{
FRandom *rng = ParseRNG(sc);
sc.MustGetToken('(');
FxExpression *min = ParseExpressionM (sc, cls);
sc.MustGetToken(',');
FxExpression *max = ParseExpressionM (sc, cls);
sc.MustGetToken(')');
if (identifier == NAME_Random)
{
return new FxRandom(rng, min, max, sc);
}
else
{
return new FxFRandom(rng, min, max, sc);
}
}
static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor *cls)
{
bool floaty = identifier == NAME_FRandomPick;
FRandom *rng;
TArray<FxExpression*> list;
list.Clear();
int index = 0;
rng = ParseRNG(sc);
sc.MustGetToken('(');
for (;;)
{
FxExpression *expr = ParseExpressionM(sc, cls);
list.Push(expr);
if (sc.CheckToken(')'))
break;
sc.MustGetToken(',');
}
return new FxRandomPick(rng, list, floaty, sc);
}
static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls)
{
FRandom *rng = ParseRNG(sc);
FxExpression *mask = NULL;
sc.MustGetToken('(');
if (!sc.CheckToken(')'))
{
mask = ParseExpressionM(sc, cls);
sc.MustGetToken(')');
}
return new FxRandom2(rng, mask, sc);
}
static FxExpression *ParseAbs(FScanner &sc, PClassActor *cls)
{
FxExpression *x = ParseExpressionM (sc, cls);
sc.MustGetToken(')');
return new FxAbs(x);
}
static FxExpression *ParseMinMax(FScanner &sc, FName identifier, PClassActor *cls)
{
TArray<FxExpression*> list;
for (;;)
{
FxExpression *expr = ParseExpressionM(sc, cls);
list.Push(expr);
if (sc.CheckToken(')'))
break;
sc.MustGetToken(',');
}
return new FxMinMax(list, identifier, sc);
}

View file

@ -632,10 +632,10 @@ public:
class FxMinMax : public FxExpression class FxMinMax : public FxExpression
{ {
TDeletingArray<FxExpression *> choices; TDeletingArray<FxExpression *> choices;
int Type; FName Type;
public: public:
FxMinMax(TArray<FxExpression*> &expr, int type, const FScriptPosition &pos); FxMinMax(TArray<FxExpression*> &expr, FName type, const FScriptPosition &pos);
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build);

View file

@ -2043,11 +2043,11 @@ ExpEmit FxAbs::Emit(VMFunctionBuilder *build)
// //
// //
//========================================================================== //==========================================================================
FxMinMax::FxMinMax(TArray<FxExpression*> &expr, int type, const FScriptPosition &pos) FxMinMax::FxMinMax(TArray<FxExpression*> &expr, FName type, const FScriptPosition &pos)
: FxExpression(pos), Type(type) : FxExpression(pos), Type(type)
{ {
assert(expr.Size() > 0); assert(expr.Size() > 0);
assert(type == TK_Min || type == TK_Max); assert(type == NAME_Min || type == NAME_Max);
ValueType = VAL_Unknown; ValueType = VAL_Unknown;
choices.Resize(expr.Size()); choices.Resize(expr.Size());
@ -2132,7 +2132,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx)
{ {
ExpVal value = static_cast<FxConstant *>(choices[j])->GetValue(); ExpVal value = static_cast<FxConstant *>(choices[j])->GetValue();
assert(value.Type == ValueType.Type); assert(value.Type == ValueType.Type);
if (Type == TK_Min) if (Type == NAME_Min)
{ {
if (value.Type == VAL_Float) if (value.Type == VAL_Float)
{ {
@ -2213,7 +2213,7 @@ ExpEmit FxMinMax::Emit(VMFunctionBuilder *build)
assert(OP_LEF_RK == OP_LEF_RR+1); assert(OP_LEF_RK == OP_LEF_RR+1);
assert(OP_LE_RK == OP_LE_RR+1); assert(OP_LE_RK == OP_LE_RR+1);
if (Type == TK_Min) if (Type == NAME_Min)
{ {
opcode = ValueType.Type == VAL_Float ? OP_LEF_RR : OP_LE_RR; opcode = ValueType.Type == VAL_Float ? OP_LEF_RR : OP_LE_RR;
opA = 1; opA = 1;