- added 'null' token to the ZScript parser which is needed for null pointers.

- removed function declaration parser from DECORATE because it is not needed anymore.
- fixed: comparison operators could not handle names.
This commit is contained in:
Christoph Oelckers 2016-10-19 00:35:34 +02:00
parent f6b3cdc23d
commit 665d752686
7 changed files with 23 additions and 272 deletions

View file

@ -171,6 +171,7 @@ std2:
'global' { RET(TK_Global); }
'self' { RET(TK_Self); }
'stop' { RET(TK_Stop); }
'null' { RET(TK_Null); }
'is' { RET(TK_Is); }
'replaces' { RET(TK_Replaces); }

View file

@ -106,6 +106,7 @@ xx(TK_Optional, "'optional'")
xx(TK_Export, "'expert'")
xx(TK_Virtual, "'virtual'")
xx(TK_Super, "'super'")
xx(TK_Null, "'null'")
xx(TK_Global, "'global'")
xx(TK_Self, "'self'")
xx(TK_Stop, "'stop'")

View file

@ -1888,6 +1888,10 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric)
{
ValueType = TypeBool;
}
else if (left->ValueType == TypeName && right->ValueType == TypeName)
{
ValueType = TypeName;
}
else if (left->IsNumeric() && right->IsNumeric())
{
if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT)
@ -2395,7 +2399,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
return NULL;
}
if (!IsNumeric() && !IsPointer())
if (!IsNumeric() && !IsPointer() && ValueType != TypeName)
{
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
delete this;

View file

@ -334,213 +334,6 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
sc.MustGetToken(';');
}
//==========================================================================
//
// ParseArgListDef
//
// Parses the argument list from a function declaration.
//
//==========================================================================
static void ParseArgListDef(FScanner &sc, PClassActor *cls,
TArray<PType *> &args, TArray<DWORD> &argflags)
{
if (!sc.CheckToken(')'))
{
while (sc.TokenType != ')')
{
int flags = 0;
PType *type = NULL;
PClass *restrict = NULL;
// Retrieve flags before type name
for (;;)
{
if (sc.CheckToken(TK_Coerce) || sc.CheckToken(TK_Native))
{
}
else
{
break;
}
}
// Read the variable type
sc.MustGetAnyToken();
switch (sc.TokenType)
{
case TK_Bool:
type = TypeBool;
break;
case TK_Int:
type = TypeSInt32;
break;
case TK_Float:
type = TypeFloat64;
break;
case TK_Sound: type = TypeSound; break;
case TK_String: type = TypeString; break;
case TK_Name: type = TypeName; break;
case TK_State: type = TypeState; break;
case TK_Color: type = TypeColor; break;
case TK_Class:
sc.MustGetToken('<');
sc.MustGetToken(TK_Identifier); // Get class name
restrict = PClass::FindClass(sc.String);
if (restrict == NULL)
{
sc.ScriptMessage("Unknown class type %s", sc.String);
FScriptPosition::ErrorCounter++;
}
else
{
type = NewClassPointer(restrict);
}
sc.MustGetToken('>');
break;
case TK_Ellipsis:
// Making the final type NULL signals a varargs function.
type = NULL;
sc.MustGetToken(')');
sc.UnGet();
break;
default:
sc.ScriptMessage ("Unknown variable type %s", sc.TokenName(sc.TokenType, sc.String).GetChars());
type = TypeSInt32;
FScriptPosition::ErrorCounter++;
break;
}
// Read the optional variable name
if (!sc.CheckToken(',') && !sc.CheckToken(')'))
{
sc.MustGetToken(TK_Identifier);
}
else
{
sc.UnGet();
}
if (sc.CheckToken('='))
{
flags |= VARF_Optional;
FxExpression *def = ParseParameter(sc, cls, type, true);
delete def;
}
args.Push(type);
argflags.Push(flags);
sc.MustGetAnyToken();
if (sc.TokenType != ',' && sc.TokenType != ')')
{
sc.ScriptError ("Expected ',' or ')' but got %s instead", sc.TokenName(sc.TokenType, sc.String).GetChars());
}
}
}
sc.MustGetToken(';');
}
//==========================================================================
//
// ParseFunctionDef
//
// Parses a native function's parameters and adds it to the class,
// if possible.
//
//==========================================================================
void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname,
TArray<PType *> &rets, DWORD funcflags)
{
assert(cls != NULL);
const AFuncDesc *afd;
TArray<PType *> args;
TArray<DWORD> argflags;
TArray<FName> argnames;
afd = FindFunction(funcname);
if (afd == NULL)
{
sc.ScriptMessage ("The function '%s' has not been exported from the executable.", funcname.GetChars());
FScriptPosition::ErrorCounter++;
}
sc.MustGetToken('(');
SetImplicitArgs(&args, &argflags, &argnames, cls, funcflags);
// This function will be removed once all internal classes have been ported so don't bother filling in the function's argument names, because for anything going through here they'll never be used.
ParseArgListDef(sc, cls, args, argflags);
if (afd != NULL)
{
PFunction *sym = new PFunction(cls, funcname);
sym->AddVariant(NewPrototype(rets, args), argflags, argnames, *(afd->VMPointer), funcflags);
if (cls->Symbols.AddSymbol(sym) == NULL)
{
delete sym;
sc.ScriptMessage ("'%s' is already defined in class '%s'.",
funcname.GetChars(), cls->TypeName.GetChars());
FScriptPosition::ErrorCounter++;
}
}
}
//==========================================================================
//
// ParseNativeFunction
//
// Parses a non-action function declaration.
//
//==========================================================================
static void ParseNativeFunction(FScanner &sc, PClassActor *cls)
{
TArray<PType *> rets(1);
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
{
sc.ScriptMessage ("functions can only be declared by native actors!");
FScriptPosition::ErrorCounter++;
}
// Read the type and make sure it's acceptable.
sc.MustGetAnyToken();
switch (sc.TokenType)
{
case TK_Bool:
rets.Push(TypeBool);
break;
case TK_Int:
rets.Push(TypeSInt32);
break;
case TK_Float:
rets.Push(TypeFloat64);
break;
case TK_State:
rets.Push(TypeState);
break;
case TK_Void:
break;
case TK_Identifier:
rets.Push(NewPointer(RUNTIME_CLASS(DObject)));
// Todo: Object type
sc.ScriptError("Object type variables not implemented yet!");
break;
default:
sc.ScriptError("Invalid return type %s", sc.String);
return;
}
sc.MustGetToken(TK_Identifier);
ParseFunctionDef(sc, cls, sc.String, rets, VARF_Method);
}
//==========================================================================
//
// ParseUserVariable
@ -1081,55 +874,6 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag)
}
}
//==========================================================================
//
// ActorActionDef
//
// Parses an action function definition. A lot of this is essentially
// documentation in the declaration for when I have a proper language
// ready.
//
//==========================================================================
static void ParseActionDef (FScanner &sc, PClassActor *cls)
{
unsigned int error = 0;
FName funcname;
TArray<PType *> rets;
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
{
sc.ScriptMessage ("Action functions can only be imported by internal class and actor definitions!");
FScriptPosition::ErrorCounter++;
}
sc.MustGetToken(TK_Native);
// check for a return value
do
{
if (sc.CheckToken(TK_Bool))
{
rets.Push(TypeBool);
}
else if (sc.CheckToken(TK_Int))
{
rets.Push(TypeSInt32);
}
else if (sc.CheckToken(TK_State))
{
rets.Push(TypeState);
}
else if (sc.CheckToken(TK_Float))
{
rets.Push(TypeFloat64);
}
}
while (sc.CheckToken(','));
sc.MustGetToken(TK_Identifier);
funcname = sc.String;
ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action);
}
//==========================================================================
//
// Starts a new actor definition
@ -1330,10 +1074,6 @@ static void ParseActor(FScanner &sc)
{
switch (sc.TokenType)
{
case TK_Action:
ParseActionDef (sc, info);
break;
case TK_Const:
ParseConstant (sc, &info->Symbols, info);
break;
@ -1342,10 +1082,6 @@ static void ParseActor(FScanner &sc)
ParseEnum (sc, &info->Symbols, info);
break;
case TK_Native:
ParseNativeFunction (sc, info);
break;
case TK_Var:
ParseUserVariable (sc, &info->Symbols, info);
break;

View file

@ -956,6 +956,13 @@ primary(X) ::= IDENTIFIER(A).
expr->Type = NULL;
X = expr;
}
primary(X) ::= NULL(T).
{
NEW_AST_NODE(Expression, expr, T);
expr->Operation = PEX_Null;
expr->Type = NULL;
X = expr;
}
primary(X) ::= SUPER(T).
{
NEW_AST_NODE(Expression, expr, T);

View file

@ -3,6 +3,7 @@ xx(Nil, )
xx(ID, )
xx(Super, )
xx(Null, )
xx(Self, )
xx(ConstValue, )
xx(FuncCall, )

View file

@ -153,6 +153,7 @@ static void InitTokenMap()
TOKENDEF (TK_Out, ZCC_OUT);
TOKENDEF (TK_Optional, ZCC_OPTIONAL);
TOKENDEF (TK_Super, ZCC_SUPER);
TOKENDEF (TK_Null, ZCC_NULL);
TOKENDEF (TK_Self, ZCC_SELF);
TOKENDEF ('~', ZCC_TILDE);
TOKENDEF ('!', ZCC_BANG);